<div dir="ltr">On 14 July 2013 02:39, Chris Forbes <span dir="ltr"><<a href="mailto:chrisf@ijw.co.nz" target="_blank">chrisf@ijw.co.nz</a>></span> wrote:<br><div class="gmail_extra"><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
Previously the SF only handled the builtin color varying specially.<br>
This patch generalizes that support to cover user-defined varyings,<br>
driven by the interpolation mode array set up alongside the VUE map.<br>
<br>
Based on the following patches from Olivier Galibert:<br>
- <a href="http://lists.freedesktop.org/archives/mesa-dev/2012-July/024335.html" target="_blank">http://lists.freedesktop.org/archives/mesa-dev/2012-July/024335.html</a><br>
- <a href="http://lists.freedesktop.org/archives/mesa-dev/2012-July/024339.html" target="_blank">http://lists.freedesktop.org/archives/mesa-dev/2012-July/024339.html</a><br>
<br>
With this patch, all the GLSL 1.3 interpolation tests that do not clip<br>
(spec/glsl-1.30/execution/interpolation/*-none.shader_test) pass.<br>
<br>
Signed-off-by: Chris Forbes <<a href="mailto:chrisf@ijw.co.nz">chrisf@ijw.co.nz</a>><br>
---<br>
 src/mesa/drivers/dri/i965/brw_fs.cpp    |   2 +-<br>
 src/mesa/drivers/dri/i965/brw_sf.c      |   9 +-<br>
 src/mesa/drivers/dri/i965/brw_sf.h      |   2 +-<br>
 src/mesa/drivers/dri/i965/brw_sf_emit.c | 187 ++++++++++++++++----------------<br>
 4 files changed, 106 insertions(+), 94 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
index afd29de..a81e97f 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp<br>
@@ -1048,7 +1048,7 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)<br>
                   inst->predicate = BRW_PREDICATE_NORMAL;<br>
                   inst->predicate_inverse = true;<br>
                }<br>
-               if (brw->gen < 6) {<br>
+               if (brw->gen < 6 && interpolation_mode == INTERP_QUALIFIER_SMOOTH) {<br>
                   emit(BRW_OPCODE_MUL, attr, attr, this->pixel_w);<br>
                }<br>
               attr.reg_offset++;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_sf.c b/src/mesa/drivers/dri/i965/brw_sf.c<br>
index 7cd383c..f7725ed 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_sf.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_sf.c<br>
@@ -138,6 +138,7 @@ brw_upload_sf_prog(struct brw_context *brw)<br>
    struct brw_sf_prog_key key;<br>
    /* _NEW_BUFFERS */<br>
    bool render_to_fbo = _mesa_is_user_fbo(ctx->DrawBuffer);<br>
+   int i;<br>
<br>
    memset(&key, 0, sizeof(key));<br>
<br>
@@ -190,7 +191,13 @@ brw_upload_sf_prog(struct brw_context *brw)<br>
       key.sprite_origin_lower_left = true;<br>
<br>
    /* _NEW_LIGHT | _NEW_PROGRAM */<br>
-   key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);<br>
+   key.has_flat_shading = 0;<br>
+   for (i = 0; i < BRW_VARYING_SLOT_COUNT; i++) {<br>
+      if (brw->interpolation_mode[i] == INTERP_QUALIFIER_FLAT) {<br>
+         key.has_flat_shading = 1;<br>
+         break;<br>
+      }<br>
+   }<br></blockquote><div><br></div><div>Having one part of the key that is just derived from another part of the key is inefficient, since it means that this computation has to happen every time the state atom ir executed.<br>
<br></div><div>I'd recommend moving has_flat_shading into brw_sf_compile, that way we can compute it in compile_sf_prog(), which only has to execute when the key changes.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

    key.do_twoside_color = ((ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||<br>
                            ctx->VertexProgram._TwoSideEnabled);<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_sf.h b/src/mesa/drivers/dri/i965/brw_sf.h<br>
index 55a860d..9bfa994 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_sf.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_sf.h<br>
@@ -50,7 +50,7 @@ struct brw_sf_prog_key {<br>
    uint8_t point_sprite_coord_replace;<br>
    GLuint primitive:2;<br>
    GLuint do_twoside_color:1;<br>
-   GLuint do_flat_shading:1;<br>
+   GLuint has_flat_shading:1;<br>
    GLuint frontface_ccw:1;<br>
    GLuint do_point_sprite:1;<br>
    GLuint do_point_coord:1;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_sf_emit.c b/src/mesa/drivers/dri/i965/brw_sf_emit.c<br>
index bd68f68..63e077d 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_sf_emit.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_sf_emit.c<br>
@@ -44,6 +44,15 @@<br>
<br>
<br>
 /**<br>
+ * Determine the vue slot corresponding to the given half of the given register.<br>
+ */<br>
+static inline int vert_reg_to_vue_slot(struct brw_sf_compile *c, GLuint reg,<br>
+                                       int half)<br>
+{<br>
+   return (reg + c->urb_entry_read_offset) * 2 + half;<br>
+}<br>
+<br>
+/**<br>
  * Determine the varying corresponding to the given half of the given<br>
  * register.  half=0 means the first half of a register, half=1 means the<br>
  * second half.<br>
@@ -51,11 +60,24 @@<br>
 static inline int vert_reg_to_varying(struct brw_sf_compile *c, GLuint reg,<br>
                                       int half)<br>
 {<br>
-   int vue_slot = (reg + c->urb_entry_read_offset) * 2 + half;<br>
+   int vue_slot = vert_reg_to_vue_slot(c, reg, half);<br>
    return c->vue_map.slot_to_varying[vue_slot];<br>
 }<br>
<br>
 /**<br>
+ * Determine the register corresponding to the given vue slot<br>
+ */<br>
+static struct brw_reg get_vue_slot(struct brw_sf_compile *c,<br>
+                                   struct brw_reg vert,<br>
+                                   int vue_slot)<br>
+{<br>
+   GLuint off = vue_slot / 2 - c->urb_entry_read_offset;<br>
+   GLuint sub = vue_slot % 2;<br>
+<br>
+   return brw_vec4_grf(<a href="http://vert.nr" target="_blank">vert.nr</a> + off, sub * 4);<br>
+}<br>
+<br>
+/**<br>
  * Determine the register corresponding to the given varying.<br>
  */<br>
 static struct brw_reg get_varying(struct brw_sf_compile *c,<br>
@@ -64,10 +86,7 @@ static struct brw_reg get_varying(struct brw_sf_compile *c,<br>
 {<br>
    int vue_slot = c->vue_map.varying_to_slot[varying];<br>
    assert (vue_slot >= c->urb_entry_read_offset);<br></blockquote><div><br></div><div>Let's move this assertion into get_vue_slot() as well.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

-   GLuint off = vue_slot / 2 - c->urb_entry_read_offset;<br>
-   GLuint sub = vue_slot % 2;<br>
-<br>
-   return brw_vec4_grf(<a href="http://vert.nr" target="_blank">vert.nr</a> + off, sub * 4);<br>
+   return get_vue_slot(c, vert, vue_slot);<br>
 }<br>
<br>
 static bool<br>
@@ -79,24 +98,9 @@ have_attr(struct brw_sf_compile *c, GLuint attr)<br>
 /***********************************************************************<br>
  * Twoside lighting<br>
  */<br>
-static void copy_bfc( struct brw_sf_compile *c,<br>
-                     struct brw_reg vert )<br>
-{<br>
-   struct brw_compile *p = &c->func;<br>
-   GLuint i;<br>
-<br>
-   for (i = 0; i < 2; i++) {<br>
-      if (have_attr(c, VARYING_SLOT_COL0+i) &&<br>
-         have_attr(c, VARYING_SLOT_BFC0+i))<br>
-        brw_MOV(p,<br>
-                get_varying(c, vert, VARYING_SLOT_COL0+i),<br>
-                get_varying(c, vert, VARYING_SLOT_BFC0+i));<br>
-   }<br>
-}<br>
-<br>
-<br>
 static void do_twoside_color( struct brw_sf_compile *c )<br>
 {<br>
+   GLuint i, need_0, need_1;<br>
    struct brw_compile *p = &c->func;<br>
    GLuint backface_conditional = c->key.frontface_ccw ? BRW_CONDITIONAL_G : BRW_CONDITIONAL_L;<br>
<br>
@@ -105,14 +109,16 @@ static void do_twoside_color( struct brw_sf_compile *c )<br>
    if (c->key.primitive == SF_UNFILLED_TRIS)<br>
       return;<br>
<br>
-   /* XXX: What happens if BFC isn't present?  This could only happen<br>
-    * for user-supplied vertex programs, as t_vp_build.c always does<br>
-    * the right thing.<br>
+   /* If the vertex shader provides backface color, do the selection. The VS<br>
+    * promises to set up the front color if the backface color is provided, but<br>
+    * it may contain junk if never written to.<br></blockquote><div><br></div><div>Can you point me to some VS code that does this?  I thought that if the VS wrote only to gl_BackColor, then the VUE map would only contain a slot for gl_BackColor.  In fact, we have specific code in the Gen6-7 SF backend to handle this case:<br>
<br>   /* If there was only a back color written but not front, use back<br>    * as the color instead of undefined<br>    */<br>   if (slot == -1 && fs_attr == VARYING_SLOT_COL0)<br>      slot = vue_map->varying_to_slot[VARYING_SLOT_BFC0];<br>
   if (slot == -1 && fs_attr == VARYING_SLOT_COL1)<br>      slot = vue_map->varying_to_slot[VARYING_SLOT_BFC1];<br><br></div><div>It seems to me that if we want backcolor to work right in all cases, we need to do a similar mapping for Gen4-5.<br>
<br></div><div>Regardless, I with Ken that it would probably be good to pull this backfacing color fix out to its own patch.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

     */<br>
-   if (!(have_attr(c, VARYING_SLOT_COL0) && have_attr(c, VARYING_SLOT_BFC0)) &&<br>
-       !(have_attr(c, VARYING_SLOT_COL1) && have_attr(c, VARYING_SLOT_BFC1)))<br>
+   need_0 = have_attr(c, VARYING_SLOT_COL0) && have_attr(c, VARYING_SLOT_BFC0);<br>
+   need_1 = have_attr(c, VARYING_SLOT_COL1) && have_attr(c, VARYING_SLOT_BFC1);<br>
+<br>
+   if (!need_0 && !need_1)<br>
       return;<br>
-<br>
+<br>
    /* Need to use BRW_EXECUTE_4 and also do an 4-wide compare in order<br>
     * to get all channels active inside the IF.  In the clipping code<br>
     * we run with NoMask, so it's not an option and we can use<br>
@@ -121,12 +127,15 @@ static void do_twoside_color( struct brw_sf_compile *c )<br>
    brw_push_insn_state(p);<br>
    brw_CMP(p, vec4(brw_null_reg()), backface_conditional, c->det, brw_imm_f(0));<br>
    brw_IF(p, BRW_EXECUTE_4);<br>
-   {<br>
-      switch (c->nr_verts) {<br>
-      case 3: copy_bfc(c, c->vert[2]);<br>
-      case 2: copy_bfc(c, c->vert[1]);<br>
-      case 1: copy_bfc(c, c->vert[0]);<br>
-      }<br>
+   for (i=0; i < c->nr_verts; i++) {<br>
+      if (need_0)<br>
+         brw_MOV(p,<br>
+                 get_varying(c, c->vert[i], VARYING_SLOT_COL0),<br>
+                 get_varying(c, c->vert[i], VARYING_SLOT_BFC0));<br>
+      if (need_1)<br>
+         brw_MOV(p,<br>
+                 get_varying(c, c->vert[i], VARYING_SLOT_COL1),<br>
+                 get_varying(c, c->vert[i], VARYING_SLOT_BFC1));<br>
    }<br>
    brw_ENDIF(p);<br>
    brw_pop_insn_state(p);<br>
@@ -138,24 +147,34 @@ static void do_twoside_color( struct brw_sf_compile *c )<br>
  * Flat shading<br>
  */<br>
<br>
-#define VARYING_SLOT_COLOR_BITS (BITFIELD64_BIT(VARYING_SLOT_COL0) | \<br>
-                                 BITFIELD64_BIT(VARYING_SLOT_COL1))<br>
-<br>
-static void copy_colors( struct brw_sf_compile *c,<br>
-                    struct brw_reg dst,<br>
-                    struct brw_reg src)<br>
+static void copy_flatshaded_attributes(struct brw_sf_compile *c,<br>
+                                       struct brw_reg dst,<br>
+                                       struct brw_reg src)<br>
 {<br>
    struct brw_compile *p = &c->func;<br>
-   GLuint i;<br>
+   int i;<br>
<br>
-   for (i = VARYING_SLOT_COL0; i <= VARYING_SLOT_COL1; i++) {<br>
-      if (have_attr(c,i))<br>
-        brw_MOV(p,<br>
-                get_varying(c, dst, i),<br>
-                get_varying(c, src, i));<br>
+   for (i = 0; i < c->vue_map.num_slots; i++) {<br>
+      if (c->key.interpolation_mode[i] == INTERP_QUALIFIER_FLAT) {<br>
+         brw_MOV(p,<br>
+                 get_vue_slot(c, dst, i),<br>
+                 get_vue_slot(c, src, i));<br>
+      }<br>
    }<br>
 }<br>
<br>
+static int count_flatshaded_attributes(struct brw_sf_compile *c)<br>
+{<br>
+   int i;<br>
+   int count = 0;<br>
+<br>
+   for (i = 0; i < c->vue_map.num_slots; i++)<br>
+      if (c->key.interpolation_mode[i] == INTERP_QUALIFIER_FLAT)<br>
+         count++;<br>
+<br>
+   return count;<br>
+}<br>
+<br>
<br>
<br>
 /* Need to use a computed jump to copy flatshaded attributes as the<br>
@@ -167,12 +186,9 @@ static void do_flatshade_triangle( struct brw_sf_compile *c )<br>
    struct brw_compile *p = &c->func;<br>
    struct brw_context *brw = p->brw;<br>
    struct brw_reg ip = brw_ip_reg();<br>
-   GLuint nr = _mesa_bitcount_64(c->key.attrs & VARYING_SLOT_COLOR_BITS);<br>
+   GLuint nr;<br>
    GLuint jmpi = 1;<br>
<br>
-   if (!nr)<br>
-      return;<br>
-<br></blockquote><div><br></div><div>It seems a shame to lose this optimization.  Can we move the call to count_flatshaded_attributes() up to the declaration of nr, and then we can keep this?<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

    /* Already done in clip program:<br>
     */<br>
    if (c->key.primitive == SF_UNFILLED_TRIS)<br>
@@ -181,21 +197,23 @@ static void do_flatshade_triangle( struct brw_sf_compile *c )<br>
    if (brw->gen == 5)<br>
        jmpi = 2;<br>
<br>
+   nr = count_flatshaded_attributes(c);<br>
+<br>
    brw_push_insn_state(p);<br>
-<br>
+<br>
    brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr*2+1)));<br>
    brw_JMPI(p, ip, ip, c->pv);<br>
<br>
-   copy_colors(c, c->vert[1], c->vert[0]);<br>
-   copy_colors(c, c->vert[2], c->vert[0]);<br>
+   copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);<br>
+   copy_flatshaded_attributes(c, c->vert[2], c->vert[0]);<br>
    brw_JMPI(p, ip, ip, brw_imm_d(jmpi*(nr*4+1)));<br>
<br>
-   copy_colors(c, c->vert[0], c->vert[1]);<br>
-   copy_colors(c, c->vert[2], c->vert[1]);<br>
+   copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);<br>
+   copy_flatshaded_attributes(c, c->vert[2], c->vert[1]);<br>
    brw_JMPI(p, ip, ip, brw_imm_d(jmpi*nr*2));<br>
