1/*
2 * Copyright © 2019 Raspberry Pi
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include "vk_descriptors.h"
25#include "vk_util.h"
26
27#include "v3dv_private.h"
28
29/*
30 * For a given descriptor defined by the descriptor_set it belongs, its
31 * binding layout, and array_index, it returns the map region assigned to it
32 * from the descriptor pool bo.
33 */
34static void*
35descriptor_bo_map(struct v3dv_device *device,
36                  struct v3dv_descriptor_set *set,
37                  const struct v3dv_descriptor_set_binding_layout *binding_layout,
38                  uint32_t array_index)
39{
40   assert(v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0);
41   return set->pool->bo->map +
42      set->base_offset + binding_layout->descriptor_offset +
43      array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type);
44}
45
46static bool
47descriptor_type_is_dynamic(VkDescriptorType type)
48{
49   switch (type) {
50   case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
51   case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
52      return true;
53      break;
54   default:
55      return false;
56   }
57}
58
59/*
60 * Tries to get a real descriptor using a descriptor map index from the
61 * descriptor_state + pipeline_layout.
62 */
63struct v3dv_descriptor *
64v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state,
65                                   struct v3dv_descriptor_map *map,
66                                   struct v3dv_pipeline_layout *pipeline_layout,
67                                   uint32_t index,
68                                   uint32_t *dynamic_offset)
69{
70   assert(index < map->num_desc);
71
72   uint32_t set_number = map->set[index];
73   assert((descriptor_state->valid & 1 << set_number));
74
75   struct v3dv_descriptor_set *set =
76      descriptor_state->descriptor_sets[set_number];
77   assert(set);
78
79   uint32_t binding_number = map->binding[index];
80   assert(binding_number < set->layout->binding_count);
81
82   const struct v3dv_descriptor_set_binding_layout *binding_layout =
83      &set->layout->binding[binding_number];
84
85   uint32_t array_index = map->array_index[index];
86   assert(array_index < binding_layout->array_size);
87
88   if (descriptor_type_is_dynamic(binding_layout->type)) {
89      uint32_t dynamic_offset_index =
90         pipeline_layout->set[set_number].dynamic_offset_start +
91         binding_layout->dynamic_offset_index + array_index;
92
93      *dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index];
94   }
95
96   return &set->descriptors[binding_layout->descriptor_index + array_index];
97}
98
99/* Equivalent to map_get_descriptor but it returns a reloc with the bo
100 * associated with that descriptor (suballocation of the descriptor pool bo)
101 *
102 * It also returns the descriptor type, so the caller could do extra
103 * validation or adding extra offsets if the bo contains more that one field.
104 */
105static struct v3dv_cl_reloc
106v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device,
107                                      struct v3dv_descriptor_state *descriptor_state,
108                                      struct v3dv_descriptor_map *map,
109                                      struct v3dv_pipeline_layout *pipeline_layout,
110                                      uint32_t index,
111                                      VkDescriptorType *out_type)
112{
113   assert(index < map->num_desc);
114
115   uint32_t set_number = map->set[index];
116   assert(descriptor_state->valid & 1 << set_number);
117
118   struct v3dv_descriptor_set *set =
119      descriptor_state->descriptor_sets[set_number];
120   assert(set);
121
122   uint32_t binding_number = map->binding[index];
123   assert(binding_number < set->layout->binding_count);
124
125   const struct v3dv_descriptor_set_binding_layout *binding_layout =
126      &set->layout->binding[binding_number];
127
128   assert(v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0);
129   *out_type = binding_layout->type;
130
131   uint32_t array_index = map->array_index[index];
132   assert(array_index < binding_layout->array_size);
133
134   struct v3dv_cl_reloc reloc = {
135      .bo = set->pool->bo,
136      .offset = set->base_offset + binding_layout->descriptor_offset +
137      array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type),
138   };
139
140   return reloc;
141}
142
143/*
144 * The difference between this method and v3dv_descriptor_map_get_descriptor,
145 * is that if the sampler are added as immutable when creating the set layout,
146 * they are bound to the set layout, so not part of the descriptor per
147 * se. This method return early in that case.
148 */
149const struct v3dv_sampler *
150v3dv_descriptor_map_get_sampler(struct v3dv_descriptor_state *descriptor_state,
151                                struct v3dv_descriptor_map *map,
152                                struct v3dv_pipeline_layout *pipeline_layout,
153                                uint32_t index)
154{
155   assert(index < map->num_desc);
156
157   uint32_t set_number = map->set[index];
158   assert(descriptor_state->valid & 1 << set_number);
159
160   struct v3dv_descriptor_set *set =
161      descriptor_state->descriptor_sets[set_number];
162   assert(set);
163
164   uint32_t binding_number = map->binding[index];
165   assert(binding_number < set->layout->binding_count);
166
167   const struct v3dv_descriptor_set_binding_layout *binding_layout =
168      &set->layout->binding[binding_number];
169
170   uint32_t array_index = map->array_index[index];
171   assert(array_index < binding_layout->array_size);
172
173   if (binding_layout->immutable_samplers_offset != 0) {
174      assert(binding_layout->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
175             binding_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
176
177      const struct v3dv_sampler *immutable_samplers =
178         v3dv_immutable_samplers(set->layout, binding_layout);
179
180      assert(immutable_samplers);
181      const struct v3dv_sampler *sampler = &immutable_samplers[array_index];
182      assert(sampler);
183
184      return sampler;
185   }
186
187   struct v3dv_descriptor *descriptor =
188      &set->descriptors[binding_layout->descriptor_index + array_index];
189
190   assert(descriptor->type == VK_DESCRIPTOR_TYPE_SAMPLER ||
191          descriptor->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
192
193   assert(descriptor->sampler);
194
195   return descriptor->sampler;
196}
197
198
199struct v3dv_cl_reloc
200v3dv_descriptor_map_get_sampler_state(struct v3dv_device *device,
201                                      struct v3dv_descriptor_state *descriptor_state,
202                                      struct v3dv_descriptor_map *map,
203                                      struct v3dv_pipeline_layout *pipeline_layout,
204                                      uint32_t index)
205{
206   VkDescriptorType type;
207   struct v3dv_cl_reloc reloc =
208      v3dv_descriptor_map_get_descriptor_bo(device, descriptor_state, map,
209                                            pipeline_layout,
210                                            index, &type);
211
212   assert(type == VK_DESCRIPTOR_TYPE_SAMPLER ||
213          type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
214
215   if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
216      reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)();
217
218   return reloc;
219}
220
221const struct v3dv_format*
222v3dv_descriptor_map_get_texture_format(struct v3dv_descriptor_state *descriptor_state,
223                                       struct v3dv_descriptor_map *map,
224                                       struct v3dv_pipeline_layout *pipeline_layout,
225                                       uint32_t index,
226                                       VkFormat *out_vk_format)
227{
228   struct v3dv_descriptor *descriptor =
229      v3dv_descriptor_map_get_descriptor(descriptor_state, map,
230                                         pipeline_layout, index, NULL);
231
232   switch (descriptor->type) {
233   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
234   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
235      assert(descriptor->buffer_view);
236      *out_vk_format = descriptor->buffer_view->vk_format;
237      return descriptor->buffer_view->format;
238   case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
239   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
240   case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
241   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
242      assert(descriptor->image_view);
243      *out_vk_format = descriptor->image_view->vk.format;
244      return descriptor->image_view->format;
245   default:
246      unreachable("descriptor type doesn't has a texture format");
247   }
248}
249
250struct v3dv_bo*
251v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state,
252                                   struct v3dv_descriptor_map *map,
253                                   struct v3dv_pipeline_layout *pipeline_layout,
254                                   uint32_t index)
255
256{
257   struct v3dv_descriptor *descriptor =
258      v3dv_descriptor_map_get_descriptor(descriptor_state, map,
259                                         pipeline_layout, index, NULL);
260
261   switch (descriptor->type) {
262   case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
263   case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
264      assert(descriptor->buffer_view);
265      return descriptor->buffer_view->buffer->mem->bo;
266   case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
267   case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
268   case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
269   case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
270      assert(descriptor->image_view);
271      struct v3dv_image *image =
272         (struct v3dv_image *) descriptor->image_view->vk.image;
273      return image->mem->bo;
274   }
275   default:
276      unreachable("descriptor type doesn't has a texture bo");
277   }
278}
279
280struct v3dv_cl_reloc
281v3dv_descriptor_map_get_texture_shader_state(struct v3dv_device *device,
282                                             struct v3dv_descriptor_state *descriptor_state,
283                                             struct v3dv_descriptor_map *map,
284                                             struct v3dv_pipeline_layout *pipeline_layout,
285                                             uint32_t index)
286{
287   VkDescriptorType type;
288   struct v3dv_cl_reloc reloc =
289      v3dv_descriptor_map_get_descriptor_bo(device,
290                                            descriptor_state, map,
291                                            pipeline_layout,
292                                            index, &type);
293
294   assert(type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
295          type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
296          type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||
297          type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||
298          type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||
299          type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);
300
301   if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)
302      reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)();
303
304   return reloc;
305}
306
307/*
308 * As anv and tu already points:
309 *
310 * "Pipeline layouts.  These have nothing to do with the pipeline.  They are
311 * just multiple descriptor set layouts pasted together."
312 */
313
314VKAPI_ATTR VkResult VKAPI_CALL
315v3dv_CreatePipelineLayout(VkDevice _device,
316                         const VkPipelineLayoutCreateInfo *pCreateInfo,
317                         const VkAllocationCallbacks *pAllocator,
318                         VkPipelineLayout *pPipelineLayout)
319{
320   V3DV_FROM_HANDLE(v3dv_device, device, _device);
321   struct v3dv_pipeline_layout *layout;
322
323   assert(pCreateInfo->sType ==
324          VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
325
326   layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout),
327                             VK_OBJECT_TYPE_PIPELINE_LAYOUT);
328   if (layout == NULL)
329      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
330
331   layout->num_sets = pCreateInfo->setLayoutCount;
332
333   uint32_t dynamic_offset_count = 0;
334   for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
335      V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout,
336                     pCreateInfo->pSetLayouts[set]);
337      layout->set[set].layout = set_layout;
338
339      layout->set[set].dynamic_offset_start = dynamic_offset_count;
340      for (uint32_t b = 0; b < set_layout->binding_count; b++) {
341         dynamic_offset_count += set_layout->binding[b].array_size *
342            set_layout->binding[b].dynamic_offset_count;
343      }
344
345      layout->shader_stages |= set_layout->shader_stages;
346   }
347
348   layout->push_constant_size = 0;
349   for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
350      const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
351      layout->push_constant_size =
352         MAX2(layout->push_constant_size, range->offset + range->size);
353   }
354
355   layout->push_constant_size = align(layout->push_constant_size, 4096);
356
357   layout->dynamic_offset_count = dynamic_offset_count;
358
359   *pPipelineLayout = v3dv_pipeline_layout_to_handle(layout);
360
361   return VK_SUCCESS;
362}
363
364VKAPI_ATTR void VKAPI_CALL
365v3dv_DestroyPipelineLayout(VkDevice _device,
366                          VkPipelineLayout _pipelineLayout,
367                          const VkAllocationCallbacks *pAllocator)
368{
369   V3DV_FROM_HANDLE(v3dv_device, device, _device);
370   V3DV_FROM_HANDLE(v3dv_pipeline_layout, pipeline_layout, _pipelineLayout);
371
372   if (!pipeline_layout)
373      return;
374   vk_object_free(&device->vk, pAllocator, pipeline_layout);
375}
376
377VKAPI_ATTR VkResult VKAPI_CALL
378v3dv_CreateDescriptorPool(VkDevice _device,
379                          const VkDescriptorPoolCreateInfo *pCreateInfo,
380                          const VkAllocationCallbacks *pAllocator,
381                          VkDescriptorPool *pDescriptorPool)
382{
383   V3DV_FROM_HANDLE(v3dv_device, device, _device);
384   struct v3dv_descriptor_pool *pool;
385   /* size is for the vulkan object descriptor pool. The final size would
386    * depend on some of FREE_DESCRIPTOR flags used
387    */
388   uint64_t size = sizeof(struct v3dv_descriptor_pool);
389   /* bo_size is for the descriptor related info that we need to have on a GPU
390    * address (so on v3dv_bo_alloc allocated memory), like for example the
391    * texture sampler state. Note that not all the descriptors use it
392    */
393   uint32_t bo_size = 0;
394   uint32_t descriptor_count = 0;
395
396   assert(pCreateInfo->poolSizeCount > 0);
397   for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {
398      /* Verify supported descriptor type */
399      switch(pCreateInfo->pPoolSizes[i].type) {
400      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
401      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
402      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
403      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
404      case VK_DESCRIPTOR_TYPE_SAMPLER:
405      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
406      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
407      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
408      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
409      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
410      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
411         break;
412      default:
413         unreachable("Unimplemented descriptor type");
414         break;
415      }
416
417      assert(pCreateInfo->pPoolSizes[i].descriptorCount > 0);
418      descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount;
419      bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) *
420         pCreateInfo->pPoolSizes[i].descriptorCount;
421   }
422
423   if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
424      uint64_t host_size =
425         pCreateInfo->maxSets * sizeof(struct v3dv_descriptor_set);
426      host_size += sizeof(struct v3dv_descriptor) * descriptor_count;
427      size += host_size;
428   } else {
429      size += sizeof(struct v3dv_descriptor_pool_entry) * pCreateInfo->maxSets;
430   }
431
432   pool = vk_object_zalloc(&device->vk, pAllocator, size,
433                           VK_OBJECT_TYPE_DESCRIPTOR_POOL);
434
435   if (!pool)
436      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
437
438   if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {
439      pool->host_memory_base = (uint8_t*)pool + sizeof(struct v3dv_descriptor_pool);
440      pool->host_memory_ptr = pool->host_memory_base;
441      pool->host_memory_end = (uint8_t*)pool + size;
442   }
443
444   pool->max_entry_count = pCreateInfo->maxSets;
445
446   if (bo_size > 0) {
447      pool->bo = v3dv_bo_alloc(device, bo_size, "descriptor pool bo", true);
448      if (!pool->bo)
449         goto out_of_device_memory;
450
451      bool ok = v3dv_bo_map(device, pool->bo, pool->bo->size);
452      if (!ok)
453         goto out_of_device_memory;
454
455      pool->current_offset = 0;
456   } else {
457      pool->bo = NULL;
458   }
459
460   *pDescriptorPool = v3dv_descriptor_pool_to_handle(pool);
461
462   return VK_SUCCESS;
463
464 out_of_device_memory:
465   vk_object_free(&device->vk, pAllocator, pool);
466   return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY);
467}
468
469static void
470descriptor_set_destroy(struct v3dv_device *device,
471                       struct v3dv_descriptor_pool *pool,
472                       struct v3dv_descriptor_set *set,
473                       bool free_bo)
474{
475   assert(!pool->host_memory_base);
476
477   if (free_bo && !pool->host_memory_base) {
478      for (uint32_t i = 0; i < pool->entry_count; i++) {
479         if (pool->entries[i].set == set) {
480            memmove(&pool->entries[i], &pool->entries[i+1],
481                    sizeof(pool->entries[i]) * (pool->entry_count - i - 1));
482            --pool->entry_count;
483            break;
484         }
485      }
486   }
487   vk_object_free(&device->vk, NULL, set);
488}
489
490VKAPI_ATTR void VKAPI_CALL
491v3dv_DestroyDescriptorPool(VkDevice _device,
492                           VkDescriptorPool _pool,
493                           const VkAllocationCallbacks *pAllocator)
494{
495   V3DV_FROM_HANDLE(v3dv_device, device, _device);
496   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, _pool);
497
498   if (!pool)
499      return;
500
501   if (!pool->host_memory_base) {
502      for(int i = 0; i < pool->entry_count; ++i) {
503         descriptor_set_destroy(device, pool, pool->entries[i].set, false);
504      }
505   }
506
507   if (pool->bo) {
508      v3dv_bo_free(device, pool->bo);
509      pool->bo = NULL;
510   }
511
512   vk_object_free(&device->vk, pAllocator, pool);
513}
514
515VKAPI_ATTR VkResult VKAPI_CALL
516v3dv_ResetDescriptorPool(VkDevice _device,
517                         VkDescriptorPool descriptorPool,
518                         VkDescriptorPoolResetFlags flags)
519{
520   V3DV_FROM_HANDLE(v3dv_device, device, _device);
521   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);
522
523   if (!pool->host_memory_base) {
524      for(int i = 0; i < pool->entry_count; ++i) {
525         descriptor_set_destroy(device, pool, pool->entries[i].set, false);
526      }
527   } else {
528      /* We clean-up the host memory, so when allocating a new set from the
529       * pool, it is already 0
530       */
531      uint32_t host_size = pool->host_memory_end - pool->host_memory_base;
532      memset(pool->host_memory_base, 0, host_size);
533   }
534
535   pool->entry_count = 0;
536   pool->host_memory_ptr = pool->host_memory_base;
537   pool->current_offset = 0;
538
539   return VK_SUCCESS;
540}
541
542VKAPI_ATTR VkResult VKAPI_CALL
543v3dv_CreateDescriptorSetLayout(VkDevice _device,
544                               const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
545                               const VkAllocationCallbacks *pAllocator,
546                               VkDescriptorSetLayout *pSetLayout)
547{
548   V3DV_FROM_HANDLE(v3dv_device, device, _device);
549   struct v3dv_descriptor_set_layout *set_layout;
550
551   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
552
553   uint32_t num_bindings = 0;
554   uint32_t immutable_sampler_count = 0;
555   for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
556      num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);
557
558      /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
559       *
560       *    "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
561       *    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
562       *    pImmutableSamplers can be used to initialize a set of immutable
563       *    samplers. [...]  If descriptorType is not one of these descriptor
564       *    types, then pImmutableSamplers is ignored.
565       *
566       * We need to be careful here and only parse pImmutableSamplers if we
567       * have one of the right descriptor types.
568       */
569      VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType;
570      if ((desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
571           desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) &&
572           pCreateInfo->pBindings[j].pImmutableSamplers) {
573         immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
574      }
575   }
576
577   uint32_t samplers_offset = sizeof(struct v3dv_descriptor_set_layout) +
578      num_bindings * sizeof(set_layout->binding[0]);
579   uint32_t size = samplers_offset +
580      immutable_sampler_count * sizeof(struct v3dv_sampler);
581
582   set_layout = vk_object_zalloc(&device->vk, pAllocator, size,
583                                 VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
584
585   if (!set_layout)
586      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
587
588   /* We just allocate all the immutable samplers at the end of the struct */
589   struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings];
590
591   assert(pCreateInfo->bindingCount == 0 || num_bindings > 0);
592
593   VkDescriptorSetLayoutBinding *bindings = NULL;
594   VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,
595                                               pCreateInfo->bindingCount, &bindings);
596   if (result != VK_SUCCESS) {
597      vk_object_free(&device->vk, pAllocator, set_layout);
598      return vk_error(device, result);
599   }
600
601   memset(set_layout->binding, 0,
602          size - sizeof(struct v3dv_descriptor_set_layout));
603
604   set_layout->binding_count = num_bindings;
605   set_layout->flags = pCreateInfo->flags;
606   set_layout->shader_stages = 0;
607   set_layout->bo_size = 0;
608
609   uint32_t descriptor_count = 0;
610   uint32_t dynamic_offset_count = 0;
611
612   for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
613      const VkDescriptorSetLayoutBinding *binding = bindings + i;
614      uint32_t binding_number = binding->binding;
615
616      switch (binding->descriptorType) {
617      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
618      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
619         break;
620      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
621      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
622         set_layout->binding[binding_number].dynamic_offset_count = 1;
623         break;
624      case VK_DESCRIPTOR_TYPE_SAMPLER:
625      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
626      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
627      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
628      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
629      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
630      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
631         /* Nothing here, just to keep the descriptor type filtering below */
632         break;
633      default:
634         unreachable("Unknown descriptor type\n");
635         break;
636      }
637
638      set_layout->binding[binding_number].type = binding->descriptorType;
639      set_layout->binding[binding_number].array_size = binding->descriptorCount;
640      set_layout->binding[binding_number].descriptor_index = descriptor_count;
641      set_layout->binding[binding_number].dynamic_offset_index = dynamic_offset_count;
642
643      if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
644           binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&
645          binding->pImmutableSamplers) {
646
647         set_layout->binding[binding_number].immutable_samplers_offset = samplers_offset;
648
649         for (uint32_t i = 0; i < binding->descriptorCount; i++)
650            samplers[i] = *v3dv_sampler_from_handle(binding->pImmutableSamplers[i]);
651
652         samplers += binding->descriptorCount;
653         samplers_offset += sizeof(struct v3dv_sampler) * binding->descriptorCount;
654      }
655
656      descriptor_count += binding->descriptorCount;
657      dynamic_offset_count += binding->descriptorCount *
658         set_layout->binding[binding_number].dynamic_offset_count;
659
660      set_layout->shader_stages |= binding->stageFlags;
661
662      set_layout->binding[binding_number].descriptor_offset = set_layout->bo_size;
663      set_layout->bo_size +=
664         v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) *
665         binding->descriptorCount;
666   }
667
668   free(bindings);
669
670   set_layout->descriptor_count = descriptor_count;
671   set_layout->dynamic_offset_count = dynamic_offset_count;
672
673   *pSetLayout = v3dv_descriptor_set_layout_to_handle(set_layout);
674
675   return VK_SUCCESS;
676}
677
678VKAPI_ATTR void VKAPI_CALL
679v3dv_DestroyDescriptorSetLayout(VkDevice _device,
680                                VkDescriptorSetLayout _set_layout,
681                                const VkAllocationCallbacks *pAllocator)
682{
683   V3DV_FROM_HANDLE(v3dv_device, device, _device);
684   V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, _set_layout);
685
686   if (!set_layout)
687      return;
688
689   vk_object_free(&device->vk, pAllocator, set_layout);
690}
691
692static inline VkResult
693out_of_pool_memory(const struct v3dv_device *device,
694                   const struct v3dv_descriptor_pool *pool)
695{
696   /* Don't log OOPM errors for internal driver pools, we handle these properly
697    * by allocating a new pool, so they don't point to real issues.
698    */
699   if (!pool->is_driver_internal)
700      return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY);
701   else
702      return VK_ERROR_OUT_OF_POOL_MEMORY;
703}
704
705static VkResult
706descriptor_set_create(struct v3dv_device *device,
707                      struct v3dv_descriptor_pool *pool,
708                      const struct v3dv_descriptor_set_layout *layout,
709                      struct v3dv_descriptor_set **out_set)
710{
711   struct v3dv_descriptor_set *set;
712   uint32_t descriptor_count = layout->descriptor_count;
713   unsigned mem_size = sizeof(struct v3dv_descriptor_set) +
714      sizeof(struct v3dv_descriptor) * descriptor_count;
715
716   if (pool->host_memory_base) {
717      if (pool->host_memory_end - pool->host_memory_ptr < mem_size)
718         return out_of_pool_memory(device, pool);
719
720      set = (struct v3dv_descriptor_set*)pool->host_memory_ptr;
721      pool->host_memory_ptr += mem_size;
722
723      vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);
724   } else {
725      set = vk_object_zalloc(&device->vk, NULL, mem_size,
726                             VK_OBJECT_TYPE_DESCRIPTOR_SET);
727
728      if (!set)
729         return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
730   }
731
732   set->pool = pool;
733
734   set->layout = layout;
735
736   /* FIXME: VK_EXT_descriptor_indexing introduces
737    * VARIABLE_DESCRIPTOR_LAYOUT_COUNT. That would affect the layout_size used
738    * below for bo allocation
739    */
740
741   uint32_t offset = 0;
742   uint32_t index = pool->entry_count;
743
744   if (layout->bo_size) {
745      if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) {
746         vk_object_free(&device->vk, NULL, set);
747         return out_of_pool_memory(device, pool);
748      }
749
750      /* We first try to allocate linearly fist, so that we don't spend time
751       * looking for gaps if the app only allocates & resets via the pool.
752       *
753       * If that fails, we try to find a gap from previously freed subregions
754       * iterating through the descriptor pool entries. Note that we are not
755       * doing that if we have a pool->host_memory_base. We only have that if
756       * VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT is not set, so in
757       * that case the user can't free subregions, so it doesn't make sense to
758       * even try (or track those subregions).
759       */
760      if (pool->current_offset + layout->bo_size <= pool->bo->size) {
761         offset = pool->current_offset;
762         pool->current_offset += layout->bo_size;
763      } else if (!pool->host_memory_base) {
764         for (index = 0; index < pool->entry_count; index++) {
765            if (pool->entries[index].offset - offset >= layout->bo_size)
766               break;
767            offset = pool->entries[index].offset + pool->entries[index].size;
768         }
769         if (pool->bo->size - offset < layout->bo_size) {
770            vk_object_free(&device->vk, NULL, set);
771            return out_of_pool_memory(device, pool);
772         }
773         memmove(&pool->entries[index + 1], &pool->entries[index],
774                 sizeof(pool->entries[0]) * (pool->entry_count - index));
775      } else {
776         assert(pool->host_memory_base);
777         return out_of_pool_memory(device, pool);
778      }
779
780      set->base_offset = offset;
781   }
782
783   if (!pool->host_memory_base) {
784      pool->entries[index].set = set;
785      pool->entries[index].offset = offset;
786      pool->entries[index].size = layout->bo_size;
787      pool->entry_count++;
788   }
789
790   /* Go through and fill out immutable samplers if we have any */
791   for (uint32_t b = 0; b < layout->binding_count; b++) {
792      if (layout->binding[b].immutable_samplers_offset == 0)
793         continue;
794
795      const struct v3dv_sampler *samplers =
796         (const struct v3dv_sampler *)((const char *)layout +
797                                       layout->binding[b].immutable_samplers_offset);
798
799      for (uint32_t i = 0; i < layout->binding[b].array_size; i++) {
800         uint32_t combined_offset =
801            layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ?
802            v3dv_X(device, combined_image_sampler_sampler_state_offset)() : 0;
803
804         void *desc_map = descriptor_bo_map(device, set, &layout->binding[b], i);
805         desc_map += combined_offset;
806
807         memcpy(desc_map,
808                samplers[i].sampler_state,
809                sizeof(samplers[i].sampler_state));
810      }
811   }
812
813   *out_set = set;
814
815   return VK_SUCCESS;
816}
817
818VKAPI_ATTR VkResult VKAPI_CALL
819v3dv_AllocateDescriptorSets(VkDevice _device,
820                            const VkDescriptorSetAllocateInfo *pAllocateInfo,
821                            VkDescriptorSet *pDescriptorSets)
822{
823   V3DV_FROM_HANDLE(v3dv_device, device, _device);
824   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, pAllocateInfo->descriptorPool);
825
826   VkResult result = VK_SUCCESS;
827   struct v3dv_descriptor_set *set = NULL;
828   uint32_t i = 0;
829
830   for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
831      V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, layout,
832                       pAllocateInfo->pSetLayouts[i]);
833
834      result = descriptor_set_create(device, pool, layout, &set);
835      if (result != VK_SUCCESS)
836         break;
837
838      pDescriptorSets[i] = v3dv_descriptor_set_to_handle(set);
839   }
840
841   if (result != VK_SUCCESS) {
842      v3dv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,
843                              i, pDescriptorSets);
844      for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
845         pDescriptorSets[i] = VK_NULL_HANDLE;
846      }
847   }
848
849   return result;
850}
851
852VKAPI_ATTR VkResult VKAPI_CALL
853v3dv_FreeDescriptorSets(VkDevice _device,
854                        VkDescriptorPool descriptorPool,
855                        uint32_t count,
856                        const VkDescriptorSet *pDescriptorSets)
857{
858   V3DV_FROM_HANDLE(v3dv_device, device, _device);
859   V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);
860
861   for (uint32_t i = 0; i < count; i++) {
862      V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]);
863      if (set && !pool->host_memory_base)
864         descriptor_set_destroy(device, pool, set, true);
865   }
866
867   return VK_SUCCESS;
868}
869
870static void
871descriptor_bo_copy(struct v3dv_device *device,
872                   struct v3dv_descriptor_set *dst_set,
873                   const struct v3dv_descriptor_set_binding_layout *dst_binding_layout,
874                   uint32_t dst_array_index,
875                   struct v3dv_descriptor_set *src_set,
876                   const struct v3dv_descriptor_set_binding_layout *src_binding_layout,
877                   uint32_t src_array_index)
878{
879   assert(dst_binding_layout->type == src_binding_layout->type);
880
881   void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, dst_array_index);
882   void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, src_array_index);
883
884   memcpy(dst_map, src_map, v3dv_X(device, descriptor_bo_size)(src_binding_layout->type));
885}
886
887static void
888write_buffer_descriptor(struct v3dv_descriptor *descriptor,
889                        VkDescriptorType desc_type,
890                        const VkDescriptorBufferInfo *buffer_info)
891{
892   V3DV_FROM_HANDLE(v3dv_buffer, buffer, buffer_info->buffer);
893
894   descriptor->type = desc_type;
895   descriptor->buffer = buffer;
896   descriptor->offset = buffer_info->offset;
897   if (buffer_info->range == VK_WHOLE_SIZE) {
898      descriptor->range = buffer->size - buffer_info->offset;
899   } else {
900      assert(descriptor->range <= UINT32_MAX);
901      descriptor->range = buffer_info->range;
902   }
903}
904
905static void
906write_image_descriptor(struct v3dv_device *device,
907                       struct v3dv_descriptor *descriptor,
908                       VkDescriptorType desc_type,
909                       struct v3dv_descriptor_set *set,
910                       const struct v3dv_descriptor_set_binding_layout *binding_layout,
911                       struct v3dv_image_view *iview,
912                       struct v3dv_sampler *sampler,
913                       uint32_t array_index)
914{
915   descriptor->type = desc_type;
916   descriptor->sampler = sampler;
917   descriptor->image_view = iview;
918
919   void *desc_map = descriptor_bo_map(device, set,
920                                      binding_layout, array_index);
921
922   if (iview) {
923      const uint32_t tex_state_index =
924         iview->vk.view_type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ||
925         desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1;
926      memcpy(desc_map,
927             iview->texture_shader_state[tex_state_index],
928             sizeof(iview->texture_shader_state[0]));
929      desc_map += v3dv_X(device, combined_image_sampler_sampler_state_offset)();
930   }
931
932   if (sampler && !binding_layout->immutable_samplers_offset) {
933      /* For immutable samplers this was already done as part of the
934       * descriptor set create, as that info can't change later
935       */
936      memcpy(desc_map,
937             sampler->sampler_state,
938             sizeof(sampler->sampler_state));
939   }
940}
941
942
943static void
944write_buffer_view_descriptor(struct v3dv_device *device,
945                             struct v3dv_descriptor *descriptor,
946                             VkDescriptorType desc_type,
947                             struct v3dv_descriptor_set *set,
948                             const struct v3dv_descriptor_set_binding_layout *binding_layout,
949                             struct v3dv_buffer_view *bview,
950                             uint32_t array_index)
951{
952   assert(bview);
953   descriptor->type = desc_type;
954   descriptor->buffer_view = bview;
955
956   void *desc_map = descriptor_bo_map(device, set, binding_layout, array_index);
957
958   memcpy(desc_map,
959          bview->texture_shader_state,
960          sizeof(bview->texture_shader_state));
961}
962
963VKAPI_ATTR void VKAPI_CALL
964v3dv_UpdateDescriptorSets(VkDevice  _device,
965                          uint32_t descriptorWriteCount,
966                          const VkWriteDescriptorSet *pDescriptorWrites,
967                          uint32_t descriptorCopyCount,
968                          const VkCopyDescriptorSet *pDescriptorCopies)
969{
970   V3DV_FROM_HANDLE(v3dv_device, device, _device);
971   for (uint32_t i = 0; i < descriptorWriteCount; i++) {
972      const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];
973      V3DV_FROM_HANDLE(v3dv_descriptor_set, set, writeset->dstSet);
974
975      const struct v3dv_descriptor_set_binding_layout *binding_layout =
976         set->layout->binding + writeset->dstBinding;
977
978      struct v3dv_descriptor *descriptor = set->descriptors;
979
980      descriptor += binding_layout->descriptor_index;
981      descriptor += writeset->dstArrayElement;
982
983      for (uint32_t j = 0; j < writeset->descriptorCount; ++j) {
984         switch(writeset->descriptorType) {
985
986         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
987         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
988         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
989         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {
990            const VkDescriptorBufferInfo *buffer_info = writeset->pBufferInfo + j;
991            write_buffer_descriptor(descriptor, writeset->descriptorType,
992                                    buffer_info);
993            break;
994         }
995         case VK_DESCRIPTOR_TYPE_SAMPLER: {
996            /* If we are here we shouldn't be modifying a immutable sampler,
997             * so we don't ensure that would work or not crash. But let the
998             * validation layers check that
999             */
1000            const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1001            V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);
1002            write_image_descriptor(device, descriptor, writeset->descriptorType,
1003                                   set, binding_layout, NULL, sampler,
1004                                   writeset->dstArrayElement + j);
1005
1006            break;
1007         }
1008         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1009         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1010         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {
1011            const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1012            V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);
1013            write_image_descriptor(device, descriptor, writeset->descriptorType,
1014                                   set, binding_layout, iview, NULL,
1015                                   writeset->dstArrayElement + j);
1016
1017            break;
1018         }
1019         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
1020            const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;
1021            V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);
1022            V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);
1023            write_image_descriptor(device, descriptor, writeset->descriptorType,
1024                                   set, binding_layout, iview, sampler,
1025                                   writeset->dstArrayElement + j);
1026
1027            break;
1028         }
1029         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1030         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {
1031            V3DV_FROM_HANDLE(v3dv_buffer_view, buffer_view,
1032                             writeset->pTexelBufferView[j]);
1033            write_buffer_view_descriptor(device, descriptor, writeset->descriptorType,
1034                                         set, binding_layout, buffer_view,
1035                                         writeset->dstArrayElement + j);
1036            break;
1037         }
1038         default:
1039            unreachable("unimplemented descriptor type");
1040            break;
1041         }
1042         descriptor++;
1043      }
1044   }
1045
1046   for (uint32_t i = 0; i < descriptorCopyCount; i++) {
1047      const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i];
1048      V3DV_FROM_HANDLE(v3dv_descriptor_set, src_set,
1049                       copyset->srcSet);
1050      V3DV_FROM_HANDLE(v3dv_descriptor_set, dst_set,
1051                       copyset->dstSet);
1052
1053      const struct v3dv_descriptor_set_binding_layout *src_binding_layout =
1054         src_set->layout->binding + copyset->srcBinding;
1055      const struct v3dv_descriptor_set_binding_layout *dst_binding_layout =
1056         dst_set->layout->binding + copyset->dstBinding;
1057
1058      assert(src_binding_layout->type == dst_binding_layout->type);
1059
1060      struct v3dv_descriptor *src_descriptor = src_set->descriptors;
1061      struct v3dv_descriptor *dst_descriptor = dst_set->descriptors;
1062
1063      src_descriptor += src_binding_layout->descriptor_index;
1064      src_descriptor += copyset->srcArrayElement;
1065
1066      dst_descriptor += dst_binding_layout->descriptor_index;
1067      dst_descriptor += copyset->dstArrayElement;
1068
1069      for (uint32_t j = 0; j < copyset->descriptorCount; j++) {
1070         *dst_descriptor = *src_descriptor;
1071         dst_descriptor++;
1072         src_descriptor++;
1073
1074         if (v3dv_X(device, descriptor_bo_size)(src_binding_layout->type) > 0) {
1075            descriptor_bo_copy(device,
1076                               dst_set, dst_binding_layout,
1077                               j + copyset->dstArrayElement,
1078                               src_set, src_binding_layout,
1079                               j + copyset->srcArrayElement);
1080         }
1081
1082      }
1083   }
1084}
1085
1086VKAPI_ATTR void VKAPI_CALL
1087v3dv_GetDescriptorSetLayoutSupport(
1088   VkDevice _device,
1089   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
1090   VkDescriptorSetLayoutSupport *pSupport)
1091{
1092   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1093   VkDescriptorSetLayoutBinding *bindings = NULL;
1094   VkResult result = vk_create_sorted_bindings(
1095      pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);
1096   if (result != VK_SUCCESS) {
1097      pSupport->supported = false;
1098      return;
1099   }
1100
1101   bool supported = true;
1102
1103   uint32_t desc_host_size = sizeof(struct v3dv_descriptor);
1104   uint32_t host_size = sizeof(struct v3dv_descriptor_set);
1105   uint32_t bo_size = 0;
1106   for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
1107      const VkDescriptorSetLayoutBinding *binding = bindings + i;
1108
1109      if ((UINT32_MAX - host_size) / desc_host_size < binding->descriptorCount) {
1110         supported = false;
1111         break;
1112      }
1113
1114      uint32_t desc_bo_size = v3dv_X(device, descriptor_bo_size)(binding->descriptorType);
1115      if (desc_bo_size > 0 &&
1116          (UINT32_MAX - bo_size) / desc_bo_size < binding->descriptorCount) {
1117         supported = false;
1118         break;
1119      }
1120
1121      host_size += binding->descriptorCount * desc_host_size;
1122      bo_size += binding->descriptorCount * desc_bo_size;
1123   }
1124
1125   free(bindings);
1126
1127   pSupport->supported = supported;
1128}
1129
1130VkResult
1131v3dv_CreateDescriptorUpdateTemplate(
1132   VkDevice _device,
1133   const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
1134   const VkAllocationCallbacks *pAllocator,
1135   VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
1136{
1137   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1138   struct v3dv_descriptor_update_template *template;
1139
1140   size_t size = sizeof(*template) +
1141      pCreateInfo->descriptorUpdateEntryCount * sizeof(template->entries[0]);
1142   template = vk_object_alloc(&device->vk, pAllocator, size,
1143                              VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
1144   if (template == NULL)
1145      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
1146
1147   template->bind_point = pCreateInfo->pipelineBindPoint;
1148
1149   assert(pCreateInfo->templateType ==
1150          VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);
1151   template->set = pCreateInfo->set;
1152
1153   template->entry_count = pCreateInfo->descriptorUpdateEntryCount;
1154   for (uint32_t i = 0; i < template->entry_count; i++) {
1155      const VkDescriptorUpdateTemplateEntry *pEntry =
1156         &pCreateInfo->pDescriptorUpdateEntries[i];
1157
1158      template->entries[i] = (struct v3dv_descriptor_template_entry) {
1159         .type = pEntry->descriptorType,
1160         .binding = pEntry->dstBinding,
1161         .array_element = pEntry->dstArrayElement,
1162         .array_count = pEntry->descriptorCount,
1163         .offset = pEntry->offset,
1164         .stride = pEntry->stride,
1165      };
1166   }
1167
1168   *pDescriptorUpdateTemplate =
1169      v3dv_descriptor_update_template_to_handle(template);
1170
1171   return VK_SUCCESS;
1172}
1173
1174void
1175v3dv_DestroyDescriptorUpdateTemplate(
1176   VkDevice _device,
1177   VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1178   const VkAllocationCallbacks *pAllocator)
1179{
1180   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1181   V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,
1182                    descriptorUpdateTemplate);
1183
1184   if (!template)
1185      return;
1186
1187   vk_object_free(&device->vk, pAllocator, template);
1188}
1189
1190void
1191v3dv_UpdateDescriptorSetWithTemplate(
1192   VkDevice _device,
1193   VkDescriptorSet descriptorSet,
1194   VkDescriptorUpdateTemplate descriptorUpdateTemplate,
1195   const void *pData)
1196{
1197   V3DV_FROM_HANDLE(v3dv_device, device, _device);
1198   V3DV_FROM_HANDLE(v3dv_descriptor_set, set, descriptorSet);
1199   V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,
1200                    descriptorUpdateTemplate);
1201
1202   for (int i = 0; i < template->entry_count; i++) {
1203      const struct v3dv_descriptor_template_entry *entry =
1204         &template->entries[i];
1205
1206      const struct v3dv_descriptor_set_binding_layout *binding_layout =
1207         set->layout->binding + entry->binding;
1208
1209      struct v3dv_descriptor *descriptor =
1210         set->descriptors +
1211         binding_layout->descriptor_index +
1212         entry->array_element;
1213
1214      switch (entry->type) {
1215      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
1216      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
1217      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
1218      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
1219         for (uint32_t j = 0; j < entry->array_count; j++) {
1220            const VkDescriptorBufferInfo *info =
1221               pData + entry->offset + j * entry->stride;
1222            write_buffer_descriptor(descriptor + j, entry->type, info);
1223         }
1224         break;
1225
1226      case VK_DESCRIPTOR_TYPE_SAMPLER:
1227      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
1228      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
1229      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
1230      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
1231         for (uint32_t j = 0; j < entry->array_count; j++) {
1232            const VkDescriptorImageInfo *info =
1233               pData + entry->offset + j * entry->stride;
1234            V3DV_FROM_HANDLE(v3dv_image_view, iview, info->imageView);
1235            V3DV_FROM_HANDLE(v3dv_sampler, sampler, info->sampler);
1236            write_image_descriptor(device, descriptor + j, entry->type,
1237                                   set, binding_layout, iview, sampler,
1238                                   entry->array_element + j);
1239         }
1240         break;
1241
1242      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
1243      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
1244         for (uint32_t j = 0; j < entry->array_count; j++) {
1245            const VkBufferView *_bview =
1246               pData + entry->offset + j * entry->stride;
1247            V3DV_FROM_HANDLE(v3dv_buffer_view, bview, *_bview);
1248            write_buffer_view_descriptor(device, descriptor + j, entry->type,
1249                                         set, binding_layout, bview,
1250                                         entry->array_element + j);
1251         }
1252         break;
1253
1254      default:
1255         unreachable("Unsupported descriptor type");
1256      }
1257   }
1258}
1259
1260VKAPI_ATTR VkResult VKAPI_CALL
1261v3dv_CreateSamplerYcbcrConversion(
1262    VkDevice _device,
1263    const VkSamplerYcbcrConversionCreateInfo *pCreateInfo,
1264    const VkAllocationCallbacks *pAllocator,
1265    VkSamplerYcbcrConversion *pYcbcrConversion)
1266{
1267   unreachable("Ycbcr sampler conversion is not supported");
1268   return VK_SUCCESS;
1269}
1270
1271VKAPI_ATTR void VKAPI_CALL
1272v3dv_DestroySamplerYcbcrConversion(
1273    VkDevice _device,
1274    VkSamplerYcbcrConversion YcbcrConversion,
1275    const VkAllocationCallbacks *pAllocator)
1276{
1277   unreachable("Ycbcr sampler conversion is not supported");
1278}
1279