summaryrefslogtreecommitdiff
path: root/src/broadcom/vulkan/v3dv_descriptor_set.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/broadcom/vulkan/v3dv_descriptor_set.c')
-rw-r--r--src/broadcom/vulkan/v3dv_descriptor_set.c600
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");
-}