From 112a856813eb2649ea7ff81768bab594033ce00a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Timur=20Krist=C3=B3f?= Date: Thu, 26 May 2022 19:03:19 +0200 Subject: [PATCH] nir: Keep track of cross-invocation mesh shader output access. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On some implementations eg. AMD RDNA2 the driver can generate a more optimal code path knowing whether outputs are indexed using the local invocation index or not. Signed-off-by: Timur Kristóf Reviewed-by: Marcin Ślusarz Part-of: --- src/compiler/nir/nir_gather_info.c | 31 +++++++++++++++++++++++++++++- src/compiler/shader_info.h | 5 +++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/src/compiler/nir/nir_gather_info.c b/src/compiler/nir/nir_gather_info.c index d372ac49ad6..60d38c4772d 100644 --- a/src/compiler/nir/nir_gather_info.c +++ b/src/compiler/nir/nir_gather_info.c @@ -36,6 +36,17 @@ src_is_invocation_id(const nir_src *src) nir_intrinsic_load_invocation_id; } +static bool +src_is_local_invocation_index(const nir_src *src) +{ + assert(src->is_ssa); + if (src->ssa->parent_instr->type != nir_instr_type_intrinsic) + return false; + + return nir_instr_as_intrinsic(src->ssa->parent_instr)->intrinsic == + nir_intrinsic_load_local_invocation_index; +} + static void get_deref_info(nir_shader *shader, nir_variable *var, nir_deref_instr *deref, bool *cross_invocation, bool *indirect) @@ -53,7 +64,10 @@ get_deref_info(nir_shader *shader, nir_variable *var, nir_deref_instr *deref, /* Vertex index is the outermost array index. */ if (is_arrayed) { assert((*p)->deref_type == nir_deref_type_array); - *cross_invocation = !src_is_invocation_id(&(*p)->arr.index); + if (shader->info.stage == MESA_SHADER_TESS_CTRL) + *cross_invocation = !src_is_invocation_id(&(*p)->arr.index); + else if (shader->info.stage == MESA_SHADER_MESH) + *cross_invocation = !src_is_local_invocation_index(&(*p)->arr.index); p++; } @@ -154,6 +168,8 @@ set_io_mask(nir_shader *shader, nir_variable *var, int offset, int len, } } + if (cross_invocation && shader->info.stage == MESA_SHADER_MESH) + shader->info.mesh.ms_cross_invocation_output_access |= bitfield; if (var->data.fb_fetch_output) { shader->info.outputs_read |= bitfield; @@ -592,6 +608,13 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader, !src_is_invocation_id(nir_get_io_arrayed_index_src(instr))) shader->info.tess.tcs_cross_invocation_outputs_read |= slot_mask; + /* NV_mesh_shader: mesh shaders can load their outputs. */ + if (shader->info.stage == MESA_SHADER_MESH && + (instr->intrinsic == nir_intrinsic_load_per_vertex_output || + instr->intrinsic == nir_intrinsic_load_per_primitive_output) && + !src_is_local_invocation_index(nir_get_io_arrayed_index_src(instr))) + shader->info.mesh.ms_cross_invocation_output_access |= slot_mask; + if (shader->info.stage == MESA_SHADER_FRAGMENT && nir_intrinsic_io_semantics(instr).fb_fetch_output) shader->info.fs.uses_fbfetch_output = true; @@ -614,6 +637,12 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, nir_shader *shader, } } + if (shader->info.stage == MESA_SHADER_MESH && + (instr->intrinsic == nir_intrinsic_store_per_vertex_output || + instr->intrinsic == nir_intrinsic_store_per_primitive_output) && + !src_is_local_invocation_index(nir_get_io_arrayed_index_src(instr))) + shader->info.mesh.ms_cross_invocation_output_access |= slot_mask; + if (shader->info.stage == MESA_SHADER_FRAGMENT && nir_intrinsic_io_semantics(instr).dual_source_blend_index) shader->info.fs.color_is_dual_source = true; diff --git a/src/compiler/shader_info.h b/src/compiler/shader_info.h index ed3596b1f3e..20974ad8dd6 100644 --- a/src/compiler/shader_info.h +++ b/src/compiler/shader_info.h @@ -505,6 +505,11 @@ typedef struct shader_info { /* Applies to MESH. */ struct { + /* Bit mask of MS outputs that are used + * with an index that is NOT the local invocation index. + */ + uint64_t ms_cross_invocation_output_access; + uint16_t max_vertices_out; uint16_t max_primitives_out; uint16_t primitive_type; /* GL_POINTS, GL_LINES or GL_TRIANGLES. */