[Mesa-dev] [PATCH 8/8] i965/gen6+: Add support for noperspective interpolation.
Paul Berry
stereotype441 at gmail.com
Mon Oct 24 14:38:46 PDT 2011
This required the following changes:
- WM setup now makes the appropriate set of barycentric coordinates
(perspective vs. noperspective) available to the fragment shader,
based on whether the shader requires perspective interpolation,
noperspective interpolation, both, or neither.
- The fragment shader backend now uses the appropriate set of
barycentric coordiantes when interpolating, based on the
interpolation mode returned by
ir_variable::determine_interpolation_mode().
- SF setup now uses _mesa_compute_flag_attributes_flat() to determine
which attributes are to be flat shaded (as opposed to the old logic,
which only flat shaded colors).
- CLIP setup now ensures that the clipper outputs non-perspective
barycentric coordinates when they are needed by the fragment shader.
Fixes the remaining piglit tests of interpolation qualifiers that were
failing:
- interpolation-flat-*-smooth-none
- interpolation-flat-other-flat-none
- interpolation-noperspective-*
- interpolation-smooth-gl_*Color-flat-*
---
src/mesa/drivers/dri/i965/brw_context.h | 3 ++-
src/mesa/drivers/dri/i965/brw_fs.cpp | 9 ++++++---
src/mesa/drivers/dri/i965/brw_wm.c | 24 ++++++++++++++++++++----
src/mesa/drivers/dri/i965/gen6_clip_state.c | 12 +++++++++++-
src/mesa/drivers/dri/i965/gen6_sf_state.c | 17 ++++++-----------
src/mesa/drivers/dri/i965/gen6_wm_state.c | 9 ++++++++-
src/mesa/drivers/dri/i965/gen7_clip_state.c | 12 +++++++++++-
src/mesa/drivers/dri/i965/gen7_sf_state.c | 17 ++++++-----------
src/mesa/drivers/dri/i965/gen7_wm_state.c | 10 ++++++++--
9 files changed, 78 insertions(+), 35 deletions(-)
diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h
index f83d5fc..bed3178 100644
--- a/src/mesa/drivers/dri/i965/brw_context.h
+++ b/src/mesa/drivers/dri/i965/brw_context.h
@@ -972,7 +972,8 @@ gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx);
/* brw_wm.c */
unsigned
-brw_compute_barycentric_interp_modes(void);
+brw_compute_barycentric_interp_modes(bool shade_model_flat,
+ const struct gl_fragment_program *fprog);
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 51d5dbe..9aa8838 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -469,7 +469,7 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
attr.reg_offset++;
}
} else {
- /* Perspective interpolation case. */
+ /* Smooth/noperspective interpolation case. */
for (unsigned int k = 0; k < type->vector_elements; k++) {
/* FINISHME: At some point we probably want to push
* this farther by giving similar treatment to the
@@ -483,8 +483,11 @@ fs_visitor::emit_general_interpolation(ir_variable *ir)
emit(BRW_OPCODE_MOV, attr, fs_reg(1.0f));
} else {
struct brw_reg interp = interp_reg(location, k);
- brw_wm_barycentric_interp_mode barycoord_mode =
- BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
+ brw_wm_barycentric_interp_mode barycoord_mode;
+ if (interpolation_mode == ir_var_interp_smooth)
+ barycoord_mode = BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
+ else
+ barycoord_mode = BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC;
emit(FS_OPCODE_LINTERP, attr,
this->delta_x[barycoord_mode],
this->delta_y[barycoord_mode], fs_reg(interp));
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c
index 546d522..3f82aec 100644
--- a/src/mesa/drivers/dri/i965/brw_wm.c
+++ b/src/mesa/drivers/dri/i965/brw_wm.c
@@ -129,10 +129,25 @@ brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c)
* (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader.
*/
unsigned
-brw_compute_barycentric_interp_modes(void)
+brw_compute_barycentric_interp_modes(bool shade_model_flat,
+ const struct gl_fragment_program *fprog)
{
- /* At the moment the only interpolation mode we support is perspective. */
- return (1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC);
+ unsigned barycentric_interp_modes = 0;
+
+ /* We only need perspective barycentric coordinates if one of the fragment
+ * shader inputs is "smooth" interpolated, or if PNTC is in use.
+ */
+ if (_mesa_compute_frag_attribs_smooth(shade_model_flat, fprog) ||
+ (fprog->Base.InputsRead & FRAG_BIT_PNTC))
+ barycentric_interp_modes |= 1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC;
+
+ /* We only need non-perspective barycentric coordinates if one of the
+ * fragment shader inputs is "noperspective" interpolated.
+ */
+ if (_mesa_compute_frag_attribs_noperspective(fprog))
+ barycentric_interp_modes |= 1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC;
+
+ return barycentric_interp_modes;
}
@@ -144,7 +159,8 @@ brw_wm_payload_setup(struct brw_context *brw,
bool uses_depth = (c->fp->program.Base.InputsRead &
(1 << FRAG_ATTRIB_WPOS)) != 0;
unsigned barycentric_interp_modes =
- brw_compute_barycentric_interp_modes();
+ brw_compute_barycentric_interp_modes(c->key.flat_shade,
+ &c->fp->program);
int i;
if (intel->gen >= 6) {
diff --git a/src/mesa/drivers/dri/i965/gen6_clip_state.c b/src/mesa/drivers/dri/i965/gen6_clip_state.c
index 9b36af4..5081969 100644
--- a/src/mesa/drivers/dri/i965/gen6_clip_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_clip_state.c
@@ -38,6 +38,14 @@ upload_clip_state(struct brw_context *brw)
struct gl_context *ctx = &intel->ctx;
uint32_t depth_clamp = 0;
uint32_t provoking, userclip;
+ uint32_t nonperspective_barycentric_enable_flag = 0;
+ /* BRW_NEW_FRAGMENT_PROGRAM */
+ const struct gl_fragment_program *fprog = brw->fragment_program;
+
+ if (_mesa_compute_frag_attribs_noperspective(fprog)) {
+ nonperspective_barycentric_enable_flag =
+ GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE;
+ }
if (!ctx->Transform.DepthClamp)
depth_clamp = GEN6_CLIP_Z_TEST;
@@ -64,6 +72,7 @@ upload_clip_state(struct brw_context *brw)
OUT_BATCH(GEN6_CLIP_ENABLE |
GEN6_CLIP_API_OGL |
GEN6_CLIP_MODE_NORMAL |
+ nonperspective_barycentric_enable_flag |
GEN6_CLIP_XY_TEST |
userclip << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT |
depth_clamp |
@@ -77,7 +86,8 @@ upload_clip_state(struct brw_context *brw)
const struct brw_tracked_state gen6_clip_state = {
.dirty = {
.mesa = _NEW_TRANSFORM | _NEW_LIGHT,
- .brw = BRW_NEW_CONTEXT,
+ .brw = (BRW_NEW_CONTEXT |
+ BRW_NEW_FRAGMENT_PROGRAM),
.cache = 0
},
.emit = upload_clip_state,
diff --git a/src/mesa/drivers/dri/i965/gen6_sf_state.c b/src/mesa/drivers/dri/i965/gen6_sf_state.c
index 67b649e..cf960f6 100644
--- a/src/mesa/drivers/dri/i965/gen6_sf_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c
@@ -118,6 +118,10 @@ upload_sf_state(struct brw_context *brw)
GLbitfield64 vs_outputs_written = brw->vs.prog_data->outputs_written;
/* BRW_NEW_FRAGMENT_PROGRAM */
uint32_t num_outputs = _mesa_bitcount_64(brw->fragment_program->Base.InputsRead);
+ /* _NEW_LIGHT */
+ GLbitfield64 flat_shaded_attrs =
+ _mesa_compute_frag_attribs_flat(ctx->Light.ShadeModel == GL_FLAT,
+ brw->fragment_program);
uint32_t dw1, dw2, dw3, dw4, dw16, dw17;
int i;
/* _NEW_BUFFER */
@@ -277,17 +281,8 @@ upload_sf_state(struct brw_context *brw)
dw16 |= (1 << input_index);
/* flat shading */
- if (ctx->Light.ShadeModel == GL_FLAT) {
- /*
- * Setup the Constant Interpolation Enable bit mask for each
- * corresponding attribute(currently, we only care two attrs:
- * FRAG_BIT_COL0 and FRAG_BIT_COL1).
- *
- * FIXME: should we care other attributes?
- */
- if (attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1)
- dw17 |= (1 << input_index);
- }
+ if (flat_shaded_attrs & BITFIELD64_BIT(attr))
+ dw17 |= (1 << input_index);
/* The hardware can only do the overrides on 16 overrides at a
* time, and the other up to 16 have to be lined up so that the
diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c
index ee4cc49..45896a9 100644
--- a/src/mesa/drivers/dri/i965/gen6_wm_state.c
+++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c
@@ -98,6 +98,10 @@ upload_wm_state(struct brw_context *brw)
const struct brw_fragment_program *fp =
brw_fragment_program_const(brw->fragment_program);
uint32_t dw2, dw4, dw5, dw6;
+ unsigned barycentric_interp_modes;
+
+ /* _NEW_LIGHT */
+ bool flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
/* CACHE_NEW_WM_PROG */
if (brw->wm.prog_data->nr_params == 0) {
@@ -168,6 +172,8 @@ upload_wm_state(struct brw_context *brw)
dw5 |= GEN6_WM_USES_SOURCE_DEPTH | GEN6_WM_USES_SOURCE_W;
if (fp->program.Base.OutputsWritten & BITFIELD64_BIT(FRAG_RESULT_DEPTH))
dw5 |= GEN6_WM_COMPUTED_DEPTH;
+ barycentric_interp_modes =
+ brw_compute_barycentric_interp_modes(flat_shade, &fp->program);
/* _NEW_COLOR */
if (fp->program.UsesKill || ctx->Color.AlphaEnabled)
@@ -178,7 +184,7 @@ upload_wm_state(struct brw_context *brw)
dw5 |= GEN6_WM_DISPATCH_ENABLE;
}
- dw6 |= brw_compute_barycentric_interp_modes() <<
+ dw6 |= barycentric_interp_modes <<
GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT;
dw6 |= _mesa_bitcount_64(brw->fragment_program->Base.InputsRead) <<
@@ -206,6 +212,7 @@ upload_wm_state(struct brw_context *brw)
const struct brw_tracked_state gen6_wm_state = {
.dirty = {
.mesa = (_NEW_LINE |
+ _NEW_LIGHT |
_NEW_COLOR |
_NEW_BUFFERS |
_NEW_PROGRAM_CONSTANTS |
diff --git a/src/mesa/drivers/dri/i965/gen7_clip_state.c b/src/mesa/drivers/dri/i965/gen7_clip_state.c
index da8d73a..1c1b554 100644
--- a/src/mesa/drivers/dri/i965/gen7_clip_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_clip_state.c
@@ -35,10 +35,18 @@ upload_clip_state(struct brw_context *brw)
uint32_t depth_clamp = 0;
uint32_t provoking, userclip;
uint32_t dw1 = GEN6_CLIP_STATISTICS_ENABLE;
+ uint32_t nonperspective_barycentric_enable_flag = 0;
+ /* BRW_NEW_FRAGMENT_PROGRAM */
+ const struct gl_fragment_program *fprog = brw->fragment_program;
/* _NEW_BUFFERS */
bool render_to_fbo = brw->intel.ctx.DrawBuffer->Name != 0;
+ if (_mesa_compute_frag_attribs_noperspective(fprog)) {
+ nonperspective_barycentric_enable_flag =
+ GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE;
+ }
+
dw1 |= GEN7_CLIP_EARLY_CULL;
/* _NEW_POLYGON */
@@ -90,6 +98,7 @@ upload_clip_state(struct brw_context *brw)
OUT_BATCH(GEN6_CLIP_ENABLE |
GEN6_CLIP_API_OGL |
GEN6_CLIP_MODE_NORMAL |
+ nonperspective_barycentric_enable_flag |
GEN6_CLIP_XY_TEST |
userclip << GEN6_USER_CLIP_CLIP_DISTANCES_SHIFT |
depth_clamp |
@@ -106,7 +115,8 @@ const struct brw_tracked_state gen7_clip_state = {
_NEW_POLYGON |
_NEW_LIGHT |
_NEW_TRANSFORM),
- .brw = BRW_NEW_CONTEXT,
+ .brw = (BRW_NEW_CONTEXT |
+ BRW_NEW_FRAGMENT_PROGRAM),
.cache = 0
},
.emit = upload_clip_state,
diff --git a/src/mesa/drivers/dri/i965/gen7_sf_state.c b/src/mesa/drivers/dri/i965/gen7_sf_state.c
index e796a01..0589f71 100644
--- a/src/mesa/drivers/dri/i965/gen7_sf_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_sf_state.c
@@ -39,6 +39,10 @@ upload_sbe_state(struct brw_context *brw)
GLbitfield64 vs_outputs_written = brw->vs.prog_data->outputs_written;
/* BRW_NEW_FRAGMENT_PROGRAM */
uint32_t num_outputs = _mesa_bitcount_64(brw->fragment_program->Base.InputsRead);
+ /* _NEW_LIGHT */
+ GLbitfield64 flat_shaded_attrs =
+ _mesa_compute_frag_attribs_flat(ctx->Light.ShadeModel == GL_FLAT,
+ brw->fragment_program);
uint32_t dw1, dw10, dw11;
int i;
int attr = 0, input_index = 0;
@@ -87,17 +91,8 @@ upload_sbe_state(struct brw_context *brw)
dw10 |= (1 << input_index);
/* flat shading */
- if (ctx->Light.ShadeModel == GL_FLAT) {
- /*
- * Setup the Constant Interpolation Enable bit mask for each
- * corresponding attribute(currently, we only care two attrs:
- * FRAG_BIT_COL0 and FRAG_BIT_COL1).
- *
- * FIXME: should we care other attributes?
- */
- if (attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1)
- dw11 |= (1 << input_index);
- }
+ if (flat_shaded_attrs & BITFIELD64_BIT(attr))
+ dw11 |= (1 << input_index);
/* The hardware can only do the overrides on 16 overrides at a
* time, and the other up to 16 have to be lined up so that the
diff --git a/src/mesa/drivers/dri/i965/gen7_wm_state.c b/src/mesa/drivers/dri/i965/gen7_wm_state.c
index e0004c5..2a9ebea 100644
--- a/src/mesa/drivers/dri/i965/gen7_wm_state.c
+++ b/src/mesa/drivers/dri/i965/gen7_wm_state.c
@@ -40,6 +40,10 @@ upload_wm_state(struct brw_context *brw)
brw_fragment_program_const(brw->fragment_program);
bool writes_depth = false;
uint32_t dw1;
+ unsigned barycentric_interp_modes;
+
+ /* _NEW_LIGHT */
+ bool flat_shade = (ctx->Light.ShadeModel == GL_FLAT);
dw1 = 0;
dw1 |= GEN7_WM_STATISTICS_ENABLE;
@@ -61,6 +65,8 @@ upload_wm_state(struct brw_context *brw)
writes_depth = true;
dw1 |= GEN7_WM_PSCDEPTH_ON;
}
+ barycentric_interp_modes =
+ brw_compute_barycentric_interp_modes(flat_shade, &fp->program);
/* _NEW_COLOR */
if (fp->program.UsesKill || ctx->Color.AlphaEnabled)
@@ -72,7 +78,7 @@ upload_wm_state(struct brw_context *brw)
dw1 |= GEN7_WM_DISPATCH_ENABLE;
}
- dw1 |= brw_compute_barycentric_interp_modes() <<
+ dw1 |= barycentric_interp_modes <<
GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT;
BEGIN_BATCH(3);
@@ -84,7 +90,7 @@ upload_wm_state(struct brw_context *brw)
const struct brw_tracked_state gen7_wm_state = {
.dirty = {
- .mesa = (_NEW_LINE | _NEW_POLYGON |
+ .mesa = (_NEW_LINE | _NEW_LIGHT | _NEW_POLYGON |
_NEW_COLOR | _NEW_BUFFERS),
.brw = (BRW_NEW_FRAGMENT_PROGRAM |
BRW_NEW_URB_FENCE |
--
1.7.6.4
More information about the mesa-dev
mailing list