<br>
-   copy_colors(c, c->vert[0], c->vert[2]);<br>
-   copy_colors(c, c->vert[1], c->vert[2]);<br>
+   copy_flatshaded_attributes(c, c->vert[0], c->vert[2]);<br>
+   copy_flatshaded_attributes(c, c->vert[1], c->vert[2]);<br>
<br>
    brw_pop_insn_state(p);<br>
 }<br>
@@ -206,12 +224,9 @@ static void do_flatshade_line( struct brw_sf_compile *c )<br>
    struct brw_compile *p = &c->func;<br>
    struct brw_context *brw = p->brw;<br>
    struct brw_reg ip = brw_ip_reg();<br>
-   GLuint nr = _mesa_bitcount_64(c->key.attrs & VARYING_SLOT_COLOR_BITS);<br>
+   GLuint nr;<br>
    GLuint jmpi = 1;<br>
<br>
-   if (!nr)<br>
-      return;<br>
-<br></blockquote><div><br></div><div>Same comment as above.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
    /* Already done in clip program:<br>
     */<br>
    if (c->key.primitive == SF_UNFILLED_TRIS)<br>
@@ -220,14 +235,16 @@ static void do_flatshade_line( struct brw_sf_compile *c )<br>
    if (brw->gen == 5)<br>
        jmpi = 2;<br>
