On 30 June 2012 11:50, Olivier Galibert <span dir="ltr"><<a href="mailto:galibert@pobox.com" target="_blank">galibert@pobox.com</a>></span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
The program keys are updated accordingly, but the values are not used<br>
yet. <br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
Signed-off-by: Olivier Galibert <<a href="mailto:galibert@pobox.com">galibert@pobox.com</a>><br>
---<br>
 src/mesa/drivers/dri/i965/brw_clip.c    |   82 ++++++++++++++++++++++++++++++-<br>
 src/mesa/drivers/dri/i965/brw_clip.h    |    1 +<br>
 src/mesa/drivers/dri/i965/brw_context.h |   59 ++++++++++++++++++++++<br>
 src/mesa/drivers/dri/i965/brw_sf.c      |    3 +-<br>
 src/mesa/drivers/dri/i965/brw_sf.h      |    1 +<br>
 src/mesa/drivers/dri/i965/brw_wm.c      |    4 ++<br>
 src/mesa/drivers/dri/i965/brw_wm.h      |    1 +<br>
 7 files changed, 149 insertions(+), 2 deletions(-)<br>
<br>
diff --git a/src/mesa/drivers/dri/i965/brw_clip.c b/src/mesa/drivers/dri/i965/brw_clip.c<br>
index d411208..52e8c47 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip.c<br>
@@ -47,6 +47,83 @@<br>
 #define FRONT_UNFILLED_BIT  0x1<br>
 #define BACK_UNFILLED_BIT   0x2<br>
<br>
+/**<br>
+ * Lookup the interpolation mode information for every element in the<br>
+ * vue.<br>
+ */<br>
+static void<br>
+brw_lookup_interpolation(struct brw_context *brw)<br>
+{<br>
+   /* pprog means "previous program", i.e. the last program before the<br>
+    * fragment shader.  It can only be the vertex shader for now, but<br>
+    * it may be a geometry shader in the future.<br>
+    */<br>
+   const struct gl_program *pprog = &brw->vertex_program->Base;<br>
+   const struct gl_fragment_program *fprog = brw->fragment_program;<br>
+   struct brw_vue_map *vue_map = &brw->vs.prog_data->vue_map;<br>
+<br>
+   /* Default everything to INTERP_QUALIFIER_NONE */<br>
+   brw_clear_interpolation_modes(brw);<br></blockquote><div><br>I'm not sure that inline functions like this one add any clarity, since they force the reader to go look up the function to know what's going on.  I would recommend replacing this with<br>
<br>memset(&brw->interpolation_mode, 0, sizeof(brw->interpolation_mode));<br> </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 there is no fragment shader, interpolation won't be needed,<br>
+    * so defaulting to none is good.<br>
+    */<br>
+   if (!fprog)<br>
+      return;<br>
+<br>
+   for (int i = 0; i < vue_map->num_slots; i++) {<br>
+      /* First lookup the vert result, skip if there isn't one */<br>
+      int vert_result = vue_map->slot_to_vert_result[i];<br>
+      if (vert_result == BRW_VERT_RESULT_MAX)<br>
+         continue;<br>
+<br>
+      /* HPOS is special, it must be linear<br>
+       */<br></blockquote><div><br>I believe this is correct, but it's counterintuitive.  Can you add an explanation as to why?<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+      if (vert_result == VERT_RESULT_HPOS) {<br>
+         brw_set_interpolation_mode(brw, i, INTERP_QUALIFIER_NOPERSPECTIVE);<br>
+         continue;<br>
+      }<br>
+<br>
+      /* There is a 1-1 mapping of vert result to frag attrib except<br>
+       * for BackColor and vars<br>
+       */<br>
+      int frag_attrib = vert_result;<br>
+      if (vert_result >= VERT_RESULT_BFC0 && vert_result <= VERT_RESULT_BFC1)<br>
+         frag_attrib = vert_result - VERT_RESULT_BFC0 + FRAG_ATTRIB_COL0;<br>
+      else if(vert_result >= VERT_RESULT_VAR0)<br>
+         frag_attrib = vert_result - VERT_RESULT_VAR0 + FRAG_ATTRIB_VAR0;<br>
+<br>
+      /* If the output is not used by the fragment shader, skip it. */<br>
+      if (!(fprog->Base.InputsRead & BITFIELD64_BIT(frag_attrib)))<br>
+         continue;<br>
+<br>
+      /* Lookup the interpolation mode */<br>
+      enum glsl_interp_qualifier interpolation_mode = fprog->InterpQualifier[frag_attrib];<br>
+<br>
+      /* If the mode is not specified, then the default varies.  Color<br>
+       * values follow the shader model, while all the rest uses<br>
+       * smooth.<br>
+       */<br>
+      if (interpolation_mode == INTERP_QUALIFIER_NONE) {<br>
+         if (frag_attrib >= FRAG_ATTRIB_COL0 && frag_attrib <= FRAG_ATTRIB_COL1)<br>
+            interpolation_mode = brw->intel.ctx.Light.ShadeModel == GL_FLAT ? INTERP_QUALIFIER_FLAT : INTERP_QUALIFIER_SMOOTH;<br>
+         else<br>
+            interpolation_mode = INTERP_QUALIFIER_SMOOTH;<br>
+      }<br>
+<br>
+      /* Finally, if we have both a front color and a back color for<br>
+       * the same channel, the selection will be done before<br>
+       * interpolation and the back color copied over the front color<br>
+       * if necessary.  So interpolating the back color is<br>
+       * unnecessary.<br>
+       */<br>
+      if (vert_result >= VERT_RESULT_BFC0 && vert_result <= VERT_RESULT_BFC1)<br>
+         if (pprog->OutputsWritten & BITFIELD64_BIT(vert_result - VERT_RESULT_BFC0 + VERT_RESULT_COL0))<br>
+            interpolation_mode = INTERP_QUALIFIER_NONE;<br>
+<br>
+      brw_set_interpolation_mode(brw, i, interpolation_mode);<br>
+   }<br>
+}<br>
<br>
 static void compile_clip_prog( struct brw_context *brw,<br>
                             struct brw_clip_prog_key *key )<br>
