1/*
2 * Copyright 2019 Google LLC
3 * SPDX-License-Identifier: MIT
4 *
5 * based in part on anv and radv which are:
6 * Copyright © 2015 Intel Corporation
7 * Copyright © 2016 Red Hat.
8 * Copyright © 2016 Bas Nieuwenhuizen
9 */
10
11#include "vn_descriptor_set.h"
12
13#include "venus-protocol/vn_protocol_driver_descriptor_pool.h"
14#include "venus-protocol/vn_protocol_driver_descriptor_set.h"
15#include "venus-protocol/vn_protocol_driver_descriptor_set_layout.h"
16#include "venus-protocol/vn_protocol_driver_descriptor_update_template.h"
17
18#include "vn_device.h"
19
20void
21vn_descriptor_set_layout_destroy(struct vn_device *dev,
22                                 struct vn_descriptor_set_layout *layout)
23{
24   VkDevice dev_handle = vn_device_to_handle(dev);
25   VkDescriptorSetLayout layout_handle =
26      vn_descriptor_set_layout_to_handle(layout);
27   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
28
29   vn_async_vkDestroyDescriptorSetLayout(dev->instance, dev_handle,
30                                         layout_handle, NULL);
31
32   vn_object_base_fini(&layout->base);
33   vk_free(alloc, layout);
34}
35
36static void
37vn_descriptor_set_destroy(struct vn_device *dev,
38                          struct vn_descriptor_set *set,
39                          const VkAllocationCallbacks *alloc)
40{
41   list_del(&set->head);
42
43   vn_descriptor_set_layout_unref(dev, set->layout);
44
45   vn_object_base_fini(&set->base);
46   vk_free(alloc, set);
47}
48
49/* descriptor set layout commands */
50
51void
52vn_GetDescriptorSetLayoutSupport(
53   VkDevice device,
54   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
55   VkDescriptorSetLayoutSupport *pSupport)
56{
57   struct vn_device *dev = vn_device_from_handle(device);
58
59   /* TODO per-device cache */
60   vn_call_vkGetDescriptorSetLayoutSupport(dev->instance, device, pCreateInfo,
61                                           pSupport);
62}
63
64static void
65vn_descriptor_set_layout_init(
66   struct vn_device *dev,
67   const VkDescriptorSetLayoutCreateInfo *create_info,
68   uint32_t last_binding,
69   struct vn_descriptor_set_layout *layout)
70{
71   VkDevice dev_handle = vn_device_to_handle(dev);
72   VkDescriptorSetLayout layout_handle =
73      vn_descriptor_set_layout_to_handle(layout);
74   const VkDescriptorSetLayoutBindingFlagsCreateInfo *binding_flags =
75      vk_find_struct_const(create_info->pNext,
76                           DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO);
77
78   /* 14.2.1. Descriptor Set Layout
79    *
80    * If bindingCount is zero or if this structure is not included in
81    * the pNext chain, the VkDescriptorBindingFlags for each descriptor
82    * set layout binding is considered to be zero.
83    */
84   if (binding_flags && !binding_flags->bindingCount)
85      binding_flags = NULL;
86
87   layout->refcount = VN_REFCOUNT_INIT(1);
88   layout->last_binding = last_binding;
89
90   for (uint32_t i = 0; i < create_info->bindingCount; i++) {
91      const VkDescriptorSetLayoutBinding *binding_info =
92         &create_info->pBindings[i];
93      struct vn_descriptor_set_layout_binding *binding =
94         &layout->bindings[binding_info->binding];
95
96      if (binding_info->binding == last_binding) {
97         /* 14.2.1. Descriptor Set Layout
98          *
99          * VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT must only be
100          * used for the last binding in the descriptor set layout (i.e. the
101          * binding with the largest value of binding).
102          *
103          * 41. Features
104          *
105          * descriptorBindingVariableDescriptorCount indicates whether the
106          * implementation supports descriptor sets with a variable-sized last
107          * binding. If this feature is not enabled,
108          * VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT must not be
109          * used.
110          */
111         layout->has_variable_descriptor_count =
112            binding_flags &&
113            (binding_flags->pBindingFlags[i] &
114             VK_DESCRIPTOR_BINDING_VARIABLE_DESCRIPTOR_COUNT_BIT);
115      }
116
117      binding->type = binding_info->descriptorType;
118      binding->count = binding_info->descriptorCount;
119
120      switch (binding_info->descriptorType) {
121      case VK_DESCRIPTOR_TYPE_SAMPLER:
122      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
123         binding->has_immutable_samplers = binding_info->pImmutableSamplers;
124         break;
125      default:
126         break;
127      }
128   }
129
130   vn_async_vkCreateDescriptorSetLayout(dev->instance, dev_handle,
131                                        create_info, NULL, &layout_handle);
132}
133
134VkResult
135vn_CreateDescriptorSetLayout(
136   VkDevice device,
137   const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
138   const VkAllocationCallbacks *pAllocator,
139   VkDescriptorSetLayout *pSetLayout)
140{
141   struct vn_device *dev = vn_device_from_handle(device);
142   /* ignore pAllocator as the layout is reference-counted */
143   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
144
145   uint32_t last_binding = 0;
146   VkDescriptorSetLayoutBinding *local_bindings = NULL;
147   VkDescriptorSetLayoutCreateInfo local_create_info;
148   if (pCreateInfo->bindingCount) {
149      /* the encoder does not ignore
150       * VkDescriptorSetLayoutBinding::pImmutableSamplers when it should
151       */
152      const size_t binding_size =
153         sizeof(*pCreateInfo->pBindings) * pCreateInfo->bindingCount;
154      local_bindings = vk_alloc(alloc, binding_size, VN_DEFAULT_ALIGN,
155                                VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
156      if (!local_bindings)
157         return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
158
159      memcpy(local_bindings, pCreateInfo->pBindings, binding_size);
160      for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {
161         VkDescriptorSetLayoutBinding *binding = &local_bindings[i];
162
163         if (last_binding < binding->binding)
164            last_binding = binding->binding;
165
166         switch (binding->descriptorType) {
167         case VK_DESCRIPTOR_TYPE_SAMPLER:
168         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
169            break;
170         default:
171            binding->pImmutableSamplers = NULL;
172            break;
173         }
174      }
175
176      local_create_info = *pCreateInfo;
177      local_create_info.pBindings = local_bindings;
178      pCreateInfo = &local_create_info;
179   }
180
181   const size_t layout_size =
182      offsetof(struct vn_descriptor_set_layout, bindings[last_binding + 1]);
183   /* allocated with the device scope */
184   struct vn_descriptor_set_layout *layout =
185      vk_zalloc(alloc, layout_size, VN_DEFAULT_ALIGN,
186                VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
187   if (!layout) {
188      vk_free(alloc, local_bindings);
189      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
190   }
191
192   vn_object_base_init(&layout->base, VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT,
193                       &dev->base);
194
195   vn_descriptor_set_layout_init(dev, pCreateInfo, last_binding, layout);
196
197   vk_free(alloc, local_bindings);
198
199   *pSetLayout = vn_descriptor_set_layout_to_handle(layout);
200
201   return VK_SUCCESS;
202}
203
204void
205vn_DestroyDescriptorSetLayout(VkDevice device,
206                              VkDescriptorSetLayout descriptorSetLayout,
207                              const VkAllocationCallbacks *pAllocator)
208{
209   struct vn_device *dev = vn_device_from_handle(device);
210   struct vn_descriptor_set_layout *layout =
211      vn_descriptor_set_layout_from_handle(descriptorSetLayout);
212
213   if (!layout)
214      return;
215
216   vn_descriptor_set_layout_unref(dev, layout);
217}
218
219/* descriptor pool commands */
220
221VkResult
222vn_CreateDescriptorPool(VkDevice device,
223                        const VkDescriptorPoolCreateInfo *pCreateInfo,
224                        const VkAllocationCallbacks *pAllocator,
225                        VkDescriptorPool *pDescriptorPool)
226{
227   struct vn_device *dev = vn_device_from_handle(device);
228   const VkAllocationCallbacks *alloc =
229      pAllocator ? pAllocator : &dev->base.base.alloc;
230
231   struct vn_descriptor_pool *pool =
232      vk_zalloc(alloc, sizeof(*pool), VN_DEFAULT_ALIGN,
233                VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
234   if (!pool)
235      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
236
237   vn_object_base_init(&pool->base, VK_OBJECT_TYPE_DESCRIPTOR_POOL,
238                       &dev->base);
239
240   pool->allocator = *alloc;
241
242   /* Without VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, the set
243    * allocation must not fail due to a fragmented pool per spec. In this
244    * case, set allocation can be asynchronous with pool resource tracking.
245    */
246   pool->async_set_allocation = !(
247      pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT);
248
249   pool->max.set_count = pCreateInfo->maxSets;
250
251   for (uint32_t i = 0; i < pCreateInfo->poolSizeCount; i++) {
252      const VkDescriptorPoolSize *pool_size = &pCreateInfo->pPoolSizes[i];
253
254      assert(pool_size->type < VN_NUM_DESCRIPTOR_TYPES);
255
256      pool->max.descriptor_counts[pool_size->type] +=
257         pool_size->descriptorCount;
258   }
259
260   list_inithead(&pool->descriptor_sets);
261
262   VkDescriptorPool pool_handle = vn_descriptor_pool_to_handle(pool);
263   vn_async_vkCreateDescriptorPool(dev->instance, device, pCreateInfo, NULL,
264                                   &pool_handle);
265
266   *pDescriptorPool = pool_handle;
267
268   return VK_SUCCESS;
269}
270
271void
272vn_DestroyDescriptorPool(VkDevice device,
273                         VkDescriptorPool descriptorPool,
274                         const VkAllocationCallbacks *pAllocator)
275{
276   struct vn_device *dev = vn_device_from_handle(device);
277   struct vn_descriptor_pool *pool =
278      vn_descriptor_pool_from_handle(descriptorPool);
279   const VkAllocationCallbacks *alloc;
280
281   if (!pool)
282      return;
283
284   alloc = pAllocator ? pAllocator : &pool->allocator;
285
286   /* We must emit vkDestroyDescriptorPool before freeing the sets in
287    * pool->descriptor_sets.  Otherwise, another thread might reuse their
288    * object ids while they still refer to the sets in the renderer.
289    */
290   vn_async_vkDestroyDescriptorPool(dev->instance, device, descriptorPool,
291                                    NULL);
292
293   list_for_each_entry_safe(struct vn_descriptor_set, set,
294                            &pool->descriptor_sets, head)
295      vn_descriptor_set_destroy(dev, set, alloc);
296
297   vn_object_base_fini(&pool->base);
298   vk_free(alloc, pool);
299}
300
301static bool
302vn_descriptor_pool_alloc_descriptors(
303   struct vn_descriptor_pool *pool,
304   const struct vn_descriptor_set_layout *layout,
305   uint32_t last_binding_descriptor_count)
306{
307   struct vn_descriptor_pool_state recovery;
308
309   if (!pool->async_set_allocation)
310      return true;
311
312   if (pool->used.set_count == pool->max.set_count)
313      return false;
314
315   /* backup current pool state to recovery */
316   recovery = pool->used;
317
318   ++pool->used.set_count;
319
320   for (uint32_t i = 0; i <= layout->last_binding; i++) {
321      const VkDescriptorType type = layout->bindings[i].type;
322      const uint32_t count = i == layout->last_binding
323                                ? last_binding_descriptor_count
324                                : layout->bindings[i].count;
325
326      pool->used.descriptor_counts[type] += count;
327
328      if (pool->used.descriptor_counts[type] >
329          pool->max.descriptor_counts[type]) {
330         /* restore pool state before this allocation */
331         pool->used = recovery;
332         return false;
333      }
334   }
335
336   return true;
337}
338
339static void
340vn_descriptor_pool_free_descriptors(
341   struct vn_descriptor_pool *pool,
342   const struct vn_descriptor_set_layout *layout,
343   uint32_t last_binding_descriptor_count)
344{
345   if (!pool->async_set_allocation)
346      return;
347
348   for (uint32_t i = 0; i <= layout->last_binding; i++) {
349      const uint32_t count = i == layout->last_binding
350                                ? last_binding_descriptor_count
351                                : layout->bindings[i].count;
352
353      pool->used.descriptor_counts[layout->bindings[i].type] -= count;
354   }
355
356   --pool->used.set_count;
357}
358
359static void
360vn_descriptor_pool_reset_descriptors(struct vn_descriptor_pool *pool)
361{
362   if (!pool->async_set_allocation)
363      return;
364
365   memset(&pool->used, 0, sizeof(pool->used));
366}
367
368VkResult
369vn_ResetDescriptorPool(VkDevice device,
370                       VkDescriptorPool descriptorPool,
371                       VkDescriptorPoolResetFlags flags)
372{
373   struct vn_device *dev = vn_device_from_handle(device);
374   struct vn_descriptor_pool *pool =
375      vn_descriptor_pool_from_handle(descriptorPool);
376   const VkAllocationCallbacks *alloc = &pool->allocator;
377
378   vn_async_vkResetDescriptorPool(dev->instance, device, descriptorPool,
379                                  flags);
380
381   list_for_each_entry_safe(struct vn_descriptor_set, set,
382                            &pool->descriptor_sets, head)
383      vn_descriptor_set_destroy(dev, set, alloc);
384
385   vn_descriptor_pool_reset_descriptors(pool);
386
387   return VK_SUCCESS;
388}
389
390/* descriptor set commands */
391
392VkResult
393vn_AllocateDescriptorSets(VkDevice device,
394                          const VkDescriptorSetAllocateInfo *pAllocateInfo,
395                          VkDescriptorSet *pDescriptorSets)
396{
397   struct vn_device *dev = vn_device_from_handle(device);
398   struct vn_descriptor_pool *pool =
399      vn_descriptor_pool_from_handle(pAllocateInfo->descriptorPool);
400   const VkAllocationCallbacks *alloc = &pool->allocator;
401   const VkDescriptorSetVariableDescriptorCountAllocateInfo *variable_info =
402      NULL;
403   VkResult result;
404
405   /* 14.2.3. Allocation of Descriptor Sets
406    *
407    * If descriptorSetCount is zero or this structure is not included in
408    * the pNext chain, then the variable lengths are considered to be zero.
409    */
410   variable_info = vk_find_struct_const(
411      pAllocateInfo->pNext,
412      DESCRIPTOR_SET_VARIABLE_DESCRIPTOR_COUNT_ALLOCATE_INFO);
413
414   if (variable_info && !variable_info->descriptorSetCount)
415      variable_info = NULL;
416
417   for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
418      struct vn_descriptor_set_layout *layout =
419         vn_descriptor_set_layout_from_handle(pAllocateInfo->pSetLayouts[i]);
420      uint32_t last_binding_descriptor_count = 0;
421      struct vn_descriptor_set *set = NULL;
422
423      /* 14.2.3. Allocation of Descriptor Sets
424       *
425       * If VkDescriptorSetAllocateInfo::pSetLayouts[i] does not include a
426       * variable count descriptor binding, then pDescriptorCounts[i] is
427       * ignored.
428       */
429      if (!layout->has_variable_descriptor_count) {
430         last_binding_descriptor_count =
431            layout->bindings[layout->last_binding].count;
432      } else if (variable_info) {
433         last_binding_descriptor_count = variable_info->pDescriptorCounts[i];
434      }
435
436      if (!vn_descriptor_pool_alloc_descriptors(
437             pool, layout, last_binding_descriptor_count)) {
438         pDescriptorSets[i] = VK_NULL_HANDLE;
439         result = VK_ERROR_OUT_OF_POOL_MEMORY;
440         goto fail;
441      }
442
443      set = vk_zalloc(alloc, sizeof(*set), VN_DEFAULT_ALIGN,
444                      VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
445      if (!set) {
446         vn_descriptor_pool_free_descriptors(pool, layout,
447                                             last_binding_descriptor_count);
448         pDescriptorSets[i] = VK_NULL_HANDLE;
449         result = VK_ERROR_OUT_OF_HOST_MEMORY;
450         goto fail;
451      }
452
453      vn_object_base_init(&set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET,
454                          &dev->base);
455
456      /* We might reorder vkCmdBindDescriptorSets after
457       * vkDestroyDescriptorSetLayout due to batching.  The spec says
458       *
459       *   VkDescriptorSetLayout objects may be accessed by commands that
460       *   operate on descriptor sets allocated using that layout, and those
461       *   descriptor sets must not be updated with vkUpdateDescriptorSets
462       *   after the descriptor set layout has been destroyed. Otherwise, a
463       *   VkDescriptorSetLayout object passed as a parameter to create
464       *   another object is not further accessed by that object after the
465       *   duration of the command it is passed into.
466       *
467       * It is ambiguous but the reordering is likely invalid.  Let's keep the
468       * layout alive with the set to defer vkDestroyDescriptorSetLayout.
469       */
470      set->layout = vn_descriptor_set_layout_ref(dev, layout);
471      set->last_binding_descriptor_count = last_binding_descriptor_count;
472      list_addtail(&set->head, &pool->descriptor_sets);
473
474      VkDescriptorSet set_handle = vn_descriptor_set_to_handle(set);
475      pDescriptorSets[i] = set_handle;
476   }
477
478   if (pool->async_set_allocation) {
479      vn_async_vkAllocateDescriptorSets(dev->instance, device, pAllocateInfo,
480                                        pDescriptorSets);
481   } else {
482      result = vn_call_vkAllocateDescriptorSets(
483         dev->instance, device, pAllocateInfo, pDescriptorSets);
484      if (result != VK_SUCCESS)
485         goto fail;
486   }
487
488   return VK_SUCCESS;
489
490fail:
491   for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
492      struct vn_descriptor_set *set =
493         vn_descriptor_set_from_handle(pDescriptorSets[i]);
494      if (!set)
495         break;
496
497      vn_descriptor_pool_free_descriptors(pool, set->layout,
498                                          set->last_binding_descriptor_count);
499
500      vn_descriptor_set_destroy(dev, set, alloc);
501   }
502
503   memset(pDescriptorSets, 0,
504          sizeof(*pDescriptorSets) * pAllocateInfo->descriptorSetCount);
505
506   return vn_error(dev->instance, result);
507}
508
509VkResult
510vn_FreeDescriptorSets(VkDevice device,
511                      VkDescriptorPool descriptorPool,
512                      uint32_t descriptorSetCount,
513                      const VkDescriptorSet *pDescriptorSets)
514{
515   struct vn_device *dev = vn_device_from_handle(device);
516   struct vn_descriptor_pool *pool =
517      vn_descriptor_pool_from_handle(descriptorPool);
518   const VkAllocationCallbacks *alloc = &pool->allocator;
519
520   vn_async_vkFreeDescriptorSets(dev->instance, device, descriptorPool,
521                                 descriptorSetCount, pDescriptorSets);
522
523   for (uint32_t i = 0; i < descriptorSetCount; i++) {
524      struct vn_descriptor_set *set =
525         vn_descriptor_set_from_handle(pDescriptorSets[i]);
526
527      if (!set)
528         continue;
529
530      vn_descriptor_set_destroy(dev, set, alloc);
531   }
532
533   return VK_SUCCESS;
534}
535
536static struct vn_update_descriptor_sets *
537vn_update_descriptor_sets_alloc(uint32_t write_count,
538                                uint32_t image_count,
539                                uint32_t buffer_count,
540                                uint32_t view_count,
541                                const VkAllocationCallbacks *alloc,
542                                VkSystemAllocationScope scope)
543{
544   const size_t writes_offset = sizeof(struct vn_update_descriptor_sets);
545   const size_t images_offset =
546      writes_offset + sizeof(VkWriteDescriptorSet) * write_count;
547   const size_t buffers_offset =
548      images_offset + sizeof(VkDescriptorImageInfo) * image_count;
549   const size_t views_offset =
550      buffers_offset + sizeof(VkDescriptorBufferInfo) * buffer_count;
551   const size_t alloc_size = views_offset + sizeof(VkBufferView) * view_count;
552
553   void *storage = vk_alloc(alloc, alloc_size, VN_DEFAULT_ALIGN, scope);
554   if (!storage)
555      return NULL;
556
557   struct vn_update_descriptor_sets *update = storage;
558   update->write_count = write_count;
559   update->writes = storage + writes_offset;
560   update->images = storage + images_offset;
561   update->buffers = storage + buffers_offset;
562   update->views = storage + views_offset;
563
564   return update;
565}
566
567static struct vn_update_descriptor_sets *
568vn_update_descriptor_sets_parse_writes(uint32_t write_count,
569                                       const VkWriteDescriptorSet *writes,
570                                       const VkAllocationCallbacks *alloc)
571{
572   uint32_t img_count = 0;
573   for (uint32_t i = 0; i < write_count; i++) {
574      const VkWriteDescriptorSet *write = &writes[i];
575      switch (write->descriptorType) {
576      case VK_DESCRIPTOR_TYPE_SAMPLER:
577      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
578      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
579      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
580      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
581         img_count += write->descriptorCount;
582         break;
583      default:
584         break;
585      }
586   }
587
588   struct vn_update_descriptor_sets *update =
589      vn_update_descriptor_sets_alloc(write_count, img_count, 0, 0, alloc,
590                                      VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
591   if (!update)
592      return NULL;
593
594   /* the encoder does not ignore
595    * VkWriteDescriptorSet::{pImageInfo,pBufferInfo,pTexelBufferView} when it
596    * should
597    *
598    * TODO make the encoder smarter
599    */
600   memcpy(update->writes, writes, sizeof(*writes) * write_count);
601   img_count = 0;
602   for (uint32_t i = 0; i < write_count; i++) {
603      const struct vn_descriptor_set *set =
604         vn_descriptor_set_from_handle(writes[i].dstSet);
605      const struct vn_descriptor_set_layout_binding *binding =
606         &set->layout->bindings[writes[i].dstBinding];
607      VkWriteDescriptorSet *write = &update->writes[i];
608      VkDescriptorImageInfo *imgs = &update->images[img_count];
609
610      switch (write->descriptorType) {
611      case VK_DESCRIPTOR_TYPE_SAMPLER:
612      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
613      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
614      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
615      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
616         memcpy(imgs, write->pImageInfo,
617                sizeof(*imgs) * write->descriptorCount);
618         img_count += write->descriptorCount;
619
620         for (uint32_t j = 0; j < write->descriptorCount; j++) {
621            switch (write->descriptorType) {
622            case VK_DESCRIPTOR_TYPE_SAMPLER:
623               imgs[j].imageView = VK_NULL_HANDLE;
624               break;
625            case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
626               if (binding->has_immutable_samplers)
627                  imgs[j].sampler = VK_NULL_HANDLE;
628               break;
629            case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
630            case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
631            case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
632               imgs[j].sampler = VK_NULL_HANDLE;
633               break;
634            default:
635               break;
636            }
637         }
638
639         write->pImageInfo = imgs;
640         write->pBufferInfo = NULL;
641         write->pTexelBufferView = NULL;
642         break;
643      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
644      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
645         write->pImageInfo = NULL;
646         write->pBufferInfo = NULL;
647         break;
648      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
649      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
650      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
651      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
652         write->pImageInfo = NULL;
653         write->pTexelBufferView = NULL;
654         break;
655      default:
656         write->pImageInfo = NULL;
657         write->pBufferInfo = NULL;
658         write->pTexelBufferView = NULL;
659         break;
660      }
661   }
662
663   return update;
664}
665
666void
667vn_UpdateDescriptorSets(VkDevice device,
668                        uint32_t descriptorWriteCount,
669                        const VkWriteDescriptorSet *pDescriptorWrites,
670                        uint32_t descriptorCopyCount,
671                        const VkCopyDescriptorSet *pDescriptorCopies)
672{
673   struct vn_device *dev = vn_device_from_handle(device);
674   const VkAllocationCallbacks *alloc = &dev->base.base.alloc;
675
676   struct vn_update_descriptor_sets *update =
677      vn_update_descriptor_sets_parse_writes(descriptorWriteCount,
678                                             pDescriptorWrites, alloc);
679   if (!update) {
680      /* TODO update one-by-one? */
681      vn_log(dev->instance, "TODO descriptor set update ignored due to OOM");
682      return;
683   }
684
685   vn_async_vkUpdateDescriptorSets(dev->instance, device, update->write_count,
686                                   update->writes, descriptorCopyCount,
687                                   pDescriptorCopies);
688
689   vk_free(alloc, update);
690}
691
692/* descriptor update template commands */
693
694static struct vn_update_descriptor_sets *
695vn_update_descriptor_sets_parse_template(
696   const VkDescriptorUpdateTemplateCreateInfo *create_info,
697   const VkAllocationCallbacks *alloc,
698   struct vn_descriptor_update_template_entry *entries)
699{
700   uint32_t img_count = 0;
701   uint32_t buf_count = 0;
702   uint32_t view_count = 0;
703   for (uint32_t i = 0; i < create_info->descriptorUpdateEntryCount; i++) {
704      const VkDescriptorUpdateTemplateEntry *entry =
705         &create_info->pDescriptorUpdateEntries[i];
706
707      switch (entry->descriptorType) {
708      case VK_DESCRIPTOR_TYPE_SAMPLER:
709      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
710      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
711      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
712      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
713         img_count += entry->descriptorCount;
714         break;
715      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
716      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
717         view_count += entry->descriptorCount;
718         break;
719      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
720      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
721      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
722      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
723         buf_count += entry->descriptorCount;
724         break;
725      default:
726         unreachable("unhandled descriptor type");
727         break;
728      }
729   }
730
731   struct vn_update_descriptor_sets *update = vn_update_descriptor_sets_alloc(
732      create_info->descriptorUpdateEntryCount, img_count, buf_count,
733      view_count, alloc, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
734   if (!update)
735      return NULL;
736
737   img_count = 0;
738   buf_count = 0;
739   view_count = 0;
740   for (uint32_t i = 0; i < create_info->descriptorUpdateEntryCount; i++) {
741      const VkDescriptorUpdateTemplateEntry *entry =
742         &create_info->pDescriptorUpdateEntries[i];
743      VkWriteDescriptorSet *write = &update->writes[i];
744
745      write->sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
746      write->pNext = NULL;
747      write->dstBinding = entry->dstBinding;
748      write->dstArrayElement = entry->dstArrayElement;
749      write->descriptorCount = entry->descriptorCount;
750      write->descriptorType = entry->descriptorType;
751
752      entries[i].offset = entry->offset;
753      entries[i].stride = entry->stride;
754
755      switch (entry->descriptorType) {
756      case VK_DESCRIPTOR_TYPE_SAMPLER:
757      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
758      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
759      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
760      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
761         write->pImageInfo = &update->images[img_count];
762         write->pBufferInfo = NULL;
763         write->pTexelBufferView = NULL;
764         img_count += entry->descriptorCount;
765         break;
766      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
767      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
768         write->pImageInfo = NULL;
769         write->pBufferInfo = NULL;
770         write->pTexelBufferView = &update->views[view_count];
771         view_count += entry->descriptorCount;
772         break;
773      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
774      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
775      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
776      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
777         write->pImageInfo = NULL;
778         write->pBufferInfo = &update->buffers[buf_count];
779         write->pTexelBufferView = NULL;
780         buf_count += entry->descriptorCount;
781         break;
782      default:
783         break;
784      }
785   }
786
787   return update;
788}
789
790VkResult
791vn_CreateDescriptorUpdateTemplate(
792   VkDevice device,
793   const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
794   const VkAllocationCallbacks *pAllocator,
795   VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
796{
797   struct vn_device *dev = vn_device_from_handle(device);
798   const VkAllocationCallbacks *alloc =
799      pAllocator ? pAllocator : &dev->base.base.alloc;
800
801   const size_t templ_size =
802      offsetof(struct vn_descriptor_update_template,
803               entries[pCreateInfo->descriptorUpdateEntryCount + 1]);
804   struct vn_descriptor_update_template *templ = vk_zalloc(
805      alloc, templ_size, VN_DEFAULT_ALIGN, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
806   if (!templ)
807      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
808
809   vn_object_base_init(&templ->base,
810                       VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE, &dev->base);
811
812   templ->update = vn_update_descriptor_sets_parse_template(
813      pCreateInfo, alloc, templ->entries);
814   if (!templ->update) {
815      vk_free(alloc, templ);
816      return vn_error(dev->instance, VK_ERROR_OUT_OF_HOST_MEMORY);
817   }
818
819   mtx_init(&templ->mutex, mtx_plain);
820
821   /* no host object */
822   VkDescriptorUpdateTemplate templ_handle =
823      vn_descriptor_update_template_to_handle(templ);
824   *pDescriptorUpdateTemplate = templ_handle;
825
826   return VK_SUCCESS;
827}
828
829void
830vn_DestroyDescriptorUpdateTemplate(
831   VkDevice device,
832   VkDescriptorUpdateTemplate descriptorUpdateTemplate,
833   const VkAllocationCallbacks *pAllocator)
834{
835   struct vn_device *dev = vn_device_from_handle(device);
836   struct vn_descriptor_update_template *templ =
837      vn_descriptor_update_template_from_handle(descriptorUpdateTemplate);
838   const VkAllocationCallbacks *alloc =
839      pAllocator ? pAllocator : &dev->base.base.alloc;
840
841   if (!templ)
842      return;
843
844   /* no host object */
845   vk_free(alloc, templ->update);
846   mtx_destroy(&templ->mutex);
847
848   vn_object_base_fini(&templ->base);
849   vk_free(alloc, templ);
850}
851
852void
853vn_UpdateDescriptorSetWithTemplate(
854   VkDevice device,
855   VkDescriptorSet descriptorSet,
856   VkDescriptorUpdateTemplate descriptorUpdateTemplate,
857   const void *pData)
858{
859   struct vn_device *dev = vn_device_from_handle(device);
860   struct vn_descriptor_set *set =
861      vn_descriptor_set_from_handle(descriptorSet);
862   struct vn_descriptor_update_template *templ =
863      vn_descriptor_update_template_from_handle(descriptorUpdateTemplate);
864   struct vn_update_descriptor_sets *update = templ->update;
865
866   /* duplicate update instead to avoid locking? */
867   mtx_lock(&templ->mutex);
868
869   for (uint32_t i = 0; i < update->write_count; i++) {
870      const struct vn_descriptor_update_template_entry *entry =
871         &templ->entries[i];
872      const struct vn_descriptor_set_layout_binding *binding =
873         &set->layout->bindings[update->writes[i].dstBinding];
874      VkWriteDescriptorSet *write = &update->writes[i];
875
876      write->dstSet = vn_descriptor_set_to_handle(set);
877
878      switch (write->descriptorType) {
879      case VK_DESCRIPTOR_TYPE_SAMPLER:
880      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
881      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
882      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
883      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
884         for (uint32_t j = 0; j < write->descriptorCount; j++) {
885            const bool need_sampler =
886               (write->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER ||
887                write->descriptorType ==
888                   VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
889               !binding->has_immutable_samplers;
890            const bool need_view =
891               write->descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER;
892            const VkDescriptorImageInfo *src =
893               pData + entry->offset + entry->stride * j;
894            VkDescriptorImageInfo *dst =
895               (VkDescriptorImageInfo *)&write->pImageInfo[j];
896
897            dst->sampler = need_sampler ? src->sampler : VK_NULL_HANDLE;
898            dst->imageView = need_view ? src->imageView : VK_NULL_HANDLE;
899            dst->imageLayout = src->imageLayout;
900         }
901         break;
902      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
903      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
904         for (uint32_t j = 0; j < write->descriptorCount; j++) {
905            const VkBufferView *src =
906               pData + entry->offset + entry->stride * j;
907            VkBufferView *dst = (VkBufferView *)&write->pTexelBufferView[j];
908            *dst = *src;
909         }
910         break;
911      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
912      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
913      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
914      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
915         for (uint32_t j = 0; j < write->descriptorCount; j++) {
916            const VkDescriptorBufferInfo *src =
917               pData + entry->offset + entry->stride * j;
918            VkDescriptorBufferInfo *dst =
919               (VkDescriptorBufferInfo *)&write->pBufferInfo[j];
920            *dst = *src;
921         }
922         break;
923      default:
924         unreachable("unhandled descriptor type");
925         break;
926      }
927   }
928
929   vn_async_vkUpdateDescriptorSets(dev->instance, device, update->write_count,
930                                   update->writes, 0, NULL);
931
932   mtx_unlock(&templ->mutex);
933}
934