<br>
+   nr = count_flatshaded_attributes(c);<br>
+<br>
    brw_push_insn_state(p);<br>
<br>
    brw_MUL(p, c->pv, c->pv, brw_imm_d(jmpi*(nr+1)));<br>
    brw_JMPI(p, ip, ip, c->pv);<br>
-   copy_colors(c, c->vert[1], c->vert[0]);<br>
+   copy_flatshaded_attributes(c, c->vert[1], c->vert[0]);<br>
<br>
    brw_JMPI(p, ip, ip, brw_imm_ud(jmpi*nr));<br>
-   copy_colors(c, c->vert[0], c->vert[1]);<br>
+   copy_flatshaded_attributes(c, c->vert[0], c->vert[1]);<br>
<br>
    brw_pop_insn_state(p);<br>
 }<br>
@@ -324,36 +341,23 @@ static void invert_det( struct brw_sf_compile *c)<br>
<br>
 static bool<br>
 calculate_masks(struct brw_sf_compile *c,<br>
-               GLuint reg,<br>
-               GLushort *pc,<br>
-               GLushort *pc_persp,<br>
-               GLushort *pc_linear)<br>
+                GLuint reg,<br>
+                GLushort *pc,<br>
+                GLushort *pc_persp,<br>
+                GLushort *pc_linear)<br>
 {<br>
    bool is_last_attr = (reg == c->nr_setup_regs - 1);<br>
-   GLbitfield64 persp_mask;<br>
-   GLbitfield64 linear_mask;<br>
-<br>
-   if (c->key.do_flat_shading)<br>
-      persp_mask = c->key.attrs & ~(BITFIELD64_BIT(VARYING_SLOT_POS) |<br>
-                                    BITFIELD64_BIT(VARYING_SLOT_COL0) |<br>
-                                    BITFIELD64_BIT(VARYING_SLOT_COL1));<br>
-   else<br>
-      persp_mask = c->key.attrs & ~(BITFIELD64_BIT(VARYING_SLOT_POS));<br>
-<br>
-   if (c->key.do_flat_shading)<br>
-      linear_mask = c->key.attrs & ~(BITFIELD64_BIT(VARYING_SLOT_COL0) |<br>
-                                     BITFIELD64_BIT(VARYING_SLOT_COL1));<br>
-   else<br>
-      linear_mask = c->key.attrs;<br>
+   enum glsl_interp_qualifier interp;<br>
<br>
    *pc_persp = 0;<br>
    *pc_linear = 0;<br>
    *pc = 0xf;<br>
<br>
-   if (persp_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 0)))<br>
+   interp = c->key.interpolation_mode[vert_reg_to_vue_slot(c, reg, 0)];<br>
+   if (interp == INTERP_QUALIFIER_SMOOTH) {<br>
+      *pc_linear = 0xf;<br>
       *pc_persp = 0xf;<br>
-<br>
-   if (linear_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 0)))<br>
+   } else if (interp == INTERP_QUALIFIER_NOPERSPECTIVE)<br>
       *pc_linear = 0xf;<br>
