diff options
Diffstat (limited to 'src/broadcom/vulkan/v3dv_descriptor_set.c')
-rw-r--r-- | src/broadcom/vulkan/v3dv_descriptor_set.c | 600 |
1 files changed, 394 insertions, 206 deletions
diff --git a/src/broadcom/vulkan/v3dv_descriptor_set.c b/src/broadcom/vulkan/v3dv_descriptor_set.c index fd9ec935611..1d777ba08d4 100644 --- a/src/broadcom/vulkan/v3dv_descriptor_set.c +++ b/src/broadcom/vulkan/v3dv_descriptor_set.c @@ -1,5 +1,5 @@ /* - * Copyright © 2019 Raspberry Pi + * Copyright © 2019 Raspberry Pi Ltd * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -28,19 +28,26 @@ /* * For a given descriptor defined by the descriptor_set it belongs, its - * binding layout, and array_index, it returns the map region assigned to it - * from the descriptor pool bo. + * binding layout, array_index, and plane, it returns the map region assigned + * to it from the descriptor pool bo. */ -static void* +static void * descriptor_bo_map(struct v3dv_device *device, struct v3dv_descriptor_set *set, const struct v3dv_descriptor_set_binding_layout *binding_layout, uint32_t array_index) { - assert(v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0); + /* Inline uniform blocks use BO memory to store UBO contents, not + * descriptor data, so their descriptor BO size is 0 even though they + * do use BO memory. + */ + uint32_t bo_size = v3dv_X(device, descriptor_bo_size)(binding_layout->type); + assert(bo_size > 0 || + binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK); + return set->pool->bo->map + set->base_offset + binding_layout->descriptor_offset + - array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type); + array_index * binding_layout->plane_stride * bo_size; } static bool @@ -102,7 +109,7 @@ v3dv_descriptor_map_get_descriptor(struct v3dv_descriptor_state *descriptor_stat * It also returns the descriptor type, so the caller could do extra * validation or adding extra offsets if the bo contains more that one field. */ -static struct v3dv_cl_reloc +struct v3dv_cl_reloc v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device, struct v3dv_descriptor_state *descriptor_state, struct v3dv_descriptor_map *map, @@ -125,8 +132,13 @@ v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device, const struct v3dv_descriptor_set_binding_layout *binding_layout = &set->layout->binding[binding_number]; - assert(v3dv_X(device, descriptor_bo_size)(binding_layout->type) > 0); - *out_type = binding_layout->type; + + uint32_t bo_size = v3dv_X(device, descriptor_bo_size)(binding_layout->type); + + assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK || + bo_size > 0); + if (out_type) + *out_type = binding_layout->type; uint32_t array_index = map->array_index[index]; assert(array_index < binding_layout->array_size); @@ -134,7 +146,7 @@ v3dv_descriptor_map_get_descriptor_bo(struct v3dv_device *device, struct v3dv_cl_reloc reloc = { .bo = set->pool->bo, .offset = set->base_offset + binding_layout->descriptor_offset + - array_index * v3dv_X(device, descriptor_bo_size)(binding_layout->type), + array_index * binding_layout->plane_stride * bo_size, }; return reloc; @@ -213,40 +225,11 @@ v3dv_descriptor_map_get_sampler_state(struct v3dv_device *device, type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) - reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)(); + reloc.offset += v3dv_X(device, combined_image_sampler_sampler_state_offset)(map->plane[index]); return reloc; } -const struct v3dv_format* -v3dv_descriptor_map_get_texture_format(struct v3dv_descriptor_state *descriptor_state, - struct v3dv_descriptor_map *map, - struct v3dv_pipeline_layout *pipeline_layout, - uint32_t index, - VkFormat *out_vk_format) -{ - struct v3dv_descriptor *descriptor = - v3dv_descriptor_map_get_descriptor(descriptor_state, map, - pipeline_layout, index, NULL); - - switch (descriptor->type) { - case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: - case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: - assert(descriptor->buffer_view); - *out_vk_format = descriptor->buffer_view->vk_format; - return descriptor->buffer_view->format; - case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: - case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: - case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: - case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: - assert(descriptor->image_view); - *out_vk_format = descriptor->image_view->vk.format; - return descriptor->image_view->format; - default: - unreachable("descriptor type doesn't has a texture format"); - } -} - struct v3dv_bo* v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_state, struct v3dv_descriptor_map *map, @@ -270,7 +253,8 @@ v3dv_descriptor_map_get_texture_bo(struct v3dv_descriptor_state *descriptor_stat assert(descriptor->image_view); struct v3dv_image *image = (struct v3dv_image *) descriptor->image_view->vk.image; - return image->mem->bo; + assert(map->plane[index] < image->plane_count); + return image->planes[map->plane[index]].mem->bo; } default: unreachable("descriptor type doesn't has a texture bo"); @@ -299,11 +283,66 @@ v3dv_descriptor_map_get_texture_shader_state(struct v3dv_device *device, type == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER); if (type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) - reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)(); + reloc.offset += v3dv_X(device, combined_image_sampler_texture_state_offset)(map->plane[index]); return reloc; } +#define SHA1_UPDATE_VALUE(ctx, x) _mesa_sha1_update(ctx, &(x), sizeof(x)); + +static void +sha1_update_ycbcr_conversion(struct mesa_sha1 *ctx, + const struct vk_ycbcr_conversion_state *conversion) +{ + SHA1_UPDATE_VALUE(ctx, conversion->format); + SHA1_UPDATE_VALUE(ctx, conversion->ycbcr_model); + SHA1_UPDATE_VALUE(ctx, conversion->ycbcr_range); + SHA1_UPDATE_VALUE(ctx, conversion->mapping); + SHA1_UPDATE_VALUE(ctx, conversion->chroma_offsets); + SHA1_UPDATE_VALUE(ctx, conversion->chroma_reconstruction); +} + +static void +sha1_update_descriptor_set_binding_layout(struct mesa_sha1 *ctx, + const struct v3dv_descriptor_set_binding_layout *layout, + const struct v3dv_descriptor_set_layout *set_layout) +{ + SHA1_UPDATE_VALUE(ctx, layout->type); + SHA1_UPDATE_VALUE(ctx, layout->array_size); + SHA1_UPDATE_VALUE(ctx, layout->descriptor_index); + SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count); + SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_index); + SHA1_UPDATE_VALUE(ctx, layout->descriptor_offset); + SHA1_UPDATE_VALUE(ctx, layout->immutable_samplers_offset); + SHA1_UPDATE_VALUE(ctx, layout->plane_stride); + + if (layout->immutable_samplers_offset) { + const struct v3dv_sampler *immutable_samplers = + v3dv_immutable_samplers(set_layout, layout); + + for (unsigned i = 0; i < layout->array_size; i++) { + const struct v3dv_sampler *sampler = &immutable_samplers[i]; + if (sampler->conversion) + sha1_update_ycbcr_conversion(ctx, &sampler->conversion->state); + } + } +} + +static void +sha1_update_descriptor_set_layout(struct mesa_sha1 *ctx, + const struct v3dv_descriptor_set_layout *layout) +{ + SHA1_UPDATE_VALUE(ctx, layout->flags); + SHA1_UPDATE_VALUE(ctx, layout->binding_count); + SHA1_UPDATE_VALUE(ctx, layout->shader_stages); + SHA1_UPDATE_VALUE(ctx, layout->descriptor_count); + SHA1_UPDATE_VALUE(ctx, layout->dynamic_offset_count); + + for (uint16_t i = 0; i < layout->binding_count; i++) + sha1_update_descriptor_set_binding_layout(ctx, &layout->binding[i], layout); +} + + /* * As anv and tu already points: * @@ -326,16 +365,17 @@ v3dv_CreatePipelineLayout(VkDevice _device, layout = vk_object_zalloc(&device->vk, pAllocator, sizeof(*layout), VK_OBJECT_TYPE_PIPELINE_LAYOUT); if (layout == NULL) - return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); layout->num_sets = pCreateInfo->setLayoutCount; + layout->ref_cnt = 1; uint32_t dynamic_offset_count = 0; for (uint32_t set = 0; set < pCreateInfo->setLayoutCount; set++) { V3DV_FROM_HANDLE(v3dv_descriptor_set_layout, set_layout, pCreateInfo->pSetLayouts[set]); + v3dv_descriptor_set_layout_ref(set_layout); layout->set[set].layout = set_layout; - layout->set[set].dynamic_offset_start = dynamic_offset_count; for (uint32_t b = 0; b < set_layout->binding_count; b++) { dynamic_offset_count += set_layout->binding[b].array_size * @@ -356,11 +396,34 @@ v3dv_CreatePipelineLayout(VkDevice _device, layout->dynamic_offset_count = dynamic_offset_count; + struct mesa_sha1 ctx; + _mesa_sha1_init(&ctx); + for (unsigned s = 0; s < layout->num_sets; s++) { + sha1_update_descriptor_set_layout(&ctx, layout->set[s].layout); + _mesa_sha1_update(&ctx, &layout->set[s].dynamic_offset_start, + sizeof(layout->set[s].dynamic_offset_start)); + } + _mesa_sha1_update(&ctx, &layout->num_sets, sizeof(layout->num_sets)); + _mesa_sha1_final(&ctx, layout->sha1); + *pPipelineLayout = v3dv_pipeline_layout_to_handle(layout); return VK_SUCCESS; } +void +v3dv_pipeline_layout_destroy(struct v3dv_device *device, + struct v3dv_pipeline_layout *layout, + const VkAllocationCallbacks *alloc) +{ + assert(layout); + + for (uint32_t i = 0; i < layout->num_sets; i++) + v3dv_descriptor_set_layout_unref(device, layout->set[i].layout); + + vk_object_free(&device->vk, alloc, layout); +} + VKAPI_ATTR void VKAPI_CALL v3dv_DestroyPipelineLayout(VkDevice _device, VkPipelineLayout _pipelineLayout, @@ -371,7 +434,8 @@ v3dv_DestroyPipelineLayout(VkDevice _device, if (!pipeline_layout) return; - vk_object_free(&device->vk, pAllocator, pipeline_layout); + + v3dv_pipeline_layout_unref(device, pipeline_layout, pAllocator); } VKAPI_ATTR VkResult VKAPI_CALL @@ -393,7 +457,10 @@ v3dv_CreateDescriptorPool(VkDevice _device, uint32_t bo_size = 0; uint32_t descriptor_count = 0; - assert(pCreateInfo->poolSizeCount > 0); + const VkDescriptorPoolInlineUniformBlockCreateInfo *inline_info = + vk_find_struct_const(pCreateInfo->pNext, + DESCRIPTOR_POOL_INLINE_UNIFORM_BLOCK_CREATE_INFO); + for (unsigned i = 0; i < pCreateInfo->poolSizeCount; ++i) { /* Verify supported descriptor type */ switch(pCreateInfo->pPoolSizes[i].type) { @@ -408,6 +475,7 @@ v3dv_CreateDescriptorPool(VkDevice _device, case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: break; default: unreachable("Unimplemented descriptor type"); @@ -415,9 +483,28 @@ v3dv_CreateDescriptorPool(VkDevice _device, } assert(pCreateInfo->pPoolSizes[i].descriptorCount > 0); - descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount; - bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) * - pCreateInfo->pPoolSizes[i].descriptorCount; + if (pCreateInfo->pPoolSizes[i].type == + VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { + /* Inline uniform blocks are specified to use the descriptor array + * size as the size in bytes of the block. + */ + assert(inline_info); + descriptor_count += inline_info->maxInlineUniformBlockBindings; + bo_size += pCreateInfo->pPoolSizes[i].descriptorCount; + } else { + descriptor_count += pCreateInfo->pPoolSizes[i].descriptorCount; + bo_size += v3dv_X(device, descriptor_bo_size)(pCreateInfo->pPoolSizes[i].type) * + pCreateInfo->pPoolSizes[i].descriptorCount; + } + } + + /* We align all our buffers to V3D_NON_COHERENT_ATOM_SIZE, make sure we + * allocate enough memory to honor that requirement for all our inline + * buffers too. + */ + if (inline_info) { + bo_size += V3D_NON_COHERENT_ATOM_SIZE * + inline_info->maxInlineUniformBlockBindings; } if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { @@ -433,7 +520,7 @@ v3dv_CreateDescriptorPool(VkDevice _device, VK_OBJECT_TYPE_DESCRIPTOR_POOL); if (!pool) - return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); if (!(pCreateInfo->flags & VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT)) { pool->host_memory_base = (uint8_t*)pool + sizeof(struct v3dv_descriptor_pool); @@ -457,13 +544,15 @@ v3dv_CreateDescriptorPool(VkDevice _device, pool->bo = NULL; } + list_inithead(&pool->set_list); + *pDescriptorPool = v3dv_descriptor_pool_to_handle(pool); return VK_SUCCESS; out_of_device_memory: vk_object_free(&device->vk, pAllocator, pool); - return vk_error(device->instance, VK_ERROR_OUT_OF_DEVICE_MEMORY); + return vk_error(device, VK_ERROR_OUT_OF_DEVICE_MEMORY); } static void @@ -498,6 +587,11 @@ v3dv_DestroyDescriptorPool(VkDevice _device, if (!pool) return; + list_for_each_entry_safe(struct v3dv_descriptor_set, set, + &pool->set_list, pool_link) { + v3dv_descriptor_set_layout_unref(device, set->layout); + } + if (!pool->host_memory_base) { for(int i = 0; i < pool->entry_count; ++i) { descriptor_set_destroy(device, pool, pool->entries[i].set, false); @@ -520,6 +614,12 @@ v3dv_ResetDescriptorPool(VkDevice _device, V3DV_FROM_HANDLE(v3dv_device, device, _device); V3DV_FROM_HANDLE(v3dv_descriptor_pool, pool, descriptorPool); + list_for_each_entry_safe(struct v3dv_descriptor_set, set, + &pool->set_list, pool_link) { + v3dv_descriptor_set_layout_unref(device, set->layout); + } + list_inithead(&pool->set_list); + if (!pool->host_memory_base) { for(int i = 0; i < pool->entry_count; ++i) { descriptor_set_destroy(device, pool, pool->entries[i].set, false); @@ -539,6 +639,15 @@ v3dv_ResetDescriptorPool(VkDevice _device, return VK_SUCCESS; } +void +v3dv_descriptor_set_layout_destroy(struct v3dv_device *device, + struct v3dv_descriptor_set_layout *set_layout) +{ + assert(set_layout->ref_cnt == 0); + vk_object_base_finish(&set_layout->base); + vk_free2(&device->vk.alloc, NULL, set_layout); +} + VKAPI_ATTR VkResult VKAPI_CALL v3dv_CreateDescriptorSetLayout(VkDevice _device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo, @@ -552,6 +661,13 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, uint32_t num_bindings = 0; uint32_t immutable_sampler_count = 0; + + /* for immutable descriptors, the plane stride is the largest plane + * count of all combined image samplers. For mutable descriptors + * this is always 1 since multiplanar images are restricted to + * immutable combined image samplers. + */ + uint8_t plane_stride = 1; for (uint32_t j = 0; j < pCreateInfo->bindingCount; j++) { num_bindings = MAX2(num_bindings, pCreateInfo->pBindings[j].binding + 1); @@ -570,22 +686,40 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, if ((desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || desc_type == VK_DESCRIPTOR_TYPE_SAMPLER) && pCreateInfo->pBindings[j].pImmutableSamplers) { - immutable_sampler_count += pCreateInfo->pBindings[j].descriptorCount; + uint32_t descriptor_count = pCreateInfo->pBindings[j].descriptorCount; + immutable_sampler_count += descriptor_count; + + for (uint32_t i = 0; i < descriptor_count; i++) { + const VkSampler vk_sampler = + pCreateInfo->pBindings[j].pImmutableSamplers[i]; + VK_FROM_HANDLE(v3dv_sampler, sampler, vk_sampler); + plane_stride = MAX2(plane_stride, sampler->plane_count); + } } } - uint32_t samplers_offset = sizeof(struct v3dv_descriptor_set_layout) + - num_bindings * sizeof(set_layout->binding[0]); + /* We place immutable samplers after the binding data. We want to use + * offsetof instead of any sizeof(struct v3dv_descriptor_set_layout) + * because the latter may include padding at the end of the struct. + */ + uint32_t samplers_offset = + offsetof(struct v3dv_descriptor_set_layout, binding[num_bindings]); + uint32_t size = samplers_offset + immutable_sampler_count * sizeof(struct v3dv_sampler); - set_layout = vk_object_zalloc(&device->vk, pAllocator, size, - VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); - + /* Descriptor set layouts are reference counted and therefore can survive + * vkDestroyPipelineSetLayout, so they need to be allocated with a device + * scope. + */ + set_layout = + vk_zalloc(&device->vk.alloc, size, 8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE); if (!set_layout) - return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); + + vk_object_base_init(&device->vk, &set_layout->base, + VK_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT); - /* We just allocate all the immutable samplers at the end of the struct */ struct v3dv_sampler *samplers = (void*) &set_layout->binding[num_bindings]; assert(pCreateInfo->bindingCount == 0 || num_bindings > 0); @@ -594,17 +728,15 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, VkResult result = vk_create_sorted_bindings(pCreateInfo->pBindings, pCreateInfo->bindingCount, &bindings); if (result != VK_SUCCESS) { - vk_object_free(&device->vk, pAllocator, set_layout); - return vk_error(device->instance, result); + v3dv_descriptor_set_layout_destroy(device, set_layout); + return vk_error(device, result); } - memset(set_layout->binding, 0, - size - sizeof(struct v3dv_descriptor_set_layout)); - set_layout->binding_count = num_bindings; set_layout->flags = pCreateInfo->flags; set_layout->shader_stages = 0; set_layout->bo_size = 0; + set_layout->ref_cnt = 1; uint32_t descriptor_count = 0; uint32_t dynamic_offset_count = 0; @@ -628,6 +760,7 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: /* Nothing here, just to keep the descriptor type filtering below */ break; default: @@ -639,6 +772,7 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, set_layout->binding[binding_number].array_size = binding->descriptorCount; set_layout->binding[binding_number].descriptor_index = descriptor_count; set_layout->binding[binding_number].dynamic_offset_index = dynamic_offset_count; + set_layout->binding[binding_number].plane_stride = plane_stride; if ((binding->descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER || binding->descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) && @@ -651,18 +785,40 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, samplers += binding->descriptorCount; samplers_offset += sizeof(struct v3dv_sampler) * binding->descriptorCount; - } - descriptor_count += binding->descriptorCount; - dynamic_offset_count += binding->descriptorCount * - set_layout->binding[binding_number].dynamic_offset_count; + set_layout->binding[binding_number].plane_stride = plane_stride; + } set_layout->shader_stages |= binding->stageFlags; - set_layout->binding[binding_number].descriptor_offset = set_layout->bo_size; - set_layout->bo_size += - v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) * - binding->descriptorCount; + if (binding->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { + dynamic_offset_count += binding->descriptorCount * + set_layout->binding[binding_number].dynamic_offset_count; + + descriptor_count += binding->descriptorCount; + + set_layout->binding[binding_number].descriptor_offset = + set_layout->bo_size; + set_layout->bo_size += + v3dv_X(device, descriptor_bo_size)(set_layout->binding[binding_number].type) * + binding->descriptorCount * set_layout->binding[binding_number].plane_stride; + } else { + /* We align all our buffers, inline buffers too. We made sure to take + * this account when calculating total BO size requirements at pool + * creation time. + */ + set_layout->bo_size = align(set_layout->bo_size, + V3D_NON_COHERENT_ATOM_SIZE); + + set_layout->binding[binding_number].descriptor_offset = + set_layout->bo_size; + + /* Inline uniform blocks are not arrayed, instead descriptorCount + * specifies the size of the buffer in bytes. + */ + set_layout->bo_size += binding->descriptorCount; + descriptor_count++; + } } free(bindings); @@ -686,7 +842,7 @@ v3dv_DestroyDescriptorSetLayout(VkDevice _device, if (!set_layout) return; - vk_object_free(&device->vk, pAllocator, set_layout); + v3dv_descriptor_set_layout_unref(device, set_layout); } static inline VkResult @@ -697,7 +853,7 @@ out_of_pool_memory(const struct v3dv_device *device, * by allocating a new pool, so they don't point to real issues. */ if (!pool->is_driver_internal) - return vk_error(device->instance, VK_ERROR_OUT_OF_POOL_MEMORY) + return vk_error(device, VK_ERROR_OUT_OF_POOL_MEMORY); else return VK_ERROR_OUT_OF_POOL_MEMORY; } @@ -705,7 +861,7 @@ out_of_pool_memory(const struct v3dv_device *device, static VkResult descriptor_set_create(struct v3dv_device *device, struct v3dv_descriptor_pool *pool, - const struct v3dv_descriptor_set_layout *layout, + struct v3dv_descriptor_set_layout *layout, struct v3dv_descriptor_set **out_set) { struct v3dv_descriptor_set *set; @@ -726,7 +882,7 @@ descriptor_set_create(struct v3dv_device *device, VK_OBJECT_TYPE_DESCRIPTOR_SET); if (!set) - return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); + return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY); } set->pool = pool; @@ -797,19 +953,24 @@ descriptor_set_create(struct v3dv_device *device, layout->binding[b].immutable_samplers_offset); for (uint32_t i = 0; i < layout->binding[b].array_size; i++) { - uint32_t combined_offset = - layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? - v3dv_X(device, combined_image_sampler_sampler_state_offset)() : 0; - - void *desc_map = descriptor_bo_map(device, set, &layout->binding[b], i); - desc_map += combined_offset; - - memcpy(desc_map, - samplers[i].sampler_state, - sizeof(samplers[i].sampler_state)); + assert(samplers[i].plane_count <= V3DV_MAX_PLANE_COUNT); + for (uint8_t plane = 0; plane < samplers[i].plane_count; plane++) { + uint32_t combined_offset = + layout->binding[b].type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? + v3dv_X(device, combined_image_sampler_sampler_state_offset)(plane) : 0; + void *desc_map = + descriptor_bo_map(device, set, &layout->binding[b], i); + desc_map += combined_offset; + + memcpy(desc_map, samplers[i].sampler_state, + sizeof(samplers[i].sampler_state)); + } } } + v3dv_descriptor_set_layout_ref(layout); + list_addtail(&set->pool_link, &pool->set_list); + *out_set = set; return VK_SUCCESS; @@ -860,8 +1021,13 @@ v3dv_FreeDescriptorSets(VkDevice _device, for (uint32_t i = 0; i < count; i++) { V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]); - if (set && !pool->host_memory_base) - descriptor_set_destroy(device, pool, set, true); + + if (set) { + v3dv_descriptor_set_layout_unref(device, set->layout); + list_del(&set->pool_link); + if (!pool->host_memory_base) + descriptor_set_destroy(device, pool, set, true); + } } return VK_SUCCESS; @@ -877,11 +1043,16 @@ descriptor_bo_copy(struct v3dv_device *device, uint32_t src_array_index) { assert(dst_binding_layout->type == src_binding_layout->type); + assert(src_binding_layout->plane_stride == dst_binding_layout->plane_stride); - void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, dst_array_index); - void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, src_array_index); + void *dst_map = descriptor_bo_map(device, dst_set, dst_binding_layout, + dst_array_index); + void *src_map = descriptor_bo_map(device, src_set, src_binding_layout, + src_array_index); - memcpy(dst_map, src_map, v3dv_X(device, descriptor_bo_size)(src_binding_layout->type)); + memcpy(dst_map, src_map, + v3dv_X(device, descriptor_bo_size)(src_binding_layout->type) * + src_binding_layout->plane_stride); } static void @@ -916,26 +1087,39 @@ write_image_descriptor(struct v3dv_device *device, descriptor->sampler = sampler; descriptor->image_view = iview; + assert(iview || sampler); + uint8_t plane_count = iview ? iview->plane_count : sampler->plane_count; + void *desc_map = descriptor_bo_map(device, set, binding_layout, array_index); - if (iview) { - const uint32_t tex_state_index = - iview->vk.view_type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY || - desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1; - memcpy(desc_map, - iview->texture_shader_state[tex_state_index], - sizeof(iview->texture_shader_state[0])); - desc_map += v3dv_X(device, combined_image_sampler_sampler_state_offset)(); - } + for (uint8_t plane = 0; plane < plane_count; plane++) { + if (iview) { + uint32_t offset = desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? + v3dv_X(device, combined_image_sampler_texture_state_offset)(plane) : 0; - if (sampler && !binding_layout->immutable_samplers_offset) { - /* For immutable samplers this was already done as part of the - * descriptor set create, as that info can't change later - */ - memcpy(desc_map, - sampler->sampler_state, - sizeof(sampler->sampler_state)); + void *plane_desc_map = desc_map + offset; + + const uint32_t tex_state_index = + iview->vk.view_type != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY || + desc_type != VK_DESCRIPTOR_TYPE_STORAGE_IMAGE ? 0 : 1; + memcpy(plane_desc_map, + iview->planes[plane].texture_shader_state[tex_state_index], + sizeof(iview->planes[plane].texture_shader_state[0])); + } + + if (sampler && !binding_layout->immutable_samplers_offset) { + uint32_t offset = desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ? + v3dv_X(device, combined_image_sampler_sampler_state_offset)(plane) : 0; + + void *plane_desc_map = desc_map + offset; + /* For immutable samplers this was already done as part of the + * descriptor set create, as that info can't change later + */ + memcpy(plane_desc_map, + sampler->sampler_state, + sizeof(sampler->sampler_state)); + } } } @@ -960,6 +1144,31 @@ write_buffer_view_descriptor(struct v3dv_device *device, sizeof(bview->texture_shader_state)); } +static void +write_inline_uniform_descriptor(struct v3dv_device *device, + struct v3dv_descriptor *descriptor, + struct v3dv_descriptor_set *set, + const struct v3dv_descriptor_set_binding_layout *binding_layout, + const void *data, + size_t offset, + size_t size) +{ + assert(binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK); + descriptor->type = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK; + descriptor->buffer = NULL; + + void *desc_map = descriptor_bo_map(device, set, binding_layout, 0); + memcpy(desc_map + offset, data, size); + + /* Inline uniform buffers allocate BO space in the pool for all inline + * buffers it may allocate and then this space is assigned to individual + * descriptors when they are written, so we define the range of an inline + * buffer as the largest range of data that the client has written to it. + */ + descriptor->offset = 0; + descriptor->range = MAX2(descriptor->range, offset + size); +} + VKAPI_ATTR void VKAPI_CALL v3dv_UpdateDescriptorSets(VkDevice _device, uint32_t descriptorWriteCount, @@ -978,9 +1187,20 @@ v3dv_UpdateDescriptorSets(VkDevice _device, struct v3dv_descriptor *descriptor = set->descriptors; descriptor += binding_layout->descriptor_index; - descriptor += writeset->dstArrayElement; - for (uint32_t j = 0; j < writeset->descriptorCount; ++j) { + /* Inline uniform blocks are not arrayed, instead they use dstArrayElement + * to specify the byte offset of the uniform update and descriptorCount + * to specify the size (in bytes) of the update. + */ + uint32_t descriptor_count; + if (writeset->descriptorType != VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { + descriptor += writeset->dstArrayElement; + descriptor_count = writeset->descriptorCount; + } else { + descriptor_count = 1; + } + + for (uint32_t j = 0; j < descriptor_count; ++j) { switch(writeset->descriptorType) { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: @@ -993,12 +1213,11 @@ v3dv_UpdateDescriptorSets(VkDevice _device, break; } case VK_DESCRIPTOR_TYPE_SAMPLER: { - /* If we are here we shouldn't be modifying a immutable sampler, - * so we don't ensure that would work or not crash. But let the - * validation layers check that - */ + /* If we are here we shouldn't be modifying an immutable sampler */ + assert(!binding_layout->immutable_samplers_offset); const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j; V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler); + write_image_descriptor(device, descriptor, writeset->descriptorType, set, binding_layout, NULL, sampler, writeset->dstArrayElement + j); @@ -1010,6 +1229,7 @@ v3dv_UpdateDescriptorSets(VkDevice _device, case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE: { const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j; V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView); + write_image_descriptor(device, descriptor, writeset->descriptorType, set, binding_layout, iview, NULL, writeset->dstArrayElement + j); @@ -1019,7 +1239,17 @@ v3dv_UpdateDescriptorSets(VkDevice _device, case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: { const VkDescriptorImageInfo *image_info = writeset->pImageInfo + j; V3DV_FROM_HANDLE(v3dv_image_view, iview, image_info->imageView); - V3DV_FROM_HANDLE(v3dv_sampler, sampler, image_info->sampler); + struct v3dv_sampler *sampler = NULL; + if (!binding_layout->immutable_samplers_offset) { + /* In general we ignore the sampler when updating a combined + * image sampler, but for YCbCr we kwnow that we must use + * immutable combined image samplers + */ + assert(iview->plane_count == 1); + V3DV_FROM_HANDLE(v3dv_sampler, _sampler, image_info->sampler); + sampler = _sampler; + } + write_image_descriptor(device, descriptor, writeset->descriptorType, set, binding_layout, iview, sampler, writeset->dstArrayElement + j); @@ -1035,6 +1265,18 @@ v3dv_UpdateDescriptorSets(VkDevice _device, writeset->dstArrayElement + j); break; } + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: { + const VkWriteDescriptorSetInlineUniformBlock *inline_write = + vk_find_struct_const(writeset->pNext, + WRITE_DESCRIPTOR_SET_INLINE_UNIFORM_BLOCK); + assert(inline_write->dataSize == writeset->descriptorCount); + write_inline_uniform_descriptor(device, descriptor, set, + binding_layout, + inline_write->pData, + writeset->dstArrayElement, /* offset */ + inline_write->dataSize); + break; + } default: unreachable("unimplemented descriptor type"); break; @@ -1061,9 +1303,25 @@ v3dv_UpdateDescriptorSets(VkDevice _device, struct v3dv_descriptor *dst_descriptor = dst_set->descriptors; src_descriptor += src_binding_layout->descriptor_index; - src_descriptor += copyset->srcArrayElement; - dst_descriptor += dst_binding_layout->descriptor_index; + + if (src_binding_layout->type == VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK) { + /* {src,dst}ArrayElement specifies src/dst start offset and + * descriptorCount specifies size (in bytes) to copy. + */ + const void *src_data = src_set->pool->bo->map + + src_set->base_offset + + src_binding_layout->descriptor_offset + + copyset->srcArrayElement; + write_inline_uniform_descriptor(device, dst_descriptor, dst_set, + dst_binding_layout, + src_data, + copyset->dstArrayElement, + copyset->descriptorCount); + continue; + } + + src_descriptor += copyset->srcArrayElement; dst_descriptor += copyset->dstArrayElement; for (uint32_t j = 0; j < copyset->descriptorCount; j++) { @@ -1127,66 +1385,6 @@ v3dv_GetDescriptorSetLayoutSupport( pSupport->supported = supported; } -VkResult -v3dv_CreateDescriptorUpdateTemplate( - VkDevice _device, - const VkDescriptorUpdateTemplateCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkDescriptorUpdateTemplate *pDescriptorUpdateTemplate) -{ - V3DV_FROM_HANDLE(v3dv_device, device, _device); - struct v3dv_descriptor_update_template *template; - - size_t size = sizeof(*template) + - pCreateInfo->descriptorUpdateEntryCount * sizeof(template->entries[0]); - template = vk_object_alloc(&device->vk, pAllocator, size, - VK_OBJECT_TYPE_DESCRIPTOR_UPDATE_TEMPLATE); - if (template == NULL) - return vk_error(device->instance, VK_ERROR_OUT_OF_HOST_MEMORY); - - template->bind_point = pCreateInfo->pipelineBindPoint; - - assert(pCreateInfo->templateType == - VK_DESCRIPTOR_UPDATE_TEMPLATE_TYPE_DESCRIPTOR_SET); - template->set = pCreateInfo->set; - - template->entry_count = pCreateInfo->descriptorUpdateEntryCount; - for (uint32_t i = 0; i < template->entry_count; i++) { - const VkDescriptorUpdateTemplateEntry *pEntry = - &pCreateInfo->pDescriptorUpdateEntries[i]; - - template->entries[i] = (struct v3dv_descriptor_template_entry) { - .type = pEntry->descriptorType, - .binding = pEntry->dstBinding, - .array_element = pEntry->dstArrayElement, - .array_count = pEntry->descriptorCount, - .offset = pEntry->offset, - .stride = pEntry->stride, - }; - } - - *pDescriptorUpdateTemplate = - v3dv_descriptor_update_template_to_handle(template); - - return VK_SUCCESS; -} - -void -v3dv_DestroyDescriptorUpdateTemplate( - VkDevice _device, - VkDescriptorUpdateTemplate descriptorUpdateTemplate, - const VkAllocationCallbacks *pAllocator) -{ - V3DV_FROM_HANDLE(v3dv_device, device, _device); - V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template, - descriptorUpdateTemplate); - - if (!template) - return; - - vk_object_free(&device->vk, pAllocator, template); -} - void v3dv_UpdateDescriptorSetWithTemplate( VkDevice _device, @@ -1196,11 +1394,11 @@ v3dv_UpdateDescriptorSetWithTemplate( { V3DV_FROM_HANDLE(v3dv_device, device, _device); V3DV_FROM_HANDLE(v3dv_descriptor_set, set, descriptorSet); - V3DV_FROM_HANDLE(v3dv_descriptor_update_template, template, + V3DV_FROM_HANDLE(vk_descriptor_update_template, template, descriptorUpdateTemplate); for (int i = 0; i < template->entry_count; i++) { - const struct v3dv_descriptor_template_entry *entry = + const struct vk_descriptor_template_entry *entry = &template->entries[i]; const struct v3dv_descriptor_set_binding_layout *binding_layout = @@ -1208,8 +1406,7 @@ v3dv_UpdateDescriptorSetWithTemplate( struct v3dv_descriptor *descriptor = set->descriptors + - binding_layout->descriptor_index + - entry->array_element; + binding_layout->descriptor_index; switch (entry->type) { case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: @@ -1219,7 +1416,8 @@ v3dv_UpdateDescriptorSetWithTemplate( for (uint32_t j = 0; j < entry->array_count; j++) { const VkDescriptorBufferInfo *info = pData + entry->offset + j * entry->stride; - write_buffer_descriptor(descriptor + j, entry->type, info); + write_buffer_descriptor(descriptor + entry->array_element + j, + entry->type, info); } break; @@ -1233,9 +1431,9 @@ v3dv_UpdateDescriptorSetWithTemplate( pData + entry->offset + j * entry->stride; V3DV_FROM_HANDLE(v3dv_image_view, iview, info->imageView); V3DV_FROM_HANDLE(v3dv_sampler, sampler, info->sampler); - write_image_descriptor(device, descriptor + j, entry->type, - set, binding_layout, iview, sampler, - entry->array_element + j); + write_image_descriptor(device, descriptor + entry->array_element + j, + entry->type, set, binding_layout, iview, + sampler, entry->array_element + j); } break; @@ -1245,34 +1443,24 @@ v3dv_UpdateDescriptorSetWithTemplate( const VkBufferView *_bview = pData + entry->offset + j * entry->stride; V3DV_FROM_HANDLE(v3dv_buffer_view, bview, *_bview); - write_buffer_view_descriptor(device, descriptor + j, entry->type, - set, binding_layout, bview, + write_buffer_view_descriptor(device, + descriptor + entry->array_element + j, + entry->type, set, binding_layout, bview, entry->array_element + j); } break; + case VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK: { + write_inline_uniform_descriptor(device, descriptor, set, + binding_layout, + pData + entry->offset, + entry->array_element, /* offset */ + entry->array_count); /* size */ + break; + } + default: unreachable("Unsupported descriptor type"); } } } - -VKAPI_ATTR VkResult VKAPI_CALL -v3dv_CreateSamplerYcbcrConversion( - VkDevice _device, - const VkSamplerYcbcrConversionCreateInfo *pCreateInfo, - const VkAllocationCallbacks *pAllocator, - VkSamplerYcbcrConversion *pYcbcrConversion) -{ - unreachable("Ycbcr sampler conversion is not supported"); - return VK_SUCCESS; -} - -VKAPI_ATTR void VKAPI_CALL -v3dv_DestroySamplerYcbcrConversion( - VkDevice _device, - VkSamplerYcbcrConversion YcbcrConversion, - const VkAllocationCallbacks *pAllocator) -{ - unreachable("Ycbcr sampler conversion is not supported"); -} |