Path: blob/21.2-virgl/src/broadcom/vulkan/v3dv_descriptor_set.c
4560 views
/*1* Copyright © 2019 Raspberry Pi2*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 "vk_descriptors.h"24#include "vk_util.h"2526#include "v3dv_private.h"2728/*29* For a given descriptor defined by the descriptor_set it belongs, its30* binding layout, and array_index, it returns the map region assigned to it31* from the descriptor pool bo.32*/33static void*34descriptor_bo_map(struct v3dv_device *device,35struct v3dv_descriptor_set *set,36const struct v3dv_descriptor_set_binding_layout *binding_layout,37uint32_t array_index)38{39assert(v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0);40return set->pool->bo->map +41set->base_offset + binding_layout->descriptor_offset +42array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type);43}4445static bool46descriptor_type_is_dynamic(VkDescriptorType type)47{48switch (type) {49case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:50case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:51return true;52break;53default:54return false;55}56}5758/*59* Tries to get a real descriptor using a descriptor map index from the60* descriptor_state + pipeline_layout.61*/62struct v3dv_descriptor *63v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state,64struct v3dv_descriptor_map *map,65struct v3dv_pipeline_layout *pipeline_layout,66uint32_t index,67uint32_t *dynamic_offset)68{69assert(index < map->num_desc);7071uint32_t set_number = map->set[index];72assert((descriptor_state->valid & 1 << set_number));7374struct v3dv_descriptor_set *set =75descriptor_state->descriptor_sets[set_number];76assert(set);7778uint32_t binding_number = map->binding[index];79assert(binding_number < set->layout->binding_count);8081const struct v3dv_descriptor_set_binding_layout *binding_layout =82&set->layout->binding[binding_number];8384uint32_t array_index = map->array_index[index];85assert(array_index < binding_layout->array_size);8687if (descriptor_type_is_dynamic(binding_layout->type)) {88uint32_t dynamic_offset_index =89pipeline_layout->set[set_number].dynamic_offset_start +90binding_layout->dynamic_offset_index + array_index;9192*dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index];93}9495return &set->descriptors[binding_layout->descriptor_index + array_index];96}9798/* Equivalent to map_get_descriptor but it returns a reloc with the bo99* associated with that descriptor (suballocation of the descriptor pool bo)100*101* It also returns the descriptor type, so the caller could do extra102* validation or adding extra offsets if the bo contains more that one field.103*/104static struct v3dv_cl_reloc105v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device,106struct v3dv_descriptor_state *descriptor_state,107struct v3dv_descriptor_map *map,108struct v3dv_pipeline_layout *pipeline_layout,109uint32_t index,110VkDescriptorType *out_type)111{112assert(index < map->num_desc);113114uint32_t set_number = map->set[index];115assert(descriptor_state->valid & 1 << set_number);116117struct v3dv_descriptor_set *set =118descriptor_state->descriptor_sets[set_number];119assert(set);120121uint32_t binding_number = map->binding[index];122assert(binding_number < set->layout->binding_count);123124const struct v3dv_descriptor_set_binding_layout *binding_layout =125&set->layout->binding[binding_number];126127assert(v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0);128*out_type = binding_layout->type;129130uint32_t array_index = map->array_index[index];131assert(array_index < binding_layout->array_size);132133struct v3dv_cl_reloc reloc = {134.bo = set->pool->bo,135.offset = set->base_offset + binding_layout->descriptor_offset +136array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type),137};138139return reloc;140}141142/*143* The difference between this method and v3dv_descriptor_map_get_descriptor,144* is that if the sampler are added as immutable when creating the set layout,145* they are bound to the set layout, so not part of the descriptor per146* se. This method return early in that case.147*/148const struct v3dv_sampler *149v3dv_descriptor_map_get_sampler(struct v3dv_descriptor_state *descriptor_state,150struct v3dv_descriptor_map *map,151struct v3dv_pipeline_layout *pipeline_layout,152uint32_t index)153{154assert(index < map->num_desc);155156uint32_t set_number = map->set[index];157assert(descriptor_state->valid & 1 << set_number);158159struct v3dv_descriptor_set *set =160descriptor_state->descriptor_sets[set_number];161assert(set);162163uint32_t binding_number = map->binding[index];164assert(binding_number < set->layout->binding_count);165166const struct v3dv_descriptor_set_binding_layout *binding_layout =167&set->layout->binding[binding_number];168169uint32_t array_index = map->array_index[index];170assert(array_index < binding_layout->array_size);171172if (binding_layout->immutable_samplers_offset != 0) {173assert(binding_layout->type == VK_DESCRIPTOR_TYPE_SAMPLER ||174binding_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);175176const struct v3dv_sampler *immutable_samplers =177v3dv_immutable_samplers(set->layout, binding_layout);178179assert(immutable_samplers);180const struct v3dv_sampler *sampler = &immutable_samplers[array_index];181assert(sampler);182183return sampler;184}185186struct v3dv_descriptor *descriptor =187&set->descriptors[binding_layout->descriptor_index + array_index];188189assert(descriptor->type == VK_DESCRIPTOR_TYPE_SAMPLER ||190descriptor->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);191192assert(descriptor->sampler);193194return descriptor->sampler;195}196197198struct v3dv_cl_reloc199v3dv_descriptor_map_get_sampler_state(struct v3dv_device *device,200struct v3dv_descriptor_state *descriptor_state,201struct v3dv_descriptor_map *map,202struct v3dv_pipeline_layout *pipeline_layout,203uint32_t index)204{205VkDescriptorType type;206struct v3dv_cl_reloc reloc =207v3dv_descriptor_map_get_descriptor_bo(device, descriptor_state, map,208pipeline_layout,209index, &type);210211assert(type == VK_DESCRIPTOR_TYPE_SAMPLER ||212type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);213214if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)215reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)();216217return reloc;218}219220const struct v3dv_format*221v3dv_descriptor_map_get_texture_format(struct v3dv_descriptor_state *descriptor_state,222struct v3dv_descriptor_map *map,223struct v3dv_pipeline_layout *pipeline_layout,224uint32_t index,225VkFormat *out_vk_format)226{227struct v3dv_descriptor *descriptor =228v3dv_descriptor_map_get_descriptor(descriptor_state, map,229pipeline_layout, index, NULL);230231switch (descriptor->type) {232case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:233case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:234assert(descriptor->buffer_view);235*out_vk_format = descriptor->buffer_view->vk_format;236return descriptor->buffer_view->format;237case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:238case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:239case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:240case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:241assert(descriptor->image_view);242*out_vk_format = descriptor->image_view->vk_format;243return descriptor->image_view->format;244default:245unreachable("descriptor type doesn't has a texture format");246}247}248249struct v3dv_bo*250v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state,251struct v3dv_descriptor_map *map,252struct v3dv_pipeline_layout *pipeline_layout,253uint32_t index)254255{256struct v3dv_descriptor *descriptor =257v3dv_descriptor_map_get_descriptor(descriptor_state, map,258pipeline_layout, index, NULL);259260switch (descriptor->type) {261case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:262case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:263assert(descriptor->buffer_view);264return descriptor->buffer_view->buffer->mem->bo;265case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:266case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:267case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:268case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:269assert(descriptor->image_view);270return descriptor->image_view->image->mem->bo;271default:272unreachable("descriptor type doesn't has a texture bo");273}274}275276struct v3dv_cl_reloc277v3dv_descriptor_map_get_texture_shader_state(struct v3dv_device *device,278struct v3dv_descriptor_state *descriptor_state,279struct v3dv_descriptor_map *map,280struct v3dv_pipeline_layout *pipeline_layout,281uint32_t index)282{283VkDescriptorType type;284struct v3dv_cl_reloc reloc =285v3dv_descriptor_map_get_descriptor_bo(device,286descriptor_state, map,287pipeline_layout,288index, &type);289290assert(type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||291type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||292type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT ||293type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ||294type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER ||295type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER);296297if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)298reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)();299300return reloc;301}302303/*304* As anv and tu already points:305*306* "Pipeline layouts. These have nothing to do with the pipeline. They are307* just multiple descriptor set layouts pasted together."308*/309310VKAPI_ATTR VkResult VKAPI_CALL311v3dv_CreatePipelineLayout(VkDevice _device,312const VkPipelineLayoutCreateInfo *pCreateInfo,313const VkAllocationCallbacks *pAllocator,314VkPipelineLayout *pPipelineLayout)315{316V3DV_FROM_HANDLE(v3dv_device, device, _device);317struct v3dv_pipeline_layout *layout;318319assert(pCreateInfo->sType ==320VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO);321322layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout),323VK_OBJECT_TYPE_PIPELINE_LAYOUT);324if (layout == NULL)325return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);326327layout->num_sets = pCreateInfo->setLayoutCount;328329uint32_t dynamic_offset_count = 0;330for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) {331V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout,332pCreateInfo->pSetLayouts[set]);333layout->set[set].layout = set_layout;334335layout->set[set].dynamic_offset_start = dynamic_offset_count;336for (uint32_t b = 0; b < set_layout->binding_count; b++) {337dynamic_offset_count += set_layout->binding[b].array_size *338set_layout->binding[b].dynamic_offset_count;339}340341layout->shader_stages |= set_layout->shader_stages;342}343344layout->push_constant_size = 0;345for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {346const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i;347layout->push_constant_size =348MAX2(layout->push_constant_size, range->offset + range->size);349}350351layout->push_constant_size = align(layout->push_constant_size, 4096);352353layout->dynamic_offset_count = dynamic_offset_count;354355*pPipelineLayout = v3dv_pipeline_layout_to_handle(layout);356357return VK_SUCCESS;358}359360VKAPI_ATTR void VKAPI_CALL361v3dv_DestroyPipelineLayout(VkDevice _device,362VkPipelineLayout _pipelineLayout,363const VkAllocationCallbacks *pAllocator)364{365V3DV_FROM_HANDLE(v3dv_device, device, _device);366V3DV_FROM_HANDLE(v3dv_pipeline_layout, pipeline_layout, _pipelineLayout);367368if (!pipeline_layout)369return;370vk_object_free(&device->vk, pAllocator, pipeline_layout);371}372373VKAPI_ATTR VkResult VKAPI_CALL374v3dv_CreateDescriptorPool(VkDevice _device,375const VkDescriptorPoolCreateInfo *pCreateInfo,376const VkAllocationCallbacks *pAllocator,377VkDescriptorPool *pDescriptorPool)378{379V3DV_FROM_HANDLE(v3dv_device, device, _device);380struct v3dv_descriptor_pool *pool;381/* size is for the vulkan object descriptor pool. The final size would382* depend on some of FREE_DESCRIPTOR flags used383*/384uint64_t size = sizeof(struct v3dv_descriptor_pool);385/* bo_size is for the descriptor related info that we need to have on a GPU386* address (so on v3dv_bo_alloc allocated memory), like for example the387* texture sampler state. Note that not all the descriptors use it388*/389uint32_t bo_size = 0;390uint32_t descriptor_count = 0;391392assert(pCreateInfo->poolSizeCount > 0);393for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) {394/* Verify supported descriptor type */395switch(pCreateInfo->pPoolSizes[i].type) {396case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:397case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:398case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:399case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:400case VK_DESCRIPTOR_TYPE_SAMPLER:401case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:402case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:403case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:404case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:405case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:406case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:407break;408default:409unreachable("Unimplemented descriptor type");410break;411}412413assert(pCreateInfo->pPoolSizes[i].descriptorCount > 0);414descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount;415bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) *416pCreateInfo->pPoolSizes[i].descriptorCount;417}418419if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {420uint64_t host_size =421pCreateInfo->maxSets * sizeof(struct v3dv_descriptor_set);422host_size += sizeof(struct v3dv_descriptor) * descriptor_count;423size += host_size;424} else {425size += sizeof(struct v3dv_descriptor_pool_entry) * pCreateInfo->maxSets;426}427428pool = vk_object_zalloc(&device->vk, pAllocator, size,429VK_OBJECT_TYPE_DESCRIPTOR_POOL);430431if (!pool)432return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);433434if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) {435pool->host_memory_base = (uint8_t*)pool + sizeof(struct v3dv_descriptor_pool);436pool->host_memory_ptr = pool->host_memory_base;437pool->host_memory_end = (uint8_t*)pool + size;438}439440pool->max_entry_count = pCreateInfo->maxSets;441442if (bo_size > 0) {443pool->bo = v3dv_bo_alloc(device, bo_size, "descriptor pool bo", true);444if (!pool->bo)445goto out_of_device_memory;446447bool ok = v3dv_bo_map(device, pool->bo, pool->bo->size);448if (!ok)449goto out_of_device_memory;450451pool->current_offset = 0;452} else {453pool->bo = NULL;454}455456*pDescriptorPool = v3dv_descriptor_pool_to_handle(pool);457458return VK_SUCCESS;459460out_of_device_memory:461vk_object_free(&device->vk, pAllocator, pool);462return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY);463}464465static void466descriptor_set_destroy(struct v3dv_device *device,467struct v3dv_descriptor_pool *pool,468struct v3dv_descriptor_set *set,469bool free_bo)470{471assert(!pool->host_memory_base);472473if (free_bo && !pool->host_memory_base) {474for (uint32_t i = 0; i < pool->entry_count; i++) {475if (pool->entries[i].set == set) {476memmove(&pool->entries[i], &pool->entries[i+1],477sizeof(pool->entries[i]) * (pool->entry_count - i - 1));478--pool->entry_count;479break;480}481}482}483vk_object_free(&device->vk, NULL, set);484}485486VKAPI_ATTR void VKAPI_CALL487v3dv_DestroyDescriptorPool(VkDevice _device,488VkDescriptorPool _pool,489const VkAllocationCallbacks *pAllocator)490{491V3DV_FROM_HANDLE(v3dv_device, device, _device);492V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, _pool);493494if (!pool)495return;496497if (!pool->host_memory_base) {498for(int i = 0; i < pool->entry_count; ++i) {499descriptor_set_destroy(device, pool, pool->entries[i].set, false);500}501}502503if (pool->bo) {504v3dv_bo_free(device, pool->bo);505pool->bo = NULL;506}507508vk_object_free(&device->vk, pAllocator, pool);509}510511VKAPI_ATTR VkResult VKAPI_CALL512v3dv_ResetDescriptorPool(VkDevice _device,513VkDescriptorPool descriptorPool,514VkDescriptorPoolResetFlags flags)515{516V3DV_FROM_HANDLE(v3dv_device, device, _device);517V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);518519if (!pool->host_memory_base) {520for(int i = 0; i < pool->entry_count; ++i) {521descriptor_set_destroy(device, pool, pool->entries[i].set, false);522}523} else {524/* We clean-up the host memory, so when allocating a new set from the525* pool, it is already 0526*/527uint32_t host_size = pool->host_memory_end - pool->host_memory_base;528memset(pool->host_memory_base, 0, host_size);529}530531pool->entry_count = 0;532pool->host_memory_ptr = pool->host_memory_base;533pool->current_offset = 0;534535return VK_SUCCESS;536}537538VKAPI_ATTR VkResult VKAPI_CALL539v3dv_CreateDescriptorSetLayout(VkDevice _device,540const VkDescriptorSetLayoutCreateInfo *pCreateInfo,541const VkAllocationCallbacks *pAllocator,542VkDescriptorSetLayout *pSetLayout)543{544V3DV_FROM_HANDLE(v3dv_device, device, _device);545struct v3dv_descriptor_set_layout *set_layout;546547assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO);548549uint32_t num_bindings = 0;550uint32_t immutable_sampler_count = 0;551for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) {552num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1);553554/* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding:555*556* "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or557* VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then558* pImmutableSamplers can be used to initialize a set of immutable559* samplers. [...] If descriptorType is not one of these descriptor560* types, then pImmutableSamplers is ignored.561*562* We need to be careful here and only parse pImmutableSamplers if we563* have one of the right descriptor types.564*/565VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType;566if ((desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||567desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) &&568pCreateInfo->pBindings[j].pImmutableSamplers) {569immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount;570}571}572573uint32_t samplers_offset = sizeof(struct v3dv_descriptor_set_layout) +574num_bindings * sizeof(set_layout->binding[0]);575uint32_t size = samplers_offset +576immutable_sampler_count * sizeof(struct v3dv_sampler);577578set_layout = vk_object_zalloc(&device->vk, pAllocator, size,579VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT);580581if (!set_layout)582return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);583584/* We just allocate all the immutable samplers at the end of the struct */585struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings];586587assert(pCreateInfo->bindingCount == 0 || num_bindings > 0);588589VkDescriptorSetLayoutBinding *bindings = NULL;590VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings,591pCreateInfo->bindingCount, &bindings);592if (result != VK_SUCCESS) {593vk_object_free(&device->vk, pAllocator, set_layout);594return vk_error(device->instance, result);595}596597memset(set_layout->binding, 0,598size - sizeof(struct v3dv_descriptor_set_layout));599600set_layout->binding_count = num_bindings;601set_layout->flags = pCreateInfo->flags;602set_layout->shader_stages = 0;603set_layout->bo_size = 0;604605uint32_t descriptor_count = 0;606uint32_t dynamic_offset_count = 0;607608for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {609const VkDescriptorSetLayoutBinding *binding = bindings + i;610uint32_t binding_number = binding->binding;611612switch (binding->descriptorType) {613case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:614case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:615break;616case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:617case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:618set_layout->binding[binding_number].dynamic_offset_count = 1;619break;620case VK_DESCRIPTOR_TYPE_SAMPLER:621case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:622case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:623case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:624case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:625case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:626case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:627/* Nothing here, just to keep the descriptor type filtering below */628break;629default:630unreachable("Unknown descriptor type\n");631break;632}633634set_layout->binding[binding_number].type = binding->descriptorType;635set_layout->binding[binding_number].array_size = binding->descriptorCount;636set_layout->binding[binding_number].descriptor_index = descriptor_count;637set_layout->binding[binding_number].dynamic_offset_index = dynamic_offset_count;638639if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||640binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) &&641binding->pImmutableSamplers) {642643set_layout->binding[binding_number].immutable_samplers_offset = samplers_offset;644645for (uint32_t i = 0; i < binding->descriptorCount; i++)646samplers[i] = *v3dv_sampler_from_handle(binding->pImmutableSamplers[i]);647648samplers += binding->descriptorCount;649samplers_offset += sizeof(struct v3dv_sampler) * binding->descriptorCount;650}651652descriptor_count += binding->descriptorCount;653dynamic_offset_count += binding->descriptorCount *654set_layout->binding[binding_number].dynamic_offset_count;655656set_layout->shader_stages |= binding->stageFlags;657658set_layout->binding[binding_number].descriptor_offset = set_layout->bo_size;659set_layout->bo_size +=660v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) *661binding->descriptorCount;662}663664free(bindings);665666set_layout->descriptor_count = descriptor_count;667set_layout->dynamic_offset_count = dynamic_offset_count;668669*pSetLayout = v3dv_descriptor_set_layout_to_handle(set_layout);670671return VK_SUCCESS;672}673674VKAPI_ATTR void VKAPI_CALL675v3dv_DestroyDescriptorSetLayout(VkDevice _device,676VkDescriptorSetLayout _set_layout,677const VkAllocationCallbacks *pAllocator)678{679V3DV_FROM_HANDLE(v3dv_device, device, _device);680V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, _set_layout);681682if (!set_layout)683return;684685vk_object_free(&device->vk, pAllocator, set_layout);686}687688static inline VkResult689out_of_pool_memory(const struct v3dv_device *device,690const struct v3dv_descriptor_pool *pool)691{692/* Don't log OOPM errors for internal driver pools, we handle these properly693* by allocating a new pool, so they don't point to real issues.694*/695if (!pool->is_driver_internal)696return vk_error(device->instance, VK_ERROR_OUT_OF_POOL_MEMORY)697else698return VK_ERROR_OUT_OF_POOL_MEMORY;699}700701static VkResult702descriptor_set_create(struct v3dv_device *device,703struct v3dv_descriptor_pool *pool,704const struct v3dv_descriptor_set_layout *layout,705struct v3dv_descriptor_set **out_set)706{707struct v3dv_descriptor_set *set;708uint32_t descriptor_count = layout->descriptor_count;709unsigned mem_size = sizeof(struct v3dv_descriptor_set) +710sizeof(struct v3dv_descriptor) * descriptor_count;711712if (pool->host_memory_base) {713if (pool->host_memory_end - pool->host_memory_ptr < mem_size)714return out_of_pool_memory(device, pool);715716set = (struct v3dv_descriptor_set*)pool->host_memory_ptr;717pool->host_memory_ptr += mem_size;718719vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET);720} else {721set = vk_object_zalloc(&device->vk, NULL, mem_size,722VK_OBJECT_TYPE_DESCRIPTOR_SET);723724if (!set)725return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);726}727728set->pool = pool;729730set->layout = layout;731732/* FIXME: VK_EXT_descriptor_indexing introduces733* VARIABLE_DESCRIPTOR_LAYOUT_COUNT. That would affect the layout_size used734* below for bo allocation735*/736737uint32_t offset = 0;738uint32_t index = pool->entry_count;739740if (layout->bo_size) {741if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) {742vk_object_free(&device->vk, NULL, set);743return out_of_pool_memory(device, pool);744}745746/* We first try to allocate linearly fist, so that we don't spend time747* looking for gaps if the app only allocates & resets via the pool.748*749* If that fails, we try to find a gap from previously freed subregions750* iterating through the descriptor pool entries. Note that we are not751* doing that if we have a pool->host_memory_base. We only have that if752* VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT is not set, so in753* that case the user can't free subregions, so it doesn't make sense to754* even try (or track those subregions).755*/756if (pool->current_offset + layout->bo_size <= pool->bo->size) {757offset = pool->current_offset;758pool->current_offset += layout->bo_size;759} else if (!pool->host_memory_base) {760for (index = 0; index < pool->entry_count; index++) {761if (pool->entries[index].offset - offset >= layout->bo_size)762break;763offset = pool->entries[index].offset + pool->entries[index].size;764}765if (pool->bo->size - offset < layout->bo_size) {766vk_object_free(&device->vk, NULL, set);767return out_of_pool_memory(device, pool);768}769memmove(&pool->entries[index + 1], &pool->entries[index],770sizeof(pool->entries[0]) * (pool->entry_count - index));771} else {772assert(pool->host_memory_base);773return out_of_pool_memory(device, pool);774}775776set->base_offset = offset;777}778779if (!pool->host_memory_base) {780pool->entries[index].set = set;781pool->entries[index].offset = offset;782pool->entries[index].size = layout->bo_size;783pool->entry_count++;784}785786/* Go through and fill out immutable samplers if we have any */787for (uint32_t b = 0; b < layout->binding_count; b++) {788if (layout->binding[b].immutable_samplers_offset == 0)789continue;790791const struct v3dv_sampler *samplers =792(const struct v3dv_sampler *)((const char *)layout +793layout->binding[b].immutable_samplers_offset);794795for (uint32_t i = 0; i < layout->binding[b].array_size; i++) {796uint32_t combined_offset =797layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ?798v3dv_X(device, combined_image_sampler_sampler_state_offset)() : 0;799800void *desc_map = descriptor_bo_map(device, set, &layout->binding[b], i);801desc_map += combined_offset;802803memcpy(desc_map,804samplers[i].sampler_state,805sizeof(samplers[i].sampler_state));806}807}808809*out_set = set;810811return VK_SUCCESS;812}813814VKAPI_ATTR VkResult VKAPI_CALL815v3dv_AllocateDescriptorSets(VkDevice _device,816const VkDescriptorSetAllocateInfo *pAllocateInfo,817VkDescriptorSet *pDescriptorSets)818{819V3DV_FROM_HANDLE(v3dv_device, device, _device);820V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, pAllocateInfo->descriptorPool);821822VkResult result = VK_SUCCESS;823struct v3dv_descriptor_set *set = NULL;824uint32_t i = 0;825826for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {827V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, layout,828pAllocateInfo->pSetLayouts[i]);829830result = descriptor_set_create(device, pool, layout, &set);831if (result != VK_SUCCESS)832break;833834pDescriptorSets[i] = v3dv_descriptor_set_to_handle(set);835}836837if (result != VK_SUCCESS) {838v3dv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool,839i, pDescriptorSets);840for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) {841pDescriptorSets[i] = VK_NULL_HANDLE;842}843}844845return result;846}847848VKAPI_ATTR VkResult VKAPI_CALL849v3dv_FreeDescriptorSets(VkDevice _device,850VkDescriptorPool descriptorPool,851uint32_t count,852const VkDescriptorSet *pDescriptorSets)853{854V3DV_FROM_HANDLE(v3dv_device, device, _device);855V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool);856857for (uint32_t i = 0; i < count; i++) {858V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]);859if (set && !pool->host_memory_base)860descriptor_set_destroy(device, pool, set, true);861}862863return VK_SUCCESS;864}865866static void867descriptor_bo_copy(struct v3dv_device *device,868struct v3dv_descriptor_set *dst_set,869const struct v3dv_descriptor_set_binding_layout *dst_binding_layout,870uint32_t dst_array_index,871struct v3dv_descriptor_set *src_set,872const struct v3dv_descriptor_set_binding_layout *src_binding_layout,873uint32_t src_array_index)874{875assert(dst_binding_layout->type == src_binding_layout->type);876877void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, dst_array_index);878void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, src_array_index);879880memcpy(dst_map, src_map, v3dv_X(device, descriptor_bo_size)(src_binding_layout->type));881}882883static void884write_buffer_descriptor(struct v3dv_descriptor *descriptor,885VkDescriptorType desc_type,886const VkDescriptorBufferInfo *buffer_info)887{888V3DV_FROM_HANDLE(v3dv_buffer, buffer, buffer_info->buffer);889890descriptor->type = desc_type;891descriptor->buffer = buffer;892descriptor->offset = buffer_info->offset;893if (buffer_info->range == VK_WHOLE_SIZE) {894descriptor->range = buffer->size - buffer_info->offset;895} else {896assert(descriptor->range <= UINT32_MAX);897descriptor->range = buffer_info->range;898}899}900901static void902write_image_descriptor(struct v3dv_device *device,903struct v3dv_descriptor *descriptor,904VkDescriptorType desc_type,905struct v3dv_descriptor_set *set,906const struct v3dv_descriptor_set_binding_layout *binding_layout,907struct v3dv_image_view *iview,908struct v3dv_sampler *sampler,909uint32_t array_index)910{911descriptor->type = desc_type;912descriptor->sampler = sampler;913descriptor->image_view = iview;914915void *desc_map = descriptor_bo_map(device, set,916binding_layout, array_index);917918if (iview) {919const uint32_t tex_state_index =920iview->type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY ||921desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1;922memcpy(desc_map,923iview->texture_shader_state[tex_state_index],924sizeof(iview->texture_shader_state[0]));925desc_map += v3dv_X(device, combined_image_sampler_sampler_state_offset)();926}927928if (sampler && !binding_layout->immutable_samplers_offset) {929/* For immutable samplers this was already done as part of the930* descriptor set create, as that info can't change later931*/932memcpy(desc_map,933sampler->sampler_state,934sizeof(sampler->sampler_state));935}936}937938939static void940write_buffer_view_descriptor(struct v3dv_device *device,941struct v3dv_descriptor *descriptor,942VkDescriptorType desc_type,943struct v3dv_descriptor_set *set,944const struct v3dv_descriptor_set_binding_layout *binding_layout,945struct v3dv_buffer_view *bview,946uint32_t array_index)947{948assert(bview);949descriptor->type = desc_type;950descriptor->buffer_view = bview;951952void *desc_map = descriptor_bo_map(device, set, binding_layout, array_index);953954memcpy(desc_map,955bview->texture_shader_state,956sizeof(bview->texture_shader_state));957}958959VKAPI_ATTR void VKAPI_CALL960v3dv_UpdateDescriptorSets(VkDevice _device,961uint32_t descriptorWriteCount,962const VkWriteDescriptorSet *pDescriptorWrites,963uint32_t descriptorCopyCount,964const VkCopyDescriptorSet *pDescriptorCopies)965{966V3DV_FROM_HANDLE(v3dv_device, device, _device);967for (uint32_t i = 0; i < descriptorWriteCount; i++) {968const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i];969V3DV_FROM_HANDLE(v3dv_descriptor_set, set, writeset->dstSet);970971const struct v3dv_descriptor_set_binding_layout *binding_layout =972set->layout->binding + writeset->dstBinding;973974struct v3dv_descriptor *descriptor = set->descriptors;975976descriptor += binding_layout->descriptor_index;977descriptor += writeset->dstArrayElement;978979for (uint32_t j = 0; j < writeset->descriptorCount; ++j) {980switch(writeset->descriptorType) {981982case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:983case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:984case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:985case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: {986const VkDescriptorBufferInfo *buffer_info = writeset->pBufferInfo + j;987write_buffer_descriptor(descriptor, writeset->descriptorType,988buffer_info);989break;990}991case VK_DESCRIPTOR_TYPE_SAMPLER: {992/* If we are here we shouldn't be modifying a immutable sampler,993* so we don't ensure that would work or not crash. But let the994* validation layers check that995*/996const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;997V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);998write_image_descriptor(device, descriptor, writeset->descriptorType,999set, binding_layout, NULL, sampler,1000writeset->dstArrayElement + j);10011002break;1003}1004case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:1005case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:1006case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: {1007const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;1008V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);1009write_image_descriptor(device, descriptor, writeset->descriptorType,1010set, binding_layout, iview, NULL,1011writeset->dstArrayElement + j);10121013break;1014}1015case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {1016const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j;1017V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView);1018V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler);1019write_image_descriptor(device, descriptor, writeset->descriptorType,1020set, binding_layout, iview, sampler,1021writeset->dstArrayElement + j);10221023break;1024}1025case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:1026case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: {1027V3DV_FROM_HANDLE(v3dv_buffer_view, buffer_view,1028writeset->pTexelBufferView[j]);1029write_buffer_view_descriptor(device, descriptor, writeset->descriptorType,1030set, binding_layout, buffer_view,1031writeset->dstArrayElement + j);1032break;1033}1034default:1035unreachable("unimplemented descriptor type");1036break;1037}1038descriptor++;1039}1040}10411042for (uint32_t i = 0; i < descriptorCopyCount; i++) {1043const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i];1044V3DV_FROM_HANDLE(v3dv_descriptor_set, src_set,1045copyset->srcSet);1046V3DV_FROM_HANDLE(v3dv_descriptor_set, dst_set,1047copyset->dstSet);10481049const struct v3dv_descriptor_set_binding_layout *src_binding_layout =1050src_set->layout->binding + copyset->srcBinding;1051const struct v3dv_descriptor_set_binding_layout *dst_binding_layout =1052dst_set->layout->binding + copyset->dstBinding;10531054assert(src_binding_layout->type == dst_binding_layout->type);10551056struct v3dv_descriptor *src_descriptor = src_set->descriptors;1057struct v3dv_descriptor *dst_descriptor = dst_set->descriptors;10581059src_descriptor += src_binding_layout->descriptor_index;1060src_descriptor += copyset->srcArrayElement;10611062dst_descriptor += dst_binding_layout->descriptor_index;1063dst_descriptor += copyset->dstArrayElement;10641065for (uint32_t j = 0; j < copyset->descriptorCount; j++) {1066*dst_descriptor = *src_descriptor;1067dst_descriptor++;1068src_descriptor++;10691070if (v3dv_X(device, descriptor_bo_size)(src_binding_layout->type) > 0) {1071descriptor_bo_copy(device,1072dst_set, dst_binding_layout,1073j + copyset->dstArrayElement,1074src_set, src_binding_layout,1075j + copyset->srcArrayElement);1076}10771078}1079}1080}10811082VKAPI_ATTR void VKAPI_CALL1083v3dv_GetDescriptorSetLayoutSupport(1084VkDevice _device,1085const VkDescriptorSetLayoutCreateInfo *pCreateInfo,1086VkDescriptorSetLayoutSupport *pSupport)1087{1088V3DV_FROM_HANDLE(v3dv_device, device, _device);1089VkDescriptorSetLayoutBinding *bindings = NULL;1090VkResult result = vk_create_sorted_bindings(1091pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings);1092if (result != VK_SUCCESS) {1093pSupport->supported = false;1094return;1095}10961097bool supported = true;10981099uint32_t desc_host_size = sizeof(struct v3dv_descriptor);1100uint32_t host_size = sizeof(struct v3dv_descriptor_set);1101uint32_t bo_size = 0;1102for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) {1103const VkDescriptorSetLayoutBinding *binding = bindings + i;11041105if ((UINT32_MAX - host_size) / desc_host_size < binding->descriptorCount) {1106supported = false;1107break;1108}11091110uint32_t desc_bo_size = v3dv_X(device, descriptor_bo_size)(binding->descriptorType);1111if (desc_bo_size > 0 &&1112(UINT32_MAX - bo_size) / desc_bo_size < binding->descriptorCount) {1113supported = false;1114break;1115}11161117host_size += binding->descriptorCount * desc_host_size;1118bo_size += binding->descriptorCount * desc_bo_size;1119}11201121free(bindings);11221123pSupport->supported = supported;1124}11251126VkResult1127v3dv_CreateDescriptorUpdateTemplate(1128VkDevice _device,1129const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo,1130const VkAllocationCallbacks *pAllocator,1131VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate)1132{1133V3DV_FROM_HANDLE(v3dv_device, device, _device);1134struct v3dv_descriptor_update_template *template;11351136size_t size = sizeof(*template) +1137pCreateInfo->descriptorUpdateEntryCount * sizeof(template->entries[0]);1138template = vk_object_alloc(&device->vk, pAllocator, size,1139VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE);1140if (template == NULL)1141return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY);11421143template->bind_point = pCreateInfo->pipelineBindPoint;11441145assert(pCreateInfo->templateType ==1146VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET);1147template->set = pCreateInfo->set;11481149template->entry_count = pCreateInfo->descriptorUpdateEntryCount;1150for (uint32_t i = 0; i < template->entry_count; i++) {1151const VkDescriptorUpdateTemplateEntry *pEntry =1152&pCreateInfo->pDescriptorUpdateEntries[i];11531154template->entries[i] = (struct v3dv_descriptor_template_entry) {1155.type = pEntry->descriptorType,1156.binding = pEntry->dstBinding,1157.array_element = pEntry->dstArrayElement,1158.array_count = pEntry->descriptorCount,1159.offset = pEntry->offset,1160.stride = pEntry->stride,1161};1162}11631164*pDescriptorUpdateTemplate =1165v3dv_descriptor_update_template_to_handle(template);11661167return VK_SUCCESS;1168}11691170void1171v3dv_DestroyDescriptorUpdateTemplate(1172VkDevice _device,1173VkDescriptorUpdateTemplate descriptorUpdateTemplate,1174const VkAllocationCallbacks *pAllocator)1175{1176V3DV_FROM_HANDLE(v3dv_device, device, _device);1177V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,1178descriptorUpdateTemplate);11791180if (!template)1181return;11821183vk_object_free(&device->vk, pAllocator, template);1184}11851186void1187v3dv_UpdateDescriptorSetWithTemplate(1188VkDevice _device,1189VkDescriptorSet descriptorSet,1190VkDescriptorUpdateTemplate descriptorUpdateTemplate,1191const void *pData)1192{1193V3DV_FROM_HANDLE(v3dv_device, device, _device);1194V3DV_FROM_HANDLE(v3dv_descriptor_set, set, descriptorSet);1195V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template,1196descriptorUpdateTemplate);11971198for (int i = 0; i < template->entry_count; i++) {1199const struct v3dv_descriptor_template_entry *entry =1200&template->entries[i];12011202const struct v3dv_descriptor_set_binding_layout *binding_layout =1203set->layout->binding + entry->binding;12041205struct v3dv_descriptor *descriptor =1206set->descriptors +1207binding_layout->descriptor_index +1208entry->array_element;12091210switch (entry->type) {1211case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:1212case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:1213case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:1214case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:1215for (uint32_t j = 0; j < entry->array_count; j++) {1216const VkDescriptorBufferInfo *info =1217pData + entry->offset + j * entry->stride;1218write_buffer_descriptor(descriptor + j, entry->type, info);1219}1220break;12211222case VK_DESCRIPTOR_TYPE_SAMPLER:1223case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:1224case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:1225case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:1226case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:1227for (uint32_t j = 0; j < entry->array_count; j++) {1228const VkDescriptorImageInfo *info =1229pData + entry->offset + j * entry->stride;1230V3DV_FROM_HANDLE(v3dv_image_view, iview, info->imageView);1231V3DV_FROM_HANDLE(v3dv_sampler, sampler, info->sampler);1232write_image_descriptor(device, descriptor + j, entry->type,1233set, binding_layout, iview, sampler,1234entry->array_element + j);1235}1236break;12371238case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:1239case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:1240for (uint32_t j = 0; j < entry->array_count; j++) {1241const VkBufferView *_bview =1242pData + entry->offset + j * entry->stride;1243V3DV_FROM_HANDLE(v3dv_buffer_view, bview, *_bview);1244write_buffer_view_descriptor(device, descriptor + j, entry->type,1245set, binding_layout, bview,1246entry->array_element + j);1247}1248break;12491250default:1251unreachable("Unsupported descriptor type");1252}1253}1254}125512561257