1/* 2 * Copyright © 2021 Collabora Ltd. 3 * 4 * Derived from: 5 * Copyright © 2016 Red Hat. 6 * Copyright © 2016 Bas Nieuwenhuizen 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice (including the next 16 * paragraph) shall be included in all copies or substantial portions of the 17 * Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 24 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 25 * DEALINGS IN THE SOFTWARE. 26 */ 27 28#include "genxml/gen_macros.h" 29 30#include "panvk_private.h" 31 32#include <assert.h> 33#include <fcntl.h> 34#include <stdbool.h> 35#include <string.h> 36#include <unistd.h> 37 38#include "util/mesa-sha1.h" 39#include "vk_descriptors.h" 40#include "vk_util.h" 41 42#include "pan_bo.h" 43#include "panvk_cs.h" 44 45static VkResult 46panvk_per_arch(descriptor_set_create)(struct panvk_device *device, 47 struct panvk_descriptor_pool *pool, 48 const struct panvk_descriptor_set_layout *layout, 49 struct panvk_descriptor_set **out_set) 50{ 51 struct panvk_descriptor_set *set; 52 53 /* TODO: Allocate from the pool! */ 54 set = vk_object_zalloc(&device->vk, NULL, 55 sizeof(struct panvk_descriptor_set), 56 VK_OBJECT_TYPE_DESCRIPTOR_SET); 57 if (!set) 58 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 59 60 set->layout = layout; 61 set->descs = vk_alloc(&device->vk.alloc, 62 sizeof(*set->descs) * layout->num_descs, 8, 63 VK_OBJECT_TYPE_DESCRIPTOR_SET); 64 if (!set->descs) 65 goto err_free_set; 66 67 if (layout->num_ubos) { 68 set->ubos = vk_zalloc(&device->vk.alloc, 69 pan_size(UNIFORM_BUFFER) * layout->num_ubos, 8, 70 VK_OBJECT_TYPE_DESCRIPTOR_SET); 71 if (!set->ubos) 72 goto err_free_set; 73 } 74 75 if (layout->num_samplers) { 76 set->samplers = vk_zalloc(&device->vk.alloc, 77 pan_size(SAMPLER) * layout->num_samplers, 8, 78 VK_OBJECT_TYPE_DESCRIPTOR_SET); 79 if (!set->samplers) 80 goto err_free_set; 81 } 82 83 if (layout->num_textures) { 84 set->textures = 85 vk_zalloc(&device->vk.alloc, 86 (PAN_ARCH >= 6 ? pan_size(TEXTURE) : sizeof(mali_ptr)) * 87 layout->num_textures, 88 8, VK_OBJECT_TYPE_DESCRIPTOR_SET); 89 if (!set->textures) 90 goto err_free_set; 91 } 92 93 for (unsigned i = 0; i < layout->binding_count; i++) { 94 if (!layout->bindings[i].immutable_samplers) 95 continue; 96 97 for (unsigned j = 0; j < layout->bindings[i].array_size; j++) { 98 set->descs[layout->bindings[i].desc_idx].image.sampler = 99 layout->bindings[i].immutable_samplers[j]; 100 } 101 } 102 103 *out_set = set; 104 return VK_SUCCESS; 105 106err_free_set: 107 vk_free(&device->vk.alloc, set->textures); 108 vk_free(&device->vk.alloc, set->samplers); 109 vk_free(&device->vk.alloc, set->ubos); 110 vk_free(&device->vk.alloc, set->descs); 111 vk_object_free(&device->vk, NULL, set); 112 return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 113} 114 115VkResult 116panvk_per_arch(AllocateDescriptorSets)(VkDevice _device, 117 const VkDescriptorSetAllocateInfo *pAllocateInfo, 118 VkDescriptorSet *pDescriptorSets) 119{ 120 VK_FROM_HANDLE(panvk_device, device, _device); 121 VK_FROM_HANDLE(panvk_descriptor_pool, pool, pAllocateInfo->descriptorPool); 122 VkResult result; 123 unsigned i; 124 125 for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 126 VK_FROM_HANDLE(panvk_descriptor_set_layout, layout, 127 pAllocateInfo->pSetLayouts[i]); 128 struct panvk_descriptor_set *set = NULL; 129 130 result = panvk_per_arch(descriptor_set_create)(device, pool, layout, &set); 131 if (result != VK_SUCCESS) 132 goto err_free_sets; 133 134 pDescriptorSets[i] = panvk_descriptor_set_to_handle(set); 135 } 136 137 return VK_SUCCESS; 138 139err_free_sets: 140 panvk_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, i, pDescriptorSets); 141 for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) 142 pDescriptorSets[i] = VK_NULL_HANDLE; 143 144 return result; 145} 146 147static void 148panvk_set_image_desc(struct panvk_descriptor *desc, 149 const VkDescriptorImageInfo *pImageInfo) 150{ 151 VK_FROM_HANDLE(panvk_sampler, sampler, pImageInfo->sampler); 152 VK_FROM_HANDLE(panvk_image_view, image_view, pImageInfo->imageView); 153 desc->image.sampler = sampler; 154 desc->image.view = image_view; 155 desc->image.layout = pImageInfo->imageLayout; 156} 157 158static void 159panvk_set_texel_buffer_view_desc(struct panvk_descriptor *desc, 160 const VkBufferView *pTexelBufferView) 161{ 162 VK_FROM_HANDLE(panvk_buffer_view, buffer_view, *pTexelBufferView); 163 desc->buffer_view = buffer_view; 164} 165 166static void 167panvk_set_buffer_info_desc(struct panvk_descriptor *desc, 168 const VkDescriptorBufferInfo *pBufferInfo) 169{ 170 VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer); 171 desc->buffer_info.buffer = buffer; 172 desc->buffer_info.offset = pBufferInfo->offset; 173 desc->buffer_info.range = pBufferInfo->range; 174} 175 176static void 177panvk_per_arch(set_ubo_desc)(void *ubo, 178 const VkDescriptorBufferInfo *pBufferInfo) 179{ 180 VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer); 181 size_t size = pBufferInfo->range == VK_WHOLE_SIZE ? 182 (buffer->bo->size - pBufferInfo->offset) : 183 pBufferInfo->range; 184 185 panvk_per_arch(emit_ubo)(buffer->bo->ptr.gpu + pBufferInfo->offset, size, ubo); 186} 187 188static void 189panvk_set_sampler_desc(void *desc, 190 const VkDescriptorImageInfo *pImageInfo) 191{ 192 VK_FROM_HANDLE(panvk_sampler, sampler, pImageInfo->sampler); 193 194 memcpy(desc, &sampler->desc, sizeof(sampler->desc)); 195} 196 197static void 198panvk_per_arch(set_texture_desc)(struct panvk_descriptor_set *set, 199 unsigned idx, 200 const VkDescriptorImageInfo *pImageInfo) 201{ 202 VK_FROM_HANDLE(panvk_image_view, view, pImageInfo->imageView); 203 204#if PAN_ARCH >= 6 205 memcpy(&((struct mali_texture_packed *)set->textures)[idx], 206 view->descs.tex, pan_size(TEXTURE)); 207#else 208 ((mali_ptr *)set->textures)[idx] = view->bo->ptr.gpu; 209#endif 210} 211 212static void 213panvk_per_arch(write_descriptor_set)(struct panvk_device *dev, 214 const VkWriteDescriptorSet *pDescriptorWrite) 215{ 216 VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorWrite->dstSet); 217 const struct panvk_descriptor_set_layout *layout = set->layout; 218 unsigned dest_offset = pDescriptorWrite->dstArrayElement; 219 unsigned binding = pDescriptorWrite->dstBinding; 220 struct mali_uniform_buffer_packed *ubos = set->ubos; 221 struct mali_sampler_packed *samplers = set->samplers; 222 unsigned src_offset = 0; 223 224 while (src_offset < pDescriptorWrite->descriptorCount && 225 binding < layout->binding_count) { 226 const struct panvk_descriptor_set_binding_layout *binding_layout = 227 &layout->bindings[binding]; 228 229 if (!binding_layout->array_size) { 230 binding++; 231 dest_offset = 0; 232 continue; 233 } 234 235 assert(pDescriptorWrite->descriptorType == binding_layout->type); 236 unsigned ndescs = MIN2(pDescriptorWrite->descriptorCount - src_offset, 237 binding_layout->array_size - dest_offset); 238 struct panvk_descriptor *descs = &set->descs[binding_layout->desc_idx + dest_offset]; 239 assert(binding_layout->desc_idx + dest_offset + ndescs <= set->layout->num_descs); 240 241 switch (pDescriptorWrite->descriptorType) { 242 case VK_DESCRIPTOR_TYPE_SAMPLER: 243 case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 244 case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 245 for (unsigned i = 0; i < ndescs; i++) { 246 const VkDescriptorImageInfo *info = &pDescriptorWrite->pImageInfo[src_offset + i]; 247 248 if ((pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER || 249 pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) && 250 !binding_layout->immutable_samplers) { 251 unsigned sampler = binding_layout->sampler_idx + dest_offset + i; 252 253 panvk_set_sampler_desc(&samplers[sampler], info); 254 } 255 256 if (pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 257 pDescriptorWrite->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) { 258 unsigned tex = binding_layout->tex_idx + dest_offset + i; 259 260 panvk_per_arch(set_texture_desc)(set, tex, info); 261 } 262 } 263 break; 264 265 case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 266 case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 267 for (unsigned i = 0; i < ndescs; i++) 268 panvk_set_image_desc(&descs[i], &pDescriptorWrite->pImageInfo[src_offset + i]); 269 break; 270 271 case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 272 case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 273 for (unsigned i = 0; i < ndescs; i++) 274 panvk_set_texel_buffer_view_desc(&descs[i], &pDescriptorWrite->pTexelBufferView[src_offset + i]); 275 break; 276 277 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 278 case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 279 for (unsigned i = 0; i < ndescs; i++) { 280 unsigned ubo = binding_layout->ubo_idx + dest_offset + i; 281 panvk_per_arch(set_ubo_desc)(&ubos[ubo], 282 &pDescriptorWrite->pBufferInfo[src_offset + i]); 283 } 284 break; 285 286 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 287 case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 288 for (unsigned i = 0; i < ndescs; i++) 289 panvk_set_buffer_info_desc(&descs[i], &pDescriptorWrite->pBufferInfo[src_offset + i]); 290 break; 291 default: 292 unreachable("Invalid type"); 293 } 294 295 src_offset += ndescs; 296 binding++; 297 dest_offset = 0; 298 } 299} 300 301static void 302panvk_copy_descriptor_set(struct panvk_device *dev, 303 const VkCopyDescriptorSet *pDescriptorCopy) 304{ 305 VK_FROM_HANDLE(panvk_descriptor_set, dest_set, pDescriptorCopy->dstSet); 306 VK_FROM_HANDLE(panvk_descriptor_set, src_set, pDescriptorCopy->srcSet); 307 const struct panvk_descriptor_set_layout *dest_layout = dest_set->layout; 308 const struct panvk_descriptor_set_layout *src_layout = dest_set->layout; 309 unsigned dest_offset = pDescriptorCopy->dstArrayElement; 310 unsigned src_offset = pDescriptorCopy->srcArrayElement; 311 unsigned dest_binding = pDescriptorCopy->dstBinding; 312 unsigned src_binding = pDescriptorCopy->srcBinding; 313 unsigned desc_count = pDescriptorCopy->descriptorCount; 314 315 while (desc_count && src_binding < src_layout->binding_count && 316 dest_binding < dest_layout->binding_count) { 317 const struct panvk_descriptor_set_binding_layout *dest_binding_layout = 318 &src_layout->bindings[dest_binding]; 319 320 if (!dest_binding_layout->array_size) { 321 dest_binding++; 322 dest_offset = 0; 323 continue; 324 } 325 326 const struct panvk_descriptor_set_binding_layout *src_binding_layout = 327 &src_layout->bindings[src_binding]; 328 329 if (!src_binding_layout->array_size) { 330 src_binding++; 331 src_offset = 0; 332 continue; 333 } 334 335 assert(dest_binding_layout->type == src_binding_layout->type); 336 337 unsigned ndescs = MAX3(desc_count, 338 dest_binding_layout->array_size - dest_offset, 339 src_binding_layout->array_size - src_offset); 340 341 struct panvk_descriptor *dest_descs = dest_set->descs + dest_binding_layout->desc_idx + dest_offset; 342 struct panvk_descriptor *src_descs = src_set->descs + src_binding_layout->desc_idx + src_offset; 343 memcpy(dest_descs, src_descs, ndescs * sizeof(*dest_descs)); 344 desc_count -= ndescs; 345 dest_offset += ndescs; 346 if (dest_offset == dest_binding_layout->array_size) { 347 dest_binding++; 348 dest_offset = 0; 349 continue; 350 } 351 src_offset += ndescs; 352 if (src_offset == src_binding_layout->array_size) { 353 src_binding++; 354 src_offset = 0; 355 continue; 356 } 357 } 358 359 assert(!desc_count); 360} 361 362void 363panvk_per_arch(UpdateDescriptorSets)(VkDevice _device, 364 uint32_t descriptorWriteCount, 365 const VkWriteDescriptorSet *pDescriptorWrites, 366 uint32_t descriptorCopyCount, 367 const VkCopyDescriptorSet *pDescriptorCopies) 368{ 369 VK_FROM_HANDLE(panvk_device, dev, _device); 370 371 for (unsigned i = 0; i < descriptorWriteCount; i++) 372 panvk_per_arch(write_descriptor_set)(dev, &pDescriptorWrites[i]); 373 for (unsigned i = 0; i < descriptorCopyCount; i++) 374 panvk_copy_descriptor_set(dev, &pDescriptorCopies[i]); 375} 376