diff options
author | Paul Berry <[email protected]> | 2012-06-21 11:21:22 -0700 |
---|---|---|
committer | Paul Berry <[email protected]> | 2012-07-02 13:27:36 -0700 |
commit | 8313f44409ceb733e9f8835926364164237b3111 (patch) | |
tree | 32f7d08f69d5e620dfebe6e62a32dddf4a98c2dd /src/mesa/drivers/dri/i965/brw_wm.c | |
parent | 3f929efa2872aa5a4402520ec9fd551392e2413a (diff) |
i965/msaa: Fix centroid interpolation of unlit pixels.
From the Ivy Bridge PRM, Vol 2 Part 1 p280-281 (3DSTATE_WM:
Barycentric Interpolation Mode):
"Errata: When Centroid Barycentric mode is required, HW may
produce incorrect interpolation results when a 2X2 pixels have
unlit pixels."
To work around this problem, after doing centroid interpolation, we
replace the centroid-interpolated values for unlit pixels with
non-centroid-interpolated values (which are interpolated at pixel
centers). This produces correct rendering at the expense of a slight
increase in shader execution time.
I've conditioned the workaround with a runtime flag
(brw->needs_unlit_centroid_workaround) in the hopes that we won't need
it in future chip generations.
Fixes piglit tests "EXT_framebuffer_multisample/interpolation {2,4}
{centroid-deriv,centroid-deriv-disabled}". All MSAA interpolation
tests pass now.
Reviewed-by: Eric Anholt <[email protected]>
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_wm.c')
-rw-r--r-- | src/mesa/drivers/dri/i965/brw_wm.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index 4a7225c7228..ae6c6bfe684 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -130,7 +130,8 @@ 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. */ static unsigned -brw_compute_barycentric_interp_modes(bool shade_model_flat, +brw_compute_barycentric_interp_modes(struct brw_context *brw, + bool shade_model_flat, const struct gl_fragment_program *fprog) { unsigned barycentric_interp_modes = 0; @@ -154,11 +155,18 @@ brw_compute_barycentric_interp_modes(bool shade_model_flat, if (attr == FRAG_ATTRIB_WPOS || attr == FRAG_ATTRIB_FACE) continue; + /* Determine the set (or sets) of barycentric coordinates needed to + * interpolate this variable. Note that when + * brw->needs_unlit_centroid_workaround is set, centroid interpolation + * uses PIXEL interpolation for unlit pixels and CENTROID interpolation + * for lit pixels, so we need both sets of barycentric coordinates. + */ if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) { if (is_centroid) { barycentric_interp_modes |= 1 << BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC; - } else { + } + if (!is_centroid || brw->needs_unlit_centroid_workaround) { barycentric_interp_modes |= 1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; } @@ -168,7 +176,8 @@ brw_compute_barycentric_interp_modes(bool shade_model_flat, if (is_centroid) { barycentric_interp_modes |= 1 << BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC; - } else { + } + if (!is_centroid || brw->needs_unlit_centroid_workaround) { barycentric_interp_modes |= 1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; } @@ -289,7 +298,8 @@ bool do_wm_prog(struct brw_context *brw, brw_init_compile(brw, &c->func, c); c->prog_data.barycentric_interp_modes = - brw_compute_barycentric_interp_modes(c->key.flat_shade, &fp->program); + brw_compute_barycentric_interp_modes(brw, c->key.flat_shade, + &fp->program); if (prog && prog->_LinkedShaders[MESA_SHADER_FRAGMENT]) { if (!brw_wm_fs_emit(brw, c, prog)) |