@@ -141,6 +218,8 @@ brw_upload_clip_prog(struct brw_context *brw)<br>
<br>
    memset(&key, 0, sizeof(key));<br>
<br>
+   brw_lookup_interpolation(brw);<br></blockquote><div><br>Can you add a comment "/* BRW_NEW_FRAGMENT_PROGRAM, _NEW_LIGHT */" above this line?  That will help remind us that this function consults the fragment program and the lighting state.<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+<br>
    /* Populate the key:<br>
     */<br>
    /* BRW_NEW_REDUCED_PRIMITIVE */<br>
@@ -150,6 +229,7 @@ brw_upload_clip_prog(struct brw_context *brw)<br>
    /* _NEW_LIGHT */<br>
    key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);<br>
    key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);<br>
+   brw_copy_interpolation_modes(brw, key.interpolation_mode);<br></blockquote><div><br>Similar to my comment above about brw_clear_interpolation_modes(), I would recommend replacing this with a simple call to memcpy().<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
    /* _NEW_TRANSFORM (also part of VUE map)*/<br>
    key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled);<br>
<br>
@@ -258,7 +338,7 @@ const struct brw_tracked_state brw_clip_prog = {<br>
                _NEW_TRANSFORM |<br>
                _NEW_POLYGON |<br>
                _NEW_BUFFERS),<br>
-      .brw   = (BRW_NEW_REDUCED_PRIMITIVE),<br>
+      .brw   = (BRW_NEW_FRAGMENT_PROGRAM|BRW_NEW_REDUCED_PRIMITIVE),<br>
       .cache = CACHE_NEW_VS_PROG<br>
    },<br>
    .emit = brw_upload_clip_prog<br>
