brw/anv: rework push constants for mesh/task shaders

Now using the same model as the compute shader.

As a result we temporarily disable the use of the Inline register for
providing push constants on Task & Mesh shaders. Since that register
is also available on the compute shader we'll try to find a way to use
the same mechanism for all 3 shaders in another MR and bring back that
optimization.

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Caio Oliveira <caio.oliveira@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32895>
This commit is contained in:
Lionel Landwerlin
2025-01-02 17:36:40 +02:00
committed by Marge Bot
parent a77e532248
commit 0808125914
7 changed files with 69 additions and 94 deletions
-47
View File
@@ -36,51 +36,6 @@
using namespace brw;
static bool
brw_nir_lower_load_uniforms_filter(const nir_instr *instr,
UNUSED const void *data)
{
if (instr->type != nir_instr_type_intrinsic)
return false;
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
return intrin->intrinsic == nir_intrinsic_load_uniform;
}
static nir_def *
brw_nir_lower_load_uniforms_impl(nir_builder *b, nir_instr *instr,
void *data)
{
assert(instr->type == nir_instr_type_intrinsic);
nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
assert(intrin->intrinsic == nir_intrinsic_load_uniform);
/* Use the first few bytes of InlineData as push constants. */
if (nir_src_is_const(intrin->src[0])) {
int offset =
BRW_TASK_MESH_PUSH_CONSTANTS_START_DW * 4 +
nir_intrinsic_base(intrin) + nir_src_as_uint(intrin->src[0]);
int range = intrin->def.num_components * intrin->def.bit_size / 8;
if ((offset + range) <= (int)(BRW_TASK_MESH_INLINE_DATA_SIZE_DW * 4)) {
return nir_load_inline_data_intel(b,
intrin->def.num_components,
intrin->def.bit_size,
.base = offset);
}
}
return brw_nir_load_global_const(b, intrin,
nir_load_inline_data_intel(b, 1, 64, 0), 0);
}
static bool
brw_nir_lower_load_uniforms(nir_shader *nir,
const struct intel_device_info *devinfo)
{
return nir_shader_lower_instructions(nir, brw_nir_lower_load_uniforms_filter,
brw_nir_lower_load_uniforms_impl,
(void *)devinfo);
}
static inline int
type_size_scalar_dwords(const struct glsl_type *type, bool bindless)
{
@@ -431,7 +386,6 @@ brw_compile_task(const struct brw_compiler *compiler,
prog_data->uses_drawid =
BITSET_TEST(nir->info.system_values_read, SYSTEM_VALUE_DRAW_ID);
NIR_PASS(_, nir, brw_nir_lower_load_uniforms, compiler->devinfo);
prog_data->base.uses_inline_data = brw_nir_uses_inline_data(nir);
brw_simd_selection_state simd_state{
@@ -1742,7 +1696,6 @@ brw_compile_mesh(const struct brw_compiler *compiler,
prog_data->autostrip_enable = brw_mesh_autostrip_enable(compiler, nir, &prog_data->map);
NIR_PASS(_, nir, brw_nir_lower_load_uniforms, compiler->devinfo);
prog_data->base.uses_inline_data = brw_nir_uses_inline_data(nir);
brw_simd_selection_state simd_state{
+3 -2
View File
@@ -205,9 +205,10 @@ fs_visitor::assign_curb_setup()
prog_data->curb_read_length = MAX2(1, prog_data->curb_read_length);
uint64_t used = 0;
bool is_compute = gl_shader_stage_is_compute(stage);
const bool shader_pulls_constants = devinfo->verx10 >= 125 &&
(gl_shader_stage_is_compute(stage) || gl_shader_stage_is_mesh(stage));
if (is_compute && devinfo->verx10 >= 125 && uniform_push_length > 0) {
if (shader_pulls_constants && uniform_push_length > 0) {
assert(devinfo->has_lsc);
brw_builder ubld = brw_builder(this, 1).exec_all().at(
cfg->first_block(), cfg->first_block()->start());
+14
View File
@@ -1208,10 +1208,24 @@ anv_cmd_buffer_merge_dynamic(struct anv_cmd_buffer *cmd_buffer,
struct anv_state
anv_cmd_buffer_gfx_push_constants(struct anv_cmd_buffer *cmd_buffer)
{
const struct intel_device_info *devinfo = cmd_buffer->device->info;
const struct anv_push_constants *data =
&cmd_buffer->state.gfx.base.push_constants;
/* For Mesh/Task shaders the 3DSTATE_(MESH|TASK)_SHADER_DATA require a 64B
* alignment.
*
* ATMS PRMs Volume 2d: Command Reference: Structures,
* 3DSTATE_MESH_SHADER_DATA_BODY::Indirect Data Start Address:
*
* "This pointer is relative to the General State Base Address. It is
* the 64-byte aligned address of the indirect data."
*/
struct anv_state state =
devinfo->verx10 >= 125 ?
anv_cmd_buffer_alloc_general_state(cmd_buffer,
align(sizeof(struct anv_push_constants), 64),
64) :
anv_cmd_buffer_alloc_temporary_state(cmd_buffer,
sizeof(struct anv_push_constants),
32 /* bottom 5 bits MBZ */);
+26 -3
View File
@@ -124,11 +124,34 @@ anv_nir_compute_push_layout(nir_shader *nir,
push_end = anv_drv_const_offset(cs.subgroup_id);
}
/* Align push_start down to a 32B boundary and make it no larger than
/* Align push_start down to a 32B (for 3DSTATE_CONSTANT) or 64B (for
* 3DSTATE_(MESH|TASK)_SHADER_DATA) boundary and make it no larger than
* push_end (no push constants is indicated by push_start = UINT_MAX).
*
* SKL PRMs, Volume 2d: Command Reference: Structures,
* 3DSTATE_CONSTANT::Constant Buffer 0 Read Length:
*
* "This field specifies the length of the constant data to be loaded
* from memory in 256-bit units."
*
* ATS-M PRMs, Volume 2d: Command Reference: Structures,
* 3DSTATE_MESH_SHADER_DATA_BODY::Indirect Data Start Address:
*
* "This pointer is relative to the General State Base Address. It is
* the 64-byte aligned address of the indirect data."
*
* COMPUTE_WALKER::Indirect Data Start Address has the same requirements as
* 3DSTATE_MESH_SHADER_DATA_BODY::Indirect Data Start Address but the push
* constant allocation for compute shader is not shared with other stages
* (unlike all Gfx stages) and so we can bound+align the allocation there
* (see anv_cmd_buffer_cs_push_constants).
*/
const unsigned push_alignment =
devinfo->verx10 >= 125 && (nir->info.stage == MESA_SHADER_TASK ||
nir->info.stage == MESA_SHADER_MESH) ?
64 : 32;
push_start = MIN2(push_start, push_end);
push_start = ROUND_DOWN_TO(push_start, 32);
push_start = ROUND_DOWN_TO(push_start, push_alignment);
/* For scalar, push data size needs to be aligned to a DWORD. */
const unsigned alignment = 4;
@@ -159,7 +182,7 @@ anv_nir_compute_push_layout(nir_shader *nir,
* brw_nir_lower_rt_intrinsics.c).
*/
unsigned base_offset =
brw_shader_stage_requires_bindless_resources(nir->info.stage) ? 0 : push_start;
brw_shader_stage_is_bindless(nir->info.stage) ? 0 : push_start;
intrin->intrinsic = nir_intrinsic_load_uniform;
nir_intrinsic_set_base(intrin,
nir_intrinsic_base(intrin) -
+2
View File
@@ -4508,6 +4508,8 @@ anv_cmd_buffer_gfx_push_constants_state_address(struct anv_cmd_buffer *cmd_buffe
struct anv_state state)
{
return anv_state_pool_state_address(
cmd_buffer->device->info->verx10 >= 125 ?
&cmd_buffer->device->general_state_pool :
&cmd_buffer->device->dynamic_state_pool, state);
}
+20 -30
View File
@@ -562,6 +562,20 @@ cmd_buffer_flush_gfx_push_constants(struct anv_cmd_buffer *cmd_buffer,
}
#if GFX_VERx10 >= 125
static inline uint32_t
get_mesh_task_push_offset(struct anv_cmd_buffer *cmd_buffer,
const struct anv_push_range *range)
{
struct anv_cmd_graphics_state *gfx_state = &cmd_buffer->state.gfx;
if (gfx_state->base.push_constants_state.alloc_size == 0) {
gfx_state->base.push_constants_state =
anv_cmd_buffer_gfx_push_constants(cmd_buffer);
}
return gfx_state->base.push_constants_state.offset + range->start * 32;
}
static void
cmd_buffer_flush_mesh_inline_data(struct anv_cmd_buffer *cmd_buffer,
VkShaderStageFlags dirty_stages)
@@ -572,47 +586,23 @@ cmd_buffer_flush_mesh_inline_data(struct anv_cmd_buffer *cmd_buffer,
if (dirty_stages & VK_SHADER_STAGE_TASK_BIT_EXT &&
anv_pipeline_has_stage(pipeline, MESA_SHADER_TASK)) {
const struct anv_shader_bin *shader = pipeline->base.shaders[MESA_SHADER_TASK];
const struct anv_pipeline_bind_map *bind_map = &shader->bind_map;
const struct anv_push_range *range = &shader->bind_map.push_ranges[0];
anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_TASK_SHADER_DATA), data) {
const struct anv_push_range *range = &bind_map->push_ranges[0];
if (range->length > 0) {
struct anv_address buffer =
get_push_range_address(cmd_buffer, shader, range);
uint64_t addr = anv_address_physical(buffer);
data.InlineData[0] = addr & 0xffffffff;
data.InlineData[1] = addr >> 32;
memcpy(&data.InlineData[BRW_TASK_MESH_PUSH_CONSTANTS_START_DW],
cmd_buffer->state.gfx.base.push_constants.client_data,
BRW_TASK_MESH_PUSH_CONSTANTS_SIZE_DW * 4);
}
if (range->length > 0)
data.IndirectDataStartAddress = get_mesh_task_push_offset(cmd_buffer, range);
}
}
if (dirty_stages & VK_SHADER_STAGE_MESH_BIT_EXT &&
anv_pipeline_has_stage(pipeline, MESA_SHADER_MESH)) {
const struct anv_shader_bin *shader = pipeline->base.shaders[MESA_SHADER_MESH];
const struct anv_pipeline_bind_map *bind_map = &shader->bind_map;
const struct anv_push_range *range = &shader->bind_map.push_ranges[0];
anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_MESH_SHADER_DATA), data) {
const struct anv_push_range *range = &bind_map->push_ranges[0];
if (range->length > 0) {
struct anv_address buffer =
get_push_range_address(cmd_buffer, shader, range);
uint64_t addr = anv_address_physical(buffer);
data.InlineData[0] = addr & 0xffffffff;
data.InlineData[1] = addr >> 32;
memcpy(&data.InlineData[BRW_TASK_MESH_PUSH_CONSTANTS_START_DW],
cmd_buffer->state.gfx.base.push_constants.client_data,
BRW_TASK_MESH_PUSH_CONSTANTS_SIZE_DW * 4);
}
if (range->length > 0)
data.IndirectDataStartAddress = get_mesh_task_push_offset(cmd_buffer, range);
}
}
+4 -12
View File
@@ -1809,12 +1809,8 @@ emit_task_state(struct anv_graphics_pipeline *pipeline)
task_dispatch.group_size,
task_dispatch.simd_size);
/*
* 3DSTATE_TASK_SHADER_DATA.InlineData[0:1] will be used for an address
* of a buffer with push constants and descriptor set table and
* InlineData[2:7] will be used for first few push constants.
*/
task.EmitInlineParameter = true;
task.EmitInlineParameter = task_prog_data->base.uses_inline_data;
task.IndirectDataLength = align(task_bin->bind_map.push_ranges[0].length * 32, 64);
task.XP0Required = task_prog_data->uses_drawid;
@@ -1912,12 +1908,8 @@ emit_mesh_state(struct anv_graphics_pipeline *pipeline)
mesh_dispatch.group_size,
mesh_dispatch.simd_size);
/*
* 3DSTATE_MESH_SHADER_DATA.InlineData[0:1] will be used for an address
* of a buffer with push constants and descriptor set table and
* InlineData[2:7] will be used for first few push constants.
*/
mesh.EmitInlineParameter = true;
mesh.EmitInlineParameter = mesh_prog_data->base.uses_inline_data;
mesh.IndirectDataLength = align(mesh_bin->bind_map.push_ranges[0].length * 32, 64);
mesh.XP0Required = mesh_prog_data->uses_drawid;