From 88d1ed0f818930fd37ea012893405f21ef1b78ea Mon Sep 17 00:00:00 2001 From: Samuel Pitoiset Date: Fri, 25 May 2018 14:59:21 +0200 Subject: [PATCH] radv: emit shader descriptor pointers consecutively This reduces the number of SET_SH_REG packets which are emitted for applications that use more than one descriptor set per stage. We should be able to emit more SET_SH_REG packets consecutively (like push constants and vertex buffers for the vertex stage), but this will be improved later. Signed-off-by: Samuel Pitoiset Reviewed-by: Bas Nieuwenhuizen --- src/amd/vulkan/radv_cmd_buffer.c | 104 +++++++++++++++++-------------- 1 file changed, 57 insertions(+), 47 deletions(-) diff --git a/src/amd/vulkan/radv_cmd_buffer.c b/src/amd/vulkan/radv_cmd_buffer.c index 3e3dbf6a857..8f351b52c9d 100644 --- a/src/amd/vulkan/radv_cmd_buffer.c +++ b/src/amd/vulkan/radv_cmd_buffer.c @@ -594,6 +594,46 @@ radv_emit_userdata_address(struct radv_cmd_buffer *cmd_buffer, base_reg + loc->sgpr_idx * 4, va, false); } +static void +radv_emit_descriptor_pointers(struct radv_cmd_buffer *cmd_buffer, + struct radv_pipeline *pipeline, + struct radv_descriptor_state *descriptors_state, + gl_shader_stage stage) +{ + struct radv_device *device = cmd_buffer->device; + struct radeon_winsys_cs *cs = cmd_buffer->cs; + uint32_t sh_base = pipeline->user_data_0[stage]; + struct radv_userdata_locations *locs = + &pipeline->shaders[stage]->info.user_sgprs_locs; + unsigned mask; + + mask = descriptors_state->dirty & descriptors_state->valid; + + for (int i = 0; i < MAX_SETS; i++) { + struct radv_userdata_info *loc = &locs->descriptor_sets[i]; + if (loc->sgpr_idx != -1 && !loc->indirect) + continue; + mask &= ~(1 << i); + } + + while (mask) { + int start, count; + + u_bit_scan_consecutive_range(&mask, &start, &count); + + struct radv_userdata_info *loc = &locs->descriptor_sets[start]; + unsigned sh_offset = sh_base + loc->sgpr_idx * 4; + + radv_emit_shader_pointer_head(cs, sh_offset, count, true); + for (int i = 0; i < count; i++) { + struct radv_descriptor_set *set = + descriptors_state->sets[start + i]; + + radv_emit_shader_pointer_body(device, cs, set->va, true); + } + } +} + static void radv_update_multisample_state(struct radv_cmd_buffer *cmd_buffer, struct radv_pipeline *pipeline) @@ -1422,47 +1462,6 @@ radv_cmd_buffer_flush_dynamic_state(struct radv_cmd_buffer *cmd_buffer) cmd_buffer->state.dirty &= ~states; } -static void -emit_stage_descriptor_set_userdata(struct radv_cmd_buffer *cmd_buffer, - struct radv_pipeline *pipeline, - int idx, - uint64_t va, - gl_shader_stage stage) -{ - struct radv_userdata_info *desc_set_loc = &pipeline->shaders[stage]->info.user_sgprs_locs.descriptor_sets[idx]; - uint32_t base_reg = pipeline->user_data_0[stage]; - - if (desc_set_loc->sgpr_idx == -1 || desc_set_loc->indirect) - return; - - assert(!desc_set_loc->indirect); - assert(desc_set_loc->num_sgprs == (HAVE_32BIT_POINTERS ? 1 : 2)); - - radv_emit_shader_pointer(cmd_buffer->device, cmd_buffer->cs, - base_reg + desc_set_loc->sgpr_idx * 4, va, false); -} - -static void -radv_emit_descriptor_set_userdata(struct radv_cmd_buffer *cmd_buffer, - VkShaderStageFlags stages, - struct radv_descriptor_set *set, - unsigned idx) -{ - if (cmd_buffer->state.pipeline) { - radv_foreach_stage(stage, stages) { - if (cmd_buffer->state.pipeline->shaders[stage]) - emit_stage_descriptor_set_userdata(cmd_buffer, cmd_buffer->state.pipeline, - idx, set->va, - stage); - } - } - - if (cmd_buffer->state.compute_pipeline && (stages & VK_SHADER_STAGE_COMPUTE_BIT)) - emit_stage_descriptor_set_userdata(cmd_buffer, cmd_buffer->state.compute_pipeline, - idx, set->va, - MESA_SHADER_COMPUTE); -} - static void radv_flush_push_descriptors(struct radv_cmd_buffer *cmd_buffer, VkPipelineBindPoint bind_point) @@ -1544,7 +1543,6 @@ radv_flush_descriptors(struct radv_cmd_buffer *cmd_buffer, VK_PIPELINE_BIND_POINT_GRAPHICS; struct radv_descriptor_state *descriptors_state = radv_get_descriptors_state(cmd_buffer, bind_point); - unsigned i; if (!descriptors_state->dirty) return; @@ -1561,13 +1559,25 @@ radv_flush_descriptors(struct radv_cmd_buffer *cmd_buffer, cmd_buffer->cs, MAX_SETS * MESA_SHADER_STAGES * 4); - for_each_bit(i, descriptors_state->dirty) { - struct radv_descriptor_set *set = descriptors_state->sets[i]; - if (!(descriptors_state->valid & (1u << i))) - continue; + if (cmd_buffer->state.pipeline) { + radv_foreach_stage(stage, stages) { + if (!cmd_buffer->state.pipeline->shaders[stage]) + continue; - radv_emit_descriptor_set_userdata(cmd_buffer, stages, set, i); + radv_emit_descriptor_pointers(cmd_buffer, + cmd_buffer->state.pipeline, + descriptors_state, stage); + } } + + if (cmd_buffer->state.compute_pipeline && + (stages & VK_SHADER_STAGE_COMPUTE_BIT)) { + radv_emit_descriptor_pointers(cmd_buffer, + cmd_buffer->state.compute_pipeline, + descriptors_state, + MESA_SHADER_COMPUTE); + } + descriptors_state->dirty = 0; descriptors_state->push_dirty = false; -- 2.30.2