panvk: Prepare dynamic buffer descriptors at bind time

We don't need to stop the panvk_buffer_desc objects to then emit the
UBOs/SSBOs descriptors at draw/dispatch time. We can simply prepare
them at bind time and cache the result, to make the
draw/dispatch preparation a simple memcpy.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Mary Guillemard <mary.guillemard@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28399>
This commit is contained in:
Boris Brezillon
2024-01-31 11:09:56 +01:00
committed by Marge Bot
parent a603c66659
commit 9c553bda9c
4 changed files with 88 additions and 54 deletions

View File

@@ -94,8 +94,8 @@ struct panvk_descriptor_state {
struct panvk_push_descriptor_set *push_sets[MAX_SETS];
struct panvk_sysvals sysvals;
struct {
struct panvk_buffer_desc ubos[MAX_DYNAMIC_UNIFORM_BUFFERS];
struct panvk_buffer_desc ssbos[MAX_DYNAMIC_STORAGE_BUFFERS];
struct mali_uniform_buffer_packed ubos[MAX_DYNAMIC_UNIFORM_BUFFERS];
struct panvk_ssbo_addr ssbos[MAX_DYNAMIC_STORAGE_BUFFERS];
} dyn;
mali_ptr sysvals_ptr;
mali_ptr ubos;

View File

@@ -64,6 +64,10 @@ unsigned
panvk_per_arch(pipeline_layout_dyn_desc_ubo_index)(
const struct panvk_pipeline_layout *layout);
unsigned
panvk_per_arch(pipeline_layout_dyn_ubos_offset)(
const struct panvk_pipeline_layout *layout);
unsigned
panvk_per_arch(pipeline_layout_total_ubo_count)(
const struct panvk_pipeline_layout *layout);

View File

@@ -424,19 +424,9 @@ panvk_cmd_prepare_dyn_ssbos(struct panvk_cmd_buffer *cmdbuf,
return;
struct panfrost_ptr ssbo_descs = pan_pool_alloc_aligned(
&cmdbuf->desc_pool.base,
pipeline->layout->num_dyn_ssbos * sizeof(struct panvk_ssbo_addr), 16);
&cmdbuf->desc_pool.base, sizeof(desc_state->dyn.ssbos), 16);
struct panvk_ssbo_addr *ssbos = ssbo_descs.cpu;
for (uint32_t i = 0; i < pipeline->layout->num_dyn_ssbos; i++) {
const struct panvk_buffer_desc *bdesc = &desc_state->dyn.ssbos[i];
ssbos[i] = (struct panvk_ssbo_addr){
.base_addr = panvk_buffer_gpu_ptr(bdesc->buffer, bdesc->offset),
.size = panvk_buffer_range(bdesc->buffer, bdesc->offset, bdesc->size),
};
}
memcpy(ssbo_descs.cpu, desc_state->dyn.ssbos, sizeof(desc_state->dyn.ssbos));
desc_state->dyn_desc_ubo = ssbo_descs.gpu;
}
@@ -479,32 +469,15 @@ panvk_cmd_prepare_ubos(struct panvk_cmd_buffer *cmdbuf,
} else {
memcpy(&ubo_descs[ubo_start], set->ubos,
set_layout->num_ubos * sizeof(*ubo_descs));
unsigned dyn_ubo_start = panvk_per_arch(pipeline_layout_ubo_start)(
pipeline->layout, s, true);
for (unsigned i = 0; i < set_layout->num_dyn_ubos; i++) {
const unsigned ubo_idx =
pipeline->layout->sets[s].dyn_ubo_offset + i;
const struct panvk_buffer_desc *bdesc =
&desc_state->dyn.ubos[ubo_idx];
mali_ptr address =
panvk_buffer_gpu_ptr(bdesc->buffer, bdesc->offset);
size_t size =
panvk_buffer_range(bdesc->buffer, bdesc->offset, bdesc->size);
if (size) {
pan_pack(&ubo_descs[dyn_ubo_start + i], UNIFORM_BUFFER, cfg) {
cfg.pointer = address;
cfg.entries = DIV_ROUND_UP(size, 16);
}
} else {
memset(&ubo_descs[dyn_ubo_start + i], 0, sizeof(*ubo_descs));
}
}
}
}
unsigned dyn_ubos_offset =
panvk_per_arch(pipeline_layout_dyn_ubos_offset)(pipeline->layout);
memcpy(&ubo_descs[dyn_ubos_offset], desc_state->dyn.ubos,
pipeline->layout->num_dyn_ubos * sizeof(*ubo_descs));
if (pipeline->layout->num_dyn_ssbos) {
unsigned dyn_desc_ubo =
panvk_per_arch(pipeline_layout_dyn_desc_ubo_index)(pipeline->layout);
@@ -2057,6 +2030,62 @@ panvk_per_arch(CmdBindIndexBuffer)(VkCommandBuffer commandBuffer,
}
}
static void
panvk_emit_dyn_ubo(struct panvk_descriptor_state *desc_state,
const struct panvk_descriptor_set *desc_set,
unsigned binding, unsigned array_idx, uint32_t dyn_offset,
unsigned dyn_ubo_slot)
{
struct mali_uniform_buffer_packed *ubo = &desc_state->dyn.ubos[dyn_ubo_slot];
const struct panvk_descriptor_set_layout *slayout = desc_set->layout;
VkDescriptorType type = slayout->bindings[binding].type;
assert(type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC);
assert(dyn_ubo_slot < ARRAY_SIZE(desc_state->dyn.ubos));
const unsigned dyn_ubo_idx = slayout->bindings[binding].dyn_ubo_idx;
const struct panvk_buffer_desc *bdesc =
&desc_set->dyn_ubos[dyn_ubo_idx + array_idx];
mali_ptr address =
panvk_buffer_gpu_ptr(bdesc->buffer, bdesc->offset + dyn_offset);
size_t size = panvk_buffer_range(bdesc->buffer,
bdesc->offset + dyn_offset, bdesc->size);
if (size) {
pan_pack(ubo, UNIFORM_BUFFER, cfg) {
cfg.pointer = address;
cfg.entries = DIV_ROUND_UP(size, 16);
}
} else {
memset(ubo, 0, sizeof(*ubo));
}
}
static void
panvk_emit_dyn_ssbo(struct panvk_descriptor_state *desc_state,
const struct panvk_descriptor_set *desc_set,
unsigned binding, unsigned array_idx, uint32_t dyn_offset,
unsigned dyn_ssbo_slot)
{
struct panvk_ssbo_addr *ssbo = &desc_state->dyn.ssbos[dyn_ssbo_slot];
const struct panvk_descriptor_set_layout *slayout = desc_set->layout;
VkDescriptorType type = slayout->bindings[binding].type;
assert(type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC);
assert(dyn_ssbo_slot < ARRAY_SIZE(desc_state->dyn.ssbos));
const unsigned dyn_ssbo_idx = slayout->bindings[binding].dyn_ssbo_idx;
const struct panvk_buffer_desc *bdesc =
&desc_set->dyn_ssbos[dyn_ssbo_idx + array_idx];
*ssbo = (struct panvk_ssbo_addr) {
.base_addr =
panvk_buffer_gpu_ptr(bdesc->buffer, bdesc->offset + dyn_offset),
.size = panvk_buffer_range(bdesc->buffer, bdesc->offset + dyn_offset,
bdesc->size),
};
}
VKAPI_ATTR void VKAPI_CALL
panvk_per_arch(CmdBindDescriptorSets)(
VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint,
@@ -2078,27 +2107,21 @@ panvk_per_arch(CmdBindDescriptorSets)(
descriptors_state->sets[idx] = set;
if (set->layout->num_dyn_ssbos || set->layout->num_dyn_ubos) {
unsigned dyn_ubo_offset = playout->sets[idx].dyn_ubo_offset;
unsigned dyn_ssbo_offset = playout->sets[idx].dyn_ssbo_offset;
unsigned dyn_ubo_slot = playout->sets[idx].dyn_ubo_offset;
unsigned dyn_ssbo_slot = playout->sets[idx].dyn_ssbo_offset;
for (unsigned b = 0; b < set->layout->binding_count; b++) {
for (unsigned e = 0; e < set->layout->bindings[b].array_size; e++) {
struct panvk_buffer_desc *bdesc = NULL;
VkDescriptorType type = set->layout->bindings[b].type;
if (set->layout->bindings[b].type ==
VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
bdesc = &descriptors_state->dyn.ubos[dyn_ubo_offset++];
*bdesc =
set->dyn_ubos[set->layout->bindings[b].dyn_ubo_idx + e];
} else if (set->layout->bindings[b].type ==
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
bdesc = &descriptors_state->dyn.ssbos[dyn_ssbo_offset++];
*bdesc =
set->dyn_ssbos[set->layout->bindings[b].dyn_ssbo_idx + e];
}
if (bdesc) {
bdesc->offset += pDynamicOffsets[dynoffset_idx++];
if (type == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) {
panvk_emit_dyn_ubo(descriptors_state, set, b, e,
pDynamicOffsets[dynoffset_idx++],
dyn_ubo_slot++);
} else if (type == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC) {
panvk_emit_dyn_ssbo(descriptors_state, set, b, e,
pDynamicOffsets[dynoffset_idx++],
dyn_ssbo_slot++);
}
}
}

View File

@@ -160,3 +160,10 @@ panvk_per_arch(pipeline_layout_total_ubo_count)(
return PANVK_NUM_BUILTIN_UBOS + layout->num_ubos + layout->num_dyn_ubos +
(layout->num_dyn_ssbos ? 1 : 0);
}
unsigned
panvk_per_arch(pipeline_layout_dyn_ubos_offset)(
const struct panvk_pipeline_layout *layout)
{
return PANVK_NUM_BUILTIN_UBOS + layout->num_ubos;
}