• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
lvp_CreateDescriptorSetLayout(VkDevice _device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorSetLayout * pSetLayout)29 VKAPI_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 
184 void
lvp_descriptor_set_layout_destroy(struct lvp_device * device,struct lvp_descriptor_set_layout * layout)185 lvp_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 
lvp_DestroyDescriptorSetLayout(VkDevice _device,VkDescriptorSetLayout _set_layout,const VkAllocationCallbacks * pAllocator)193 VKAPI_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 
lvp_CreatePipelineLayout(VkDevice _device,const VkPipelineLayoutCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkPipelineLayout * pPipelineLayout)207 VKAPI_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 
lvp_DestroyPipelineLayout(VkDevice _device,VkPipelineLayout _pipelineLayout,const VkAllocationCallbacks * pAllocator)246 VKAPI_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 
263 VkResult
lvp_descriptor_set_create(struct lvp_device * device,struct lvp_descriptor_set_layout * layout,struct lvp_descriptor_set ** out_set)264 lvp_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 
301 void
lvp_descriptor_set_destroy(struct lvp_device * device,struct lvp_descriptor_set * set)302 lvp_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 
lvp_AllocateDescriptorSets(VkDevice _device,const VkDescriptorSetAllocateInfo * pAllocateInfo,VkDescriptorSet * pDescriptorSets)310 VKAPI_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 
lvp_FreeDescriptorSets(VkDevice _device,VkDescriptorPool descriptorPool,uint32_t count,const VkDescriptorSet * pDescriptorSets)340 VKAPI_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 
lvp_UpdateDescriptorSets(VkDevice _device,uint32_t descriptorWriteCount,const VkWriteDescriptorSet * pDescriptorWrites,uint32_t descriptorCopyCount,const VkCopyDescriptorSet * pDescriptorCopies)358 VKAPI_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 
lvp_CreateDescriptorPool(VkDevice _device,const VkDescriptorPoolCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorPool * pDescriptorPool)480 VKAPI_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 
lvp_reset_descriptor_pool(struct lvp_device * device,struct lvp_descriptor_pool * pool)502 static 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 
lvp_DestroyDescriptorPool(VkDevice _device,VkDescriptorPool _pool,const VkAllocationCallbacks * pAllocator)513 VKAPI_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 
lvp_ResetDescriptorPool(VkDevice _device,VkDescriptorPool _pool,VkDescriptorPoolResetFlags flags)529 VKAPI_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 
lvp_GetDescriptorSetLayoutSupport(VkDevice device,const VkDescriptorSetLayoutCreateInfo * pCreateInfo,VkDescriptorSetLayoutSupport * pSupport)541 VKAPI_ATTR void VKAPI_CALL lvp_GetDescriptorSetLayoutSupport(VkDevice device,
542                                        const VkDescriptorSetLayoutCreateInfo* pCreateInfo,
543                                        VkDescriptorSetLayoutSupport* pSupport)
544 {
545    pSupport->supported = true;
546 }
547 
lvp_CreateDescriptorUpdateTemplate(VkDevice _device,const VkDescriptorUpdateTemplateCreateInfo * pCreateInfo,const VkAllocationCallbacks * pAllocator,VkDescriptorUpdateTemplate * pDescriptorUpdateTemplate)548 VKAPI_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 
lvp_DestroyDescriptorUpdateTemplate(VkDevice _device,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const VkAllocationCallbacks * pAllocator)586 VKAPI_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 
lvp_UpdateDescriptorSetWithTemplate(VkDevice _device,VkDescriptorSet descriptorSet,VkDescriptorUpdateTemplate descriptorUpdateTemplate,const void * pData)600 VKAPI_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