<br>
    /* Maybe only processs one attribute on the final round:<br>
@@ -361,11 +365,12 @@ calculate_masks(struct brw_sf_compile *c,<br>
    if (vert_reg_to_varying(c, reg, 1) != BRW_VARYING_SLOT_COUNT) {<br>
       *pc |= 0xf0;<br>
<br>
-      if (persp_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 1)))<br>
-        *pc_persp |= 0xf0;<br>
-<br>
-      if (linear_mask & BITFIELD64_BIT(vert_reg_to_varying(c, reg, 1)))<br>
-        *pc_linear |= 0xf0;<br>
+      interp = c->key.interpolation_mode[vert_reg_to_vue_slot(c, reg, 1)];<br>
+      if (interp == INTERP_QUALIFIER_SMOOTH) {<br>
+         *pc_linear |= 0xf0;<br>
+         *pc_persp |= 0xf0;<br>
+      } else if (interp == INTERP_QUALIFIER_NOPERSPECTIVE)<br>
+         *pc_linear |= 0xf0;<br>
    }<br>
<br>
    return is_last_attr;<br>
@@ -418,7 +423,7 @@ void brw_emit_tri_setup(struct brw_sf_compile *c, bool allocate)<br>
    if (c->key.do_twoside_color)<br>
       do_twoside_color(c);<br>
<br>
-   if (c->key.do_flat_shading)<br>
+   if (c->key.has_flat_shading)<br>
       do_flatshade_triangle(c);<br>
<br>
<br>
@@ -504,7 +509,7 @@ void brw_emit_line_setup(struct brw_sf_compile *c, bool allocate)<br>
    invert_det(c);<br>
    copy_z_inv_w(c);<br>
<br>
-   if (c->key.do_flat_shading)<br>
+   if (c->key.has_flat_shading)<br>
       do_flatshade_line(c);<br>
<br>
    for (i = 0; i < c->nr_setup_regs; i++)<br>
<span class=""><font color="#888888">--<br>
1.8.3.2<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div></div>