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">
At this point all interpolation tests with fixed clipping work.<br>
<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      |    9 ++<br>
 src/mesa/drivers/dri/i965/brw_clip.h      |    1 +<br>
 src/mesa/drivers/dri/i965/brw_clip_util.c |  133 ++++++++++++++++++++++++++---<br>
 3 files changed, 132 insertions(+), 11 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 952eb4a..6bfdf24 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip.c<br>
@@ -234,6 +234,15 @@ brw_upload_clip_prog(struct brw_context *brw)<br>
          break;<br>
       }<br>
    }<br>
+   key.has_noperspective_shading = 0;<br>
+   for (i = 0; i < BRW_VERT_RESULT_MAX; i++) {<br>
+      if (brw_get_interpolation_mode(brw, i) == INTERP_QUALIFIER_NOPERSPECTIVE &&<br>
+          brw->vs.prog_data->vue_map.slot_to_vert_result[i] != VERT_RESULT_HPOS) {<br>
+         key.has_noperspective_shading = 1;<br>
+         break;<br>
+      }<br>
+   }<br>
+<br>
    key.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);<br>
    brw_copy_interpolation_modes(brw, key.interpolation_mode);<br>
    /* _NEW_TRANSFORM (also part of VUE map)*/<br>
diff --git a/src/mesa/drivers/dri/i965/brw_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h<br>
index 0ea0394..2a7245a 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip.h<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip.h<br>
@@ -47,6 +47,7 @@ struct brw_clip_prog_key {<br>
    GLuint primitive:4;<br>
    GLuint nr_userclip:4;<br>
    GLuint has_flat_shading:1;<br>
+   GLuint has_noperspective_shading:1;<br>
    GLuint pv_first:1;<br>
    GLuint do_unfilled:1;<br>
    GLuint fill_cw:2;           /* includes cull information */<br>
diff --git a/src/mesa/drivers/dri/i965/brw_clip_util.c b/src/mesa/drivers/dri/i965/brw_clip_util.c<br>
index 7b0205a..5bdcef8 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip_util.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip_util.c<br>
@@ -129,6 +129,8 @@ static void brw_clip_project_vertex( struct brw_clip_compile *c,<br>
<br>
 /* Interpolate between two vertices and put the result into a0.0.<br>
  * Increment a0.0 accordingly.<br>
+ *<br>
+ * Beware that dest_ptr can be equal to v0_ptr.<br>
  */<br>
 void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
                             struct brw_indirect dest_ptr,<br>
@@ -138,8 +140,9 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
                             bool force_edgeflag)<br>
 {<br>
    struct brw_compile *p = &c->func;<br>
-   struct brw_reg tmp = get_tmp(c);<br>
-   GLuint slot;<br>
+   struct brw_context *brw = p->brw;<br>
+   struct brw_reg tmp, t_nopersp, v0_ndc_copy;<br>
+   GLuint slot, delta;<br>
<br>
    /* Just copy the vertex header:<br>
     */<br>
@@ -148,13 +151,119 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
     * back on Ironlake, so needn't change it<br>
     */<br>
    brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1);<br>
-<br>
-   /* Iterate over each attribute (could be done in pairs?)<br>
+<br>
+   /*<br>
+    * First handle the 3D and NDC positioning, in case we need<br>
+    * noperspective interpolation.  Doing it early has no performance<br>
+    * impact in any case.<br>
+    */<br>
+<br>
+   /* Start by picking up the v0 NDC coordinates, because that vertex<br>
+    * may be shared with the destination.<br>
+    */<br>
+   if (c->key.has_noperspective_shading) {<br>
+      v0_ndc_copy = get_tmp(c);<br>
+      brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr,<br>
+                                       brw_vert_result_to_offset(&c->vue_map,<br>
+                                                                 BRW_VERT_RESULT_NDC)));<br>
+   }<br></blockquote><div><br>Style nit-pick: this is a lot of indentation.  How about this instead:<br><br>   if (c->key.has_noperspective_shading) {<br>      unsigned offset =<br>         brw_vert_result_to_offset(&c->vue_map, BRW_VERT_RESULT_NDC);<br>
      v0_ndc_copy = get_tmp(c);<br>      brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset));<br>   }<br><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>
