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:
committed by
Marge Bot
parent
a77e532248
commit
0808125914
@@ -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{
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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 */);
|
||||
|
||||
@@ -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) -
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user