1/*
2 * Copyright © 2019 Red Hat.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24#include "lvp_private.h"
25#include "vk_descriptors.h"
26#include "vk_util.h"
27#include "u_math.h"
28
29VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout(
30    VkDevice                                    _device,
31    const VkDescriptorSetLayoutCreateInfo*      pCreateInfo,
32    const VkAllocationCallbacks*                pAllocator,
33    VkDescriptorSetLayout*                      pSetLayout)
34{
35   LVP_FROM_HANDLE(lvp_device, device, _device);
36   struct lvp_descriptor_set_layout *set_layout;
37
38   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);
39   uint32_t num_bindings = 0;
40   uint32_t immutable_sampler_count = 0;
41   for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
42      num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);
43      /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:
44       *
45       *    "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or
46       *    VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then
47       *    pImmutableSamplers can be used to initialize a set of immutable
48       *    samplers. [...]  If descriptorType is not one of these descriptor
49       *    types, then pImmutableSamplers is ignored.
50       *
51       * We need to be careful here and only parse pImmutableSamplers if we
52       * have one of the right descriptor types.
53       */
54      VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType;
55      if ((desc_type == VK_DESCRIPTOR_TYPE_SAMPLER ||
56           desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&
57          pCreateInfo->pBindings[j].pImmutableSamplers)
58         immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;
59   }
60
61   size_t size = sizeof(struct lvp_descriptor_set_layout) +
62                 num_bindings * sizeof(set_layout->binding[0]) +
63                 immutable_sampler_count * sizeof(struct lvp_sampler *);
64
65   set_layout = vk_zalloc2(&device->vk.alloc, pAllocator, size, 8,
66                           VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
67   if (!set_layout)
68      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
69
70   vk_object_base_init(&device->vk, &set_layout->base,
71                       VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);
72   set_layout->ref_cnt = 1;
73   /* We just allocate all the samplers at the end of the struct */
74   struct lvp_sampler **samplers =
75      (struct lvp_sampler **)&set_layout->binding[num_bindings];
76
77   set_layout->alloc = pAllocator;
78   set_layout->binding_count = num_bindings;
79   set_layout->shader_stages = 0;
80   set_layout->size = 0;
81
82   VkDescriptorSetLayoutBinding *bindings = NULL;
83   VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,
84                                               pCreateInfo->bindingCount,
85                                               &bindings);
86   if (result != VK_SUCCESS) {
87      vk_object_base_finish(&set_layout->base);
88      vk_free2(&device->vk.alloc, pAllocator, set_layout);
89      return vk_error(device, result);
90   }
91
92   uint32_t dynamic_offset_count = 0;
93   for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {
94      const VkDescriptorSetLayoutBinding *binding = bindings + j;
95      uint32_t b = binding->binding;
96
97      set_layout->binding[b].array_size = binding->descriptorCount;
98      set_layout->binding[b].descriptor_index = set_layout->size;
99      set_layout->binding[b].type = binding->descriptorType;
100      set_layout->binding[b].valid = true;
101      set_layout->size += binding->descriptorCount;
102
103      for (gl_shader_stage stage = MESA_SHADER_VERTEX; stage < MESA_SHADER_STAGES; stage++) {
104         set_layout->binding[b].stage[stage].const_buffer_index = -1;
105         set_layout->binding[b].stage[stage].shader_buffer_index = -1;
106         set_layout->binding[b].stage[stage].sampler_index = -1;
107         set_layout->binding[b].stage[stage].sampler_view_index = -1;
108         set_layout->binding[b].stage[stage].image_index = -1;
109      }
110
111      if (binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||
112          binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
113         set_layout->binding[b].dynamic_index = dynamic_offset_count;
114         dynamic_offset_count += binding->descriptorCount;
115      }
116      switch (binding->descriptorType) {
117      case VK_DESCRIPTOR_TYPE_SAMPLER:
118      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
119         lvp_foreach_stage(s, binding->stageFlags) {
120            set_layout->binding[b].stage[s].sampler_index = set_layout->stage[s].sampler_count;
121            set_layout->stage[s].sampler_count += binding->descriptorCount;
122         }
123         if (binding->pImmutableSamplers) {
124            set_layout->binding[b].immutable_samplers = samplers;
125            samplers += binding->descriptorCount;
126
127            for (uint32_t i = 0; i < binding->descriptorCount; i++)
128               set_layout->binding[b].immutable_samplers[i] =
129                  lvp_sampler_from_handle(binding->pImmutableSamplers[i]);
130         }
131         break;
132      default:
133         break;
134      }
135
136      switch (binding->descriptorType) {
137      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
138      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
139         lvp_foreach_stage(s, binding->stageFlags) {
140            set_layout->binding[b].stage[s].const_buffer_index = set_layout->stage[s].const_buffer_count;
141            set_layout->stage[s].const_buffer_count += binding->descriptorCount;
142         }
143        break;
144      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
145      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
146         lvp_foreach_stage(s, binding->stageFlags) {
147            set_layout->binding[b].stage[s].shader_buffer_index = set_layout->stage[s].shader_buffer_count;
148            set_layout->stage[s].shader_buffer_count += binding->descriptorCount;
149         }
150         break;
151
152      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
153      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
154      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
155         lvp_foreach_stage(s, binding->stageFlags) {
156            set_layout->binding[b].stage[s].image_index = set_layout->stage[s].image_count;
157            set_layout->stage[s].image_count += binding->descriptorCount;
158         }
159         break;
160      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
161      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
162      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
163         lvp_foreach_stage(s, binding->stageFlags) {
164            set_layout->binding[b].stage[s].sampler_view_index = set_layout->stage[s].sampler_view_count;
165            set_layout->stage[s].sampler_view_count += binding->descriptorCount;
166         }
167         break;
168      default:
169         break;
170      }
171
172      set_layout->shader_stages |= binding->stageFlags;
173   }
174
175   free(bindings);
176
177   set_layout->dynamic_offset_count = dynamic_offset_count;
178
179   *pSetLayout = lvp_descriptor_set_layout_to_handle(set_layout);
180
181   return VK_SUCCESS;
182}
183
184void
185lvp_descriptor_set_layout_destroy(struct lvp_device *device,
186                                  struct lvp_descriptor_set_layout *layout)
187{
188   assert(layout->ref_cnt == 0);
189   vk_object_base_finish(&layout->base);
190   vk_free2(&device->vk.alloc, layout->alloc, layout);
191}
192
193VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorSetLayout(
194    VkDevice                                    _device,
195    VkDescriptorSetLayout                       _set_layout,
196    const VkAllocationCallbacks*                pAllocator)
197{
198   LVP_FROM_HANDLE(lvp_device, device, _device);
199   LVP_FROM_HANDLE(lvp_descriptor_set_layout, set_layout, _set_layout);
200
201   if (!_set_layout)
202     return;
203
204   lvp_descriptor_set_layout_unref(device, set_layout);
205}
206
207VKAPI_ATTR VkResult VKAPI_CALL lvp_CreatePipelineLayout(
208    VkDevice                                    _device,
209    const VkPipelineLayoutCreateInfo*           pCreateInfo,
210    const VkAllocationCallbacks*                pAllocator,
211    VkPipelineLayout*                           pPipelineLayout)
212{
213   LVP_FROM_HANDLE(lvp_device, device, _device);
214   struct lvp_pipeline_layout *layout;
215
216   assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);
217
218   layout = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*layout), 8,
219                       VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
220   if (layout == NULL)
221      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
222
223   vk_object_base_init(&device->vk, &layout->base,
224                       VK_OBJECT_TYPE_PIPELINE_LAYOUT);
225   layout->num_sets = pCreateInfo->setLayoutCount;
226
227   for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {
228      LVP_FROM_HANDLE(lvp_descriptor_set_layout, set_layout,
229                      pCreateInfo->pSetLayouts[set]);
230      layout->set[set].layout = set_layout;
231      lvp_descriptor_set_layout_ref(set_layout);
232   }
233
234   layout->push_constant_size = 0;
235   for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
236      const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;
237      layout->push_constant_size = MAX2(layout->push_constant_size,
238                                        range->offset + range->size);
239   }
240   layout->push_constant_size = align(layout->push_constant_size, 16);
241   *pPipelineLayout = lvp_pipeline_layout_to_handle(layout);
242
243   return VK_SUCCESS;
244}
245
246VKAPI_ATTR void VKAPI_CALL lvp_DestroyPipelineLayout(
247    VkDevice                                    _device,
248    VkPipelineLayout                            _pipelineLayout,
249    const VkAllocationCallbacks*                pAllocator)
250{
251   LVP_FROM_HANDLE(lvp_device, device, _device);
252   LVP_FROM_HANDLE(lvp_pipeline_layout, pipeline_layout, _pipelineLayout);
253
254   if (!_pipelineLayout)
255     return;
256   for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)
257      lvp_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);
258
259   vk_object_base_finish(&pipeline_layout->base);
260   vk_free2(&device->vk.alloc, pAllocator, pipeline_layout);
261}
262
263VkResult
264lvp_descriptor_set_create(struct lvp_device *device,
265                          struct lvp_descriptor_set_layout *layout,
266                          struct lvp_descriptor_set **out_set)
267{
268   struct lvp_descriptor_set *set;
269   size_t size = sizeof(*set) + layout->size * sizeof(set->descriptors[0]);
270
271   set = vk_alloc(&device->vk.alloc /* XXX: Use the pool */, size, 8,
272                   VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
273   if (!set)
274      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
275
276   /* A descriptor set may not be 100% filled. Clear the set so we can can
277    * later detect holes in it.
278    */
279   memset(set, 0, size);
280
281   vk_object_base_init(&device->vk, &set->base,
282                       VK_OBJECT_TYPE_DESCRIPTOR_SET);
283   set->layout = layout;
284   lvp_descriptor_set_layout_ref(layout);
285
286   /* Go through and fill out immutable samplers if we have any */
287   struct lvp_descriptor *desc = set->descriptors;
288   for (uint32_t b = 0; b < layout->binding_count; b++) {
289      if (layout->binding[b].immutable_samplers) {
290         for (uint32_t i = 0; i < layout->binding[b].array_size; i++)
291            desc[i].info.sampler = layout->binding[b].immutable_samplers[i];
292      }
293      desc += layout->binding[b].array_size;
294   }
295
296   *out_set = set;
297
298   return VK_SUCCESS;
299}
300
301void
302lvp_descriptor_set_destroy(struct lvp_device *device,
303                           struct lvp_descriptor_set *set)
304{
305   lvp_descriptor_set_layout_unref(device, set->layout);
306   vk_object_base_finish(&set->base);
307   vk_free(&device->vk.alloc, set);
308}
309
310VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateDescriptorSets(
311    VkDevice                                    _device,
312    const VkDescriptorSetAllocateInfo*          pAllocateInfo,
313    VkDescriptorSet*                            pDescriptorSets)
314{
315   LVP_FROM_HANDLE(lvp_device, device, _device);
316   LVP_FROM_HANDLE(lvp_descriptor_pool, pool, pAllocateInfo->descriptorPool);
317   VkResult result = VK_SUCCESS;
318   struct lvp_descriptor_set *set;
319   uint32_t i;
320
321   for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
322      LVP_FROM_HANDLE(lvp_descriptor_set_layout, layout,
323                      pAllocateInfo->pSetLayouts[i]);
324
325      result = lvp_descriptor_set_create(device, layout, &set);
326      if (result != VK_SUCCESS)
327         break;
328
329      list_addtail(&set->link, &pool->sets);
330      pDescriptorSets[i] = lvp_descriptor_set_to_handle(set);
331   }
332
333   if (result != VK_SUCCESS)
334      lvp_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,
335                             i, pDescriptorSets);
336
337   return result;
338}
339
340VKAPI_ATTR VkResult VKAPI_CALL lvp_FreeDescriptorSets(
341    VkDevice                                    _device,
342    VkDescriptorPool                            descriptorPool,
343    uint32_t                                    count,
344    const VkDescriptorSet*                      pDescriptorSets)
345{
346   LVP_FROM_HANDLE(lvp_device, device, _device);
347   for (uint32_t i = 0; i < count; i++) {
348      LVP_FROM_HANDLE(lvp_descriptor_set, set, pDescriptorSets[i]);
349
350      if (!set)
351         continue;
352      list_del(&set->link);
353      lvp_descriptor_set_destroy(device, set);
354   }
355   return VK_SUCCESS;
356}
357
358VKAPI_ATTR void VKAPI_CALL lvp_UpdateDescriptorSets(
359    VkDevice                                    _device,
360    uint32_t                                    descriptorWriteCount,
361    const VkWriteDescriptorSet*                 pDescriptorWrites,
362    uint32_t                                    descriptorCopyCount,
363    const VkCopyDescriptorSet*                  pDescriptorCopies)
364{
365   for (uint32_t i = 0; i < descriptorWriteCount; i++) {
366      const VkWriteDescriptorSet *write = &pDescriptorWrites[i];
367      LVP_FROM_HANDLE(lvp_descriptor_set, set, write->dstSet);
368      const struct lvp_descriptor_set_binding_layout *bind_layout =
369         &set->layout->binding[write->dstBinding];
370      struct lvp_descriptor *desc =
371         &set->descriptors[bind_layout->descriptor_index];
372      desc += write->dstArrayElement;
373
374      switch (write->descriptorType) {
375      case VK_DESCRIPTOR_TYPE_SAMPLER:
376         for (uint32_t j = 0; j < write->descriptorCount; j++) {
377            LVP_FROM_HANDLE(lvp_sampler, sampler,
378                            write->pImageInfo[j].sampler);
379
380            desc[j] = (struct lvp_descriptor) {
381               .type = VK_DESCRIPTOR_TYPE_SAMPLER,
382               .info.sampler = sampler,
383            };
384         }
385         break;
386
387      case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
388         for (uint32_t j = 0; j < write->descriptorCount; j++) {
389            LVP_FROM_HANDLE(lvp_image_view, iview,
390                            write->pImageInfo[j].imageView);
391            desc[j].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
392            desc[j].info.iview = iview;
393            /*
394             * All consecutive bindings updated via a single VkWriteDescriptorSet structure, except those
395             * with a descriptorCount of zero, must all either use immutable samplers or must all not
396             * use immutable samplers
397             */
398            if (bind_layout->immutable_samplers) {
399               desc[j].info.sampler = bind_layout->immutable_samplers[j];
400            } else {
401               LVP_FROM_HANDLE(lvp_sampler, sampler,
402                               write->pImageInfo[j].sampler);
403
404               desc[j].info.sampler = sampler;
405            }
406         }
407         break;
408
409      case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
410      case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
411      case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
412         for (uint32_t j = 0; j < write->descriptorCount; j++) {
413            LVP_FROM_HANDLE(lvp_image_view, iview,
414                            write->pImageInfo[j].imageView);
415
416            desc[j] = (struct lvp_descriptor) {
417               .type = write->descriptorType,
418               .info.iview = iview,
419            };
420         }
421         break;
422
423      case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
424      case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
425         for (uint32_t j = 0; j < write->descriptorCount; j++) {
426            LVP_FROM_HANDLE(lvp_buffer_view, bview,
427                            write->pTexelBufferView[j]);
428
429            desc[j] = (struct lvp_descriptor) {
430               .type = write->descriptorType,
431               .info.buffer_view = bview,
432            };
433         }
434         break;
435
436      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
437      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
438      case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
439      case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
440         for (uint32_t j = 0; j < write->descriptorCount; j++) {
441            assert(write->pBufferInfo[j].buffer);
442            LVP_FROM_HANDLE(lvp_buffer, buffer, write->pBufferInfo[j].buffer);
443            assert(buffer);
444            desc[j] = (struct lvp_descriptor) {
445               .type = write->descriptorType,
446               .info.offset = write->pBufferInfo[j].offset,
447               .info.buffer = buffer,
448               .info.range =  write->pBufferInfo[j].range,
449            };
450
451         }
452
453      default:
454         break;
455      }
456   }
457
458   for (uint32_t i = 0; i < descriptorCopyCount; i++) {
459      const VkCopyDescriptorSet *copy = &pDescriptorCopies[i];
460      LVP_FROM_HANDLE(lvp_descriptor_set, src, copy->srcSet);
461      LVP_FROM_HANDLE(lvp_descriptor_set, dst, copy->dstSet);
462
463      const struct lvp_descriptor_set_binding_layout *src_layout =
464         &src->layout->binding[copy->srcBinding];
465      struct lvp_descriptor *src_desc =
466         &src->descriptors[src_layout->descriptor_index];
467      src_desc += copy->srcArrayElement;
468
469      const struct lvp_descriptor_set_binding_layout *dst_layout =
470         &dst->layout->binding[copy->dstBinding];
471      struct lvp_descriptor *dst_desc =
472         &dst->descriptors[dst_layout->descriptor_index];
473      dst_desc += copy->dstArrayElement;
474
475      for (uint32_t j = 0; j < copy->descriptorCount; j++)
476         dst_desc[j] = src_desc[j];
477   }
478}
479
480VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorPool(
481    VkDevice                                    _device,
482    const VkDescriptorPoolCreateInfo*           pCreateInfo,
483    const VkAllocationCallbacks*                pAllocator,
484    VkDescriptorPool*                           pDescriptorPool)
485{
486   LVP_FROM_HANDLE(lvp_device, device, _device);
487   struct lvp_descriptor_pool *pool;
488   size_t size = sizeof(struct lvp_descriptor_pool);
489   pool = vk_zalloc2(&device->vk.alloc, pAllocator, size, 8,
490                     VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
491   if (!pool)
492      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
493
494   vk_object_base_init(&device->vk, &pool->base,
495                       VK_OBJECT_TYPE_DESCRIPTOR_POOL);
496   pool->flags = pCreateInfo->flags;
497   list_inithead(&pool->sets);
498   *pDescriptorPool = lvp_descriptor_pool_to_handle(pool);
499   return VK_SUCCESS;
500}
501
502static void lvp_reset_descriptor_pool(struct lvp_device *device,
503                                      struct lvp_descriptor_pool *pool)
504{
505   struct lvp_descriptor_set *set, *tmp;
506   LIST_FOR_EACH_ENTRY_SAFE(set, tmp, &pool->sets, link) {
507      lvp_descriptor_set_layout_unref(device, set->layout);
508      list_del(&set->link);
509      vk_free(&device->vk.alloc, set);
510   }
511}
512
513VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorPool(
514    VkDevice                                    _device,
515    VkDescriptorPool                            _pool,
516    const VkAllocationCallbacks*                pAllocator)
517{
518   LVP_FROM_HANDLE(lvp_device, device, _device);
519   LVP_FROM_HANDLE(lvp_descriptor_pool, pool, _pool);
520
521   if (!_pool)
522      return;
523
524   lvp_reset_descriptor_pool(device, pool);
525   vk_object_base_finish(&pool->base);
526   vk_free2(&device->vk.alloc, pAllocator, pool);
527}
528
529VKAPI_ATTR VkResult VKAPI_CALL lvp_ResetDescriptorPool(
530    VkDevice                                    _device,
531    VkDescriptorPool                            _pool,
532    VkDescriptorPoolResetFlags                  flags)
533{
534   LVP_FROM_HANDLE(lvp_device, device, _device);
535   LVP_FROM_HANDLE(lvp_descriptor_pool, pool, _pool);
536
537   lvp_reset_descriptor_pool(device, pool);
538   return VK_SUCCESS;
539}
540
541VKAPI_ATTR void VKAPI_CALL lvp_GetDescriptorSetLayoutSupport(VkDevice device,
542                                       const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
543                                       VkDescriptorSetLayoutSupport* pSupport)
544{
545   pSupport->supported = true;
546}
547
548VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorUpdateTemplate(VkDevice _device,
549                                            const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,
550                                            const VkAllocationCallbacks *pAllocator,
551                                            VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)
552{
553   LVP_FROM_HANDLE(lvp_device, device, _device);
554   const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount;
555   const size_t size = sizeof(struct lvp_descriptor_update_template) +
556      sizeof(VkDescriptorUpdateTemplateEntry) * entry_count;
557
558   struct lvp_descriptor_update_template *templ;
559
560   templ = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
561   if (!templ)
562      return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
563
564   vk_object_base_init(&device->vk, &templ->base,
565                       VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);
566
567   templ->type = pCreateInfo->templateType;
568   templ->bind_point = pCreateInfo->pipelineBindPoint;
569   templ->set = pCreateInfo->set;
570   /* This parameter is ignored if templateType is not VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR */
571   if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR)
572      templ->pipeline_layout = lvp_pipeline_layout_from_handle(pCreateInfo->pipelineLayout);
573   else
574      templ->pipeline_layout = NULL;
575   templ->entry_count = entry_count;
576
577   VkDescriptorUpdateTemplateEntry *entries = (VkDescriptorUpdateTemplateEntry *)(templ + 1);
578   for (unsigned i = 0; i < entry_count; i++) {
579      entries[i] = pCreateInfo->pDescriptorUpdateEntries[i];
580   }
581
582   *pDescriptorUpdateTemplate = lvp_descriptor_update_template_to_handle(templ);
583   return VK_SUCCESS;
584}
585
586VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorUpdateTemplate(VkDevice _device,
587                                         VkDescriptorUpdateTemplate descriptorUpdateTemplate,
588                                         const VkAllocationCallbacks *pAllocator)
589{
590   LVP_FROM_HANDLE(lvp_device, device, _device);
591   LVP_FROM_HANDLE(lvp_descriptor_update_template, templ, descriptorUpdateTemplate);
592
593   if (!templ)
594      return;
595
596   vk_object_base_finish(&templ->base);
597   vk_free2(&device->vk.alloc, pAllocator, templ);
598}
599
600VKAPI_ATTR void VKAPI_CALL lvp_UpdateDescriptorSetWithTemplate(VkDevice _device,
601                                         VkDescriptorSet descriptorSet,
602                                         VkDescriptorUpdateTemplate descriptorUpdateTemplate,
603                                         const void *pData)
604{
605   LVP_FROM_HANDLE(lvp_descriptor_set, set, descriptorSet);
606   LVP_FROM_HANDLE(lvp_descriptor_update_template, templ, descriptorUpdateTemplate);
607   uint32_t i, j;
608
609   for (i = 0; i < templ->entry_count; ++i) {
610      VkDescriptorUpdateTemplateEntry *entry = &templ->entry[i];
611      const uint8_t *pSrc = ((const uint8_t *) pData) + entry->offset;
612      const struct lvp_descriptor_set_binding_layout *bind_layout =
613         &set->layout->binding[entry->dstBinding];
614      struct lvp_descriptor *desc =
615         &set->descriptors[bind_layout->descriptor_index];
616      for (j = 0; j < entry->descriptorCount; ++j) {
617         unsigned idx = j + entry->dstArrayElement;
618         switch (entry->descriptorType) {
619         case VK_DESCRIPTOR_TYPE_SAMPLER: {
620            LVP_FROM_HANDLE(lvp_sampler, sampler,
621                            *(VkSampler *)pSrc);
622            desc[idx] = (struct lvp_descriptor) {
623               .type = VK_DESCRIPTOR_TYPE_SAMPLER,
624               .info.sampler = sampler,
625            };
626            break;
627         }
628         case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
629            VkDescriptorImageInfo *info = (VkDescriptorImageInfo *)pSrc;
630            desc[idx] = (struct lvp_descriptor) {
631               .type = entry->descriptorType,
632               .info.iview = lvp_image_view_from_handle(info->imageView),
633               .info.sampler = lvp_sampler_from_handle(info->sampler),
634            };
635            break;
636         }
637         case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
638         case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
639         case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
640            LVP_FROM_HANDLE(lvp_image_view, iview,
641                            ((VkDescriptorImageInfo *)pSrc)->imageView);
642            desc[idx] = (struct lvp_descriptor) {
643               .type = entry->descriptorType,
644               .info.iview = iview,
645            };
646            break;
647         }
648         case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
649         case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
650            LVP_FROM_HANDLE(lvp_buffer_view, bview,
651                            *(VkBufferView *)pSrc);
652            desc[idx] = (struct lvp_descriptor) {
653               .type = entry->descriptorType,
654               .info.buffer_view = bview,
655            };
656            break;
657         }
658
659         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
660         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
661         case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
662         case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
663            VkDescriptorBufferInfo *info = (VkDescriptorBufferInfo *)pSrc;
664            desc[idx] = (struct lvp_descriptor) {
665               .type = entry->descriptorType,
666               .info.offset = info->offset,
667               .info.buffer = lvp_buffer_from_handle(info->buffer),
668               .info.range =  info->range,
669            };
670            break;
671         }
672         default:
673            break;
674         }
675         pSrc += entry->stride;
676      }
677   }
678}
679