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