From 5d1089b88dfbcd241527170b49b7a0608c24e97c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandro=20Pi=C3=B1eiro?= Date: Mon, 24 Feb 2020 11:32:57 +0100 Subject: [PATCH] v3dv/descriptor: support for dynamic ubo/ssbo Part-of: --- src/broadcom/vulkan/v3dv_cmd_buffer.c | 16 ++++++++-- src/broadcom/vulkan/v3dv_descriptor_set.c | 23 +++++++++++++ src/broadcom/vulkan/v3dv_pipeline.c | 7 ++-- src/broadcom/vulkan/v3dv_private.h | 15 +++++++++ src/broadcom/vulkan/v3dv_uniforms.c | 39 +++++++++++++++++++++-- 5 files changed, 92 insertions(+), 8 deletions(-) diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c index b455b7838f7..59eab90cb19 100644 --- a/src/broadcom/vulkan/v3dv_cmd_buffer.c +++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c @@ -2346,16 +2346,28 @@ v3dv_CmdBindDescriptorSets(VkCommandBuffer commandBuffer, const uint32_t *pDynamicOffsets) { V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer); + V3DV_FROM_HANDLE(v3dv_pipeline_layout, layout, _layout); + + uint32_t dyn_index = 0; assert(pipelineBindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS); assert(firstSet + descriptorSetCount <= MAX_SETS); + struct v3dv_descriptor_state *descriptor_state = + &cmd_buffer->state.descriptor_state; + for (uint32_t i = 0; i < descriptorSetCount; i++) { V3DV_FROM_HANDLE(v3dv_descriptor_set, set, pDescriptorSets[i]); uint32_t index = firstSet + i; - cmd_buffer->state.descriptor_state.descriptor_sets[index] = set; - cmd_buffer->state.descriptor_state.valid |= (1u << index); + descriptor_state->descriptor_sets[index] = set; + descriptor_state->valid |= (1u << index); + + for (uint32_t j = 0; j < set->layout->dynamic_offset_count; j++, dyn_index++) { + uint32_t idx = j + layout->set[i + firstSet].dynamic_offset_start; + + descriptor_state->dynamic_offsets[idx] = pDynamicOffsets[dyn_index]; + } } cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_DESCRIPTOR_SETS; diff --git a/src/broadcom/vulkan/v3dv_descriptor_set.c b/src/broadcom/vulkan/v3dv_descriptor_set.c index 42eb505ff6d..625a80f0456 100644 --- a/src/broadcom/vulkan/v3dv_descriptor_set.c +++ b/src/broadcom/vulkan/v3dv_descriptor_set.c @@ -51,12 +51,21 @@ v3dv_CreatePipelineLayout(VkDevice _device, layout->num_sets = pCreateInfo->setLayoutCount; + 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]); 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 * + set_layout->binding[b].dynamic_offset_count; + } } + layout->dynamic_offset_count = dynamic_offset_count; + *pPipelineLayout = v3dv_pipeline_layout_to_handle(layout); return VK_SUCCESS; @@ -94,6 +103,9 @@ v3dv_CreateDescriptorPool(VkDevice _device, case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + break; default: unreachable("Unimplemented descriptor type"); break; @@ -264,6 +276,7 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, set_layout->shader_stages = 0; uint32_t descriptor_count = 0; + uint32_t dynamic_offset_count = 0; for (uint32_t i = 0; i < pCreateInfo->bindingCount; i++) { const VkDescriptorSetLayoutBinding *binding = bindings + i; @@ -273,6 +286,10 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + set_layout->binding[binding_number].dynamic_offset_count = 1; + break; default: unreachable("Unknown descriptor type\n"); break; @@ -281,8 +298,11 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, set_layout->binding[binding_number].type = binding->descriptorType; 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; descriptor_count += binding->descriptorCount; + dynamic_offset_count += binding->descriptorCount * + set_layout->binding[binding_number].dynamic_offset_count; /* FIXME: right now we don't use shader_stages. We could explore if we * could use it to add another filter to upload or allocate the @@ -294,6 +314,7 @@ v3dv_CreateDescriptorSetLayout(VkDevice _device, vk_free2(&device->alloc, pAllocator, bindings); set_layout->descriptor_count = descriptor_count; + set_layout->dynamic_offset_count = dynamic_offset_count; *pSetLayout = v3dv_descriptor_set_layout_to_handle(set_layout); @@ -435,6 +456,8 @@ v3dv_UpdateDescriptorSets(VkDevice _device, switch(writeset->descriptorType) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: { const VkDescriptorBufferInfo *buffer_info = writeset->pBufferInfo + j; diff --git a/src/broadcom/vulkan/v3dv_pipeline.c b/src/broadcom/vulkan/v3dv_pipeline.c index 69d6155c038..689cdef333c 100644 --- a/src/broadcom/vulkan/v3dv_pipeline.c +++ b/src/broadcom/vulkan/v3dv_pipeline.c @@ -975,8 +975,6 @@ pipeline_compile_graphics(struct v3dv_pipeline *pipeline, next_stage = stages[stage]; } - V3DV_FROM_HANDLE(v3dv_pipeline_layout, layout, pCreateInfo->layout); - /* Compiling to vir */ for (int stage = MESA_SHADER_STAGES - 1; stage >= 0; stage--) { if (stages[stage] == NULL || stages[stage]->entrypoint == NULL) @@ -984,7 +982,7 @@ pipeline_compile_graphics(struct v3dv_pipeline *pipeline, struct v3dv_pipeline_stage *p_stage = stages[stage]; - pipeline_lower_nir(pipeline, p_stage, layout); + pipeline_lower_nir(pipeline, p_stage, pipeline->layout); switch(stage) { case MESA_SHADER_VERTEX: @@ -1608,6 +1606,9 @@ pipeline_init(struct v3dv_pipeline *pipeline, pipeline->device = device; + V3DV_FROM_HANDLE(v3dv_pipeline_layout, layout, pCreateInfo->layout); + pipeline->layout = layout; + V3DV_FROM_HANDLE(v3dv_render_pass, render_pass, pCreateInfo->renderPass); assert(pCreateInfo->subpass < render_pass->subpass_count); pipeline->subpass = &render_pass->subpasses[pCreateInfo->subpass]; diff --git a/src/broadcom/vulkan/v3dv_private.h b/src/broadcom/vulkan/v3dv_private.h index 943c4e00674..1c45d99ac5f 100644 --- a/src/broadcom/vulkan/v3dv_private.h +++ b/src/broadcom/vulkan/v3dv_private.h @@ -123,6 +123,11 @@ pack_emit_reloc(void *cl, const void *reloc) {} #define MAX_PUSH_CONSTANTS_SIZE 128 +#define MAX_DYNAMIC_UNIFORM_BUFFERS 16 +#define MAX_DYNAMIC_STORAGE_BUFFERS 8 +#define MAX_DYNAMIC_BUFFERS \ + (MAX_DYNAMIC_UNIFORM_BUFFERS + MAX_DYNAMIC_STORAGE_BUFFERS) + struct v3dv_instance; #ifdef USE_V3D_SIMULATOR @@ -574,6 +579,7 @@ struct v3dv_vertex_binding { struct v3dv_descriptor_state { struct v3dv_descriptor_set *descriptor_sets[MAX_SETS]; uint32_t valid; + uint32_t dynamic_offsets[MAX_DYNAMIC_BUFFERS]; }; struct v3dv_cmd_buffer_state { @@ -772,6 +778,9 @@ struct v3dv_descriptor_set_binding_layout { uint32_t array_size; uint32_t descriptor_index; + + uint32_t dynamic_offset_count; + uint32_t dynamic_offset_index; }; struct v3dv_descriptor_set_layout { @@ -786,6 +795,9 @@ struct v3dv_descriptor_set_layout { /* Number of descriptors in this descriptor set */ uint32_t descriptor_count; + /* Number of dynamic offsets used by this descriptor set */ + uint16_t dynamic_offset_count; + /* Bindings in this descriptor set */ struct v3dv_descriptor_set_binding_layout binding[0]; }; @@ -797,6 +809,7 @@ struct v3dv_pipeline_layout { } set[MAX_SETS]; uint32_t num_sets; + uint32_t dynamic_offset_count; }; struct v3dv_descriptor_map { @@ -824,6 +837,8 @@ struct v3dv_pipeline { struct v3dv_dynamic_state dynamic_state; + struct v3dv_pipeline_layout *layout; + enum v3dv_ez_state ez_state; bool primitive_restart; diff --git a/src/broadcom/vulkan/v3dv_uniforms.c b/src/broadcom/vulkan/v3dv_uniforms.c index 20e318896b5..70151cf3192 100644 --- a/src/broadcom/vulkan/v3dv_uniforms.c +++ b/src/broadcom/vulkan/v3dv_uniforms.c @@ -27,10 +27,31 @@ #include "v3dv_private.h" +static bool +descriptor_type_is_dynamic(VkDescriptorType type) +{ + switch (type) { + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER: + return false; + break; + case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC: + case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: + return true; + break; + default: + assert(!"descriptor type not supported.\n"); + break; + } + return false; +} + static struct v3dv_descriptor * get_descriptor(struct v3dv_descriptor_state *descriptor_state, struct v3dv_descriptor_map *map, - uint32_t index) + struct v3dv_pipeline_layout *pipeline_layout, + uint32_t index, + uint32_t *dynamic_offset) { assert(index >= 0 && index < map->num_desc); @@ -50,6 +71,14 @@ get_descriptor(struct v3dv_descriptor_state *descriptor_state, uint32_t array_index = map->array_index[index]; assert(array_index < binding_layout->array_size); + if (descriptor_type_is_dynamic(binding_layout->type)) { + uint32_t dynamic_offset_index = + pipeline_layout->set[set_number].dynamic_offset_start + + binding_layout->dynamic_offset_index + array_index; + + *dynamic_offset = descriptor_state->dynamic_offsets[dynamic_offset_index]; + } + return &set->descriptors[binding_layout->descriptor_index + array_index]; } @@ -172,6 +201,8 @@ v3dv_write_uniforms(struct v3dv_cmd_buffer *cmd_buffer, v3d_unit_data_get_offset(data) : 0; /* FIXME */ + uint32_t dynamic_offset = 0; + /* For ubos, index is shifted, as 0 is reserved for push constants. */ struct v3dv_descriptor *descriptor = NULL; @@ -191,13 +222,15 @@ v3dv_write_uniforms(struct v3dv_cmd_buffer *cmd_buffer, data; descriptor = - get_descriptor(descriptor_state, map, index); + get_descriptor(descriptor_state, map, + pipeline->layout, + index, &dynamic_offset); assert(descriptor); } cl_aligned_reloc(&job->indirect, &uniforms, descriptor->bo, - descriptor->offset + offset); + descriptor->offset + offset + dynamic_offset); break; }