Path: blob/21.2-virgl/src/gallium/frontends/lavapipe/lvp_descriptor_set.c
4565 views
/*1* Copyright © 2019 Red Hat.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sublicense,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS20* IN THE SOFTWARE.21*/2223#include "lvp_private.h"24#include "vk_descriptors.h"25#include "vk_util.h"26#include "u_math.h"2728VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorSetLayout(29VkDevice _device,30const VkDescriptorSetLayoutCreateInfo* pCreateInfo,31const VkAllocationCallbacks* pAllocator,32VkDescriptorSetLayout* pSetLayout)33{34LVP_FROM_HANDLE(lvp_device, device, _device);35struct lvp_descriptor_set_layout *set_layout;3637assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);38uint32_t num_bindings = 0;39uint32_t immutable_sampler_count = 0;40for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {41num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);42/* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:43*44* "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or45* VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then46* pImmutableSamplers can be used to initialize a set of immutable47* samplers. [...] If descriptorType is not one of these descriptor48* types, then pImmutableSamplers is ignored.49*50* We need to be careful here and only parse pImmutableSamplers if we51* have one of the right descriptor types.52*/53VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType;54if ((desc_type == VK_DESCRIPTOR_TYPE_SAMPLER ||55desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) &&56pCreateInfo->pBindings[j].pImmutableSamplers)57immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;58}5960size_t size = sizeof(struct lvp_descriptor_set_layout) +61num_bindings * sizeof(set_layout->binding[0]) +62immutable_sampler_count * sizeof(struct lvp_sampler *);6364set_layout = vk_zalloc2(&device->vk.alloc, pAllocator, size, 8,65VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);66if (!set_layout)67return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);6869vk_object_base_init(&device->vk, &set_layout->base,70VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);71set_layout->ref_cnt = 1;72/* We just allocate all the samplers at the end of the struct */73struct lvp_sampler **samplers =74(struct lvp_sampler **)&set_layout->binding[num_bindings];7576set_layout->alloc = pAllocator;77set_layout->binding_count = num_bindings;78set_layout->shader_stages = 0;79set_layout->size = 0;8081VkDescriptorSetLayoutBinding *bindings = NULL;82VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,83pCreateInfo->bindingCount,84&bindings);85if (result != VK_SUCCESS) {86vk_object_base_finish(&set_layout->base);87vk_free2(&device->vk.alloc, pAllocator, set_layout);88return vk_error(device->instance, result);89}9091uint32_t dynamic_offset_count = 0;92for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {93const VkDescriptorSetLayoutBinding *binding = bindings + j;94uint32_t b = binding->binding;9596set_layout->binding[b].array_size = binding->descriptorCount;97set_layout->binding[b].descriptor_index = set_layout->size;98set_layout->binding[b].type = binding->descriptorType;99set_layout->binding[b].valid = true;100set_layout->size += binding->descriptorCount;101102for (gl_shader_stage stage = MESA_SHADER_VERTEX; stage < MESA_SHADER_STAGES; stage++) {103set_layout->binding[b].stage[stage].const_buffer_index = -1;104set_layout->binding[b].stage[stage].shader_buffer_index = -1;105set_layout->binding[b].stage[stage].sampler_index = -1;106set_layout->binding[b].stage[stage].sampler_view_index = -1;107set_layout->binding[b].stage[stage].image_index = -1;108}109110if (binding->descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC ||111binding->descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {112set_layout->binding[b].dynamic_index = dynamic_offset_count;113dynamic_offset_count += binding->descriptorCount;114}115switch (binding->descriptorType) {116case VK_DESCRIPTOR_TYPE_SAMPLER:117case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:118lvp_foreach_stage(s, binding->stageFlags) {119set_layout->binding[b].stage[s].sampler_index = set_layout->stage[s].sampler_count;120set_layout->stage[s].sampler_count += binding->descriptorCount;121}122if (binding->pImmutableSamplers) {123set_layout->binding[b].immutable_samplers = samplers;124samplers += binding->descriptorCount;125126for (uint32_t i = 0; i < binding->descriptorCount; i++)127set_layout->binding[b].immutable_samplers[i] =128lvp_sampler_from_handle(binding->pImmutableSamplers[i]);129}130break;131default:132break;133}134135switch (binding->descriptorType) {136case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:137case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:138lvp_foreach_stage(s, binding->stageFlags) {139set_layout->binding[b].stage[s].const_buffer_index = set_layout->stage[s].const_buffer_count;140set_layout->stage[s].const_buffer_count += binding->descriptorCount;141}142break;143case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:144case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:145lvp_foreach_stage(s, binding->stageFlags) {146set_layout->binding[b].stage[s].shader_buffer_index = set_layout->stage[s].shader_buffer_count;147set_layout->stage[s].shader_buffer_count += binding->descriptorCount;148}149break;150151case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:152case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:153case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:154lvp_foreach_stage(s, binding->stageFlags) {155set_layout->binding[b].stage[s].image_index = set_layout->stage[s].image_count;156set_layout->stage[s].image_count += binding->descriptorCount;157}158break;159case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:160case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:161case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:162lvp_foreach_stage(s, binding->stageFlags) {163set_layout->binding[b].stage[s].sampler_view_index = set_layout->stage[s].sampler_view_count;164set_layout->stage[s].sampler_view_count += binding->descriptorCount;165}166break;167default:168break;169}170171set_layout->shader_stages |= binding->stageFlags;172}173174free(bindings);175176set_layout->dynamic_offset_count = dynamic_offset_count;177178*pSetLayout = lvp_descriptor_set_layout_to_handle(set_layout);179180return VK_SUCCESS;181}182183void184lvp_descriptor_set_layout_destroy(struct lvp_device *device,185struct lvp_descriptor_set_layout *layout)186{187assert(layout->ref_cnt == 0);188vk_object_base_finish(&layout->base);189vk_free2(&device->vk.alloc, layout->alloc, layout);190}191192VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorSetLayout(193VkDevice _device,194VkDescriptorSetLayout _set_layout,195const VkAllocationCallbacks* pAllocator)196{197LVP_FROM_HANDLE(lvp_device, device, _device);198LVP_FROM_HANDLE(lvp_descriptor_set_layout, set_layout, _set_layout);199200if (!_set_layout)201return;202203lvp_descriptor_set_layout_unref(device, set_layout);204}205206VKAPI_ATTR VkResult VKAPI_CALL lvp_CreatePipelineLayout(207VkDevice _device,208const VkPipelineLayoutCreateInfo* pCreateInfo,209const VkAllocationCallbacks* pAllocator,210VkPipelineLayout* pPipelineLayout)211{212LVP_FROM_HANDLE(lvp_device, device, _device);213struct lvp_pipeline_layout *layout;214215assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);216217layout = vk_alloc2(&device->vk.alloc, pAllocator, sizeof(*layout), 8,218VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);219if (layout == NULL)220return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);221222vk_object_base_init(&device->vk, &layout->base,223VK_OBJECT_TYPE_PIPELINE_LAYOUT);224layout->num_sets = pCreateInfo->setLayoutCount;225226for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {227LVP_FROM_HANDLE(lvp_descriptor_set_layout, set_layout,228pCreateInfo->pSetLayouts[set]);229layout->set[set].layout = set_layout;230lvp_descriptor_set_layout_ref(set_layout);231}232233layout->push_constant_size = 0;234for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {235const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;236layout->push_constant_size = MAX2(layout->push_constant_size,237range->offset + range->size);238}239layout->push_constant_size = align(layout->push_constant_size, 16);240*pPipelineLayout = lvp_pipeline_layout_to_handle(layout);241242return VK_SUCCESS;243}244245VKAPI_ATTR void VKAPI_CALL lvp_DestroyPipelineLayout(246VkDevice _device,247VkPipelineLayout _pipelineLayout,248const VkAllocationCallbacks* pAllocator)249{250LVP_FROM_HANDLE(lvp_device, device, _device);251LVP_FROM_HANDLE(lvp_pipeline_layout, pipeline_layout, _pipelineLayout);252253if (!_pipelineLayout)254return;255for (uint32_t i = 0; i < pipeline_layout->num_sets; i++)256lvp_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout);257258vk_object_base_finish(&pipeline_layout->base);259vk_free2(&device->vk.alloc, pAllocator, pipeline_layout);260}261262VkResult263lvp_descriptor_set_create(struct lvp_device *device,264struct lvp_descriptor_set_layout *layout,265struct lvp_descriptor_set **out_set)266{267struct lvp_descriptor_set *set;268size_t size = sizeof(*set) + layout->size * sizeof(set->descriptors[0]);269270set = vk_alloc(&device->vk.alloc /* XXX: Use the pool */, size, 8,271VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);272if (!set)273return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);274275/* A descriptor set may not be 100% filled. Clear the set so we can can276* later detect holes in it.277*/278memset(set, 0, size);279280vk_object_base_init(&device->vk, &set->base,281VK_OBJECT_TYPE_DESCRIPTOR_SET);282set->layout = layout;283lvp_descriptor_set_layout_ref(layout);284285/* Go through and fill out immutable samplers if we have any */286struct lvp_descriptor *desc = set->descriptors;287for (uint32_t b = 0; b < layout->binding_count; b++) {288if (layout->binding[b].immutable_samplers) {289for (uint32_t i = 0; i < layout->binding[b].array_size; i++)290desc[i].info.sampler = layout->binding[b].immutable_samplers[i];291}292desc += layout->binding[b].array_size;293}294295*out_set = set;296297return VK_SUCCESS;298}299300void301lvp_descriptor_set_destroy(struct lvp_device *device,302struct lvp_descriptor_set *set)303{304lvp_descriptor_set_layout_unref(device, set->layout);305vk_object_base_finish(&set->base);306vk_free(&device->vk.alloc, set);307}308309VKAPI_ATTR VkResult VKAPI_CALL lvp_AllocateDescriptorSets(310VkDevice _device,311const VkDescriptorSetAllocateInfo* pAllocateInfo,312VkDescriptorSet* pDescriptorSets)313{314LVP_FROM_HANDLE(lvp_device, device, _device);315LVP_FROM_HANDLE(lvp_descriptor_pool, pool, pAllocateInfo->descriptorPool);316VkResult result = VK_SUCCESS;317struct lvp_descriptor_set *set;318uint32_t i;319320for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {321LVP_FROM_HANDLE(lvp_descriptor_set_layout, layout,322pAllocateInfo->pSetLayouts[i]);323324result = lvp_descriptor_set_create(device, layout, &set);325if (result != VK_SUCCESS)326break;327328list_addtail(&set->link, &pool->sets);329pDescriptorSets[i] = lvp_descriptor_set_to_handle(set);330}331332if (result != VK_SUCCESS)333lvp_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,334i, pDescriptorSets);335336return result;337}338339VKAPI_ATTR VkResult VKAPI_CALL lvp_FreeDescriptorSets(340VkDevice _device,341VkDescriptorPool descriptorPool,342uint32_t count,343const VkDescriptorSet* pDescriptorSets)344{345LVP_FROM_HANDLE(lvp_device, device, _device);346for (uint32_t i = 0; i < count; i++) {347LVP_FROM_HANDLE(lvp_descriptor_set, set, pDescriptorSets[i]);348349if (!set)350continue;351list_del(&set->link);352lvp_descriptor_set_destroy(device, set);353}354return VK_SUCCESS;355}356357VKAPI_ATTR void VKAPI_CALL lvp_UpdateDescriptorSets(358VkDevice _device,359uint32_t descriptorWriteCount,360const VkWriteDescriptorSet* pDescriptorWrites,361uint32_t descriptorCopyCount,362const VkCopyDescriptorSet* pDescriptorCopies)363{364for (uint32_t i = 0; i < descriptorWriteCount; i++) {365const VkWriteDescriptorSet *write = &pDescriptorWrites[i];366LVP_FROM_HANDLE(lvp_descriptor_set, set, write->dstSet);367const struct lvp_descriptor_set_binding_layout *bind_layout =368&set->layout->binding[write->dstBinding];369struct lvp_descriptor *desc =370&set->descriptors[bind_layout->descriptor_index];371desc += write->dstArrayElement;372373switch (write->descriptorType) {374case VK_DESCRIPTOR_TYPE_SAMPLER:375for (uint32_t j = 0; j < write->descriptorCount; j++) {376LVP_FROM_HANDLE(lvp_sampler, sampler,377write->pImageInfo[j].sampler);378379desc[j] = (struct lvp_descriptor) {380.type = VK_DESCRIPTOR_TYPE_SAMPLER,381.info.sampler = sampler,382};383}384break;385386case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:387for (uint32_t j = 0; j < write->descriptorCount; j++) {388LVP_FROM_HANDLE(lvp_image_view, iview,389write->pImageInfo[j].imageView);390desc[j].type = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;391desc[j].info.iview = iview;392/*393* All consecutive bindings updated via a single VkWriteDescriptorSet structure, except those394* with a descriptorCount of zero, must all either use immutable samplers or must all not395* use immutable samplers396*/397if (bind_layout->immutable_samplers) {398desc[j].info.sampler = bind_layout->immutable_samplers[j];399} else {400LVP_FROM_HANDLE(lvp_sampler, sampler,401write->pImageInfo[j].sampler);402403desc[j].info.sampler = sampler;404}405}406break;407408case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:409case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:410case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:411for (uint32_t j = 0; j < write->descriptorCount; j++) {412LVP_FROM_HANDLE(lvp_image_view, iview,413write->pImageInfo[j].imageView);414415desc[j] = (struct lvp_descriptor) {416.type = write->descriptorType,417.info.iview = iview,418};419}420break;421422case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:423case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:424for (uint32_t j = 0; j < write->descriptorCount; j++) {425LVP_FROM_HANDLE(lvp_buffer_view, bview,426write->pTexelBufferView[j]);427428desc[j] = (struct lvp_descriptor) {429.type = write->descriptorType,430.info.buffer_view = bview,431};432}433break;434435case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:436case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:437case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:438case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:439for (uint32_t j = 0; j < write->descriptorCount; j++) {440assert(write->pBufferInfo[j].buffer);441LVP_FROM_HANDLE(lvp_buffer, buffer, write->pBufferInfo[j].buffer);442assert(buffer);443desc[j] = (struct lvp_descriptor) {444.type = write->descriptorType,445.info.offset = write->pBufferInfo[j].offset,446.info.buffer = buffer,447.info.range = write->pBufferInfo[j].range,448};449450}451452default:453break;454}455}456457for (uint32_t i = 0; i < descriptorCopyCount; i++) {458const VkCopyDescriptorSet *copy = &pDescriptorCopies[i];459LVP_FROM_HANDLE(lvp_descriptor_set, src, copy->srcSet);460LVP_FROM_HANDLE(lvp_descriptor_set, dst, copy->dstSet);461462const struct lvp_descriptor_set_binding_layout *src_layout =463&src->layout->binding[copy->srcBinding];464struct lvp_descriptor *src_desc =465&src->descriptors[src_layout->descriptor_index];466src_desc += copy->srcArrayElement;467468const struct lvp_descriptor_set_binding_layout *dst_layout =469&dst->layout->binding[copy->dstBinding];470struct lvp_descriptor *dst_desc =471&dst->descriptors[dst_layout->descriptor_index];472dst_desc += copy->dstArrayElement;473474for (uint32_t j = 0; j < copy->descriptorCount; j++)475dst_desc[j] = src_desc[j];476}477}478479VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorPool(480VkDevice _device,481const VkDescriptorPoolCreateInfo* pCreateInfo,482const VkAllocationCallbacks* pAllocator,483VkDescriptorPool* pDescriptorPool)484{485LVP_FROM_HANDLE(lvp_device, device, _device);486struct lvp_descriptor_pool *pool;487size_t size = sizeof(struct lvp_descriptor_pool);488pool = vk_zalloc2(&device->vk.alloc, pAllocator, size, 8,489VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);490if (!pool)491return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);492493vk_object_base_init(&device->vk, &pool->base,494VK_OBJECT_TYPE_DESCRIPTOR_POOL);495pool->flags = pCreateInfo->flags;496list_inithead(&pool->sets);497*pDescriptorPool = lvp_descriptor_pool_to_handle(pool);498return VK_SUCCESS;499}500501static void lvp_reset_descriptor_pool(struct lvp_device *device,502struct lvp_descriptor_pool *pool)503{504struct lvp_descriptor_set *set, *tmp;505LIST_FOR_EACH_ENTRY_SAFE(set, tmp, &pool->sets, link) {506lvp_descriptor_set_layout_unref(device, set->layout);507list_del(&set->link);508vk_free(&device->vk.alloc, set);509}510}511512VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorPool(513VkDevice _device,514VkDescriptorPool _pool,515const VkAllocationCallbacks* pAllocator)516{517LVP_FROM_HANDLE(lvp_device, device, _device);518LVP_FROM_HANDLE(lvp_descriptor_pool, pool, _pool);519520if (!_pool)521return;522523lvp_reset_descriptor_pool(device, pool);524vk_object_base_finish(&pool->base);525vk_free2(&device->vk.alloc, pAllocator, pool);526}527528VKAPI_ATTR VkResult VKAPI_CALL lvp_ResetDescriptorPool(529VkDevice _device,530VkDescriptorPool _pool,531VkDescriptorPoolResetFlags flags)532{533LVP_FROM_HANDLE(lvp_device, device, _device);534LVP_FROM_HANDLE(lvp_descriptor_pool, pool, _pool);535536lvp_reset_descriptor_pool(device, pool);537return VK_SUCCESS;538}539540VKAPI_ATTR void VKAPI_CALL lvp_GetDescriptorSetLayoutSupport(VkDevice device,541const VkDescriptorSetLayoutCreateInfo* pCreateInfo,542VkDescriptorSetLayoutSupport* pSupport)543{544pSupport->supported = true;545}546547VKAPI_ATTR VkResult VKAPI_CALL lvp_CreateDescriptorUpdateTemplate(VkDevice _device,548const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,549const VkAllocationCallbacks *pAllocator,550VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)551{552LVP_FROM_HANDLE(lvp_device, device, _device);553const uint32_t entry_count = pCreateInfo->descriptorUpdateEntryCount;554const size_t size = sizeof(struct lvp_descriptor_update_template) +555sizeof(VkDescriptorUpdateTemplateEntry) * entry_count;556557struct lvp_descriptor_update_template *templ;558559templ = vk_alloc2(&device->vk.alloc, pAllocator, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);560if (!templ)561return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);562563vk_object_base_init(&device->vk, &templ->base,564VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);565566templ->type = pCreateInfo->templateType;567templ->bind_point = pCreateInfo->pipelineBindPoint;568templ->set = pCreateInfo->set;569/* This parameter is ignored if templateType is not VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR */570if (pCreateInfo->templateType == VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_PUSH_DESCRIPTORS_KHR)571templ->pipeline_layout = lvp_pipeline_layout_from_handle(pCreateInfo->pipelineLayout);572else573templ->pipeline_layout = NULL;574templ->entry_count = entry_count;575576VkDescriptorUpdateTemplateEntry *entries = (VkDescriptorUpdateTemplateEntry *)(templ + 1);577for (unsigned i = 0; i < entry_count; i++) {578entries[i] = pCreateInfo->pDescriptorUpdateEntries[i];579}580581*pDescriptorUpdateTemplate = lvp_descriptor_update_template_to_handle(templ);582return VK_SUCCESS;583}584585VKAPI_ATTR void VKAPI_CALL lvp_DestroyDescriptorUpdateTemplate(VkDevice _device,586VkDescriptorUpdateTemplate descriptorUpdateTemplate,587const VkAllocationCallbacks *pAllocator)588{589LVP_FROM_HANDLE(lvp_device, device, _device);590LVP_FROM_HANDLE(lvp_descriptor_update_template, templ, descriptorUpdateTemplate);591592if (!templ)593return;594595vk_object_base_finish(&templ->base);596vk_free2(&device->vk.alloc, pAllocator, templ);597}598599VKAPI_ATTR void VKAPI_CALL lvp_UpdateDescriptorSetWithTemplate(VkDevice _device,600VkDescriptorSet descriptorSet,601VkDescriptorUpdateTemplate descriptorUpdateTemplate,602const void *pData)603{604LVP_FROM_HANDLE(lvp_descriptor_set, set, descriptorSet);605LVP_FROM_HANDLE(lvp_descriptor_update_template, templ, descriptorUpdateTemplate);606uint32_t i, j;607608for (i = 0; i < templ->entry_count; ++i) {609VkDescriptorUpdateTemplateEntry *entry = &templ->entry[i];610const uint8_t *pSrc = ((const uint8_t *) pData) + entry->offset;611const struct lvp_descriptor_set_binding_layout *bind_layout =612&set->layout->binding[entry->dstBinding];613struct lvp_descriptor *desc =614&set->descriptors[bind_layout->descriptor_index];615for (j = 0; j < entry->descriptorCount; ++j) {616unsigned idx = j + entry->dstArrayElement;617switch (entry->descriptorType) {618case VK_DESCRIPTOR_TYPE_SAMPLER: {619LVP_FROM_HANDLE(lvp_sampler, sampler,620*(VkSampler *)pSrc);621desc[idx] = (struct lvp_descriptor) {622.type = VK_DESCRIPTOR_TYPE_SAMPLER,623.info.sampler = sampler,624};625break;626}627case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {628VkDescriptorImageInfo *info = (VkDescriptorImageInfo *)pSrc;629desc[idx] = (struct lvp_descriptor) {630.type = entry->descriptorType,631.info.iview = lvp_image_view_from_handle(info->imageView),632.info.sampler = lvp_sampler_from_handle(info->sampler),633};634break;635}636case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:637case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:638case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {639LVP_FROM_HANDLE(lvp_image_view, iview,640((VkDescriptorImageInfo *)pSrc)->imageView);641desc[idx] = (struct lvp_descriptor) {642.type = entry->descriptorType,643.info.iview = iview,644};645break;646}647case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:648case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {649LVP_FROM_HANDLE(lvp_buffer_view, bview,650*(VkBufferView *)pSrc);651desc[idx] = (struct lvp_descriptor) {652.type = entry->descriptorType,653.info.buffer_view = bview,654};655break;656}657658case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:659case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:660case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:661case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {662VkDescriptorBufferInfo *info = (VkDescriptorBufferInfo *)pSrc;663desc[idx] = (struct lvp_descriptor) {664.type = entry->descriptorType,665.info.offset = info->offset,666.info.buffer = lvp_buffer_from_handle(info->buffer),667.info.range = info->range,668};669break;670}671default:672break;673}674pSrc += entry->stride;675}676}677}678679680