nir: Add flipping of gl_PointCoord.y in nir_lower_wpos_ytransform.
authorEric Anholt <eric@anholt.net>
Fri, 6 Jul 2018 20:43:06 +0000 (13:43 -0700)
committerEric Anholt <eric@anholt.net>
Thu, 26 Jul 2018 18:00:34 +0000 (11:00 -0700)
This is controlled by a new nir_shader_compiler_options flag, and fixes
dEQP-GLES3.functional.shaders.builtin_variable.pointcoord on V3D.

Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
src/broadcom/compiler/nir_to_vir.c
src/compiler/nir/nir.h
src/compiler/nir/nir_lower_wpos_ytransform.c

index 51cb8845cdbb9c30dba455415754b54895510821..158c1c3e9f3686adfc9263b8062f5a07d0c93d01 100644 (file)
@@ -1927,6 +1927,7 @@ const nir_shader_compiler_options v3d_nir_options = {
         .lower_ifind_msb = true,
         .lower_ldexp = true,
         .lower_mul_high = true,
+        .lower_wpos_pntc = true,
         .native_integers = true,
 };
 
index 3bfe7d7f7bf83e781f46b7942caa133259ec1b97..4213d6208cbb3021f31f736fe2bb3b1af62f2c50 100644 (file)
@@ -2024,6 +2024,9 @@ typedef struct nir_shader_compiler_options {
 
    bool lower_device_index_to_zero;
 
+   /* Set if nir_lower_wpos_ytransform() should also invert gl_PointCoord. */
+   bool lower_wpos_pntc;
+
    /**
     * Should nir_lower_io() create load_interpolated_input intrinsics?
     *
index f6f642c8cf93f593359ef83490d962f68e992975..fc61beb7872a7cc2a99e7ef59295aaaa2b9ceb3a 100644 (file)
@@ -231,6 +231,31 @@ lower_fragcoord(lower_wpos_ytransform_state *state,
    emit_wpos_adjustment(state, intr, fragcoord, invert, adjX, adjY);
 }
 
+static void
+lower_load_pointcoord(lower_wpos_ytransform_state *state,
+                      nir_intrinsic_instr *intr)
+{
+   nir_builder *b = &state->b;
+   b->cursor = nir_after_instr(&intr->instr);
+
+   nir_ssa_def *pntc = &intr->dest.ssa;
+   nir_ssa_def *transform = get_transform(state);
+   nir_ssa_def *y = nir_channel(b, pntc, 1);
+   /* The offset is 1 if we're flipping, 0 otherwise. */
+   nir_ssa_def *offset = nir_fmax(b, nir_channel(b, transform, 2),
+                                  nir_imm_float(b, 0.0));
+   /* Flip the sign of y if we're flipping. */
+   nir_ssa_def *scaled = nir_fmul(b, y, nir_channel(b, transform, 0));
+
+   /* Reassemble the vector. */
+   nir_ssa_def *flipped_pntc = nir_vec2(b,
+                                        nir_channel(b, pntc, 0),
+                                        nir_fadd(b, offset, scaled));
+
+   nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, nir_src_for_ssa(flipped_pntc),
+                                  flipped_pntc->parent_instr);
+}
+
 /* turns 'fddy(p)' into 'fddy(fmul(p, transform.x))' */
 static void
 lower_fddy(lower_wpos_ytransform_state *state, nir_alu_instr *fddy)
@@ -310,6 +335,10 @@ lower_wpos_ytransform_block(lower_wpos_ytransform_state *state, nir_block *block
             } else if (var->data.mode == nir_var_system_value &&
                        var->data.location == SYSTEM_VALUE_SAMPLE_POS) {
                lower_load_sample_pos(state, intr);
+            } else if (var->data.mode == nir_var_shader_in &&
+                       var->data.location == VARYING_SLOT_PNTC &&
+                       state->shader->options->lower_wpos_pntc) {
+               lower_load_pointcoord(state, intr);
             }
          } else if (intr->intrinsic == nir_intrinsic_load_frag_coord) {
             lower_fragcoord(state, intr, NULL);