panvk: Add support for storage/uniform buffers with dynamic offsets

The idea of storing offsets in a separate UBO and lowering accesses to
UBOs/SSBOs with a dynamic offset was not great. Let's apply the offset
at UBO/SSBO emission time instead.

Signed-off-by: Boris Brezillon <boris.brezillon@collabora.com>
Reviewed-by: Jason Ekstrand <jason.ekstrand@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15248>
This commit is contained in:
Boris Brezillon
2021-09-23 15:40:46 +02:00
committed by Marge Bot
parent 13378e4129
commit 0e7e1b64fc
8 changed files with 133 additions and 79 deletions
+28 -18
View File
@@ -66,7 +66,7 @@ panvk_CmdBindIndexBuffer(VkCommandBuffer commandBuffer,
void
panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
VkPipelineBindPoint pipelineBindPoint,
VkPipelineLayout _layout,
VkPipelineLayout layout,
uint32_t firstSet,
uint32_t descriptorSetCount,
const VkDescriptorSet *pDescriptorSets,
@@ -74,36 +74,46 @@ panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
const uint32_t *pDynamicOffsets)
{
VK_FROM_HANDLE(panvk_cmd_buffer, cmdbuf, commandBuffer);
VK_FROM_HANDLE(panvk_pipeline_layout, layout, _layout);
VK_FROM_HANDLE(panvk_pipeline_layout, playout, layout);
struct panvk_descriptor_state *descriptors_state =
&cmdbuf->bind_points[pipelineBindPoint].desc_state;
unsigned dynoffset_idx = 0;
for (unsigned i = 0; i < descriptorSetCount; ++i) {
unsigned idx = i + firstSet;
VK_FROM_HANDLE(panvk_descriptor_set, set, pDescriptorSets[i]);
descriptors_state->sets[idx].set = set;
descriptors_state->sets[idx] = set;
if (layout->num_dynoffsets) {
assert(dynamicOffsetCount >= set->layout->num_dynoffsets);
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;
descriptors_state->sets[idx].dynoffsets =
pan_pool_alloc_aligned(&cmdbuf->desc_pool.base,
ALIGN(layout->num_dynoffsets, 4) *
sizeof(*pDynamicOffsets),
16);
memcpy(descriptors_state->sets[idx].dynoffsets.cpu,
pDynamicOffsets,
sizeof(*pDynamicOffsets) * set->layout->num_dynoffsets);
dynamicOffsetCount -= set->layout->num_dynoffsets;
pDynamicOffsets += set->layout->num_dynoffsets;
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;
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 (set->layout->num_ssbos)
if (set->layout->num_ssbos || set->layout->num_dyn_ssbos)
descriptors_state->dirty |= PANVK_DYNAMIC_SSBO;
if (set->layout->num_ubos || set->layout->num_ssbos || set->layout->num_dynoffsets)
if (set->layout->num_ubos || set->layout->num_dyn_ubos ||
set->layout->num_ssbos || set->layout->num_dyn_ssbos)
descriptors_state->ubos = 0;
if (set->layout->num_textures)
@@ -113,7 +123,7 @@ panvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
descriptors_state->samplers = 0;
}
assert(!dynamicOffsetCount);
assert(dynoffset_idx == dynamicOffsetCount);
}
void
+20 -13
View File
@@ -87,7 +87,7 @@ panvk_CreateDescriptorSetLayout(VkDevice _device,
set_layout->binding_count = num_bindings;
unsigned sampler_idx = 0, tex_idx = 0, ubo_idx = 0, ssbo_idx = 0;
unsigned dynoffset_idx = 0, desc_idx = 0;
unsigned dyn_ubo_idx = 0, dyn_ssbo_idx = 0, desc_idx = 0;
for (unsigned i = 0; i < pCreateInfo->bindingCount; i++) {
const VkDescriptorSetLayoutBinding *binding = &bindings[i];
@@ -128,17 +128,17 @@ panvk_CreateDescriptorSetLayout(VkDevice _device,
tex_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
binding_layout->dynoffset_idx = dynoffset_idx;
dynoffset_idx += binding_layout->array_size;
FALLTHROUGH;
binding_layout->dyn_ubo_idx = dyn_ubo_idx;
dyn_ubo_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
binding_layout->ubo_idx = ubo_idx;
ubo_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
binding_layout->dynoffset_idx = dynoffset_idx;
dynoffset_idx += binding_layout->array_size;
FALLTHROUGH;
binding_layout->dyn_ssbo_idx = dyn_ssbo_idx;
dyn_ssbo_idx += binding_layout->array_size;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
binding_layout->ssbo_idx = ssbo_idx;
ssbo_idx += binding_layout->array_size;
@@ -152,8 +152,9 @@ panvk_CreateDescriptorSetLayout(VkDevice _device,
set_layout->num_samplers = sampler_idx;
set_layout->num_textures = tex_idx;
set_layout->num_ubos = ubo_idx;
set_layout->num_dyn_ubos = dyn_ubo_idx;
set_layout->num_ssbos = ssbo_idx;
set_layout->num_dynoffsets = dynoffset_idx;
set_layout->num_dyn_ssbos = dyn_ssbo_idx;
free(bindings);
*pSetLayout = panvk_descriptor_set_layout_to_handle(set_layout);
@@ -273,7 +274,8 @@ panvk_CreatePipelineLayout(VkDevice _device,
layout->num_sets = pCreateInfo->setLayoutCount;
_mesa_sha1_init(&ctx);
unsigned sampler_idx = 0, tex_idx = 0, ssbo_idx = 0, ubo_idx = 0, dynoffset_idx = 0;
unsigned sampler_idx = 0, tex_idx = 0, ssbo_idx = 0, ubo_idx = 0;
unsigned dyn_ubo_idx = 0, dyn_ssbo_idx = 0;
for (unsigned set = 0; set < pCreateInfo->setLayoutCount; set++) {
VK_FROM_HANDLE(panvk_descriptor_set_layout, set_layout,
pCreateInfo->pSetLayouts[set]);
@@ -281,13 +283,15 @@ panvk_CreatePipelineLayout(VkDevice _device,
layout->sets[set].sampler_offset = sampler_idx;
layout->sets[set].tex_offset = tex_idx;
layout->sets[set].ubo_offset = ubo_idx;
layout->sets[set].dyn_ubo_offset = dyn_ubo_idx;
layout->sets[set].ssbo_offset = ssbo_idx;
layout->sets[set].dynoffset_offset = dynoffset_idx;
layout->sets[set].dyn_ssbo_offset = dyn_ssbo_idx;
sampler_idx += set_layout->num_samplers;
tex_idx += set_layout->num_textures;
ubo_idx += set_layout->num_ubos + (set_layout->num_dynoffsets != 0);
ubo_idx += set_layout->num_ubos;
dyn_ubo_idx += set_layout->num_dyn_ubos;
ssbo_idx += set_layout->num_ssbos;
dynoffset_idx += set_layout->num_dynoffsets;
dyn_ssbo_idx += set_layout->num_dyn_ssbos;
for (unsigned b = 0; b < set_layout->binding_count; b++) {
struct panvk_descriptor_set_binding_layout *binding_layout =
@@ -320,8 +324,9 @@ panvk_CreatePipelineLayout(VkDevice _device,
layout->num_samplers = sampler_idx;
layout->num_textures = tex_idx;
layout->num_ubos = ubo_idx;
layout->num_dyn_ubos = dyn_ubo_idx;
layout->num_ssbos = ssbo_idx;
layout->num_dynoffsets = dynoffset_idx;
layout->num_dyn_ssbos = dyn_ssbo_idx;
_mesa_sha1_final(&ctx, layout->sha1);
@@ -436,7 +441,9 @@ panvk_descriptor_set_destroy(struct panvk_device *device,
vk_free(&device->vk.alloc, set->textures);
vk_free(&device->vk.alloc, set->samplers);
vk_free(&device->vk.alloc, set->ubos);
vk_free(&device->vk.alloc, set->dyn_ubos);
vk_free(&device->vk.alloc, set->ssbos);
vk_free(&device->vk.alloc, set->dyn_ssbos);
vk_free(&device->vk.alloc, set->descs);
vk_object_free(&device->vk, NULL, set);
}
+17 -13
View File
@@ -357,7 +357,9 @@ struct panvk_descriptor_set {
const struct panvk_descriptor_set_layout *layout;
struct panvk_descriptor *descs;
struct panvk_buffer_desc *ssbos;
struct panvk_buffer_desc *dyn_ssbos;
void *ubos;
struct panvk_buffer_desc *dyn_ubos;
void *samplers;
void *textures;
};
@@ -377,13 +379,11 @@ struct panvk_descriptor_set_binding_layout {
unsigned sampler_idx;
unsigned tex_idx;
};
struct {
union {
unsigned ssbo_idx;
unsigned ubo_idx;
};
unsigned dynoffset_idx;
};
unsigned ssbo_idx;
unsigned dyn_ssbo_idx;
unsigned ubo_idx;
unsigned dyn_ubo_idx;
unsigned img_idx;
};
/* Shader stages affected by this set+binding */
@@ -405,8 +405,9 @@ struct panvk_descriptor_set_layout {
unsigned num_samplers;
unsigned num_textures;
unsigned num_ubos;
unsigned num_dyn_ubos;
unsigned num_ssbos;
unsigned num_dynoffsets;
unsigned num_dyn_ssbos;
/* Number of bindings in this descriptor set */
uint32_t binding_count;
@@ -422,8 +423,9 @@ struct panvk_pipeline_layout {
unsigned num_samplers;
unsigned num_textures;
unsigned num_ubos;
unsigned num_dyn_ubos;
unsigned num_ssbos;
unsigned num_dynoffsets;
unsigned num_dyn_ssbos;
uint32_t num_sets;
struct {
@@ -436,8 +438,9 @@ struct panvk_pipeline_layout {
unsigned sampler_offset;
unsigned tex_offset;
unsigned ubo_offset;
unsigned dyn_ubo_offset;
unsigned ssbo_offset;
unsigned dynoffset_offset;
unsigned dyn_ssbo_offset;
} sets[MAX_SETS];
};
@@ -491,10 +494,11 @@ enum panvk_dynamic_state_bits {
struct panvk_descriptor_state {
uint32_t dirty;
const struct panvk_descriptor_set *sets[MAX_SETS];
struct {
const struct panvk_descriptor_set *set;
struct panfrost_ptr dynoffsets;
} sets[MAX_SETS];
struct panvk_buffer_desc ubos[MAX_DYNAMIC_UNIFORM_BUFFERS];
struct panvk_buffer_desc ssbos[MAX_DYNAMIC_STORAGE_BUFFERS];
} dyn;
mali_ptr sysvals[MESA_SHADER_STAGES];
mali_ptr ubos;
mali_ptr textures;
+14 -9
View File
@@ -305,10 +305,14 @@ panvk_sysval_upload_ssbo_info(struct panvk_cmd_buffer *cmdbuf,
for (unsigned s = 0; s < pipeline->layout->num_sets; s++) {
unsigned ssbo_offset = pipeline->layout->sets[s].ssbo_offset;
unsigned num_ssbos = pipeline->layout->sets[s].layout->num_ssbos;
unsigned dyn_ssbo_offset = pipeline->layout->sets[s].dyn_ssbo_offset + pipeline->layout->num_ssbos;
unsigned num_dyn_ssbos = pipeline->layout->sets[s].layout->num_dyn_ssbos;
const struct panvk_buffer_desc *ssbo = NULL;
if (ssbo_id >= ssbo_offset && ssbo_id < (ssbo_offset + num_ssbos))
ssbo = &desc_state->sets[s].set->ssbos[ssbo_id - ssbo_offset];
ssbo = &desc_state->sets[s]->ssbos[ssbo_id - ssbo_offset];
else if (ssbo_id >= dyn_ssbo_offset && ssbo_id < (dyn_ssbo_offset + num_dyn_ssbos))
ssbo = &desc_state->dyn.ssbos[ssbo_id - pipeline->layout->num_ssbos];
if (ssbo) {
data->u64[0] = ssbo->buffer->bo->ptr.gpu + ssbo->offset;
@@ -446,14 +450,14 @@ panvk_cmd_prepare_textures(struct panvk_cmd_buffer *cmdbuf,
void *texture = textures.cpu;
for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) {
if (!desc_state->sets[i].set) continue;
if (!desc_state->sets[i]) continue;
memcpy(texture,
desc_state->sets[i].set->textures,
desc_state->sets[i].set->layout->num_textures *
desc_state->sets[i]->textures,
desc_state->sets[i]->layout->num_textures *
tex_entry_size);
texture += desc_state->sets[i].set->layout->num_textures *
texture += desc_state->sets[i]->layout->num_textures *
tex_entry_size;
}
@@ -479,14 +483,15 @@ panvk_cmd_prepare_samplers(struct panvk_cmd_buffer *cmdbuf,
void *sampler = samplers.cpu;
for (unsigned i = 0; i < ARRAY_SIZE(desc_state->sets); i++) {
if (!desc_state->sets[i].set) continue;
if (!desc_state->sets[i]) continue;
memcpy(sampler,
desc_state->sets[i].set->samplers,
desc_state->sets[i].set->layout->num_samplers *
desc_state->sets[i]->samplers,
desc_state->sets[i]->layout->num_samplers *
pan_size(SAMPLER));
sampler += desc_state->sets[i].set->layout->num_samplers;
sampler += desc_state->sets[i]->layout->num_samplers *
pan_size(SAMPLER);
}
desc_state->samplers = samplers.gpu;
+16 -8
View File
@@ -352,25 +352,33 @@ panvk_per_arch(emit_ubos)(const struct panvk_pipeline *pipeline,
for (unsigned i = 0; i < ARRAY_SIZE(state->sets); i++) {
const struct panvk_descriptor_set_layout *set_layout =
pipeline->layout->sets[i].layout;
const struct panvk_descriptor_set *set = state->sets[i].set;
const struct panvk_descriptor_set *set = state->sets[i];
unsigned offset = pipeline->layout->sets[i].ubo_offset;
if (!set_layout)
continue;
if (!set) {
unsigned num_ubos = (set_layout->num_dynoffsets != 0) + set_layout->num_ubos;
memset(&ubos[offset], 0, num_ubos * sizeof(*ubos));
memset(&ubos[offset], 0, set_layout->num_ubos * sizeof(*ubos));
} else {
memcpy(&ubos[offset], set->ubos, set_layout->num_ubos * sizeof(*ubos));
if (set_layout->num_dynoffsets) {
panvk_per_arch(emit_ubo)(state->sets[i].dynoffsets.gpu,
set->layout->num_dynoffsets * sizeof(uint32_t),
&ubos[offset + set_layout->num_ubos]);
}
}
}
unsigned offset = pipeline->layout->num_ubos;
for (unsigned i = 0; i < pipeline->layout->num_dyn_ubos; i++) {
const struct panvk_buffer_desc *bdesc = &state->dyn.ubos[i];
size_t size = (bdesc->size == VK_WHOLE_SIZE && bdesc->buffer) ?
(bdesc->buffer->bo->size - bdesc->offset) :
bdesc->size;
mali_ptr address = bdesc->buffer ? bdesc->buffer->bo->ptr.gpu + bdesc->offset : 0;
if (size)
panvk_per_arch(emit_ubo)(address, size, &ubos[offset + i]);
else
memset(&ubos[offset + i], 0, sizeof(*ubos));
}
for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) {
if (!pipeline->sysvals[i].ids.sysval_count)
continue;
+28 -14
View File
@@ -72,6 +72,14 @@ panvk_per_arch(descriptor_set_create)(struct panvk_device *device,
goto err_free_set;
}
if (layout->num_dyn_ubos) {
set->dyn_ubos = vk_zalloc(&device->vk.alloc,
sizeof(*set->dyn_ubos) * layout->num_dyn_ubos, 8,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->dyn_ubos)
goto err_free_set;
}
if (layout->num_ssbos) {
set->ssbos = vk_zalloc(&device->vk.alloc,
sizeof(*set->ssbos) * layout->num_ssbos, 8,
@@ -80,6 +88,14 @@ panvk_per_arch(descriptor_set_create)(struct panvk_device *device,
goto err_free_set;
}
if (layout->num_dyn_ssbos) {
set->dyn_ssbos = vk_zalloc(&device->vk.alloc,
sizeof(*set->dyn_ssbos) * layout->num_dyn_ssbos, 8,
VK_OBJECT_TYPE_DESCRIPTOR_SET);
if (!set->dyn_ssbos)
goto err_free_set;
}
if (layout->num_samplers) {
set->samplers = vk_zalloc(&device->vk.alloc,
pan_size(SAMPLER) * layout->num_samplers, 8,
@@ -115,7 +131,9 @@ err_free_set:
vk_free(&device->vk.alloc, set->textures);
vk_free(&device->vk.alloc, set->samplers);
vk_free(&device->vk.alloc, set->ssbos);
vk_free(&device->vk.alloc, set->dyn_ssbos);
vk_free(&device->vk.alloc, set->ubos);
vk_free(&device->vk.alloc, set->dyn_ubos);
vk_free(&device->vk.alloc, set->descs);
vk_object_free(&device->vk, NULL, set);
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
@@ -172,16 +190,6 @@ panvk_set_texel_buffer_view_desc(struct panvk_descriptor *desc,
desc->buffer_view = buffer_view;
}
static void
panvk_set_buffer_info_desc(struct panvk_descriptor *desc,
const VkDescriptorBufferInfo *pBufferInfo)
{
VK_FROM_HANDLE(panvk_buffer, buffer, pBufferInfo->buffer);
desc->buffer_info.buffer = buffer;
desc->buffer_info.offset = pBufferInfo->offset;
desc->buffer_info.range = pBufferInfo->range;
}
static void
panvk_set_buffer_desc(struct panvk_buffer_desc *bdesc,
const VkDescriptorBufferInfo *pBufferInfo)
@@ -295,14 +303,18 @@ panvk_per_arch(write_descriptor_set)(struct panvk_device *dev,
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
for (unsigned i = 0; i < ndescs; i++) {
unsigned ubo = binding_layout->ubo_idx + dest_offset + i;
panvk_per_arch(set_ubo_desc)(&ubos[ubo],
&pDescriptorWrite->pBufferInfo[src_offset + i]);
}
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
for (unsigned i = 0; i < ndescs; i++) {
unsigned ubo = binding_layout->dyn_ubo_idx + dest_offset + i;
panvk_set_buffer_desc(&set->dyn_ubos[ubo], &pDescriptorWrite->pBufferInfo[src_offset + i]);
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
for (unsigned i = 0; i < ndescs; i++) {
unsigned ssbo = binding_layout->ssbo_idx + dest_offset + i;
@@ -310,8 +322,10 @@ panvk_per_arch(write_descriptor_set)(struct panvk_device *dev,
}
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
for (unsigned i = 0; i < ndescs; i++)
panvk_set_buffer_info_desc(&descs[i], &pDescriptorWrite->pBufferInfo[src_offset + i]);
for (unsigned i = 0; i < ndescs; i++) {
unsigned ssbo = binding_layout->dyn_ssbo_idx + dest_offset + i;
panvk_set_buffer_desc(&set->dyn_ssbos[ssbo], &pDescriptorWrite->pBufferInfo[src_offset + i]);
}
break;
default:
unreachable("Invalid type");
+2 -2
View File
@@ -126,7 +126,7 @@ panvk_pipeline_builder_compile_shaders(struct panvk_pipeline_builder *builder,
}
/* compile shaders in reverse order */
unsigned sysval_ubo = builder->layout->num_ubos;
unsigned sysval_ubo = builder->layout->num_ubos + builder->layout->num_dyn_ubos;
for (gl_shader_stage stage = MESA_SHADER_STAGES - 1;
stage > MESA_SHADER_NONE; stage--) {
@@ -361,7 +361,7 @@ panvk_pipeline_builder_init_shaders(struct panvk_pipeline_builder *builder,
pipeline->cs.local_size = shader->local_size;
}
pipeline->num_ubos = builder->layout->num_ubos;
pipeline->num_ubos = builder->layout->num_ubos + builder->layout->num_dyn_ubos;
for (unsigned i = 0; i < ARRAY_SIZE(pipeline->sysvals); i++) {
if (pipeline->sysvals[i].ids.sysval_count)
pipeline->num_ubos = MAX2(pipeline->num_ubos, pipeline->sysvals[i].ubo_idx + 1);
+8 -2
View File
@@ -150,14 +150,20 @@ lower_vulkan_resource_index(nir_builder *b, nir_intrinsic_instr *intr,
unsigned base;
switch (binding_layout->type) {
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
base = binding_layout->ubo_idx + ctx->layout->sets[set].ubo_offset;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
base = binding_layout->dyn_ubo_idx + ctx->layout->num_ubos +
ctx->layout->sets[set].dyn_ubo_offset;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
base = binding_layout->ssbo_idx + ctx->layout->sets[set].ssbo_offset;
break;
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
base = binding_layout->dyn_ssbo_idx + ctx->layout->num_ssbos +
ctx->layout->sets[set].dyn_ssbo_offset;
break;
default:
unreachable("Invalid descriptor type");
break;