diff --git a/src/mesa/drivers/dri/i965/brw_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h<br>
index 9185651..6f811ae 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip.h<br>
@@ -43,6 +43,7 @@<br>
  */<br>
 struct brw_clip_prog_key {<br>
    GLbitfield64 attrs;<br>
+   GLbitfield64 interpolation_mode[2]; /* copy of the main context */<br>
    GLuint primitive:4;<br>
    GLuint nr_userclip:4;<br>
    GLuint do_flat_shading:1;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h<br>
index 69659c4e..1a417e5 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_context.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_context.h<br>
@@ -1041,6 +1041,17 @@ struct brw_context<br>
    uint32_t render_target_format[MESA_FORMAT_COUNT];<br>
    bool format_supported_as_render_target[MESA_FORMAT_COUNT];<br>
<br>
+   /* Interpolation modes, two bits per vue slot, values equal to<br>
+    * glsl_interp_qualifier.<br>
+    *<br>
+    * Used on gen4/5 by the clipper, sf and wm stages.  Given the<br>
+    * update order, the clipper is resposible to update it.<br></blockquote><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+    *<br>
+    * Ignored on gen 6+<br>
+    */<br>
+<br>
+   GLbitfield64 interpolation_mode[2]; /* two bits per vue slot */<br>
+<br></blockquote><div><br>I don't think the space savings is worth the complication here.  How about changing this (and the other new interpolation_mode arrays) to:<br><br>unsigned char interpolation_mode[BRW_VERT_RESULT_MAX];<br>
<br>Then we can replace brw_set_interpolation_mode() and brw_get_interpolation_mode() by simply indexing into the array.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

    /* PrimitiveRestart */<br>
    struct {<br>
       bool in_progress;<br>
@@ -1262,6 +1273,54 @@ brw_program_reloc(struct brw_context *brw, uint32_t state_offset,<br>
<br>
 bool brw_do_cubemap_normalize(struct exec_list *instructions);<br>
<br>
+/**<br>
+ * Pre-gen6, interpolation mode has to be resolved for code generation<br>
+ * in clipper, sf and wm.  The resolution is done once by the clipper<br>
+ * and stored in the interpolation_mode array and in the keys.  These<br>
+ * functions allow access to that packed array.<br>
+ */<br>
+<br>
+/* INTERP_QUALIFIER_NONE is required to be 0, so initialization is easy */<br>
+static inline<br>
+void brw_clear_interpolation_modes(struct brw_context *brw)<br>
+{<br>
+   brw->interpolation_mode[0] = brw->interpolation_mode[1] = 0;<br>
+}<br>
+<br>
+static inline<br>
+void brw_clear_interpolation_modes_key(GLbitfield64 *interpolation_mode)<br>
+{<br>
+   interpolation_mode[0] = interpolation_mode[1] = 0;<br>
+}<br>
+<br>
+/* Store an interpolation mode */<br>
+static inline<br>
+void brw_set_interpolation_mode(struct brw_context *brw, int slot, enum glsl_interp_qualifier mode)<br>
+{<br>
+   int idx = slot >> 5;<br>
+   int shift = 2*(slot & 31);<br>
+   brw->interpolation_mode[idx] =<br>
+      (brw->interpolation_mode[idx] & ~(3ULL << shift))<br>
+      | (((GLbitfield64)mode) << shift);<br>
+}<br>
+<br>
+/* Retrieve an interpolation mode */<br>
+static inline<br>
+enum glsl_interp_qualifier brw_get_interpolation_mode(struct brw_context *brw, int slot)<br>
+{<br>
+   int idx = slot >> 5;<br>
+   int shift = 2*(slot & 31);<br>
+   return (enum glsl_interp_qualifier)((brw->interpolation_mode[idx] >> shift) & 3);<br>
+}<br>
+<br>
+/* Copy the interpolation mode information to a key */<br>
+static inline<br>
+void brw_copy_interpolation_modes(struct brw_context *brw, GLbitfield64 *dest)<br>
+{<br>
+   dest[0] = brw->interpolation_mode[0];<br>
+   dest[1] = brw->interpolation_mode[1];<br>
+}<br>
+<br></blockquote><div><br>If we change the type of interpolation_mode, and use memset() and memcpy() where they make sense, I think we can eliminate the need for all these inline functions.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

 #ifdef __cplusplus<br>
 }<br>
 #endif<br>
diff --git a/src/mesa/drivers/dri/i965/brw_sf.c b/src/mesa/drivers/dri/i965/brw_sf.c<br>
index 7867ab5..0cc4fc7 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_sf.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_sf.c<br>
@@ -194,6 +194,7 @@ brw_upload_sf_prog(struct brw_context *brw)<br>
    key.do_flat_shading = (ctx->Light.ShadeModel == GL_FLAT);<br>
    key.do_twoside_color = (ctx->Light.Enabled && ctx->Light.Model.TwoSide) ||<br>
      ctx->VertexProgram._TwoSideEnabled;<br>
+   brw_copy_interpolation_modes(brw, key.interpolation_mode);<br></blockquote><div><br>This can also be replaced with a call to memcpy().  Also, we should put a comment "/* BRW_NEW_FRAGMENT_PROGRAM, _NEW_LIGHT */" above it.<br>
 </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
<br>
    /* _NEW_POLYGON */<br>
    if (key.do_twoside_color) {<br>
@@ -216,7 +217,7 @@ const struct brw_tracked_state brw_sf_prog = {<br>
    .dirty = {<br>
       .mesa  = (_NEW_HINT | _NEW_LIGHT | _NEW_POLYGON | _NEW_POINT |<br>
                 _NEW_TRANSFORM | _NEW_BUFFERS),<br>
-      .brw   = (BRW_NEW_REDUCED_PRIMITIVE),<br>
+      .brw   = (BRW_NEW_FRAGMENT_PROGRAM|BRW_NEW_REDUCED_PRIMITIVE),<br>
       .cache = CACHE_NEW_VS_PROG<br>
    },<br>
    .emit = brw_upload_sf_prog<br>
diff --git a/src/mesa/drivers/dri/i965/brw_sf.h b/src/mesa/drivers/dri/i965/brw_sf.h<br>
index f908fc0..0a8135c 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_sf.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_sf.h<br>
@@ -46,6 +46,7 @@<br>
<br>
 struct brw_sf_prog_key {<br>
    GLbitfield64 attrs;<br>
+   GLbitfield64 interpolation_mode[2]; /* copy of the main context */<br>
    uint8_t point_sprite_coord_replace;<br>
    GLuint primitive:2;<br>
    GLuint do_twoside_color:1;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c<br>
index 4a7225c..c7c1c45 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_wm.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_wm.c<br>
@@ -504,6 +504,10 @@ static void brw_wm_populate_key( struct brw_context *brw,<br>
<br>
    /* _NEW_LIGHT */<br>
    key->flat_shade = (ctx->Light.ShadeModel == GL_FLAT);<br>
+   if (intel->gen < 6)<br>
+      brw_copy_interpolation_modes(brw, key->interpolation_mode);<br>
+   else<br>
+      brw_clear_interpolation_modes_key(key->interpolation_mode);<br></blockquote><div><br>The "else" part isn't necessary, since we memset() the key to zero at the top of the function.<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

<br>
    /* _NEW_FRAG_CLAMP | _NEW_BUFFERS */<br>
    key->clamp_fragment_color = ctx->Color._ClampFragmentColor;<br>
diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h<br>
index 2cde2a0..53b83f8 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_wm.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_wm.h<br>
@@ -60,6 +60,7 @@<br>
 #define AA_ALWAYS    2<br>
<br>
 struct brw_wm_prog_key {<br>
+   GLbitfield64 interpolation_mode[2]; /* copy of the main context for gen4-5, 0 for gen6+ */<br>
    uint8_t iz_lookup;<br>
    GLuint stats_wm:1;<br>
    GLuint flat_shade:1;<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.7.10.rc3.1.gb306<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>