anv: add dynamic buffer offsets support with independent sets
With independent sets, we're not able to compute immediate values for the index at which to read anv_push_constants::dynamic_offsets to get the offset of a dynamic buffer. This is because the pipeline layout may not have all the descriptor set layouts when we compile the shader. To solve that issue, we insert a layer of indirection. This reworks the dynamic buffer offset storage with a 2D array in anv_cmd_pipeline_state : dynamic_offsets[MAX_SETS][MAX_DYN_BUFFERS] When the pipeline or the dynamic buffer offsets are updated, we flatten that array into the anv_push_constants::dynamic_offsets[MAX_DYN_BUFFERS] array. For shaders compiled with independent sets, the bottom 6 bits of element X in anv_push_constants::desc_sets[] is used to specify the base offsets into the anv_push_constants::dynamic_offsets[] for the set X. The computation in the shader is now something like : base_dyn_buffer_set_idx = anv_push_constants::desc_sets[set_idx] & 0x3f dyn_buffer_offset = anv_push_constants::dynamic_offsets[base_dyn_buffer_set_idx + dynamic_buffer_idx] It was suggested by Faith to use a different push constant buffer with dynamic_offsets prepared for each stage when using independent sets instead, but it feels easier to understand this way. And there is some room for optimization if you are set X and that you know all the sets in the range [0, X], then you can still avoid the indirection. Separate push constant allocations per stage do have a CPU cost. Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Emma Anholt <emma@anholt.net> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15637>
This commit is contained in:
committed by
Marge Bot
parent
16c7c37718
commit
0b8a2de2a1
@@ -405,6 +405,32 @@ void anv_CmdBindPipeline(
|
||||
|
||||
state = &cmd_buffer->state.gfx.base;
|
||||
stages = gfx_pipeline->base.active_stages;
|
||||
|
||||
/* When the pipeline is using independent states and dynamic buffers,
|
||||
* this will trigger an update of anv_push_constants::dynamic_base_index
|
||||
* & anv_push_constants::dynamic_offsets.
|
||||
*/
|
||||
struct anv_push_constants *push =
|
||||
&cmd_buffer->state.gfx.base.push_constants;
|
||||
struct anv_pipeline_sets_layout *layout = &gfx_pipeline->base.base.layout;
|
||||
if (layout->independent_sets && layout->num_dynamic_buffers > 0) {
|
||||
bool modified = false;
|
||||
for (uint32_t s = 0; s < layout->num_sets; s++) {
|
||||
if (layout->set[s].layout == NULL)
|
||||
continue;
|
||||
|
||||
assert(layout->set[s].dynamic_offset_start < MAX_DYNAMIC_BUFFERS);
|
||||
if (layout->set[s].layout->dynamic_offset_count > 0 &&
|
||||
(push->desc_sets[s] & ANV_DESCRIPTOR_SET_DYNAMIC_INDEX_MASK) != layout->set[s].dynamic_offset_start) {
|
||||
push->desc_sets[s] &= ~ANV_DESCRIPTOR_SET_DYNAMIC_INDEX_MASK;
|
||||
push->desc_sets[s] |= (layout->set[s].dynamic_offset_start &
|
||||
ANV_DESCRIPTOR_SET_DYNAMIC_INDEX_MASK);
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
if (modified)
|
||||
cmd_buffer->state.push_constants_dirty |= stages;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -438,7 +464,7 @@ void anv_CmdBindPipeline(
|
||||
static void
|
||||
anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
|
||||
VkPipelineBindPoint bind_point,
|
||||
struct anv_pipeline_layout *layout,
|
||||
struct anv_pipeline_sets_layout *layout,
|
||||
uint32_t set_index,
|
||||
struct anv_descriptor_set *set,
|
||||
uint32_t *dynamic_offset_count,
|
||||
@@ -516,7 +542,9 @@ anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
|
||||
struct anv_push_constants *push = &pipe_state->push_constants;
|
||||
|
||||
struct anv_address addr = anv_descriptor_set_address(set);
|
||||
push->desc_sets[set_index] = anv_address_physical(addr);
|
||||
push->desc_sets[set_index] &= ~ANV_DESCRIPTOR_SET_ADDRESS_MASK;
|
||||
push->desc_sets[set_index] |= (anv_address_physical(addr) &
|
||||
ANV_DESCRIPTOR_SET_ADDRESS_MASK);
|
||||
|
||||
if (addr.bo) {
|
||||
anv_reloc_list_add_bo(cmd_buffer->batch.relocs,
|
||||
@@ -536,6 +564,11 @@ anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
|
||||
uint32_t *push_offsets =
|
||||
&push->dynamic_offsets[dynamic_offset_start];
|
||||
|
||||
memcpy(pipe_state->dynamic_offsets[set_index].offsets,
|
||||
*dynamic_offsets,
|
||||
sizeof(uint32_t) * MIN2(*dynamic_offset_count,
|
||||
set_layout->dynamic_offset_count));
|
||||
|
||||
/* Assert that everything is in range */
|
||||
assert(set_layout->dynamic_offset_count <= *dynamic_offset_count);
|
||||
assert(dynamic_offset_start + set_layout->dynamic_offset_count <=
|
||||
@@ -543,7 +576,8 @@ anv_cmd_buffer_bind_descriptor_set(struct anv_cmd_buffer *cmd_buffer,
|
||||
|
||||
for (uint32_t i = 0; i < set_layout->dynamic_offset_count; i++) {
|
||||
if (push_offsets[i] != (*dynamic_offsets)[i]) {
|
||||
push_offsets[i] = (*dynamic_offsets)[i];
|
||||
pipe_state->dynamic_offsets[set_index].offsets[i] =
|
||||
push_offsets[i] = (*dynamic_offsets)[i];
|
||||
/* dynamic_offset_stages[] elements could contain blanket
|
||||
* values like VK_SHADER_STAGE_ALL, so limit this to the
|
||||
* binding point's bits.
|
||||
@@ -575,12 +609,15 @@ void anv_CmdBindDescriptorSets(
|
||||
const uint32_t* pDynamicOffsets)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _layout);
|
||||
struct anv_pipeline_sets_layout *layout = &pipeline_layout->sets_layout;
|
||||
|
||||
assert(firstSet + descriptorSetCount <= MAX_SETS);
|
||||
|
||||
for (uint32_t i = 0; i < descriptorSetCount; i++) {
|
||||
ANV_FROM_HANDLE(anv_descriptor_set, set, pDescriptorSets[i]);
|
||||
if (set == NULL)
|
||||
continue;
|
||||
anv_cmd_buffer_bind_descriptor_set(cmd_buffer, pipelineBindPoint,
|
||||
layout, firstSet + i, set,
|
||||
&dynamicOffsetCount,
|
||||
@@ -728,8 +765,8 @@ struct anv_state
|
||||
anv_cmd_buffer_cs_push_constants(struct anv_cmd_buffer *cmd_buffer)
|
||||
{
|
||||
const struct intel_device_info *devinfo = cmd_buffer->device->info;
|
||||
struct anv_push_constants *data =
|
||||
&cmd_buffer->state.compute.base.push_constants;
|
||||
struct anv_cmd_pipeline_state *pipe_state = &cmd_buffer->state.compute.base;
|
||||
struct anv_push_constants *data = &pipe_state->push_constants;
|
||||
struct anv_compute_pipeline *pipeline = cmd_buffer->state.compute.pipeline;
|
||||
const struct brw_cs_prog_data *cs_prog_data = get_cs_prog_data(pipeline);
|
||||
const struct anv_push_range *range = &pipeline->cs->bind_map.push_ranges[0];
|
||||
@@ -906,7 +943,8 @@ void anv_CmdPushDescriptorSetKHR(
|
||||
const VkWriteDescriptorSet* pDescriptorWrites)
|
||||
{
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _layout);
|
||||
struct anv_pipeline_sets_layout *layout = &pipeline_layout->sets_layout;
|
||||
|
||||
assert(_set < MAX_SETS);
|
||||
|
||||
@@ -1003,7 +1041,8 @@ void anv_CmdPushDescriptorSetWithTemplateKHR(
|
||||
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
|
||||
VK_FROM_HANDLE(vk_descriptor_update_template, template,
|
||||
descriptorUpdateTemplate);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, layout, _layout);
|
||||
ANV_FROM_HANDLE(anv_pipeline_layout, pipeline_layout, _layout);
|
||||
struct anv_pipeline_sets_layout *layout = &pipeline_layout->sets_layout;
|
||||
|
||||
assert(_set < MAX_PUSH_DESCRIPTORS);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user