1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright © 2019 Raspberry Pi Ltd 3bf215546Sopenharmony_ci * 4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation 7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 10bf215546Sopenharmony_ci * 11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next 12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the 13bf215546Sopenharmony_ci * Software. 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21bf215546Sopenharmony_ci * IN THE SOFTWARE. 22bf215546Sopenharmony_ci */ 23bf215546Sopenharmony_ci 24bf215546Sopenharmony_ci#include "vk_descriptors.h" 25bf215546Sopenharmony_ci#include "vk_util.h" 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci#include "v3dv_private.h" 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/* 30bf215546Sopenharmony_ci * For a given descriptor defined by the descriptor_set it belongs, its 31bf215546Sopenharmony_ci * binding layout, and array_index, it returns the map region assigned to it 32bf215546Sopenharmony_ci * from the descriptor pool bo. 33bf215546Sopenharmony_ci */ 34bf215546Sopenharmony_cistatic void * 35bf215546Sopenharmony_cidescriptor_bo_map(struct v3dv_device *device, 36bf215546Sopenharmony_ci struct v3dv_descriptor_set *set, 37bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout, 38bf215546Sopenharmony_ci uint32_t array_index) 39bf215546Sopenharmony_ci{ 40bf215546Sopenharmony_ci /* Inline uniform blocks use BO memory to store UBO contents, not 41bf215546Sopenharmony_ci * descriptor data, so their descriptor BO size is 0 even though they 42bf215546Sopenharmony_ci * do use BO memory. 43bf215546Sopenharmony_ci */ 44bf215546Sopenharmony_ci uint32_t bo_size = v3dv_X(device, descriptor_bo_size)(binding_layout->type); 45bf215546Sopenharmony_ci assert(bo_size > 0 || 46bf215546Sopenharmony_ci binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK); 47bf215546Sopenharmony_ci 48bf215546Sopenharmony_ci return set->pool->bo->map + 49bf215546Sopenharmony_ci set->base_offset + binding_layout->descriptor_offset + 50bf215546Sopenharmony_ci array_index * bo_size; 51bf215546Sopenharmony_ci} 52bf215546Sopenharmony_ci 53bf215546Sopenharmony_cistatic bool 54bf215546Sopenharmony_cidescriptor_type_is_dynamic(VkDescriptorType type) 55bf215546Sopenharmony_ci{ 56bf215546Sopenharmony_ci switch (type) { 57bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 58bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 59bf215546Sopenharmony_ci return true; 60bf215546Sopenharmony_ci break; 61bf215546Sopenharmony_ci default: 62bf215546Sopenharmony_ci return false; 63bf215546Sopenharmony_ci } 64bf215546Sopenharmony_ci} 65bf215546Sopenharmony_ci 66bf215546Sopenharmony_ci/* 67bf215546Sopenharmony_ci * Tries to get a real descriptor using a descriptor map index from the 68bf215546Sopenharmony_ci * descriptor_state + pipeline_layout. 69bf215546Sopenharmony_ci */ 70bf215546Sopenharmony_cistruct v3dv_descriptor * 71bf215546Sopenharmony_civ3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_state, 72bf215546Sopenharmony_ci struct v3dv_descriptor_map *map, 73bf215546Sopenharmony_ci struct v3dv_pipeline_layout *pipeline_layout, 74bf215546Sopenharmony_ci uint32_t index, 75bf215546Sopenharmony_ci uint32_t *dynamic_offset) 76bf215546Sopenharmony_ci{ 77bf215546Sopenharmony_ci assert(index < map->num_desc); 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci uint32_t set_number = map->set[index]; 80bf215546Sopenharmony_ci assert((descriptor_state->valid & 1 << set_number)); 81bf215546Sopenharmony_ci 82bf215546Sopenharmony_ci struct v3dv_descriptor_set *set = 83bf215546Sopenharmony_ci descriptor_state->descriptor_sets[set_number]; 84bf215546Sopenharmony_ci assert(set); 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci uint32_t binding_number = map->binding[index]; 87bf215546Sopenharmony_ci assert(binding_number < set->layout->binding_count); 88bf215546Sopenharmony_ci 89bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout = 90bf215546Sopenharmony_ci &set->layout->binding[binding_number]; 91bf215546Sopenharmony_ci 92bf215546Sopenharmony_ci uint32_t array_index = map->array_index[index]; 93bf215546Sopenharmony_ci assert(array_index < binding_layout->array_size); 94bf215546Sopenharmony_ci 95bf215546Sopenharmony_ci if (descriptor_type_is_dynamic(binding_layout->type)) { 96bf215546Sopenharmony_ci uint32_t dynamic_offset_index = 97bf215546Sopenharmony_ci pipeline_layout->set[set_number].dynamic_offset_start + 98bf215546Sopenharmony_ci binding_layout->dynamic_offset_index + array_index; 99bf215546Sopenharmony_ci 100bf215546Sopenharmony_ci *dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index]; 101bf215546Sopenharmony_ci } 102bf215546Sopenharmony_ci 103bf215546Sopenharmony_ci return &set->descriptors[binding_layout->descriptor_index + array_index]; 104bf215546Sopenharmony_ci} 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_ci/* Equivalent to map_get_descriptor but it returns a reloc with the bo 107bf215546Sopenharmony_ci * associated with that descriptor (suballocation of the descriptor pool bo) 108bf215546Sopenharmony_ci * 109bf215546Sopenharmony_ci * It also returns the descriptor type, so the caller could do extra 110bf215546Sopenharmony_ci * validation or adding extra offsets if the bo contains more that one field. 111bf215546Sopenharmony_ci */ 112bf215546Sopenharmony_cistruct v3dv_cl_reloc 113bf215546Sopenharmony_civ3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device, 114bf215546Sopenharmony_ci struct v3dv_descriptor_state *descriptor_state, 115bf215546Sopenharmony_ci struct v3dv_descriptor_map *map, 116bf215546Sopenharmony_ci struct v3dv_pipeline_layout *pipeline_layout, 117bf215546Sopenharmony_ci uint32_t index, 118bf215546Sopenharmony_ci VkDescriptorType *out_type) 119bf215546Sopenharmony_ci{ 120bf215546Sopenharmony_ci assert(index < map->num_desc); 121bf215546Sopenharmony_ci 122bf215546Sopenharmony_ci uint32_t set_number = map->set[index]; 123bf215546Sopenharmony_ci assert(descriptor_state->valid & 1 << set_number); 124bf215546Sopenharmony_ci 125bf215546Sopenharmony_ci struct v3dv_descriptor_set *set = 126bf215546Sopenharmony_ci descriptor_state->descriptor_sets[set_number]; 127bf215546Sopenharmony_ci assert(set); 128bf215546Sopenharmony_ci 129bf215546Sopenharmony_ci uint32_t binding_number = map->binding[index]; 130bf215546Sopenharmony_ci assert(binding_number < set->layout->binding_count); 131bf215546Sopenharmony_ci 132bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout = 133bf215546Sopenharmony_ci &set->layout->binding[binding_number]; 134bf215546Sopenharmony_ci 135bf215546Sopenharmony_ci assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK || 136bf215546Sopenharmony_ci v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0); 137bf215546Sopenharmony_ci if (out_type) 138bf215546Sopenharmony_ci *out_type = binding_layout->type; 139bf215546Sopenharmony_ci 140bf215546Sopenharmony_ci uint32_t array_index = map->array_index[index]; 141bf215546Sopenharmony_ci assert(array_index < binding_layout->array_size); 142bf215546Sopenharmony_ci 143bf215546Sopenharmony_ci struct v3dv_cl_reloc reloc = { 144bf215546Sopenharmony_ci .bo = set->pool->bo, 145bf215546Sopenharmony_ci .offset = set->base_offset + binding_layout->descriptor_offset + 146bf215546Sopenharmony_ci array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type), 147bf215546Sopenharmony_ci }; 148bf215546Sopenharmony_ci 149bf215546Sopenharmony_ci return reloc; 150bf215546Sopenharmony_ci} 151bf215546Sopenharmony_ci 152bf215546Sopenharmony_ci/* 153bf215546Sopenharmony_ci * The difference between this method and v3dv_descriptor_map_get_descriptor, 154bf215546Sopenharmony_ci * is that if the sampler are added as immutable when creating the set layout, 155bf215546Sopenharmony_ci * they are bound to the set layout, so not part of the descriptor per 156bf215546Sopenharmony_ci * se. This method return early in that case. 157bf215546Sopenharmony_ci */ 158bf215546Sopenharmony_ciconst struct v3dv_sampler * 159bf215546Sopenharmony_civ3dv_descriptor_map_get_sampler(struct v3dv_descriptor_state *descriptor_state, 160bf215546Sopenharmony_ci struct v3dv_descriptor_map *map, 161bf215546Sopenharmony_ci struct v3dv_pipeline_layout *pipeline_layout, 162bf215546Sopenharmony_ci uint32_t index) 163bf215546Sopenharmony_ci{ 164bf215546Sopenharmony_ci assert(index < map->num_desc); 165bf215546Sopenharmony_ci 166bf215546Sopenharmony_ci uint32_t set_number = map->set[index]; 167bf215546Sopenharmony_ci assert(descriptor_state->valid & 1 << set_number); 168bf215546Sopenharmony_ci 169bf215546Sopenharmony_ci struct v3dv_descriptor_set *set = 170bf215546Sopenharmony_ci descriptor_state->descriptor_sets[set_number]; 171bf215546Sopenharmony_ci assert(set); 172bf215546Sopenharmony_ci 173bf215546Sopenharmony_ci uint32_t binding_number = map->binding[index]; 174bf215546Sopenharmony_ci assert(binding_number < set->layout->binding_count); 175bf215546Sopenharmony_ci 176bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout = 177bf215546Sopenharmony_ci &set->layout->binding[binding_number]; 178bf215546Sopenharmony_ci 179bf215546Sopenharmony_ci uint32_t array_index = map->array_index[index]; 180bf215546Sopenharmony_ci assert(array_index < binding_layout->array_size); 181bf215546Sopenharmony_ci 182bf215546Sopenharmony_ci if (binding_layout->immutable_samplers_offset != 0) { 183bf215546Sopenharmony_ci assert(binding_layout->type == VK_DESCRIPTOR_TYPE_SAMPLER || 184bf215546Sopenharmony_ci binding_layout->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 185bf215546Sopenharmony_ci 186bf215546Sopenharmony_ci const struct v3dv_sampler *immutable_samplers = 187bf215546Sopenharmony_ci v3dv_immutable_samplers(set->layout, binding_layout); 188bf215546Sopenharmony_ci 189bf215546Sopenharmony_ci assert(immutable_samplers); 190bf215546Sopenharmony_ci const struct v3dv_sampler *sampler = &immutable_samplers[array_index]; 191bf215546Sopenharmony_ci assert(sampler); 192bf215546Sopenharmony_ci 193bf215546Sopenharmony_ci return sampler; 194bf215546Sopenharmony_ci } 195bf215546Sopenharmony_ci 196bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor = 197bf215546Sopenharmony_ci &set->descriptors[binding_layout->descriptor_index + array_index]; 198bf215546Sopenharmony_ci 199bf215546Sopenharmony_ci assert(descriptor->type == VK_DESCRIPTOR_TYPE_SAMPLER || 200bf215546Sopenharmony_ci descriptor->type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 201bf215546Sopenharmony_ci 202bf215546Sopenharmony_ci assert(descriptor->sampler); 203bf215546Sopenharmony_ci 204bf215546Sopenharmony_ci return descriptor->sampler; 205bf215546Sopenharmony_ci} 206bf215546Sopenharmony_ci 207bf215546Sopenharmony_ci 208bf215546Sopenharmony_cistruct v3dv_cl_reloc 209bf215546Sopenharmony_civ3dv_descriptor_map_get_sampler_state(struct v3dv_device *device, 210bf215546Sopenharmony_ci struct v3dv_descriptor_state *descriptor_state, 211bf215546Sopenharmony_ci struct v3dv_descriptor_map *map, 212bf215546Sopenharmony_ci struct v3dv_pipeline_layout *pipeline_layout, 213bf215546Sopenharmony_ci uint32_t index) 214bf215546Sopenharmony_ci{ 215bf215546Sopenharmony_ci VkDescriptorType type; 216bf215546Sopenharmony_ci struct v3dv_cl_reloc reloc = 217bf215546Sopenharmony_ci v3dv_descriptor_map_get_descriptor_bo(device, descriptor_state, map, 218bf215546Sopenharmony_ci pipeline_layout, 219bf215546Sopenharmony_ci index, &type); 220bf215546Sopenharmony_ci 221bf215546Sopenharmony_ci assert(type == VK_DESCRIPTOR_TYPE_SAMPLER || 222bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 223bf215546Sopenharmony_ci 224bf215546Sopenharmony_ci if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 225bf215546Sopenharmony_ci reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)(); 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci return reloc; 228bf215546Sopenharmony_ci} 229bf215546Sopenharmony_ci 230bf215546Sopenharmony_cistruct v3dv_bo* 231bf215546Sopenharmony_civ3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state, 232bf215546Sopenharmony_ci struct v3dv_descriptor_map *map, 233bf215546Sopenharmony_ci struct v3dv_pipeline_layout *pipeline_layout, 234bf215546Sopenharmony_ci uint32_t index) 235bf215546Sopenharmony_ci 236bf215546Sopenharmony_ci{ 237bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor = 238bf215546Sopenharmony_ci v3dv_descriptor_map_get_descriptor(descriptor_state, map, 239bf215546Sopenharmony_ci pipeline_layout, index, NULL); 240bf215546Sopenharmony_ci 241bf215546Sopenharmony_ci switch (descriptor->type) { 242bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 243bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 244bf215546Sopenharmony_ci assert(descriptor->buffer_view); 245bf215546Sopenharmony_ci return descriptor->buffer_view->buffer->mem->bo; 246bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 247bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 248bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 249bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: { 250bf215546Sopenharmony_ci assert(descriptor->image_view); 251bf215546Sopenharmony_ci struct v3dv_image *image = 252bf215546Sopenharmony_ci (struct v3dv_image *) descriptor->image_view->vk.image; 253bf215546Sopenharmony_ci return image->mem->bo; 254bf215546Sopenharmony_ci } 255bf215546Sopenharmony_ci default: 256bf215546Sopenharmony_ci unreachable("descriptor type doesn't has a texture bo"); 257bf215546Sopenharmony_ci } 258bf215546Sopenharmony_ci} 259bf215546Sopenharmony_ci 260bf215546Sopenharmony_cistruct v3dv_cl_reloc 261bf215546Sopenharmony_civ3dv_descriptor_map_get_texture_shader_state(struct v3dv_device *device, 262bf215546Sopenharmony_ci struct v3dv_descriptor_state *descriptor_state, 263bf215546Sopenharmony_ci struct v3dv_descriptor_map *map, 264bf215546Sopenharmony_ci struct v3dv_pipeline_layout *pipeline_layout, 265bf215546Sopenharmony_ci uint32_t index) 266bf215546Sopenharmony_ci{ 267bf215546Sopenharmony_ci VkDescriptorType type; 268bf215546Sopenharmony_ci struct v3dv_cl_reloc reloc = 269bf215546Sopenharmony_ci v3dv_descriptor_map_get_descriptor_bo(device, 270bf215546Sopenharmony_ci descriptor_state, map, 271bf215546Sopenharmony_ci pipeline_layout, 272bf215546Sopenharmony_ci index, &type); 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci assert(type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE || 275bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 276bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT || 277bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE || 278bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER || 279bf215546Sopenharmony_ci type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); 280bf215546Sopenharmony_ci 281bf215546Sopenharmony_ci if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) 282bf215546Sopenharmony_ci reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)(); 283bf215546Sopenharmony_ci 284bf215546Sopenharmony_ci return reloc; 285bf215546Sopenharmony_ci} 286bf215546Sopenharmony_ci 287bf215546Sopenharmony_ci#define SHA1_UPDATE_VALUE(ctx, x) _mesa_sha1_update(ctx, &(x), sizeof(x)); 288bf215546Sopenharmony_ci 289bf215546Sopenharmony_cistatic void 290bf215546Sopenharmony_cisha1_update_descriptor_set_binding_layout(struct mesa_sha1 *ctx, 291bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *layout) 292bf215546Sopenharmony_ci{ 293bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->type); 294bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->array_size); 295bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->descriptor_index); 296bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count); 297bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_index); 298bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->descriptor_offset); 299bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->immutable_samplers_offset); 300bf215546Sopenharmony_ci} 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_cistatic void 303bf215546Sopenharmony_cisha1_update_descriptor_set_layout(struct mesa_sha1 *ctx, 304bf215546Sopenharmony_ci const struct v3dv_descriptor_set_layout *layout) 305bf215546Sopenharmony_ci{ 306bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->flags); 307bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->binding_count); 308bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->shader_stages); 309bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->descriptor_count); 310bf215546Sopenharmony_ci SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count); 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci for (uint16_t i = 0; i < layout->binding_count; i++) 313bf215546Sopenharmony_ci sha1_update_descriptor_set_binding_layout(ctx, &layout->binding[i]); 314bf215546Sopenharmony_ci} 315bf215546Sopenharmony_ci 316bf215546Sopenharmony_ci 317bf215546Sopenharmony_ci/* 318bf215546Sopenharmony_ci * As anv and tu already points: 319bf215546Sopenharmony_ci * 320bf215546Sopenharmony_ci * "Pipeline layouts. These have nothing to do with the pipeline. They are 321bf215546Sopenharmony_ci * just multiple descriptor set layouts pasted together." 322bf215546Sopenharmony_ci */ 323bf215546Sopenharmony_ci 324bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 325bf215546Sopenharmony_civ3dv_CreatePipelineLayout(VkDevice _device, 326bf215546Sopenharmony_ci const VkPipelineLayoutCreateInfo *pCreateInfo, 327bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 328bf215546Sopenharmony_ci VkPipelineLayout *pPipelineLayout) 329bf215546Sopenharmony_ci{ 330bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 331bf215546Sopenharmony_ci struct v3dv_pipeline_layout *layout; 332bf215546Sopenharmony_ci 333bf215546Sopenharmony_ci assert(pCreateInfo->sType == 334bf215546Sopenharmony_ci VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO); 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout), 337bf215546Sopenharmony_ci VK_OBJECT_TYPE_PIPELINE_LAYOUT); 338bf215546Sopenharmony_ci if (layout == NULL) 339bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 340bf215546Sopenharmony_ci 341bf215546Sopenharmony_ci layout->num_sets = pCreateInfo->setLayoutCount; 342bf215546Sopenharmony_ci 343bf215546Sopenharmony_ci uint32_t dynamic_offset_count = 0; 344bf215546Sopenharmony_ci for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) { 345bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, 346bf215546Sopenharmony_ci pCreateInfo->pSetLayouts[set]); 347bf215546Sopenharmony_ci v3dv_descriptor_set_layout_ref(set_layout); 348bf215546Sopenharmony_ci layout->set[set].layout = set_layout; 349bf215546Sopenharmony_ci layout->set[set].dynamic_offset_start = dynamic_offset_count; 350bf215546Sopenharmony_ci for (uint32_t b = 0; b < set_layout->binding_count; b++) { 351bf215546Sopenharmony_ci dynamic_offset_count += set_layout->binding[b].array_size * 352bf215546Sopenharmony_ci set_layout->binding[b].dynamic_offset_count; 353bf215546Sopenharmony_ci } 354bf215546Sopenharmony_ci 355bf215546Sopenharmony_ci layout->shader_stages |= set_layout->shader_stages; 356bf215546Sopenharmony_ci } 357bf215546Sopenharmony_ci 358bf215546Sopenharmony_ci layout->push_constant_size = 0; 359bf215546Sopenharmony_ci for (unsigned i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) { 360bf215546Sopenharmony_ci const VkPushConstantRange *range = pCreateInfo->pPushConstantRanges + i; 361bf215546Sopenharmony_ci layout->push_constant_size = 362bf215546Sopenharmony_ci MAX2(layout->push_constant_size, range->offset + range->size); 363bf215546Sopenharmony_ci } 364bf215546Sopenharmony_ci 365bf215546Sopenharmony_ci layout->push_constant_size = align(layout->push_constant_size, 4096); 366bf215546Sopenharmony_ci 367bf215546Sopenharmony_ci layout->dynamic_offset_count = dynamic_offset_count; 368bf215546Sopenharmony_ci 369bf215546Sopenharmony_ci struct mesa_sha1 ctx; 370bf215546Sopenharmony_ci _mesa_sha1_init(&ctx); 371bf215546Sopenharmony_ci for (unsigned s = 0; s < layout->num_sets; s++) { 372bf215546Sopenharmony_ci sha1_update_descriptor_set_layout(&ctx, layout->set[s].layout); 373bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, &layout->set[s].dynamic_offset_start, 374bf215546Sopenharmony_ci sizeof(layout->set[s].dynamic_offset_start)); 375bf215546Sopenharmony_ci } 376bf215546Sopenharmony_ci _mesa_sha1_update(&ctx, &layout->num_sets, sizeof(layout->num_sets)); 377bf215546Sopenharmony_ci _mesa_sha1_final(&ctx, layout->sha1); 378bf215546Sopenharmony_ci 379bf215546Sopenharmony_ci *pPipelineLayout = v3dv_pipeline_layout_to_handle(layout); 380bf215546Sopenharmony_ci 381bf215546Sopenharmony_ci return VK_SUCCESS; 382bf215546Sopenharmony_ci} 383bf215546Sopenharmony_ci 384bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 385bf215546Sopenharmony_civ3dv_DestroyPipelineLayout(VkDevice _device, 386bf215546Sopenharmony_ci VkPipelineLayout _pipelineLayout, 387bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 388bf215546Sopenharmony_ci{ 389bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 390bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_pipeline_layout, pipeline_layout, _pipelineLayout); 391bf215546Sopenharmony_ci 392bf215546Sopenharmony_ci if (!pipeline_layout) 393bf215546Sopenharmony_ci return; 394bf215546Sopenharmony_ci 395bf215546Sopenharmony_ci for (uint32_t i = 0; i < pipeline_layout->num_sets; i++) 396bf215546Sopenharmony_ci v3dv_descriptor_set_layout_unref(device, pipeline_layout->set[i].layout); 397bf215546Sopenharmony_ci 398bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pipeline_layout); 399bf215546Sopenharmony_ci} 400bf215546Sopenharmony_ci 401bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 402bf215546Sopenharmony_civ3dv_CreateDescriptorPool(VkDevice _device, 403bf215546Sopenharmony_ci const VkDescriptorPoolCreateInfo *pCreateInfo, 404bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 405bf215546Sopenharmony_ci VkDescriptorPool *pDescriptorPool) 406bf215546Sopenharmony_ci{ 407bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 408bf215546Sopenharmony_ci struct v3dv_descriptor_pool *pool; 409bf215546Sopenharmony_ci /* size is for the vulkan object descriptor pool. The final size would 410bf215546Sopenharmony_ci * depend on some of FREE_DESCRIPTOR flags used 411bf215546Sopenharmony_ci */ 412bf215546Sopenharmony_ci uint64_t size = sizeof(struct v3dv_descriptor_pool); 413bf215546Sopenharmony_ci /* bo_size is for the descriptor related info that we need to have on a GPU 414bf215546Sopenharmony_ci * address (so on v3dv_bo_alloc allocated memory), like for example the 415bf215546Sopenharmony_ci * texture sampler state. Note that not all the descriptors use it 416bf215546Sopenharmony_ci */ 417bf215546Sopenharmony_ci uint32_t bo_size = 0; 418bf215546Sopenharmony_ci uint32_t descriptor_count = 0; 419bf215546Sopenharmony_ci 420bf215546Sopenharmony_ci const VkDescriptorPoolInlineUniformBlockCreateInfo *inline_info = 421bf215546Sopenharmony_ci vk_find_struct_const(pCreateInfo->pNext, 422bf215546Sopenharmony_ci DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO); 423bf215546Sopenharmony_ci 424bf215546Sopenharmony_ci for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) { 425bf215546Sopenharmony_ci /* Verify supported descriptor type */ 426bf215546Sopenharmony_ci switch(pCreateInfo->pPoolSizes[i].type) { 427bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 428bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 429bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 430bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 431bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: 432bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 433bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 434bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 435bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 436bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 437bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 438bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: 439bf215546Sopenharmony_ci break; 440bf215546Sopenharmony_ci default: 441bf215546Sopenharmony_ci unreachable("Unimplemented descriptor type"); 442bf215546Sopenharmony_ci break; 443bf215546Sopenharmony_ci } 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci assert(pCreateInfo->pPoolSizes[i].descriptorCount > 0); 446bf215546Sopenharmony_ci if (pCreateInfo->pPoolSizes[i].type == 447bf215546Sopenharmony_ci VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { 448bf215546Sopenharmony_ci /* Inline uniform blocks are specified to use the descriptor array 449bf215546Sopenharmony_ci * size as the size in bytes of the block. 450bf215546Sopenharmony_ci */ 451bf215546Sopenharmony_ci assert(inline_info); 452bf215546Sopenharmony_ci descriptor_count += inline_info->maxInlineUniformBlockBindings; 453bf215546Sopenharmony_ci bo_size += pCreateInfo->pPoolSizes[i].descriptorCount; 454bf215546Sopenharmony_ci } else { 455bf215546Sopenharmony_ci descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount; 456bf215546Sopenharmony_ci bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) * 457bf215546Sopenharmony_ci pCreateInfo->pPoolSizes[i].descriptorCount; 458bf215546Sopenharmony_ci } 459bf215546Sopenharmony_ci } 460bf215546Sopenharmony_ci 461bf215546Sopenharmony_ci /* We align all our buffers to V3D_NON_COHERENT_ATOM_SIZE, make sure we 462bf215546Sopenharmony_ci * allocate enough memory to honor that requirement for all our inline 463bf215546Sopenharmony_ci * buffers too. 464bf215546Sopenharmony_ci */ 465bf215546Sopenharmony_ci if (inline_info) { 466bf215546Sopenharmony_ci bo_size += V3D_NON_COHERENT_ATOM_SIZE * 467bf215546Sopenharmony_ci inline_info->maxInlineUniformBlockBindings; 468bf215546Sopenharmony_ci } 469bf215546Sopenharmony_ci 470bf215546Sopenharmony_ci if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { 471bf215546Sopenharmony_ci uint64_t host_size = 472bf215546Sopenharmony_ci pCreateInfo->maxSets * sizeof(struct v3dv_descriptor_set); 473bf215546Sopenharmony_ci host_size += sizeof(struct v3dv_descriptor) * descriptor_count; 474bf215546Sopenharmony_ci size += host_size; 475bf215546Sopenharmony_ci } else { 476bf215546Sopenharmony_ci size += sizeof(struct v3dv_descriptor_pool_entry) * pCreateInfo->maxSets; 477bf215546Sopenharmony_ci } 478bf215546Sopenharmony_ci 479bf215546Sopenharmony_ci pool = vk_object_zalloc(&device->vk, pAllocator, size, 480bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_POOL); 481bf215546Sopenharmony_ci 482bf215546Sopenharmony_ci if (!pool) 483bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 484bf215546Sopenharmony_ci 485bf215546Sopenharmony_ci if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { 486bf215546Sopenharmony_ci pool->host_memory_base = (uint8_t*)pool + sizeof(struct v3dv_descriptor_pool); 487bf215546Sopenharmony_ci pool->host_memory_ptr = pool->host_memory_base; 488bf215546Sopenharmony_ci pool->host_memory_end = (uint8_t*)pool + size; 489bf215546Sopenharmony_ci } 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci pool->max_entry_count = pCreateInfo->maxSets; 492bf215546Sopenharmony_ci 493bf215546Sopenharmony_ci if (bo_size > 0) { 494bf215546Sopenharmony_ci pool->bo = v3dv_bo_alloc(device, bo_size, "descriptor pool bo", true); 495bf215546Sopenharmony_ci if (!pool->bo) 496bf215546Sopenharmony_ci goto out_of_device_memory; 497bf215546Sopenharmony_ci 498bf215546Sopenharmony_ci bool ok = v3dv_bo_map(device, pool->bo, pool->bo->size); 499bf215546Sopenharmony_ci if (!ok) 500bf215546Sopenharmony_ci goto out_of_device_memory; 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci pool->current_offset = 0; 503bf215546Sopenharmony_ci } else { 504bf215546Sopenharmony_ci pool->bo = NULL; 505bf215546Sopenharmony_ci } 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci list_inithead(&pool->set_list); 508bf215546Sopenharmony_ci 509bf215546Sopenharmony_ci *pDescriptorPool = v3dv_descriptor_pool_to_handle(pool); 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci return VK_SUCCESS; 512bf215546Sopenharmony_ci 513bf215546Sopenharmony_ci out_of_device_memory: 514bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pool); 515bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY); 516bf215546Sopenharmony_ci} 517bf215546Sopenharmony_ci 518bf215546Sopenharmony_cistatic void 519bf215546Sopenharmony_cidescriptor_set_destroy(struct v3dv_device *device, 520bf215546Sopenharmony_ci struct v3dv_descriptor_pool *pool, 521bf215546Sopenharmony_ci struct v3dv_descriptor_set *set, 522bf215546Sopenharmony_ci bool free_bo) 523bf215546Sopenharmony_ci{ 524bf215546Sopenharmony_ci assert(!pool->host_memory_base); 525bf215546Sopenharmony_ci 526bf215546Sopenharmony_ci if (free_bo && !pool->host_memory_base) { 527bf215546Sopenharmony_ci for (uint32_t i = 0; i < pool->entry_count; i++) { 528bf215546Sopenharmony_ci if (pool->entries[i].set == set) { 529bf215546Sopenharmony_ci memmove(&pool->entries[i], &pool->entries[i+1], 530bf215546Sopenharmony_ci sizeof(pool->entries[i]) * (pool->entry_count - i - 1)); 531bf215546Sopenharmony_ci --pool->entry_count; 532bf215546Sopenharmony_ci break; 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci } 535bf215546Sopenharmony_ci } 536bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, set); 537bf215546Sopenharmony_ci} 538bf215546Sopenharmony_ci 539bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 540bf215546Sopenharmony_civ3dv_DestroyDescriptorPool(VkDevice _device, 541bf215546Sopenharmony_ci VkDescriptorPool _pool, 542bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 543bf215546Sopenharmony_ci{ 544bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 545bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, _pool); 546bf215546Sopenharmony_ci 547bf215546Sopenharmony_ci if (!pool) 548bf215546Sopenharmony_ci return; 549bf215546Sopenharmony_ci 550bf215546Sopenharmony_ci list_for_each_entry_safe(struct v3dv_descriptor_set, set, 551bf215546Sopenharmony_ci &pool->set_list, pool_link) { 552bf215546Sopenharmony_ci v3dv_descriptor_set_layout_unref(device, set->layout); 553bf215546Sopenharmony_ci } 554bf215546Sopenharmony_ci 555bf215546Sopenharmony_ci if (!pool->host_memory_base) { 556bf215546Sopenharmony_ci for(int i = 0; i < pool->entry_count; ++i) { 557bf215546Sopenharmony_ci descriptor_set_destroy(device, pool, pool->entries[i].set, false); 558bf215546Sopenharmony_ci } 559bf215546Sopenharmony_ci } 560bf215546Sopenharmony_ci 561bf215546Sopenharmony_ci if (pool->bo) { 562bf215546Sopenharmony_ci v3dv_bo_free(device, pool->bo); 563bf215546Sopenharmony_ci pool->bo = NULL; 564bf215546Sopenharmony_ci } 565bf215546Sopenharmony_ci 566bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, pool); 567bf215546Sopenharmony_ci} 568bf215546Sopenharmony_ci 569bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 570bf215546Sopenharmony_civ3dv_ResetDescriptorPool(VkDevice _device, 571bf215546Sopenharmony_ci VkDescriptorPool descriptorPool, 572bf215546Sopenharmony_ci VkDescriptorPoolResetFlags flags) 573bf215546Sopenharmony_ci{ 574bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 575bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool); 576bf215546Sopenharmony_ci 577bf215546Sopenharmony_ci list_for_each_entry_safe(struct v3dv_descriptor_set, set, 578bf215546Sopenharmony_ci &pool->set_list, pool_link) { 579bf215546Sopenharmony_ci v3dv_descriptor_set_layout_unref(device, set->layout); 580bf215546Sopenharmony_ci } 581bf215546Sopenharmony_ci list_inithead(&pool->set_list); 582bf215546Sopenharmony_ci 583bf215546Sopenharmony_ci if (!pool->host_memory_base) { 584bf215546Sopenharmony_ci for(int i = 0; i < pool->entry_count; ++i) { 585bf215546Sopenharmony_ci descriptor_set_destroy(device, pool, pool->entries[i].set, false); 586bf215546Sopenharmony_ci } 587bf215546Sopenharmony_ci } else { 588bf215546Sopenharmony_ci /* We clean-up the host memory, so when allocating a new set from the 589bf215546Sopenharmony_ci * pool, it is already 0 590bf215546Sopenharmony_ci */ 591bf215546Sopenharmony_ci uint32_t host_size = pool->host_memory_end - pool->host_memory_base; 592bf215546Sopenharmony_ci memset(pool->host_memory_base, 0, host_size); 593bf215546Sopenharmony_ci } 594bf215546Sopenharmony_ci 595bf215546Sopenharmony_ci pool->entry_count = 0; 596bf215546Sopenharmony_ci pool->host_memory_ptr = pool->host_memory_base; 597bf215546Sopenharmony_ci pool->current_offset = 0; 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci return VK_SUCCESS; 600bf215546Sopenharmony_ci} 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_civoid 603bf215546Sopenharmony_civ3dv_descriptor_set_layout_destroy(struct v3dv_device *device, 604bf215546Sopenharmony_ci struct v3dv_descriptor_set_layout *set_layout) 605bf215546Sopenharmony_ci{ 606bf215546Sopenharmony_ci assert(set_layout->ref_cnt == 0); 607bf215546Sopenharmony_ci vk_object_base_finish(&set_layout->base); 608bf215546Sopenharmony_ci vk_free2(&device->vk.alloc, NULL, set_layout); 609bf215546Sopenharmony_ci} 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 612bf215546Sopenharmony_civ3dv_CreateDescriptorSetLayout(VkDevice _device, 613bf215546Sopenharmony_ci const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 614bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 615bf215546Sopenharmony_ci VkDescriptorSetLayout *pSetLayout) 616bf215546Sopenharmony_ci{ 617bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 618bf215546Sopenharmony_ci struct v3dv_descriptor_set_layout *set_layout; 619bf215546Sopenharmony_ci 620bf215546Sopenharmony_ci assert(pCreateInfo->sType == VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO); 621bf215546Sopenharmony_ci 622bf215546Sopenharmony_ci uint32_t num_bindings = 0; 623bf215546Sopenharmony_ci uint32_t immutable_sampler_count = 0; 624bf215546Sopenharmony_ci for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) { 625bf215546Sopenharmony_ci num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1); 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci /* From the Vulkan 1.1.97 spec for VkDescriptorSetLayoutBinding: 628bf215546Sopenharmony_ci * 629bf215546Sopenharmony_ci * "If descriptorType specifies a VK_DESCRIPTOR_TYPE_SAMPLER or 630bf215546Sopenharmony_ci * VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER type descriptor, then 631bf215546Sopenharmony_ci * pImmutableSamplers can be used to initialize a set of immutable 632bf215546Sopenharmony_ci * samplers. [...] If descriptorType is not one of these descriptor 633bf215546Sopenharmony_ci * types, then pImmutableSamplers is ignored. 634bf215546Sopenharmony_ci * 635bf215546Sopenharmony_ci * We need to be careful here and only parse pImmutableSamplers if we 636bf215546Sopenharmony_ci * have one of the right descriptor types. 637bf215546Sopenharmony_ci */ 638bf215546Sopenharmony_ci VkDescriptorType desc_type = pCreateInfo->pBindings[j].descriptorType; 639bf215546Sopenharmony_ci if ((desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 640bf215546Sopenharmony_ci desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) && 641bf215546Sopenharmony_ci pCreateInfo->pBindings[j].pImmutableSamplers) { 642bf215546Sopenharmony_ci immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount; 643bf215546Sopenharmony_ci } 644bf215546Sopenharmony_ci } 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_ci /* We place immutable samplers after the binding data. We want to use 647bf215546Sopenharmony_ci * offsetof instead of any sizeof(struct v3dv_descriptor_set_layout) 648bf215546Sopenharmony_ci * because the latter may include padding at the end of the struct. 649bf215546Sopenharmony_ci */ 650bf215546Sopenharmony_ci uint32_t samplers_offset = 651bf215546Sopenharmony_ci offsetof(struct v3dv_descriptor_set_layout, binding[num_bindings]); 652bf215546Sopenharmony_ci 653bf215546Sopenharmony_ci uint32_t size = samplers_offset + 654bf215546Sopenharmony_ci immutable_sampler_count * sizeof(struct v3dv_sampler); 655bf215546Sopenharmony_ci 656bf215546Sopenharmony_ci /* Descriptor set layouts are reference counted and therefore can survive 657bf215546Sopenharmony_ci * vkDestroyPipelineSetLayout, so they need to be allocated with a device 658bf215546Sopenharmony_ci * scope. 659bf215546Sopenharmony_ci */ 660bf215546Sopenharmony_ci set_layout = 661bf215546Sopenharmony_ci vk_zalloc(&device->vk.alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); 662bf215546Sopenharmony_ci if (!set_layout) 663bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 664bf215546Sopenharmony_ci 665bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &set_layout->base, 666bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings]; 669bf215546Sopenharmony_ci 670bf215546Sopenharmony_ci assert(pCreateInfo->bindingCount == 0 || num_bindings > 0); 671bf215546Sopenharmony_ci 672bf215546Sopenharmony_ci VkDescriptorSetLayoutBinding *bindings = NULL; 673bf215546Sopenharmony_ci VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings, 674bf215546Sopenharmony_ci pCreateInfo->bindingCount, &bindings); 675bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 676bf215546Sopenharmony_ci v3dv_descriptor_set_layout_destroy(device, set_layout); 677bf215546Sopenharmony_ci return vk_error(device, result); 678bf215546Sopenharmony_ci } 679bf215546Sopenharmony_ci 680bf215546Sopenharmony_ci set_layout->binding_count = num_bindings; 681bf215546Sopenharmony_ci set_layout->flags = pCreateInfo->flags; 682bf215546Sopenharmony_ci set_layout->shader_stages = 0; 683bf215546Sopenharmony_ci set_layout->bo_size = 0; 684bf215546Sopenharmony_ci set_layout->ref_cnt = 1; 685bf215546Sopenharmony_ci 686bf215546Sopenharmony_ci uint32_t descriptor_count = 0; 687bf215546Sopenharmony_ci uint32_t dynamic_offset_count = 0; 688bf215546Sopenharmony_ci 689bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { 690bf215546Sopenharmony_ci const VkDescriptorSetLayoutBinding *binding = bindings + i; 691bf215546Sopenharmony_ci uint32_t binding_number = binding->binding; 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci switch (binding->descriptorType) { 694bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 695bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 696bf215546Sopenharmony_ci break; 697bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 698bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 699bf215546Sopenharmony_ci set_layout->binding[binding_number].dynamic_offset_count = 1; 700bf215546Sopenharmony_ci break; 701bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: 702bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 703bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 704bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 705bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 706bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 707bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 708bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: 709bf215546Sopenharmony_ci /* Nothing here, just to keep the descriptor type filtering below */ 710bf215546Sopenharmony_ci break; 711bf215546Sopenharmony_ci default: 712bf215546Sopenharmony_ci unreachable("Unknown descriptor type\n"); 713bf215546Sopenharmony_ci break; 714bf215546Sopenharmony_ci } 715bf215546Sopenharmony_ci 716bf215546Sopenharmony_ci set_layout->binding[binding_number].type = binding->descriptorType; 717bf215546Sopenharmony_ci set_layout->binding[binding_number].array_size = binding->descriptorCount; 718bf215546Sopenharmony_ci set_layout->binding[binding_number].descriptor_index = descriptor_count; 719bf215546Sopenharmony_ci set_layout->binding[binding_number].dynamic_offset_index = dynamic_offset_count; 720bf215546Sopenharmony_ci 721bf215546Sopenharmony_ci if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || 722bf215546Sopenharmony_ci binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) && 723bf215546Sopenharmony_ci binding->pImmutableSamplers) { 724bf215546Sopenharmony_ci 725bf215546Sopenharmony_ci set_layout->binding[binding_number].immutable_samplers_offset = samplers_offset; 726bf215546Sopenharmony_ci 727bf215546Sopenharmony_ci for (uint32_t i = 0; i < binding->descriptorCount; i++) 728bf215546Sopenharmony_ci samplers[i] = *v3dv_sampler_from_handle(binding->pImmutableSamplers[i]); 729bf215546Sopenharmony_ci 730bf215546Sopenharmony_ci samplers += binding->descriptorCount; 731bf215546Sopenharmony_ci samplers_offset += sizeof(struct v3dv_sampler) * binding->descriptorCount; 732bf215546Sopenharmony_ci } 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci set_layout->shader_stages |= binding->stageFlags; 735bf215546Sopenharmony_ci 736bf215546Sopenharmony_ci if (binding->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { 737bf215546Sopenharmony_ci dynamic_offset_count += binding->descriptorCount * 738bf215546Sopenharmony_ci set_layout->binding[binding_number].dynamic_offset_count; 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci descriptor_count += binding->descriptorCount; 741bf215546Sopenharmony_ci 742bf215546Sopenharmony_ci set_layout->binding[binding_number].descriptor_offset = 743bf215546Sopenharmony_ci set_layout->bo_size; 744bf215546Sopenharmony_ci set_layout->bo_size += 745bf215546Sopenharmony_ci v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) * 746bf215546Sopenharmony_ci binding->descriptorCount; 747bf215546Sopenharmony_ci } else { 748bf215546Sopenharmony_ci /* We align all our buffers, inline buffers too. We made sure to take 749bf215546Sopenharmony_ci * this account when calculating total BO size requirements at pool 750bf215546Sopenharmony_ci * creation time. 751bf215546Sopenharmony_ci */ 752bf215546Sopenharmony_ci set_layout->bo_size = align(set_layout->bo_size, 753bf215546Sopenharmony_ci V3D_NON_COHERENT_ATOM_SIZE); 754bf215546Sopenharmony_ci 755bf215546Sopenharmony_ci set_layout->binding[binding_number].descriptor_offset = 756bf215546Sopenharmony_ci set_layout->bo_size; 757bf215546Sopenharmony_ci 758bf215546Sopenharmony_ci /* Inline uniform blocks are not arrayed, instead descriptorCount 759bf215546Sopenharmony_ci * specifies the size of the buffer in bytes. 760bf215546Sopenharmony_ci */ 761bf215546Sopenharmony_ci set_layout->bo_size += binding->descriptorCount; 762bf215546Sopenharmony_ci descriptor_count++; 763bf215546Sopenharmony_ci } 764bf215546Sopenharmony_ci } 765bf215546Sopenharmony_ci 766bf215546Sopenharmony_ci free(bindings); 767bf215546Sopenharmony_ci 768bf215546Sopenharmony_ci set_layout->descriptor_count = descriptor_count; 769bf215546Sopenharmony_ci set_layout->dynamic_offset_count = dynamic_offset_count; 770bf215546Sopenharmony_ci 771bf215546Sopenharmony_ci *pSetLayout = v3dv_descriptor_set_layout_to_handle(set_layout); 772bf215546Sopenharmony_ci 773bf215546Sopenharmony_ci return VK_SUCCESS; 774bf215546Sopenharmony_ci} 775bf215546Sopenharmony_ci 776bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 777bf215546Sopenharmony_civ3dv_DestroyDescriptorSetLayout(VkDevice _device, 778bf215546Sopenharmony_ci VkDescriptorSetLayout _set_layout, 779bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 780bf215546Sopenharmony_ci{ 781bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 782bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, _set_layout); 783bf215546Sopenharmony_ci 784bf215546Sopenharmony_ci if (!set_layout) 785bf215546Sopenharmony_ci return; 786bf215546Sopenharmony_ci 787bf215546Sopenharmony_ci v3dv_descriptor_set_layout_unref(device, set_layout); 788bf215546Sopenharmony_ci} 789bf215546Sopenharmony_ci 790bf215546Sopenharmony_cistatic inline VkResult 791bf215546Sopenharmony_ciout_of_pool_memory(const struct v3dv_device *device, 792bf215546Sopenharmony_ci const struct v3dv_descriptor_pool *pool) 793bf215546Sopenharmony_ci{ 794bf215546Sopenharmony_ci /* Don't log OOPM errors for internal driver pools, we handle these properly 795bf215546Sopenharmony_ci * by allocating a new pool, so they don't point to real issues. 796bf215546Sopenharmony_ci */ 797bf215546Sopenharmony_ci if (!pool->is_driver_internal) 798bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY); 799bf215546Sopenharmony_ci else 800bf215546Sopenharmony_ci return VK_ERROR_OUT_OF_POOL_MEMORY; 801bf215546Sopenharmony_ci} 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_cistatic VkResult 804bf215546Sopenharmony_cidescriptor_set_create(struct v3dv_device *device, 805bf215546Sopenharmony_ci struct v3dv_descriptor_pool *pool, 806bf215546Sopenharmony_ci struct v3dv_descriptor_set_layout *layout, 807bf215546Sopenharmony_ci struct v3dv_descriptor_set **out_set) 808bf215546Sopenharmony_ci{ 809bf215546Sopenharmony_ci struct v3dv_descriptor_set *set; 810bf215546Sopenharmony_ci uint32_t descriptor_count = layout->descriptor_count; 811bf215546Sopenharmony_ci unsigned mem_size = sizeof(struct v3dv_descriptor_set) + 812bf215546Sopenharmony_ci sizeof(struct v3dv_descriptor) * descriptor_count; 813bf215546Sopenharmony_ci 814bf215546Sopenharmony_ci if (pool->host_memory_base) { 815bf215546Sopenharmony_ci if (pool->host_memory_end - pool->host_memory_ptr < mem_size) 816bf215546Sopenharmony_ci return out_of_pool_memory(device, pool); 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci set = (struct v3dv_descriptor_set*)pool->host_memory_ptr; 819bf215546Sopenharmony_ci pool->host_memory_ptr += mem_size; 820bf215546Sopenharmony_ci 821bf215546Sopenharmony_ci vk_object_base_init(&device->vk, &set->base, VK_OBJECT_TYPE_DESCRIPTOR_SET); 822bf215546Sopenharmony_ci } else { 823bf215546Sopenharmony_ci set = vk_object_zalloc(&device->vk, NULL, mem_size, 824bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_SET); 825bf215546Sopenharmony_ci 826bf215546Sopenharmony_ci if (!set) 827bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 828bf215546Sopenharmony_ci } 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci set->pool = pool; 831bf215546Sopenharmony_ci 832bf215546Sopenharmony_ci set->layout = layout; 833bf215546Sopenharmony_ci 834bf215546Sopenharmony_ci /* FIXME: VK_EXT_descriptor_indexing introduces 835bf215546Sopenharmony_ci * VARIABLE_DESCRIPTOR_LAYOUT_COUNT. That would affect the layout_size used 836bf215546Sopenharmony_ci * below for bo allocation 837bf215546Sopenharmony_ci */ 838bf215546Sopenharmony_ci 839bf215546Sopenharmony_ci uint32_t offset = 0; 840bf215546Sopenharmony_ci uint32_t index = pool->entry_count; 841bf215546Sopenharmony_ci 842bf215546Sopenharmony_ci if (layout->bo_size) { 843bf215546Sopenharmony_ci if (!pool->host_memory_base && pool->entry_count == pool->max_entry_count) { 844bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, set); 845bf215546Sopenharmony_ci return out_of_pool_memory(device, pool); 846bf215546Sopenharmony_ci } 847bf215546Sopenharmony_ci 848bf215546Sopenharmony_ci /* We first try to allocate linearly fist, so that we don't spend time 849bf215546Sopenharmony_ci * looking for gaps if the app only allocates & resets via the pool. 850bf215546Sopenharmony_ci * 851bf215546Sopenharmony_ci * If that fails, we try to find a gap from previously freed subregions 852bf215546Sopenharmony_ci * iterating through the descriptor pool entries. Note that we are not 853bf215546Sopenharmony_ci * doing that if we have a pool->host_memory_base. We only have that if 854bf215546Sopenharmony_ci * VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT is not set, so in 855bf215546Sopenharmony_ci * that case the user can't free subregions, so it doesn't make sense to 856bf215546Sopenharmony_ci * even try (or track those subregions). 857bf215546Sopenharmony_ci */ 858bf215546Sopenharmony_ci if (pool->current_offset + layout->bo_size <= pool->bo->size) { 859bf215546Sopenharmony_ci offset = pool->current_offset; 860bf215546Sopenharmony_ci pool->current_offset += layout->bo_size; 861bf215546Sopenharmony_ci } else if (!pool->host_memory_base) { 862bf215546Sopenharmony_ci for (index = 0; index < pool->entry_count; index++) { 863bf215546Sopenharmony_ci if (pool->entries[index].offset - offset >= layout->bo_size) 864bf215546Sopenharmony_ci break; 865bf215546Sopenharmony_ci offset = pool->entries[index].offset + pool->entries[index].size; 866bf215546Sopenharmony_ci } 867bf215546Sopenharmony_ci if (pool->bo->size - offset < layout->bo_size) { 868bf215546Sopenharmony_ci vk_object_free(&device->vk, NULL, set); 869bf215546Sopenharmony_ci return out_of_pool_memory(device, pool); 870bf215546Sopenharmony_ci } 871bf215546Sopenharmony_ci memmove(&pool->entries[index + 1], &pool->entries[index], 872bf215546Sopenharmony_ci sizeof(pool->entries[0]) * (pool->entry_count - index)); 873bf215546Sopenharmony_ci } else { 874bf215546Sopenharmony_ci assert(pool->host_memory_base); 875bf215546Sopenharmony_ci return out_of_pool_memory(device, pool); 876bf215546Sopenharmony_ci } 877bf215546Sopenharmony_ci 878bf215546Sopenharmony_ci set->base_offset = offset; 879bf215546Sopenharmony_ci } 880bf215546Sopenharmony_ci 881bf215546Sopenharmony_ci if (!pool->host_memory_base) { 882bf215546Sopenharmony_ci pool->entries[index].set = set; 883bf215546Sopenharmony_ci pool->entries[index].offset = offset; 884bf215546Sopenharmony_ci pool->entries[index].size = layout->bo_size; 885bf215546Sopenharmony_ci pool->entry_count++; 886bf215546Sopenharmony_ci } 887bf215546Sopenharmony_ci 888bf215546Sopenharmony_ci /* Go through and fill out immutable samplers if we have any */ 889bf215546Sopenharmony_ci for (uint32_t b = 0; b < layout->binding_count; b++) { 890bf215546Sopenharmony_ci if (layout->binding[b].immutable_samplers_offset == 0) 891bf215546Sopenharmony_ci continue; 892bf215546Sopenharmony_ci 893bf215546Sopenharmony_ci const struct v3dv_sampler *samplers = 894bf215546Sopenharmony_ci (const struct v3dv_sampler *)((const char *)layout + 895bf215546Sopenharmony_ci layout->binding[b].immutable_samplers_offset); 896bf215546Sopenharmony_ci 897bf215546Sopenharmony_ci for (uint32_t i = 0; i < layout->binding[b].array_size; i++) { 898bf215546Sopenharmony_ci uint32_t combined_offset = 899bf215546Sopenharmony_ci layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? 900bf215546Sopenharmony_ci v3dv_X(device, combined_image_sampler_sampler_state_offset)() : 0; 901bf215546Sopenharmony_ci 902bf215546Sopenharmony_ci void *desc_map = descriptor_bo_map(device, set, &layout->binding[b], i); 903bf215546Sopenharmony_ci desc_map += combined_offset; 904bf215546Sopenharmony_ci 905bf215546Sopenharmony_ci memcpy(desc_map, 906bf215546Sopenharmony_ci samplers[i].sampler_state, 907bf215546Sopenharmony_ci sizeof(samplers[i].sampler_state)); 908bf215546Sopenharmony_ci } 909bf215546Sopenharmony_ci } 910bf215546Sopenharmony_ci 911bf215546Sopenharmony_ci v3dv_descriptor_set_layout_ref(layout); 912bf215546Sopenharmony_ci list_addtail(&set->pool_link, &pool->set_list); 913bf215546Sopenharmony_ci 914bf215546Sopenharmony_ci *out_set = set; 915bf215546Sopenharmony_ci 916bf215546Sopenharmony_ci return VK_SUCCESS; 917bf215546Sopenharmony_ci} 918bf215546Sopenharmony_ci 919bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 920bf215546Sopenharmony_civ3dv_AllocateDescriptorSets(VkDevice _device, 921bf215546Sopenharmony_ci const VkDescriptorSetAllocateInfo *pAllocateInfo, 922bf215546Sopenharmony_ci VkDescriptorSet *pDescriptorSets) 923bf215546Sopenharmony_ci{ 924bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 925bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, pAllocateInfo->descriptorPool); 926bf215546Sopenharmony_ci 927bf215546Sopenharmony_ci VkResult result = VK_SUCCESS; 928bf215546Sopenharmony_ci struct v3dv_descriptor_set *set = NULL; 929bf215546Sopenharmony_ci uint32_t i = 0; 930bf215546Sopenharmony_ci 931bf215546Sopenharmony_ci for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 932bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, layout, 933bf215546Sopenharmony_ci pAllocateInfo->pSetLayouts[i]); 934bf215546Sopenharmony_ci 935bf215546Sopenharmony_ci result = descriptor_set_create(device, pool, layout, &set); 936bf215546Sopenharmony_ci if (result != VK_SUCCESS) 937bf215546Sopenharmony_ci break; 938bf215546Sopenharmony_ci 939bf215546Sopenharmony_ci pDescriptorSets[i] = v3dv_descriptor_set_to_handle(set); 940bf215546Sopenharmony_ci } 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 943bf215546Sopenharmony_ci v3dv_FreeDescriptorSets(_device, pAllocateInfo->descriptorPool, 944bf215546Sopenharmony_ci i, pDescriptorSets); 945bf215546Sopenharmony_ci for (i = 0; i < pAllocateInfo->descriptorSetCount; i++) { 946bf215546Sopenharmony_ci pDescriptorSets[i] = VK_NULL_HANDLE; 947bf215546Sopenharmony_ci } 948bf215546Sopenharmony_ci } 949bf215546Sopenharmony_ci 950bf215546Sopenharmony_ci return result; 951bf215546Sopenharmony_ci} 952bf215546Sopenharmony_ci 953bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 954bf215546Sopenharmony_civ3dv_FreeDescriptorSets(VkDevice _device, 955bf215546Sopenharmony_ci VkDescriptorPool descriptorPool, 956bf215546Sopenharmony_ci uint32_t count, 957bf215546Sopenharmony_ci const VkDescriptorSet *pDescriptorSets) 958bf215546Sopenharmony_ci{ 959bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 960bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool); 961bf215546Sopenharmony_ci 962bf215546Sopenharmony_ci for (uint32_t i = 0; i < count; i++) { 963bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]); 964bf215546Sopenharmony_ci 965bf215546Sopenharmony_ci if (set) { 966bf215546Sopenharmony_ci v3dv_descriptor_set_layout_unref(device, set->layout); 967bf215546Sopenharmony_ci list_del(&set->pool_link); 968bf215546Sopenharmony_ci if (!pool->host_memory_base) 969bf215546Sopenharmony_ci descriptor_set_destroy(device, pool, set, true); 970bf215546Sopenharmony_ci } 971bf215546Sopenharmony_ci } 972bf215546Sopenharmony_ci 973bf215546Sopenharmony_ci return VK_SUCCESS; 974bf215546Sopenharmony_ci} 975bf215546Sopenharmony_ci 976bf215546Sopenharmony_cistatic void 977bf215546Sopenharmony_cidescriptor_bo_copy(struct v3dv_device *device, 978bf215546Sopenharmony_ci struct v3dv_descriptor_set *dst_set, 979bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *dst_binding_layout, 980bf215546Sopenharmony_ci uint32_t dst_array_index, 981bf215546Sopenharmony_ci struct v3dv_descriptor_set *src_set, 982bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *src_binding_layout, 983bf215546Sopenharmony_ci uint32_t src_array_index) 984bf215546Sopenharmony_ci{ 985bf215546Sopenharmony_ci assert(dst_binding_layout->type == src_binding_layout->type); 986bf215546Sopenharmony_ci 987bf215546Sopenharmony_ci void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, dst_array_index); 988bf215546Sopenharmony_ci void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, src_array_index); 989bf215546Sopenharmony_ci 990bf215546Sopenharmony_ci memcpy(dst_map, src_map, v3dv_X(device, descriptor_bo_size)(src_binding_layout->type)); 991bf215546Sopenharmony_ci} 992bf215546Sopenharmony_ci 993bf215546Sopenharmony_cistatic void 994bf215546Sopenharmony_ciwrite_buffer_descriptor(struct v3dv_descriptor *descriptor, 995bf215546Sopenharmony_ci VkDescriptorType desc_type, 996bf215546Sopenharmony_ci const VkDescriptorBufferInfo *buffer_info) 997bf215546Sopenharmony_ci{ 998bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer, buffer, buffer_info->buffer); 999bf215546Sopenharmony_ci 1000bf215546Sopenharmony_ci descriptor->type = desc_type; 1001bf215546Sopenharmony_ci descriptor->buffer = buffer; 1002bf215546Sopenharmony_ci descriptor->offset = buffer_info->offset; 1003bf215546Sopenharmony_ci if (buffer_info->range == VK_WHOLE_SIZE) { 1004bf215546Sopenharmony_ci descriptor->range = buffer->size - buffer_info->offset; 1005bf215546Sopenharmony_ci } else { 1006bf215546Sopenharmony_ci assert(descriptor->range <= UINT32_MAX); 1007bf215546Sopenharmony_ci descriptor->range = buffer_info->range; 1008bf215546Sopenharmony_ci } 1009bf215546Sopenharmony_ci} 1010bf215546Sopenharmony_ci 1011bf215546Sopenharmony_cistatic void 1012bf215546Sopenharmony_ciwrite_image_descriptor(struct v3dv_device *device, 1013bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor, 1014bf215546Sopenharmony_ci VkDescriptorType desc_type, 1015bf215546Sopenharmony_ci struct v3dv_descriptor_set *set, 1016bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout, 1017bf215546Sopenharmony_ci struct v3dv_image_view *iview, 1018bf215546Sopenharmony_ci struct v3dv_sampler *sampler, 1019bf215546Sopenharmony_ci uint32_t array_index) 1020bf215546Sopenharmony_ci{ 1021bf215546Sopenharmony_ci descriptor->type = desc_type; 1022bf215546Sopenharmony_ci descriptor->sampler = sampler; 1023bf215546Sopenharmony_ci descriptor->image_view = iview; 1024bf215546Sopenharmony_ci 1025bf215546Sopenharmony_ci void *desc_map = descriptor_bo_map(device, set, 1026bf215546Sopenharmony_ci binding_layout, array_index); 1027bf215546Sopenharmony_ci 1028bf215546Sopenharmony_ci if (iview) { 1029bf215546Sopenharmony_ci const uint32_t tex_state_index = 1030bf215546Sopenharmony_ci iview->vk.view_type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY || 1031bf215546Sopenharmony_ci desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1; 1032bf215546Sopenharmony_ci memcpy(desc_map, 1033bf215546Sopenharmony_ci iview->texture_shader_state[tex_state_index], 1034bf215546Sopenharmony_ci sizeof(iview->texture_shader_state[0])); 1035bf215546Sopenharmony_ci desc_map += v3dv_X(device, combined_image_sampler_sampler_state_offset)(); 1036bf215546Sopenharmony_ci } 1037bf215546Sopenharmony_ci 1038bf215546Sopenharmony_ci if (sampler && !binding_layout->immutable_samplers_offset) { 1039bf215546Sopenharmony_ci /* For immutable samplers this was already done as part of the 1040bf215546Sopenharmony_ci * descriptor set create, as that info can't change later 1041bf215546Sopenharmony_ci */ 1042bf215546Sopenharmony_ci memcpy(desc_map, 1043bf215546Sopenharmony_ci sampler->sampler_state, 1044bf215546Sopenharmony_ci sizeof(sampler->sampler_state)); 1045bf215546Sopenharmony_ci } 1046bf215546Sopenharmony_ci} 1047bf215546Sopenharmony_ci 1048bf215546Sopenharmony_ci 1049bf215546Sopenharmony_cistatic void 1050bf215546Sopenharmony_ciwrite_buffer_view_descriptor(struct v3dv_device *device, 1051bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor, 1052bf215546Sopenharmony_ci VkDescriptorType desc_type, 1053bf215546Sopenharmony_ci struct v3dv_descriptor_set *set, 1054bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout, 1055bf215546Sopenharmony_ci struct v3dv_buffer_view *bview, 1056bf215546Sopenharmony_ci uint32_t array_index) 1057bf215546Sopenharmony_ci{ 1058bf215546Sopenharmony_ci assert(bview); 1059bf215546Sopenharmony_ci descriptor->type = desc_type; 1060bf215546Sopenharmony_ci descriptor->buffer_view = bview; 1061bf215546Sopenharmony_ci 1062bf215546Sopenharmony_ci void *desc_map = descriptor_bo_map(device, set, binding_layout, array_index); 1063bf215546Sopenharmony_ci 1064bf215546Sopenharmony_ci memcpy(desc_map, 1065bf215546Sopenharmony_ci bview->texture_shader_state, 1066bf215546Sopenharmony_ci sizeof(bview->texture_shader_state)); 1067bf215546Sopenharmony_ci} 1068bf215546Sopenharmony_ci 1069bf215546Sopenharmony_cistatic void 1070bf215546Sopenharmony_ciwrite_inline_uniform_descriptor(struct v3dv_device *device, 1071bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor, 1072bf215546Sopenharmony_ci struct v3dv_descriptor_set *set, 1073bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout, 1074bf215546Sopenharmony_ci const void *data, 1075bf215546Sopenharmony_ci size_t offset, 1076bf215546Sopenharmony_ci size_t size) 1077bf215546Sopenharmony_ci{ 1078bf215546Sopenharmony_ci assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK); 1079bf215546Sopenharmony_ci descriptor->type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; 1080bf215546Sopenharmony_ci descriptor->buffer = NULL; 1081bf215546Sopenharmony_ci 1082bf215546Sopenharmony_ci void *desc_map = descriptor_bo_map(device, set, binding_layout, 0); 1083bf215546Sopenharmony_ci memcpy(desc_map + offset, data, size); 1084bf215546Sopenharmony_ci 1085bf215546Sopenharmony_ci /* Inline uniform buffers allocate BO space in the pool for all inline 1086bf215546Sopenharmony_ci * buffers it may allocate and then this space is assigned to individual 1087bf215546Sopenharmony_ci * descriptors when they are written, so we define the range of an inline 1088bf215546Sopenharmony_ci * buffer as the largest range of data that the client has written to it. 1089bf215546Sopenharmony_ci */ 1090bf215546Sopenharmony_ci descriptor->offset = 0; 1091bf215546Sopenharmony_ci descriptor->range = MAX2(descriptor->range, offset + size); 1092bf215546Sopenharmony_ci} 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1095bf215546Sopenharmony_civ3dv_UpdateDescriptorSets(VkDevice _device, 1096bf215546Sopenharmony_ci uint32_t descriptorWriteCount, 1097bf215546Sopenharmony_ci const VkWriteDescriptorSet *pDescriptorWrites, 1098bf215546Sopenharmony_ci uint32_t descriptorCopyCount, 1099bf215546Sopenharmony_ci const VkCopyDescriptorSet *pDescriptorCopies) 1100bf215546Sopenharmony_ci{ 1101bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 1102bf215546Sopenharmony_ci for (uint32_t i = 0; i < descriptorWriteCount; i++) { 1103bf215546Sopenharmony_ci const VkWriteDescriptorSet *writeset = &pDescriptorWrites[i]; 1104bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set, set, writeset->dstSet); 1105bf215546Sopenharmony_ci 1106bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout = 1107bf215546Sopenharmony_ci set->layout->binding + writeset->dstBinding; 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor = set->descriptors; 1110bf215546Sopenharmony_ci 1111bf215546Sopenharmony_ci descriptor += binding_layout->descriptor_index; 1112bf215546Sopenharmony_ci 1113bf215546Sopenharmony_ci /* Inline uniform blocks are not arrayed, instead they use dstArrayElement 1114bf215546Sopenharmony_ci * to specify the byte offset of the uniform update and descriptorCount 1115bf215546Sopenharmony_ci * to specify the size (in bytes) of the update. 1116bf215546Sopenharmony_ci */ 1117bf215546Sopenharmony_ci uint32_t descriptor_count; 1118bf215546Sopenharmony_ci if (writeset->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { 1119bf215546Sopenharmony_ci descriptor += writeset->dstArrayElement; 1120bf215546Sopenharmony_ci descriptor_count = writeset->descriptorCount; 1121bf215546Sopenharmony_ci } else { 1122bf215546Sopenharmony_ci descriptor_count = 1; 1123bf215546Sopenharmony_ci } 1124bf215546Sopenharmony_ci 1125bf215546Sopenharmony_ci for (uint32_t j = 0; j < descriptor_count; ++j) { 1126bf215546Sopenharmony_ci switch(writeset->descriptorType) { 1127bf215546Sopenharmony_ci 1128bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1129bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1130bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1131bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: { 1132bf215546Sopenharmony_ci const VkDescriptorBufferInfo *buffer_info = writeset->pBufferInfo + j; 1133bf215546Sopenharmony_ci write_buffer_descriptor(descriptor, writeset->descriptorType, 1134bf215546Sopenharmony_ci buffer_info); 1135bf215546Sopenharmony_ci break; 1136bf215546Sopenharmony_ci } 1137bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: { 1138bf215546Sopenharmony_ci /* If we are here we shouldn't be modifying a immutable sampler, 1139bf215546Sopenharmony_ci * so we don't ensure that would work or not crash. But let the 1140bf215546Sopenharmony_ci * validation layers check that 1141bf215546Sopenharmony_ci */ 1142bf215546Sopenharmony_ci const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j; 1143bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler); 1144bf215546Sopenharmony_ci write_image_descriptor(device, descriptor, writeset->descriptorType, 1145bf215546Sopenharmony_ci set, binding_layout, NULL, sampler, 1146bf215546Sopenharmony_ci writeset->dstArrayElement + j); 1147bf215546Sopenharmony_ci 1148bf215546Sopenharmony_ci break; 1149bf215546Sopenharmony_ci } 1150bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 1151bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1152bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: { 1153bf215546Sopenharmony_ci const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j; 1154bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView); 1155bf215546Sopenharmony_ci write_image_descriptor(device, descriptor, writeset->descriptorType, 1156bf215546Sopenharmony_ci set, binding_layout, iview, NULL, 1157bf215546Sopenharmony_ci writeset->dstArrayElement + j); 1158bf215546Sopenharmony_ci 1159bf215546Sopenharmony_ci break; 1160bf215546Sopenharmony_ci } 1161bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { 1162bf215546Sopenharmony_ci const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j; 1163bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView); 1164bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler); 1165bf215546Sopenharmony_ci write_image_descriptor(device, descriptor, writeset->descriptorType, 1166bf215546Sopenharmony_ci set, binding_layout, iview, sampler, 1167bf215546Sopenharmony_ci writeset->dstArrayElement + j); 1168bf215546Sopenharmony_ci 1169bf215546Sopenharmony_ci break; 1170bf215546Sopenharmony_ci } 1171bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1172bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: { 1173bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer_view, buffer_view, 1174bf215546Sopenharmony_ci writeset->pTexelBufferView[j]); 1175bf215546Sopenharmony_ci write_buffer_view_descriptor(device, descriptor, writeset->descriptorType, 1176bf215546Sopenharmony_ci set, binding_layout, buffer_view, 1177bf215546Sopenharmony_ci writeset->dstArrayElement + j); 1178bf215546Sopenharmony_ci break; 1179bf215546Sopenharmony_ci } 1180bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: { 1181bf215546Sopenharmony_ci const VkWriteDescriptorSetInlineUniformBlock *inline_write = 1182bf215546Sopenharmony_ci vk_find_struct_const(writeset->pNext, 1183bf215546Sopenharmony_ci WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK); 1184bf215546Sopenharmony_ci assert(inline_write->dataSize == writeset->descriptorCount); 1185bf215546Sopenharmony_ci write_inline_uniform_descriptor(device, descriptor, set, 1186bf215546Sopenharmony_ci binding_layout, 1187bf215546Sopenharmony_ci inline_write->pData, 1188bf215546Sopenharmony_ci writeset->dstArrayElement, /* offset */ 1189bf215546Sopenharmony_ci inline_write->dataSize); 1190bf215546Sopenharmony_ci break; 1191bf215546Sopenharmony_ci } 1192bf215546Sopenharmony_ci default: 1193bf215546Sopenharmony_ci unreachable("unimplemented descriptor type"); 1194bf215546Sopenharmony_ci break; 1195bf215546Sopenharmony_ci } 1196bf215546Sopenharmony_ci descriptor++; 1197bf215546Sopenharmony_ci } 1198bf215546Sopenharmony_ci } 1199bf215546Sopenharmony_ci 1200bf215546Sopenharmony_ci for (uint32_t i = 0; i < descriptorCopyCount; i++) { 1201bf215546Sopenharmony_ci const VkCopyDescriptorSet *copyset = &pDescriptorCopies[i]; 1202bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set, src_set, 1203bf215546Sopenharmony_ci copyset->srcSet); 1204bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set, dst_set, 1205bf215546Sopenharmony_ci copyset->dstSet); 1206bf215546Sopenharmony_ci 1207bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *src_binding_layout = 1208bf215546Sopenharmony_ci src_set->layout->binding + copyset->srcBinding; 1209bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *dst_binding_layout = 1210bf215546Sopenharmony_ci dst_set->layout->binding + copyset->dstBinding; 1211bf215546Sopenharmony_ci 1212bf215546Sopenharmony_ci assert(src_binding_layout->type == dst_binding_layout->type); 1213bf215546Sopenharmony_ci 1214bf215546Sopenharmony_ci struct v3dv_descriptor *src_descriptor = src_set->descriptors; 1215bf215546Sopenharmony_ci struct v3dv_descriptor *dst_descriptor = dst_set->descriptors; 1216bf215546Sopenharmony_ci 1217bf215546Sopenharmony_ci src_descriptor += src_binding_layout->descriptor_index; 1218bf215546Sopenharmony_ci dst_descriptor += dst_binding_layout->descriptor_index; 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci if (src_binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { 1221bf215546Sopenharmony_ci /* {src,dst}ArrayElement specifies src/dst start offset and 1222bf215546Sopenharmony_ci * descriptorCount specifies size (in bytes) to copy. 1223bf215546Sopenharmony_ci */ 1224bf215546Sopenharmony_ci const void *src_data = src_set->pool->bo->map + 1225bf215546Sopenharmony_ci src_set->base_offset + 1226bf215546Sopenharmony_ci src_binding_layout->descriptor_offset + 1227bf215546Sopenharmony_ci copyset->srcArrayElement; 1228bf215546Sopenharmony_ci write_inline_uniform_descriptor(device, dst_descriptor, dst_set, 1229bf215546Sopenharmony_ci dst_binding_layout, 1230bf215546Sopenharmony_ci src_data, 1231bf215546Sopenharmony_ci copyset->dstArrayElement, 1232bf215546Sopenharmony_ci copyset->descriptorCount); 1233bf215546Sopenharmony_ci continue; 1234bf215546Sopenharmony_ci } 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci src_descriptor += copyset->srcArrayElement; 1237bf215546Sopenharmony_ci dst_descriptor += copyset->dstArrayElement; 1238bf215546Sopenharmony_ci 1239bf215546Sopenharmony_ci for (uint32_t j = 0; j < copyset->descriptorCount; j++) { 1240bf215546Sopenharmony_ci *dst_descriptor = *src_descriptor; 1241bf215546Sopenharmony_ci dst_descriptor++; 1242bf215546Sopenharmony_ci src_descriptor++; 1243bf215546Sopenharmony_ci 1244bf215546Sopenharmony_ci if (v3dv_X(device, descriptor_bo_size)(src_binding_layout->type) > 0) { 1245bf215546Sopenharmony_ci descriptor_bo_copy(device, 1246bf215546Sopenharmony_ci dst_set, dst_binding_layout, 1247bf215546Sopenharmony_ci j + copyset->dstArrayElement, 1248bf215546Sopenharmony_ci src_set, src_binding_layout, 1249bf215546Sopenharmony_ci j + copyset->srcArrayElement); 1250bf215546Sopenharmony_ci } 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_ci } 1253bf215546Sopenharmony_ci } 1254bf215546Sopenharmony_ci} 1255bf215546Sopenharmony_ci 1256bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1257bf215546Sopenharmony_civ3dv_GetDescriptorSetLayoutSupport( 1258bf215546Sopenharmony_ci VkDevice _device, 1259bf215546Sopenharmony_ci const VkDescriptorSetLayoutCreateInfo *pCreateInfo, 1260bf215546Sopenharmony_ci VkDescriptorSetLayoutSupport *pSupport) 1261bf215546Sopenharmony_ci{ 1262bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 1263bf215546Sopenharmony_ci VkDescriptorSetLayoutBinding *bindings = NULL; 1264bf215546Sopenharmony_ci VkResult result = vk_create_sorted_bindings( 1265bf215546Sopenharmony_ci pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings); 1266bf215546Sopenharmony_ci if (result != VK_SUCCESS) { 1267bf215546Sopenharmony_ci pSupport->supported = false; 1268bf215546Sopenharmony_ci return; 1269bf215546Sopenharmony_ci } 1270bf215546Sopenharmony_ci 1271bf215546Sopenharmony_ci bool supported = true; 1272bf215546Sopenharmony_ci 1273bf215546Sopenharmony_ci uint32_t desc_host_size = sizeof(struct v3dv_descriptor); 1274bf215546Sopenharmony_ci uint32_t host_size = sizeof(struct v3dv_descriptor_set); 1275bf215546Sopenharmony_ci uint32_t bo_size = 0; 1276bf215546Sopenharmony_ci for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { 1277bf215546Sopenharmony_ci const VkDescriptorSetLayoutBinding *binding = bindings + i; 1278bf215546Sopenharmony_ci 1279bf215546Sopenharmony_ci if ((UINT32_MAX - host_size) / desc_host_size < binding->descriptorCount) { 1280bf215546Sopenharmony_ci supported = false; 1281bf215546Sopenharmony_ci break; 1282bf215546Sopenharmony_ci } 1283bf215546Sopenharmony_ci 1284bf215546Sopenharmony_ci uint32_t desc_bo_size = v3dv_X(device, descriptor_bo_size)(binding->descriptorType); 1285bf215546Sopenharmony_ci if (desc_bo_size > 0 && 1286bf215546Sopenharmony_ci (UINT32_MAX - bo_size) / desc_bo_size < binding->descriptorCount) { 1287bf215546Sopenharmony_ci supported = false; 1288bf215546Sopenharmony_ci break; 1289bf215546Sopenharmony_ci } 1290bf215546Sopenharmony_ci 1291bf215546Sopenharmony_ci host_size += binding->descriptorCount * desc_host_size; 1292bf215546Sopenharmony_ci bo_size += binding->descriptorCount * desc_bo_size; 1293bf215546Sopenharmony_ci } 1294bf215546Sopenharmony_ci 1295bf215546Sopenharmony_ci free(bindings); 1296bf215546Sopenharmony_ci 1297bf215546Sopenharmony_ci pSupport->supported = supported; 1298bf215546Sopenharmony_ci} 1299bf215546Sopenharmony_ci 1300bf215546Sopenharmony_ciVkResult 1301bf215546Sopenharmony_civ3dv_CreateDescriptorUpdateTemplate( 1302bf215546Sopenharmony_ci VkDevice _device, 1303bf215546Sopenharmony_ci const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo, 1304bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1305bf215546Sopenharmony_ci VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate) 1306bf215546Sopenharmony_ci{ 1307bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 1308bf215546Sopenharmony_ci struct v3dv_descriptor_update_template *template; 1309bf215546Sopenharmony_ci 1310bf215546Sopenharmony_ci size_t size = sizeof(*template) + 1311bf215546Sopenharmony_ci pCreateInfo->descriptorUpdateEntryCount * sizeof(template->entries[0]); 1312bf215546Sopenharmony_ci template = vk_object_alloc(&device->vk, pAllocator, size, 1313bf215546Sopenharmony_ci VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE); 1314bf215546Sopenharmony_ci if (template == NULL) 1315bf215546Sopenharmony_ci return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); 1316bf215546Sopenharmony_ci 1317bf215546Sopenharmony_ci template->bind_point = pCreateInfo->pipelineBindPoint; 1318bf215546Sopenharmony_ci 1319bf215546Sopenharmony_ci assert(pCreateInfo->templateType == 1320bf215546Sopenharmony_ci VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET); 1321bf215546Sopenharmony_ci template->set = pCreateInfo->set; 1322bf215546Sopenharmony_ci 1323bf215546Sopenharmony_ci template->entry_count = pCreateInfo->descriptorUpdateEntryCount; 1324bf215546Sopenharmony_ci for (uint32_t i = 0; i < template->entry_count; i++) { 1325bf215546Sopenharmony_ci const VkDescriptorUpdateTemplateEntry *pEntry = 1326bf215546Sopenharmony_ci &pCreateInfo->pDescriptorUpdateEntries[i]; 1327bf215546Sopenharmony_ci 1328bf215546Sopenharmony_ci template->entries[i] = (struct v3dv_descriptor_template_entry) { 1329bf215546Sopenharmony_ci .type = pEntry->descriptorType, 1330bf215546Sopenharmony_ci .binding = pEntry->dstBinding, 1331bf215546Sopenharmony_ci .array_element = pEntry->dstArrayElement, 1332bf215546Sopenharmony_ci .array_count = pEntry->descriptorCount, 1333bf215546Sopenharmony_ci .offset = pEntry->offset, 1334bf215546Sopenharmony_ci .stride = pEntry->stride, 1335bf215546Sopenharmony_ci }; 1336bf215546Sopenharmony_ci } 1337bf215546Sopenharmony_ci 1338bf215546Sopenharmony_ci *pDescriptorUpdateTemplate = 1339bf215546Sopenharmony_ci v3dv_descriptor_update_template_to_handle(template); 1340bf215546Sopenharmony_ci 1341bf215546Sopenharmony_ci return VK_SUCCESS; 1342bf215546Sopenharmony_ci} 1343bf215546Sopenharmony_ci 1344bf215546Sopenharmony_civoid 1345bf215546Sopenharmony_civ3dv_DestroyDescriptorUpdateTemplate( 1346bf215546Sopenharmony_ci VkDevice _device, 1347bf215546Sopenharmony_ci VkDescriptorUpdateTemplate descriptorUpdateTemplate, 1348bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 1349bf215546Sopenharmony_ci{ 1350bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 1351bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template, 1352bf215546Sopenharmony_ci descriptorUpdateTemplate); 1353bf215546Sopenharmony_ci 1354bf215546Sopenharmony_ci if (!template) 1355bf215546Sopenharmony_ci return; 1356bf215546Sopenharmony_ci 1357bf215546Sopenharmony_ci vk_object_free(&device->vk, pAllocator, template); 1358bf215546Sopenharmony_ci} 1359bf215546Sopenharmony_ci 1360bf215546Sopenharmony_civoid 1361bf215546Sopenharmony_civ3dv_UpdateDescriptorSetWithTemplate( 1362bf215546Sopenharmony_ci VkDevice _device, 1363bf215546Sopenharmony_ci VkDescriptorSet descriptorSet, 1364bf215546Sopenharmony_ci VkDescriptorUpdateTemplate descriptorUpdateTemplate, 1365bf215546Sopenharmony_ci const void *pData) 1366bf215546Sopenharmony_ci{ 1367bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_device, device, _device); 1368bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_set, set, descriptorSet); 1369bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template, 1370bf215546Sopenharmony_ci descriptorUpdateTemplate); 1371bf215546Sopenharmony_ci 1372bf215546Sopenharmony_ci for (int i = 0; i < template->entry_count; i++) { 1373bf215546Sopenharmony_ci const struct v3dv_descriptor_template_entry *entry = 1374bf215546Sopenharmony_ci &template->entries[i]; 1375bf215546Sopenharmony_ci 1376bf215546Sopenharmony_ci const struct v3dv_descriptor_set_binding_layout *binding_layout = 1377bf215546Sopenharmony_ci set->layout->binding + entry->binding; 1378bf215546Sopenharmony_ci 1379bf215546Sopenharmony_ci struct v3dv_descriptor *descriptor = 1380bf215546Sopenharmony_ci set->descriptors + 1381bf215546Sopenharmony_ci binding_layout->descriptor_index; 1382bf215546Sopenharmony_ci 1383bf215546Sopenharmony_ci switch (entry->type) { 1384bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: 1385bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: 1386bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: 1387bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: 1388bf215546Sopenharmony_ci for (uint32_t j = 0; j < entry->array_count; j++) { 1389bf215546Sopenharmony_ci const VkDescriptorBufferInfo *info = 1390bf215546Sopenharmony_ci pData + entry->offset + j * entry->stride; 1391bf215546Sopenharmony_ci write_buffer_descriptor(descriptor + entry->array_element + j, 1392bf215546Sopenharmony_ci entry->type, info); 1393bf215546Sopenharmony_ci } 1394bf215546Sopenharmony_ci break; 1395bf215546Sopenharmony_ci 1396bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLER: 1397bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: 1398bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: 1399bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: 1400bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: 1401bf215546Sopenharmony_ci for (uint32_t j = 0; j < entry->array_count; j++) { 1402bf215546Sopenharmony_ci const VkDescriptorImageInfo *info = 1403bf215546Sopenharmony_ci pData + entry->offset + j * entry->stride; 1404bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_image_view, iview, info->imageView); 1405bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_sampler, sampler, info->sampler); 1406bf215546Sopenharmony_ci write_image_descriptor(device, descriptor + entry->array_element + j, 1407bf215546Sopenharmony_ci entry->type, set, binding_layout, iview, 1408bf215546Sopenharmony_ci sampler, entry->array_element + j); 1409bf215546Sopenharmony_ci } 1410bf215546Sopenharmony_ci break; 1411bf215546Sopenharmony_ci 1412bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: 1413bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: 1414bf215546Sopenharmony_ci for (uint32_t j = 0; j < entry->array_count; j++) { 1415bf215546Sopenharmony_ci const VkBufferView *_bview = 1416bf215546Sopenharmony_ci pData + entry->offset + j * entry->stride; 1417bf215546Sopenharmony_ci V3DV_FROM_HANDLE(v3dv_buffer_view, bview, *_bview); 1418bf215546Sopenharmony_ci write_buffer_view_descriptor(device, 1419bf215546Sopenharmony_ci descriptor + entry->array_element + j, 1420bf215546Sopenharmony_ci entry->type, set, binding_layout, bview, 1421bf215546Sopenharmony_ci entry->array_element + j); 1422bf215546Sopenharmony_ci } 1423bf215546Sopenharmony_ci break; 1424bf215546Sopenharmony_ci 1425bf215546Sopenharmony_ci case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: { 1426bf215546Sopenharmony_ci write_inline_uniform_descriptor(device, descriptor, set, 1427bf215546Sopenharmony_ci binding_layout, 1428bf215546Sopenharmony_ci pData + entry->offset, 1429bf215546Sopenharmony_ci entry->array_element, /* offset */ 1430bf215546Sopenharmony_ci entry->array_count); /* size */ 1431bf215546Sopenharmony_ci break; 1432bf215546Sopenharmony_ci } 1433bf215546Sopenharmony_ci 1434bf215546Sopenharmony_ci default: 1435bf215546Sopenharmony_ci unreachable("Unsupported descriptor type"); 1436bf215546Sopenharmony_ci } 1437bf215546Sopenharmony_ci } 1438bf215546Sopenharmony_ci} 1439bf215546Sopenharmony_ci 1440bf215546Sopenharmony_ciVKAPI_ATTR VkResult VKAPI_CALL 1441bf215546Sopenharmony_civ3dv_CreateSamplerYcbcrConversion( 1442bf215546Sopenharmony_ci VkDevice _device, 1443bf215546Sopenharmony_ci const VkSamplerYcbcrConversionCreateInfo *pCreateInfo, 1444bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator, 1445bf215546Sopenharmony_ci VkSamplerYcbcrConversion *pYcbcrConversion) 1446bf215546Sopenharmony_ci{ 1447bf215546Sopenharmony_ci unreachable("Ycbcr sampler conversion is not supported"); 1448bf215546Sopenharmony_ci return VK_SUCCESS; 1449bf215546Sopenharmony_ci} 1450bf215546Sopenharmony_ci 1451bf215546Sopenharmony_ciVKAPI_ATTR void VKAPI_CALL 1452bf215546Sopenharmony_civ3dv_DestroySamplerYcbcrConversion( 1453bf215546Sopenharmony_ci VkDevice _device, 1454bf215546Sopenharmony_ci VkSamplerYcbcrConversion YcbcrConversion, 1455bf215546Sopenharmony_ci const VkAllocationCallbacks *pAllocator) 1456bf215546Sopenharmony_ci{ 1457bf215546Sopenharmony_ci unreachable("Ycbcr sampler conversion is not supported"); 1458bf215546Sopenharmony_ci} 1459