On 14 July 2013 02:39, Chris Forbes <chr...@ijw.co.nz> wrote: > Adds support for interpolating noperspective varyings linearly in screen > space when clipping. > > Based on Olivier Galibert's patch from last year: > http://lists.freedesktop.org/archives/mesa-dev/2012-July/024341.html > > At this point all -fixed and -vertex interpolation tests work. > > [V1-2]: Signed-off-by: Olivier Galibert <galibert at pobox.com> > Signed-off-by: Chris Forbes <chr...@ijw.co.nz> > --- > src/mesa/drivers/dri/i965/brw_clip.c | 8 ++ > src/mesa/drivers/dri/i965/brw_clip.h | 1 + > src/mesa/drivers/dri/i965/brw_clip_util.c | 120 > +++++++++++++++++++++++++++--- > 3 files changed, 119 insertions(+), 10 deletions(-) > > diff --git a/src/mesa/drivers/dri/i965/brw_clip.c > b/src/mesa/drivers/dri/i965/brw_clip.c > index 7df4b18..6dd3759 100644 > --- a/src/mesa/drivers/dri/i965/brw_clip.c > +++ b/src/mesa/drivers/dri/i965/brw_clip.c > @@ -211,6 +211,14 @@ brw_upload_clip_prog(struct brw_context *brw) > } > } > > + key.has_noperspective_shading = 0; > + for (i = 0; i < brw->vue_map_geom_out.num_slots; i++) { > + if (key.interpolation_mode[i] == INTERP_QUALIFIER_NOPERSPECTIVE) { > + key.has_noperspective_shading = 1; > + break; > + } > + } > + >
As with key.has_flat_shading, I'd prefer to see this moved to compile_clip_prog() and brw_clip_compile. > key.pv_first = (ctx->Light.ProvokingVertex == > GL_FIRST_VERTEX_CONVENTION); > /* _NEW_TRANSFORM (also part of VUE map)*/ > key.nr_userclip = _mesa_bitcount_64(ctx->Transform.ClipPlanesEnabled); > diff --git a/src/mesa/drivers/dri/i965/brw_clip.h > b/src/mesa/drivers/dri/i965/brw_clip.h > index 656254b..90e3e33 100644 > --- a/src/mesa/drivers/dri/i965/brw_clip.h > +++ b/src/mesa/drivers/dri/i965/brw_clip.h > @@ -47,6 +47,7 @@ struct brw_clip_prog_key { > GLuint primitive:4; > GLuint nr_userclip:4; > GLuint has_flat_shading:1; > + GLuint has_noperspective_shading:1; > GLuint pv_first:1; > GLuint do_unfilled:1; > GLuint fill_cw:2; /* includes cull information */ > diff --git a/src/mesa/drivers/dri/i965/brw_clip_util.c > b/src/mesa/drivers/dri/i965/brw_clip_util.c > index 8a21c1f..56c9ccd 100644 > --- a/src/mesa/drivers/dri/i965/brw_clip_util.c > +++ b/src/mesa/drivers/dri/i965/brw_clip_util.c > @@ -128,6 +128,8 @@ static void brw_clip_project_vertex( struct > brw_clip_compile *c, > > /* Interpolate between two vertices and put the result into a0.0. > * Increment a0.0 accordingly. > + * > + * Beware that dest_ptr can be equal to v0_ptr! > */ > void brw_clip_interp_vertex( struct brw_clip_compile *c, > struct brw_indirect dest_ptr, > @@ -137,7 +139,7 @@ void brw_clip_interp_vertex( struct brw_clip_compile > *c, > bool force_edgeflag) > { > struct brw_compile *p = &c->func; > - struct brw_reg tmp = get_tmp(c); > + struct brw_reg t_nopersp, v0_ndc_copy; > GLuint slot; > > /* Just copy the vertex header: > @@ -148,12 +150,107 @@ void brw_clip_interp_vertex( struct > brw_clip_compile *c, > */ > brw_copy_indirect_to_indirect(p, dest_ptr, v0_ptr, 1); > > - /* Iterate over each attribute (could be done in pairs?) > + > + /* First handle the 3D and NDC interpolation, in case we > + * need noperspective interpolation. Doing it early has no > + * performance impact in any case. > + */ > + > + /* Take a copy of the v0 NDC coordinates, in case dest == v0. */ > + if (c->key.has_noperspective_shading) { > + GLuint offset = brw_varying_to_offset(&c->vue_map, > + BRW_VARYING_SLOT_NDC); > + v0_ndc_copy = get_tmp(c); > + brw_MOV(p, v0_ndc_copy, deref_4f(v0_ptr, offset)); > + } > + > + /* Compute the new 3D position > + * > + * dest_hpos = v0_hpos * (1 - t0) + v1_hpos * t0 > + */ > + { > + GLuint delta = brw_varying_to_offset(&c->vue_map, VARYING_SLOT_POS); > + struct brw_reg tmp = get_tmp(c); > + brw_MUL(p, vec4(brw_null_reg()), deref_4f(v1_ptr, delta), t0); > + brw_MAC(p, tmp, negate(deref_4f(v0_ptr, delta)), t0); > + brw_ADD(p, deref_4f(dest_ptr, delta), deref_4f(v0_ptr, delta), tmp); > + release_tmp(c, tmp); > + } > + > + /* Recreate the projected (NDC) coordinate in the new vertex header */ > + brw_clip_project_vertex(c, dest_ptr); > + > + /* If we have noperspective attributes, > + * we need to compute the screen-space t > + */ > + if (c->key.has_noperspective_shading) { > + GLuint delta = brw_varying_to_offset(&c->vue_map, > + BRW_VARYING_SLOT_NDC); > + struct brw_reg tmp = get_tmp(c); > + t_nopersp = get_tmp(c); > + > + /* t_nopersp = vec4(v1.xy, dest.xy) */ > + brw_MOV(p, t_nopersp, deref_4f(v1_ptr, delta)); > + brw_MOV(p, tmp, deref_4f(dest_ptr, delta)); > + brw_set_access_mode(p, BRW_ALIGN_16); > + brw_MOV(p, > + brw_writemask(t_nopersp, WRITEMASK_ZW), > + brw_swizzle(tmp, 0, 1, 0, 1)); > + > + /* t_nopersp = vec4(v1.xy, dest.xy) - v0.xyxy */ > + brw_ADD(p, t_nopersp, t_nopersp, > + negate(brw_swizzle(v0_ndc_copy, 0, 1, 0, 1))); > + > + /* Add the absolute values of the X and Y deltas so that if > + * the points aren't in the same place on the screen we get > + * nonzero values to divide. > + * > + * After that, we have vert1 - vert0 in t_nopersp.x and > + * vertnew - vert0 in t_nopersp.y > + * > + * t_nopersp = vec2(|v1.x -v0.x| + |v1.y -v0.y|, > + * |dest.x-v0.x| + |dest.y-v0.y|) > + */ > + brw_ADD(p, > + brw_writemask(t_nopersp, WRITEMASK_XY), > + brw_abs(brw_swizzle(t_nopersp, 0, 2, 0, 0)), > + brw_abs(brw_swizzle(t_nopersp, 1, 3, 0, 0))); > + brw_set_access_mode(p, BRW_ALIGN_1); > + > + /* If the points are in the same place, just substitute a > + * value to avoid divide-by-zero > + */ > + brw_CMP(p, vec1(brw_null_reg()), BRW_CONDITIONAL_EQ, > + vec1(t_nopersp), > + brw_imm_f(0)); > + brw_IF(p, BRW_EXECUTE_1); > + brw_MOV(p, t_nopersp, brw_imm_vf4(VF_ONE, VF_ZERO, VF_ZERO, > VF_ZERO)); > + brw_ENDIF(p); > + > + /* Now compute t_nopersp = t_nopersp.y/t_nopersp.x and broadcast > it. */ > + brw_math_invert(p, get_element(t_nopersp, 0), > get_element(t_nopersp, 0)); > + brw_MUL(p, vec1(t_nopersp), vec1(t_nopersp), > + vec1(suboffset(t_nopersp, 1))); > + brw_set_access_mode(p, BRW_ALIGN_16); > + brw_MOV(p, t_nopersp, brw_swizzle(t_nopersp, 0, 0, 0, 0)); > + brw_set_access_mode(p, BRW_ALIGN_1); > + > + release_tmp(c, tmp); > + release_tmp(c, v0_ndc_copy); > + } > 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 Acked-by: Paul Berry <stereotype...@gmail.com> > + > + /* Now we can iterate over each attribute > + * (could be done in pairs?) > */ > for (slot = 0; slot < c->vue_map.num_slots; slot++) { > int varying = c->vue_map.slot_to_varying[slot]; > GLuint delta = brw_vue_slot_to_offset(slot); > > + /* HPOS is already handled above */ > + if (varying == VARYING_SLOT_POS) > + continue; > + > + > if (varying == VARYING_SLOT_EDGE) { > if (force_edgeflag) > brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(1)); > @@ -173,20 +270,27 @@ void brw_clip_interp_vertex( struct brw_clip_compile > *c, > * > * New = attr0 + t*attr1 - t*attr0 > */ > + struct brw_reg tmp = get_tmp(c); > + struct brw_reg t = > + c->key.interpolation_mode[slot] == > INTERP_QUALIFIER_NOPERSPECTIVE ? > + t_nopersp : t0; > + > brw_MUL(p, > vec4(brw_null_reg()), > deref_4f(v1_ptr, delta), > - t0); > + t); > > brw_MAC(p, > tmp, > negate(deref_4f(v0_ptr, delta)), > - t0); > + t); > > brw_ADD(p, > deref_4f(dest_ptr, delta), > deref_4f(v0_ptr, delta), > tmp); > + > + release_tmp(c, tmp); > } > } > > @@ -196,12 +300,8 @@ void brw_clip_interp_vertex( struct brw_clip_compile > *c, > brw_MOV(p, deref_4f(dest_ptr, delta), brw_imm_f(0)); > } > > - release_tmp(c, tmp); > - > - /* Recreate the projected (NDC) coordinate in the new vertex > - * header: > - */ > - brw_clip_project_vertex(c, dest_ptr ); > + if (c->key.has_noperspective_shading) > + release_tmp(c, t_nopersp); > } > > void brw_clip_emit_vue(struct brw_clip_compile *c, > -- > 1.8.3.2 > > _______________________________________________ > mesa-dev mailing list > mesa-dev@lists.freedesktop.org > http://lists.freedesktop.org/mailman/listinfo/mesa-dev >
_______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev