<p dir="ltr">For the series</p>
<p dir="ltr">Reviewed-by: Chris Forbes <<a href="mailto:chrisf@ijw.co.nz">chrisf@ijw.co.nz</a>></p>
<div class="gmail_quote">On Oct 27, 2015 7:03 AM, "Kenneth Graunke" <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>> wrote:<br type="attribution"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Normally, we could read gl_Layer from bits 26:16 of R0.0.  However, the<br>
specification requires that bogus out-of-range 32-bit values written by<br>
previous stages need to appear in the fragment shader as-written.<br>
<br>
Instead, we pass in the full 32-bit value from the VUE header as an<br>
extra flat-shaded varying.  We have the SF override the value to 0<br>
when the previous stage didn't actually write a value (it's actually<br>
defined to return 0).<br>
<br>
Signed-off-by: Kenneth Graunke <<a href="mailto:kenneth@whitecape.org">kenneth@whitecape.org</a>><br>
Cc: Chris Forbes <<a href="mailto:chrisf@ijw.co.nz">chrisf@ijw.co.nz</a>><br>
---<br>
 src/mesa/drivers/dri/i965/brw_fs.cpp         |  7 ++++++-<br>
 src/mesa/drivers/dri/i965/brw_fs_nir.cpp     |  8 +++++++<br>
 src/mesa/drivers/dri/i965/gen6_sf_state.c    | 31 ++++++++++++++++++++++++++++<br>
 src/mesa/drivers/dri/i965/intel_extensions.c |  1 +<br>
 4 files changed, 46 insertions(+), 1 deletion(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
index 2eef7af..5a82b04 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
@@ -1442,6 +1442,9 @@ fs_visitor::calculate_urb_setup()<br>
             }<br>
          }<br>
       } else {<br>
+         bool include_vue_header =<br>
+            nir->info.inputs_read & (VARYING_BIT_LAYER | VARYING_BIT_VIEWPORT);<br>
+<br>
          /* We have enough input varyings that the SF/SBE pipeline stage can't<br>
           * arbitrarily rearrange them to suit our whim; we have to put them<br>
           * in an order that matches the output of the previous pipeline stage<br>
@@ -1451,7 +1454,9 @@ fs_visitor::calculate_urb_setup()<br>
          brw_compute_vue_map(devinfo, &prev_stage_vue_map,<br>
                              key->input_slots_valid,<br>
                              nir->info.separate_shader);<br>
-         int first_slot = 2 * BRW_SF_URB_ENTRY_READ_OFFSET;<br>
+         int first_slot =<br>
+            include_vue_header ? 0 : 2 * BRW_SF_URB_ENTRY_READ_OFFSET;<br>
+<br>
          assert(prev_stage_vue_map.num_slots <= first_slot + 32);<br>
          for (int slot = first_slot; slot < prev_stage_vue_map.num_slots;<br>
               slot++) {<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp<br>
index 4950ba4..9c1f95c 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp<br>
@@ -71,6 +71,14 @@ fs_visitor::nir_setup_inputs()<br>
                                              var->data.origin_upper_left);<br>
          emit_percomp(bld, fs_inst(BRW_OPCODE_MOV, bld.dispatch_width(),<br>
                                    input, reg), 0xF);<br>
+      } else if (var->data.location == VARYING_SLOT_LAYER) {<br>
+         struct brw_reg reg = suboffset(interp_reg(VARYING_SLOT_LAYER, 1), 3);<br>
+         reg.type = BRW_REGISTER_TYPE_D;<br>
+         bld.emit(FS_OPCODE_CINTERP, retype(input, BRW_REGISTER_TYPE_D), reg);<br>
+      } else if (var->data.location == VARYING_SLOT_VIEWPORT) {<br>
+         struct brw_reg reg = suboffset(interp_reg(VARYING_SLOT_VIEWPORT, 2), 3);<br>
+         reg.type = BRW_REGISTER_TYPE_D;<br>
+         bld.emit(FS_OPCODE_CINTERP, retype(input, BRW_REGISTER_TYPE_D), reg);<br>
       } else {<br>
          emit_general_interpolation(input, var->name, var->type,<br>
                                     (glsl_interp_qualifier) var->data.interpolation,<br>
diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c<br>
index 0c8c053..2634e6b 100644<br>
--- a/src/mesa/drivers/dri/i965/gen6_sf_state.c<br>
+++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c<br>
@@ -60,6 +60,23 @@ get_attr_override(const struct brw_vue_map *vue_map, int urb_entry_read_offset,<br>
    /* Find the VUE slot for this attribute. */<br>
    int slot = vue_map->varying_to_slot[fs_attr];<br>
<br>
+   /* Viewport and Layer are stored in the VUE header.  We need to override<br>
+    * them to zero if earlier stages didn't write them, as GL requires that<br>
+    * they read back as zero when not explicitly set.<br>
+    */<br>
+   if (fs_attr == VARYING_SLOT_VIEWPORT || fs_attr == VARYING_SLOT_LAYER) {<br>
+      unsigned override =<br>
+         ATTRIBUTE_0_OVERRIDE_X | ATTRIBUTE_0_OVERRIDE_W |<br>
+         ATTRIBUTE_CONST_0000 << ATTRIBUTE_0_CONST_SOURCE_SHIFT;<br>
+<br>
+      if (!(vue_map->slots_valid & VARYING_BIT_LAYER))<br>
+         override |= ATTRIBUTE_0_OVERRIDE_Y;<br>
+      if (!(vue_map->slots_valid & VARYING_BIT_VIEWPORT))<br>
+         override |= ATTRIBUTE_0_OVERRIDE_Z;<br>
+<br>
+      return override;<br>
+   }<br>
+<br>
    /* If there was only a back color written but not front, use back<br>
     * as the color instead of undefined<br>
     */<br>
@@ -169,6 +186,20 @@ calculate_attr_overrides(const struct brw_context *brw,<br>
<br>
    *urb_entry_read_offset = BRW_SF_URB_ENTRY_READ_OFFSET;<br>
<br>
+   /* BRW_NEW_FRAGMENT_PROGRAM<br>
+    *<br>
+    * If the fragment shader reads VARYING_SLOT_LAYER, then we need to pass in<br>
+    * the full vertex header.  Otherwise, we can program the SF to start<br>
+    * reading at an offset of 1 (2 varying slots) to skip unnecessary data:<br>
+    * - VARYING_SLOT_PSIZ and BRW_VARYING_SLOT_NDC on gen4-5<br>
+    * - VARYING_SLOT_{PSIZ,LAYER} and VARYING_SLOT_POS on gen6+<br>
+    */<br>
+<br>
+   bool fs_needs_vue_header = brw->fragment_program->Base.InputsRead &<br>
+      (VARYING_BIT_LAYER | VARYING_BIT_VIEWPORT);<br>
+<br>
+   *urb_entry_read_offset = fs_needs_vue_header ? 0 : 1;<br>
+<br>
    /* _NEW_LIGHT */<br>
    bool shade_model_flat = brw->ctx.Light.ShadeModel == GL_FLAT;<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/intel_extensions.c b/src/mesa/drivers/dri/i965/intel_extensions.c<br>
index c6826d6..4433410 100644<br>
--- a/src/mesa/drivers/dri/i965/intel_extensions.c<br>
+++ b/src/mesa/drivers/dri/i965/intel_extensions.c<br>
@@ -287,6 +287,7 @@ intelInitExtensions(struct gl_context *ctx)<br>
       ctx->Extensions.ARB_conditional_render_inverted = true;<br>
       ctx->Extensions.ARB_draw_buffers_blend = true;<br>
       ctx->Extensions.ARB_ES3_compatibility = true;<br>
+      ctx->Extensions.ARB_fragment_layer_viewport = true;<br>
       ctx->Extensions.ARB_sample_shading = true;<br>
       ctx->Extensions.ARB_shading_language_420pack = true;<br>
       ctx->Extensions.ARB_shading_language_packing = true;<br>
--<br>
2.6.2<br>
<br>
</blockquote></div>