<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">
Adds support for interpolating noperspective varyings linearly in screen<br>
space when clipping.<br>
<br>
Based on Olivier Galibert's patch from last year:<br>
<a href="http://lists.freedesktop.org/archives/mesa-dev/2012-July/024341.html" target="_blank">http://lists.freedesktop.org/archives/mesa-dev/2012-July/024341.html</a><br>
<br>
At this point all -fixed and -vertex interpolation tests work.<br>
<br>
[V1-2]: Signed-off-by: Olivier Galibert <galibert at <a href="http://pobox.com" target="_blank">pobox.com</a>><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_clip.c | 8 ++<br>
src/mesa/drivers/dri/i965/brw_clip.h | 1 +<br>
src/mesa/drivers/dri/i965/brw_clip_util.c | 120 +++++++++++++++++++++++++++---<br>
3 files changed, 119 insertions(+), 10 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 7df4b18..6dd3759 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip.c<br>
@@ -211,6 +211,14 @@ brw_upload_clip_prog(struct brw_context *brw)<br>
}<br>
}<br>
<br>
+ key.has_noperspective_shading = 0;<br>
+ for (i = 0; i < brw->vue_map_geom_out.num_slots; i++) {<br>
+ if (key.interpolation_mode[i] == INTERP_QUALIFIER_NOPERSPECTIVE) {<br>
+ key.has_noperspective_shading = 1;<br>
+ break;<br>
+ }<br>
+ }<br>
+<br></blockquote><div><br></div><div>As with key.has_flat_shading, I'd prefer to see this moved to compile_clip_prog() and brw_clip_compile.<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.pv_first = (ctx->Light.ProvokingVertex == GL_FIRST_VERTEX_CONVENTION);<br>
/* _NEW_TRANSFORM (also part of VUE map)*/<br>
key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled);<br>
diff --git a/src/mesa/drivers/dri/i965/brw_clip.h b/src/mesa/drivers/dri/i965/brw_clip.h<br>
index 656254b..90e3e33 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 8a21c1f..56c9ccd 100644<br>
--- a/src/mesa/drivers/dri/i965/brw_clip_util.c<br>
+++ b/src/mesa/drivers/dri/i965/brw_clip_util.c<br>
@@ -128,6 +128,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>
@@ -137,7 +139,7 @@ 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>
+ struct brw_reg t_nopersp, v0_ndc_copy;<br>
GLuint slot;<br>
<br>
/* Just copy the vertex header:<br>
@@ -148,12 +150,107 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<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>
+ /* First handle the 3D and NDC interpolation, in case we<br>
+ * need noperspective interpolation. Doing it early has no<br>
+ * performance impact in any case.<br>
+ */<br>
+<br>
+ /* Take a copy of the v0 NDC coordinates, in case dest == v0. */<br>
+ if (c->key.has_noperspective_shading) {<br>
+ GLuint offset = brw_varying_to_offset(&c->vue_map,<br>
+ BRW_VARYING_SLOT_NDC);<br>
+ v0_ndc_copy = get_tmp(c);<br>
+ brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset));<br>
+ }<br>
+<br>
+ /* Compute the new 3D position<br>
+ *<br>
+ * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0<br>
+ */<br>
+ {<br>
+ GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS);<br>
+ struct brw_reg tmp = get_tmp(c);<br>
+ brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0);<br>
+ brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0);<br>
+ brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp);<br>
+ release_tmp(c, tmp);<br>
+ }<br>
+<br>
+ /* Recreate the projected (NDC) coordinate in the new vertex header */<br>
+ brw_clip_project_vertex(c, dest_ptr);<br>
+<br>
+ /* If we have noperspective attributes,<br>
+ * we need to compute the screen-space t<br>
+ */<br>
+ if (c->key.has_noperspective_shading) {<br>
+ GLuint delta = brw_varying_to_offset(&c->vue_map,<br>
+ BRW_VARYING_SLOT_NDC);<br>
+ struct brw_reg tmp = get_tmp(c);<br>
+ t_nopersp = get_tmp(c);<br>
+<br>
+ /* t_nopersp = vec4(v1.xy, dest.xy) */<br>
+ 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>
+ /* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */<br>
+ brw_ADD(p, t_nopersp, t_nopersp,<br>
+ negate(brw_swizzle(v0_ndc_copy, 0, 1, 0, 1)));<br>
+<br>
+ /* Add the absolute values of the X and Y deltas so that if<br>
+ * the points aren't in the same place on the screen we get<br>
+ * nonzero values to divide.<br>
+ *<br>
+ * After that, we have vert1 - vert0 in t_nopersp.x and<br>
+ * vertnew - vert0 in t_nopersp.y<br>
+ *<br>
+ * t_nopersp = vec2(|v1.x -v0.x| + |v1.y -v0.y|,<br>
+ * |dest.x-v0.x| + |dest.y-v0.y|)<br>
+ */<br>
+ 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, just substitute a<br>
+ * value to avoid divide-by-zero<br>
+ */<br>
+ brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ,<br>
+ vec1(t_nopersp),<br>
+ brw_imm_f(0));<br>
+ 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, vec1(t_nopersp), 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>
+<br>
+ release_tmp(c, tmp);<br>
+ release_tmp(c, v0_ndc_copy);<br>
+ }<br></blockquote><div><br></div><div>I haven't had a chance to work through all the math above, but I trust that the piglit tests are adequate, so for this I'm just going to say<br><br></div><div>Acked-by: Paul Berry <<a href="mailto:stereotype441@gmail.com">stereotype441@gmail.com</a>><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>
+ /* Now we can iterate over each attribute<br>
+ * (could be done in pairs?)<br>
*/<br>
for (slot = 0; slot < c->vue_map.num_slots; slot++) {<br>
int varying = c->vue_map.slot_to_varying[slot];<br>
GLuint delta = brw_vue_slot_to_offset(slot);<br>
<br>
+ /* HPOS is already handled above */<br>
+ if (varying == VARYING_SLOT_POS)<br>
+ continue;<br>
+<br>
+<br>
if (varying == VARYING_SLOT_EDGE) {<br>
if (force_edgeflag)<br>
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1));<br>
@@ -173,20 +270,27 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
*<br>
* New = attr0 + t*attr1 - t*attr0<br>
*/<br>
+ struct brw_reg tmp = get_tmp(c);<br>
+ struct brw_reg t =<br>
+ c->key.interpolation_mode[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>
deref_4f(v0_ptr, delta),<br>
tmp);<br>
+<br>
+ release_tmp(c, tmp);<br>
}<br>
}<br>
<br>
@@ -196,12 +300,8 @@ void brw_clip_interp_vertex( struct brw_clip_compile *c,<br>
brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0));<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=""><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>