radv: add a function to get push constant layout info for DGC

Instead of duplicating the same code.

Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36793>
This commit is contained in:
Samuel Pitoiset
2025-08-14 15:50:54 +02:00
parent d9281f1fb1
commit 01c72a2539
+103 -94
View File
@@ -165,6 +165,82 @@ radv_dgc_get_shader(const VkGeneratedCommandsPipelineInfoEXT *pipeline_info,
return NULL;
}
struct radv_dgc_pc_layout_info {
VkShaderStageFlags stages;
bool need_upload;
struct {
uint64_t inline_push_const_mask;
uint16_t upload_sgpr;
uint16_t inline_sgpr;
} shaders[MESA_VULKAN_SHADER_STAGES];
};
static void
radv_dgc_get_pc_layout_info(const struct radv_indirect_command_layout *layout,
const struct radv_indirect_execution_set *ies,
const VkGeneratedCommandsPipelineInfoEXT *pipeline_info,
const VkGeneratedCommandsShaderInfoEXT *eso_info, struct radv_dgc_pc_layout_info *pc_info)
{
struct radv_shader *shaders[MESA_VULKAN_SHADER_STAGES] = {0};
memset(pc_info, 0, sizeof(*pc_info));
if (layout->vk.dgc_info & BITFIELD_BIT(MESA_VK_DGC_IES)) {
pc_info->need_upload = ies->uses_upload_sgpr;
} else {
if (pipeline_info) {
VK_FROM_HANDLE(radv_pipeline, pipeline, pipeline_info->pipeline);
if (layout->vk.dgc_info & BITFIELD_BIT(MESA_VK_DGC_RT)) {
const struct radv_ray_tracing_pipeline *rt_pipeline = radv_pipeline_to_ray_tracing(pipeline);
struct radv_shader *rt_prolog = rt_pipeline->prolog;
shaders[MESA_SHADER_COMPUTE] = rt_prolog;
} else {
memcpy(shaders, pipeline->shaders, sizeof(shaders));
}
} else if (eso_info) {
for (unsigned i = 0; i < eso_info->shaderCount; ++i) {
VK_FROM_HANDLE(radv_shader_object, shader_object, eso_info->pShaders[i]);
struct radv_shader *shader = shader_object->shader;
mesa_shader_stage stage = shader->info.stage;
shaders[stage] = shader;
}
}
for (unsigned i = 0; i < ARRAY_SIZE(shaders); ++i) {
const struct radv_shader *shader = shaders[i];
if (!shader)
continue;
const struct radv_userdata_locations *locs = &shader->info.user_sgprs_locs;
if (locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx == -1 &&
locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx == -1)
continue;
if (locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx >= 0) {
pc_info->shaders[i].upload_sgpr =
(shader->info.user_data_0 + 4 * locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx - SI_SH_REG_OFFSET) >>
2;
pc_info->need_upload = true;
}
if (locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx >= 0) {
pc_info->shaders[i].inline_sgpr =
(shader->info.user_data_0 + 4 * locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx -
SI_SH_REG_OFFSET) >>
2;
pc_info->shaders[i].inline_push_const_mask = shader->info.inline_push_constant_mask;
}
pc_info->stages |= mesa_to_vk_shader_stage(i);
}
}
}
static void
radv_get_sequence_size_compute(const struct radv_indirect_command_layout *layout,
const struct radv_indirect_execution_set *ies, const void *pNext, uint32_t *cmd_size,
@@ -373,59 +449,35 @@ radv_get_sequence_size(const struct radv_indirect_command_layout *layout, const
if (layout->vk.dgc_info & (BITFIELD_BIT(MESA_VK_DGC_PC) | BITFIELD_BIT(MESA_VK_DGC_SI))) {
VK_FROM_HANDLE(radv_pipeline_layout, pipeline_layout, layout->vk.layout);
bool need_copy = false;
struct radv_dgc_pc_layout_info dgc_pc_info;
radv_dgc_get_pc_layout_info(layout, ies, pipeline_info, eso_info, &dgc_pc_info);
if (layout->vk.dgc_info & BITFIELD_BIT(MESA_VK_DGC_IES)) {
if (ies->uses_upload_sgpr) {
*cmd_size += 3 * 4;
need_copy = true;
}
*cmd_size += (3 * util_bitcount64(layout->push_constant_mask)) * 4;
} else {
struct radv_shader *shaders[MESA_VULKAN_SHADER_STAGES] = {0};
if (pipeline_info) {
VK_FROM_HANDLE(radv_pipeline, pipeline, pipeline_info->pipeline);
radv_foreach_stage (s, dgc_pc_info.stages) {
const uint16_t upload_sgpr = dgc_pc_info.shaders[s].upload_sgpr;
const uint16_t inline_sgpr = dgc_pc_info.shaders[s].inline_sgpr;
if (layout->vk.dgc_info & BITFIELD_BIT(MESA_VK_DGC_RT)) {
const struct radv_ray_tracing_pipeline *rt_pipeline = radv_pipeline_to_ray_tracing(pipeline);
struct radv_shader *rt_prolog = rt_pipeline->prolog;
shaders[MESA_SHADER_COMPUTE] = rt_prolog;
} else {
memcpy(shaders, pipeline->shaders, sizeof(shaders));
}
} else if (eso_info) {
for (unsigned i = 0; i < eso_info->shaderCount; ++i) {
VK_FROM_HANDLE(radv_shader_object, shader_object, eso_info->pShaders[i]);
struct radv_shader *shader = shader_object->shader;
mesa_shader_stage stage = shader->info.stage;
shaders[stage] = shader;
}
}
for (unsigned i = 0; i < ARRAY_SIZE(shaders); ++i) {
const struct radv_shader *shader = shaders[i];
if (!shader)
continue;
const struct radv_userdata_locations *locs = &shader->info.user_sgprs_locs;
if (locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx >= 0) {
if (upload_sgpr) {
/* One PKT3_SET_SH_REG for emitting push constants pointer (32-bit) */
if (i == MESA_SHADER_TASK) {
if (s == MESA_SHADER_TASK) {
*ace_cmd_size += 3 * 4;
} else {
*cmd_size += 3 * 4;
}
need_copy = true;
}
if (locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx >= 0) {
if (inline_sgpr) {
/* One PKT3_SET_SH_REG writing all inline push constants. */
const uint32_t inline_pc_size = (3 * util_bitcount64(layout->push_constant_mask)) * 4;
if (i == MESA_SHADER_TASK) {
if (s == MESA_SHADER_TASK) {
*ace_cmd_size += inline_pc_size;
} else {
*cmd_size += inline_pc_size;
@@ -434,7 +486,7 @@ radv_get_sequence_size(const struct radv_indirect_command_layout *layout, const
}
}
if (need_copy) {
if (dgc_pc_info.need_upload) {
*upload_size += pipeline_layout->push_constant_size;
}
}
@@ -3205,70 +3257,27 @@ radv_prepare_dgc(struct radv_cmd_buffer *cmd_buffer, const VkGeneratedCommandsIn
params.params_addr = radv_buffer_get_va(cmd_buffer->upload.upload_bo) + upload_offset;
if (layout->push_constant_mask) {
VkShaderStageFlags pc_stages = 0;
struct radv_dgc_pc_layout_info dgc_pc_info;
radv_dgc_get_pc_layout_info(layout, ies, pipeline_info, eso_info, &dgc_pc_info);
params.const_copy = dgc_pc_info.need_upload;
params.push_constant_stages = dgc_pc_info.stages;
params.push_constant_size = pipeline_layout->push_constant_size / 4;
uint32_t *desc = upload_data;
upload_data = (char *)upload_data + MESA_VULKAN_SHADER_STAGES * 12;
struct radv_shader *shaders[MESA_VULKAN_SHADER_STAGES] = {0};
if (pipeline_info) {
VK_FROM_HANDLE(radv_pipeline, pipeline, pipeline_info->pipeline);
radv_foreach_stage (s, dgc_pc_info.stages) {
const uint64_t inline_push_const_mask = dgc_pc_info.shaders[s].inline_push_const_mask;
const uint16_t upload_sgpr = dgc_pc_info.shaders[s].upload_sgpr;
const uint16_t inline_sgpr = dgc_pc_info.shaders[s].inline_sgpr;
if (layout->vk.dgc_info & BITFIELD_BIT(MESA_VK_DGC_RT)) {
const struct radv_ray_tracing_pipeline *rt_pipeline = radv_pipeline_to_ray_tracing(pipeline);
struct radv_shader *rt_prolog = rt_pipeline->prolog;
shaders[MESA_SHADER_COMPUTE] = rt_prolog;
} else {
memcpy(shaders, pipeline->shaders, sizeof(shaders));
}
} else if (eso_info) {
for (unsigned i = 0; i < eso_info->shaderCount; ++i) {
VK_FROM_HANDLE(radv_shader_object, shader_object, eso_info->pShaders[i]);
struct radv_shader *shader = shader_object->shader;
mesa_shader_stage stage = shader->info.stage;
shaders[stage] = shader;
}
desc[s * 3] = upload_sgpr | (inline_sgpr << 16);
desc[s * 3 + 1] = inline_push_const_mask;
desc[s * 3 + 2] = inline_push_const_mask >> 32;
}
for (unsigned i = 0; i < ARRAY_SIZE(shaders); i++) {
const struct radv_shader *shader = shaders[i];
if (!shader)
continue;
const struct radv_userdata_locations *locs = &shader->info.user_sgprs_locs;
if (locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx >= 0) {
params.const_copy = 1;
}
if (locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx >= 0 ||
locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx >= 0) {
unsigned upload_sgpr = 0;
unsigned inline_sgpr = 0;
if (locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx >= 0) {
upload_sgpr = (shader->info.user_data_0 + 4 * locs->shader_data[AC_UD_PUSH_CONSTANTS].sgpr_idx -
SI_SH_REG_OFFSET) >>
2;
}
if (locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx >= 0) {
inline_sgpr = (shader->info.user_data_0 + 4 * locs->shader_data[AC_UD_INLINE_PUSH_CONSTANTS].sgpr_idx -
SI_SH_REG_OFFSET) >>
2;
desc[i * 3 + 1] = shader->info.inline_push_constant_mask;
desc[i * 3 + 2] = shader->info.inline_push_constant_mask >> 32;
}
desc[i * 3] = upload_sgpr | (inline_sgpr << 16);
pc_stages |= mesa_to_vk_shader_stage(i);
}
}
params.push_constant_stages = pc_stages;
params.push_constant_size = pipeline_layout->push_constant_size / 4;
memcpy(upload_data, state_cmd_buffer->push_constants, pipeline_layout->push_constant_size);
upload_data = (char *)upload_data + pipeline_layout->push_constant_size;
}