From 6a5fb31fefbc24a5ad375a26206328e416f4e846 Mon Sep 17 00:00:00 2001 From: Kenneth Graunke Date: Tue, 5 May 2020 11:03:12 -0700 Subject: [PATCH] nir: Fix divergence analysis for tessellation input/outputs MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The load_per_vertex_{input,output} intrinsics simply mean that they're reading an arrayed input/output, which have one element per invocation. Most accesses to those use gl_InvocationID as the subscript. However, it's totally possible to read any element of the array. For example, an evaluation shader might read gl_in[2].gl_Position, or a control shader might read output[0]. For threads processing a single patch, an input/output load is convergent if and only if both sources (the per-vertex-array subscript and the offset) are convergent. For threads processing multiple patches, we continued to mark them divergent. Reviewed-by: Jason Ekstrand Acked-by: Daniel Schürmann Part-of: --- src/compiler/nir/nir_divergence_analysis.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/src/compiler/nir/nir_divergence_analysis.c b/src/compiler/nir/nir_divergence_analysis.c index 6589299cad4..3e2e4b86e20 100644 --- a/src/compiler/nir/nir_divergence_analysis.c +++ b/src/compiler/nir/nir_divergence_analysis.c @@ -145,6 +145,16 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) else is_divergent = true; break; + case nir_intrinsic_load_per_vertex_input: + is_divergent = instr->src[0].ssa->divergent || + instr->src[1].ssa->divergent; + if (stage == MESA_SHADER_TESS_CTRL) + is_divergent |= !(options & nir_divergence_single_patch_per_tcs_subgroup); + if (stage == MESA_SHADER_TESS_EVAL) + is_divergent |= !(options & nir_divergence_single_patch_per_tes_subgroup); + else + is_divergent = true; + break; case nir_intrinsic_load_input_vertex: is_divergent = instr->src[1].ssa->divergent; assert(stage == MESA_SHADER_FRAGMENT); @@ -158,6 +168,12 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) else is_divergent = true; break; + case nir_intrinsic_load_per_vertex_output: + assert(stage == MESA_SHADER_TESS_CTRL); + is_divergent = instr->src[0].ssa->divergent || + instr->src[1].ssa->divergent || + !(options & nir_divergence_single_patch_per_tcs_subgroup); + break; case nir_intrinsic_load_layer_id: case nir_intrinsic_load_front_face: assert(stage == MESA_SHADER_FRAGMENT); @@ -302,8 +318,6 @@ visit_intrinsic(nir_intrinsic_instr *instr, struct divergence_state *state) case nir_intrinsic_load_sample_pos: case nir_intrinsic_load_vertex_id_zero_base: case nir_intrinsic_load_vertex_id: - case nir_intrinsic_load_per_vertex_input: - case nir_intrinsic_load_per_vertex_output: case nir_intrinsic_load_instance_id: case nir_intrinsic_load_invocation_id: case nir_intrinsic_load_local_invocation_id: -- 2.30.2