v3dv/descriptor: support for dynamic ubo/ssbo
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6766>
diff --git a/src/broadcom/vulkan/v3dv_cmd_buffer.c b/src/broadcom/vulkan/v3dv_cmd_buffer.c
index b455b78..59eab90 100644
--- a/src/broadcom/vulkan/v3dv_cmd_buffer.c
+++ b/src/broadcom/vulkan/v3dv_cmd_buffer.c
@@ -2346,16 +2346,28 @@
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 42eb505..625a80f 100644
--- a/src/broadcom/vulkan/v3dv_descriptor_set.c
+++ b/src/broadcom/vulkan/v3dv_descriptor_set.c
@@ -51,12 +51,21 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
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 69d6155..689cdef 100644
--- a/src/broadcom/vulkan/v3dv_pipeline.c
+++ b/src/broadcom/vulkan/v3dv_pipeline.c
@@ -975,8 +975,6 @@
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 @@
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->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 943c4e0..1c45d99 100644
--- a/src/broadcom/vulkan/v3dv_private.h
+++ b/src/broadcom/vulkan/v3dv_private.h
@@ -123,6 +123,11 @@
#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_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 @@
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 @@
/* 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 @@
} set[MAX_SETS];
uint32_t num_sets;
+ uint32_t dynamic_offset_count;
};
struct v3dv_descriptor_map {
@@ -824,6 +837,8 @@
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 20e3188..70151cf 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 @@
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 @@
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 @@
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;
}