[Mesa-dev] [PATCH 2/2] i965 Gen6: Implement gl_ClipVertex.
Kenneth Graunke
kenneth at whitecape.org
Thu Sep 29 23:16:18 PDT 2011
On 09/27/2011 11:05 AM, Paul Berry wrote:
> This patch implements proper support for gl_ClipVertex by causing the
> new VS backend to populate the clip distance VUE slots using
> VERT_RESULT_CLIP_VERTEX when appropriate, and by using the
> untransformed clip planes in ctx->Transform.EyeUserPlane rather than
> the transformed clip planes in ctx->Transform._ClipUserPlane.
>
> When fixed functionality is in use the driver needs to do the old
> behavior (clip based on VERT_RESULT_HPOS and
> ctx->Transform._ClipUserPlane). This happens automatically because we
> use the old VS backend for fixed functionality.
>
> Fixes the following Piglit tests on i965 Gen6:
> - vs-clip-vertex-const-accept
> - vs-clip-vertex-const-reject
> - vs-clip-vertex-different-from-position
> - vs-clip-vertex-equal-to-position
> - vs-clip-vertex-homogeneity
> - vs-clip-based-on-position
> - vs-clip-based-on-position-homogeneity
> - clip-plane-transformation clipvert_pos
> - clip-plane-transformation pos_clipvert
> - clip-plane-transformation pos
> ---
> src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 31 ++++++++++++++++++++++-
> src/mesa/drivers/dri/i965/brw_vs.c | 8 +++++-
> 2 files changed, 36 insertions(+), 3 deletions(-)
>
> diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> index e5eda22..f335a86 100644
> --- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
> @@ -553,7 +553,16 @@ vec4_visitor::setup_uniform_clipplane_values()
> this->userplane[compacted_clipplane_index] = dst_reg(UNIFORM, this->uniforms);
> this->userplane[compacted_clipplane_index].type = BRW_REGISTER_TYPE_F;
> for (int j = 0; j < 4; ++j) {
> - c->prog_data.param[this->uniforms * 4 + j] = &ctx->Transform._ClipUserPlane[i][j];
> + /* For fixed functionality shaders, we need to clip based on
> + * ctx->Transform._ClipUserPlane (which has been transformed by
> + * Mesa core into clip coordinates). For user-supplied vertex
> + * shaders, we need to use the untransformed clip planes in
> + * ctx->Transform.EyeUserPlane. Since vec4_visitor is currently
> + * only used for user-supplied vertex shaders, we can hardcode
> + * this to EyeUserPlane for now.
> + */
> + c->prog_data.param[this->uniforms * 4 + j]
> + = &ctx->Transform.EyeUserPlane[i][j];
So, we trade support for fixed function clipping for gl_ClipVertex
clipping? That seems really unfortunate. I know we don't use the new
VS backend for fixed function today, but we will.
Couldn't you just do:
const bool clip_vertex = c->prog_data.outputs_written &
BITFIELD64_BIT(VERT_RESULT_CLIP_VERTEX);
c->prog_data.param[this->uniforms * 4 + j] =
clip_vertex ? ctx->Transform.EyeUserPlane[i][j]
: ctx->Transform._ClipUserPlane[i][j];
...or is outputs_written not available at this point in time?
Yeah, I know it's untested, and untested code = broken code, and all
that, but...if you already know what you need to do...why not just do it?
> }
> ++compacted_clipplane_index;
> ++this->uniforms;
> @@ -1840,9 +1849,27 @@ vec4_visitor::emit_clip_distances(struct brw_reg reg, int offset)
> return;
> }
>
> + /* From the GLSL 1.30 spec, section 7.1 (Vertex Shader Special Variables):
> + *
> + * "If a linked set of shaders forming the vertex stage contains no
> + * static write to gl_ClipVertex or gl_ClipDistance, but the
> + * application has requested clipping against user clip planes through
> + * the API, then the coordinate written to gl_Position is used for
> + * comparison against the user clip planes."
> + *
> + * This function is only called if the shader didn't write to
> + * gl_ClipDistance. Accordingly, we use gl_ClipVertex to perform clipping
> + * if the user wrote to it; otherwise we use gl_Position.
> + */
> + gl_vert_result clip_vertex = VERT_RESULT_CLIP_VERTEX;
> + if (!(c->prog_data.outputs_written
> + & BITFIELD64_BIT(VERT_RESULT_CLIP_VERTEX))) {
> + clip_vertex = VERT_RESULT_HPOS;
> + }
> +
> for (int i = 0; i + offset < c->key.nr_userclip && i < 4; ++i) {
> emit(DP4(dst_reg(brw_writemask(reg, 1 << i)),
> - src_reg(output_reg[VERT_RESULT_HPOS]),
> + src_reg(output_reg[clip_vertex]),
> src_reg(this->userplane[i + offset])));
> }
> }
> diff --git a/src/mesa/drivers/dri/i965/brw_vs.c b/src/mesa/drivers/dri/i965/brw_vs.c
> index 93c6838..4fd260f 100644
> --- a/src/mesa/drivers/dri/i965/brw_vs.c
> +++ b/src/mesa/drivers/dri/i965/brw_vs.c
> @@ -137,11 +137,17 @@ brw_compute_vue_map(struct brw_vue_map *vue_map,
> /* The hardware doesn't care about the rest of the vertex outputs, so just
> * assign them contiguously. Don't reassign outputs that already have a
> * slot.
> + *
> + * Also, don't assign a slot for VERT_RESULT_CLIP_VERTEX, since it is
> + * unsupported in pre-GEN6, and in GEN6+ the vertex shader converts it into
> + * clip distances.
> */
> for (int i = 0; i < VERT_RESULT_MAX; ++i) {
> if ((outputs_written & BITFIELD64_BIT(i)) &&
> vue_map->vert_result_to_slot[i] == -1) {
I'd probably just fold this into the surrounding if statement...
if (...) {
if (...) {
}
}
looks a little odd, IMHO. Especially since the outer if statement's
conditional already spans multiple lines.
> - assign_vue_slot(vue_map, i);
> + if (i != VERT_RESULT_CLIP_VERTEX) {
> + assign_vue_slot(vue_map, i);
> + }
> }
> }
> }
More information about the mesa-dev
mailing list