+   /*<br>
+    * Compute the new 3D position<br>
+    */<br>
+<br>
+   delta = brw_vert_result_to_offset(&c->vue_map, VERT_RESULT_HPOS);<br>
+   tmp = get_tmp(c);<br>
+   brw_MUL(p,<br>
+           vec4(brw_null_reg()),<br>
+           deref_4f(v1_ptr, delta),<br>
+           t0);<br>
+<br>
+   brw_MAC(p,<br>
+           tmp,<br>
+           negate(deref_4f(v0_ptr, delta)),<br>
+           t0);<br>
+<br>
+   brw_ADD(p,<br>
+           deref_4f(dest_ptr, delta),<br>
+           deref_4f(v0_ptr, delta),<br>
+           tmp);<br>
+   release_tmp(c, tmp);<br></blockquote><div><br>Since delta and tmp are used elsewhere in this function for other purposes, I would feel more comfortable if we created a local scope for them by enclosing this small chunk of code in curly braces, e.g.:<br>
<br>   {<br>      /*<br>       * Compute the new 3D position<br>       */<br><br>      GLuint delta = brw_vert_result_to_offset(&c->vue_map, VERT_RESULT_HPOS);<br>      struct brw_reg tmp = get_tmp(c);<br>      brw_MUL(p,<br>
              vec4(brw_null_reg()),<br>              deref_4f(v1_ptr, delta),<br>              t0);<br><br>      brw_MAC(p,<br>              tmp,<br>              negate(deref_4f(v0_ptr, delta)),<br>              t0);<br>
<br>      brw_ADD(p,<br>              deref_4f(dest_ptr, delta),<br>              deref_4f(v0_ptr, delta),<br>              tmp);<br>      release_tmp(c, tmp);<br>   }<br><br></div><div>Also, it would be nice to have a comment above each small group of instructions showing what they compute as a formula.  For example, above these three instructions we could say:<br>
<br>/* dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0 */<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>
+   /* Then recreate the projected (NDC) coordinate in the new vertex<br>
+    * header<br>
     */<br>
+   brw_clip_project_vertex(c, dest_ptr);<br>
+<br>
+   /*<br>
+    * If we have noperspective attributes, we now need to compute the<br>
+    * screen-space t.<br>
+    */<br>
+   if (c->key.has_noperspective_shading) {<br>
+      delta = brw_vert_result_to_offset(&c->vue_map, BRW_VERT_RESULT_NDC);<br>
+      t_nopersp = get_tmp(c);<br>
+      tmp = get_tmp(c);<br></blockquote><div><br>Along the same lines as my previous comment, I'd prefer to make these three variables local to this scope, e.g.:<br><br>   if (c->key.has_noperspective_shading) {<br>
      GLuint delta = brw_vert_result_to_offset(&c->vue_map, BRW_VERT_RESULT_NDC);<br>      struct brw_reg t_nopersp = get_tmp(c);<br>      struct brw_reg tmp = get_tmp(c);<br><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>
+      /* Build a register with coordinates from the second and new vertices */<br></blockquote><div><br>In the code below, I could really use some comments to clarify the computation you're doing.  I'll insert some suggestions inline:<br>
 <br>      /* t_nopersp = vec4(v1_ndc.xy, dest_ndc.xy) */<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta));<br>
+      brw_MOV(p, tmp, deref_4f(dest_ptr, delta));<br>
+      brw_set_access_mode(p, BRW_ALIGN_16);<br>
+      brw_MOV(p,<br>
+              brw_writemask(t_nopersp, WRITEMASK_ZW),<br>
+              brw_swizzle(tmp, 0,1,0,1));<br>
+<br>
+      /* Subtract the coordinates of the first vertex */<br></blockquote><div>      /* t_nopersp -= v0_ndc_copy.xyxy<br>       * Therefore t_nopersp = vec4(v1_ndc.xy - v0_ndc.xy,<br>       *                            dest_ndc.xy - v0_ndc.xy)<br>
       */ <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      brw_ADD(p, t_nopersp, t_nopersp, negate(brw_swizzle(v0_ndc_copy, 0,1,0,1)));<br>
+<br>
+      /* Add the absolute value of the X and Y deltas so that if the<br>
+       * points aren't in the same place on the screen we get non-zero<br>
+       * values to divide.<br>
+       *<br>
+       * After that we have vert1-vert0 in t_nopersp.x and vertnew-vert0 in t_nopersp.y.<br>
+       */<br></blockquote><div>      /* t_nopersp.xy = |t_nopersp.xz| + |t_nopersp.yw|<br>       * Therefore:<br>       * t_nopersp = vec4(|v1_ndc.x - v0_ndc.x| + |v1_ndc.y - v0_ndc.y|,<br>       *                  |dest_ndc.x - v0_ndc.x| + |dest_ndc.y - v0_ndc.y|,<br>
       *                  <don't care>, <don't care>)<br>       */ <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
+      brw_ADD(p,<br>
+              brw_writemask(t_nopersp, WRITEMASK_XY),<br>
+              brw_abs(brw_swizzle(t_nopersp, 0,2,0,0)),<br>
+              brw_abs(brw_swizzle(t_nopersp, 1,3,0,0)));<br>
+      brw_set_access_mode(p, BRW_ALIGN_1);<br>
+<br>
+      /* If the points are in the same place (vert1-vert0 == 0), just<br>
+       * substitute a value that will ensure that we don't divide by<br>
+       * 0.<br>
+       */<br>
+      brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ,<br>
+              vec1(t_nopersp),<br>
+              brw_imm_f(1));<br></blockquote><div><br>Shouldn't this be brw_imm_f(0)?<br> </div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">

+      brw_IF(p, BRW_EXECUTE_1);<br>
+      brw_MOV(p, t_nopersp, brw_imm_vf4(VF_ONE, VF_ZERO, VF_ZERO, VF_ZERO));<br>
+      brw_ENDIF(p);<br>
+<br>
+      /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast it */<br>
+      brw_math_invert(p, get_element(t_nopersp, 0), get_element(t_nopersp, 0));<br>
+      brw_MUL(p,<br>
+              vec1(t_nopersp),<br>
+              vec1(t_nopersp),<br>
+              vec1(suboffset(t_nopersp, 1)));<br>
+      brw_set_access_mode(p, BRW_ALIGN_16);<br>
+      brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, 0,0,0,0));<br>
+      brw_set_access_mode(p, BRW_ALIGN_1);<br></blockquote><div><br>That was a very clever computation.  Well done.<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>
+      release_tmp(c, tmp);<br>
+      release_tmp(c, v0_ndc_copy);<br>
+   }<br>
+<br>
+   /* Now we can iterate over each attribute<br>
+    * (could be done in pairs?)<br>
+    */<br>
+   tmp = get_tmp(c);<br>
    for (slot = 0; slot < c->vue_map.num_slots; slot++) {<br>
       int vert_result = c->vue_map.slot_to_vert_result[slot];<br>
       GLuint delta = brw_vue_slot_to_offset(slot);<br>
<br>
+      /* HPOS is already handled */<br>
+      if(vert_result == VERT_RESULT_HPOS)<br>
+         continue;<br>
+<br>
       if (vert_result == VERT_RESULT_EDGE) {<br>
         if (force_edgeflag)<br>
            brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));<br>
@@ -174,15 +283,20 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
          *<br>
          *        New = attr0 + t*attr1 - t*attr0<br>
          */<br>
+<br>
+         struct brw_reg t =<br>
+            brw_get_interpolation_mode(brw, slot) == INTERP_QUALIFIER_NOPERSPECTIVE ?<br>
+            t_nopersp : t0;<br>
+<br>
         brw_MUL(p,<br>
                 vec4(brw_null_reg()),<br>
                 deref_4f(v1_ptr, delta),<br>
-                t0);<br>
+                t);<br>
<br>
         brw_MAC(p,<br>
                 tmp,<br>
                 negate(deref_4f(v0_ptr, delta)),<br>
-                t0);<br>
+                t);<br>
<br>
         brw_ADD(p,<br>
                 deref_4f(dest_ptr, delta),<br>
@@ -198,11 +312,8 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
    }<br>
<br>
    release_tmp(c, tmp);<br>
-<br>
-   /* Recreate the projected (NDC) coordinate in the new vertex<br>
-    * header:<br>
-    */<br>
-   brw_clip_project_vertex(c, dest_ptr );<br>
+   if (c->key.has_noperspective_shading)<br>
+      release_tmp(c, t_nopersp);<br>
 }<br>
<br>
 void brw_clip_emit_vue(struct brw_clip_compile *c,<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>With the exception of my question about brw_imm_f(0), all of my comments on this patch are stylistic suggestions.  So assuming we get the brw_imm_f(0) thing figured out, this patch is:<br>
<br>Reviewed-by: Paul Berry <<a href="mailto:stereotype441@gmail.com">stereotype441@gmail.com</a>><br>