From: Paul Berry Date: Sat, 22 Oct 2011 16:33:16 +0000 (-0700) Subject: i965/gen6+: Add support for noperspective interpolation. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5aa96286e7e1a5380673eb75e8653616b48751fd;p=mesa.git i965/gen6+: Add support for noperspective interpolation. 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 gl_fragment_program::InterpQualifier 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-* Reviewed-by: Eric Anholt --- diff --git a/src/mesa/drivers/dri/i965/brw_context.h b/src/mesa/drivers/dri/i965/brw_context.h index 4ae8580ac57..1d6e58b0cfc 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -978,7 +978,12 @@ 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); + +/* gen6_clip_state.c */ +bool +brw_fprog_uses_noperspective(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 185e00d5a28..31c311661f0 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 == INTERP_QUALIFIER_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 81dad4f76da..63c770debcc 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -129,10 +129,41 @@ 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; + int attr; + + /* Loop through all fragment shader inputs to figure out what interpolation + * modes are in use, and set the appropriate bits in + * barycentric_interp_modes. + */ + for (attr = 0; attr < FRAG_ATTRIB_MAX; ++attr) { + enum glsl_interp_qualifier interp_qualifier = + fprog->InterpQualifier[attr]; + bool is_gl_Color = attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1; + + /* Ignore unused inputs. */ + if (!(fprog->Base.InputsRead & BITFIELD64_BIT(attr))) + continue; + + /* Ignore WPOS and FACE, because they don't require interpolation. */ + if (attr == FRAG_ATTRIB_WPOS || attr == FRAG_ATTRIB_FACE) + continue; + + if (interp_qualifier == INTERP_QUALIFIER_NOPERSPECTIVE) { + barycentric_interp_modes |= + 1 << BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC; + } else if (interp_qualifier == INTERP_QUALIFIER_SMOOTH || + (!(shade_model_flat && is_gl_Color) && + interp_qualifier == INTERP_QUALIFIER_NONE)) { + barycentric_interp_modes |= + 1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; + } + } + + return barycentric_interp_modes; } @@ -144,7 +175,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 9b36af47dde..b3bb8aee3ec 100644 --- a/src/mesa/drivers/dri/i965/gen6_clip_state.c +++ b/src/mesa/drivers/dri/i965/gen6_clip_state.c @@ -31,6 +31,26 @@ #include "brw_util.h" #include "intel_batchbuffer.h" +/** + * Return true if at least one of the inputs used by the given fragment + * program has the GLSL "noperspective" interpolation qualifier. + */ +bool +brw_fprog_uses_noperspective(const struct gl_fragment_program *fprog) +{ + int attr; + for (attr = 0; attr < FRAG_ATTRIB_MAX; ++attr) { + /* Ignore unused inputs. */ + if (!(fprog->Base.InputsRead & BITFIELD64_BIT(attr))) + continue; + + if (fprog->InterpQualifier[attr] == INTERP_QUALIFIER_NOPERSPECTIVE) + return true; + } + return false; +} + + static void upload_clip_state(struct brw_context *brw) { @@ -38,6 +58,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 (brw_fprog_uses_noperspective(fprog)) { + nonperspective_barycentric_enable_flag = + GEN6_CLIP_NON_PERSPECTIVE_BARYCENTRIC_ENABLE; + } if (!ctx->Transform.DepthClamp) depth_clamp = GEN6_CLIP_Z_TEST; @@ -64,6 +92,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 +106,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 67b649e7b79..67119d8d182 100644 --- a/src/mesa/drivers/dri/i965/gen6_sf_state.c +++ b/src/mesa/drivers/dri/i965/gen6_sf_state.c @@ -118,6 +118,8 @@ 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 */ + bool shade_model_flat = ctx->Light.ShadeModel == GL_FLAT; uint32_t dw1, dw2, dw3, dw4, dw16, dw17; int i; /* _NEW_BUFFER */ @@ -263,6 +265,10 @@ upload_sf_state(struct brw_context *brw) * they source from. */ for (; attr < FRAG_ATTRIB_MAX; attr++) { + enum glsl_interp_qualifier interp_qualifier = + brw->fragment_program->InterpQualifier[attr]; + bool is_gl_Color = attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1; + if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) continue; @@ -277,17 +283,10 @@ 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 (interp_qualifier == INTERP_QUALIFIER_FLAT || + (shade_model_flat && is_gl_Color && + interp_qualifier == INTERP_QUALIFIER_NONE)) + 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 178375f4133..ac1b1a3cc5e 100644 --- a/src/mesa/drivers/dri/i965/gen6_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c @@ -99,6 +99,9 @@ upload_wm_state(struct brw_context *brw) brw_fragment_program_const(brw->fragment_program); uint32_t dw2, dw4, dw5, dw6; + /* _NEW_LIGHT */ + bool flat_shade = (ctx->Light.ShadeModel == GL_FLAT); + /* CACHE_NEW_WM_PROG */ if (brw->wm.prog_data->nr_params == 0) { /* Disable the push constant buffers. */ @@ -168,6 +171,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; + dw6 |= brw_compute_barycentric_interp_modes(flat_shade, &fp->program) << + GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; /* _NEW_COLOR */ if (fp->program.UsesKill || ctx->Color.AlphaEnabled) @@ -178,9 +183,6 @@ upload_wm_state(struct brw_context *brw) dw5 |= GEN6_WM_DISPATCH_ENABLE; } - dw6 |= brw_compute_barycentric_interp_modes() << - GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; - dw6 |= _mesa_bitcount_64(brw->fragment_program->Base.InputsRead) << GEN6_WM_NUM_SF_OUTPUTS_SHIFT; @@ -206,6 +208,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 da8d73a698e..c32cd988297 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 (brw_fprog_uses_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 e796a01b74d..d3ffbd39b4b 100644 --- a/src/mesa/drivers/dri/i965/gen7_sf_state.c +++ b/src/mesa/drivers/dri/i965/gen7_sf_state.c @@ -39,6 +39,8 @@ 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 */ + bool shade_model_flat = ctx->Light.ShadeModel == GL_FLAT; uint32_t dw1, dw10, dw11; int i; int attr = 0, input_index = 0; @@ -74,6 +76,10 @@ upload_sbe_state(struct brw_context *brw) * they source from. */ for (; attr < FRAG_ATTRIB_MAX; attr++) { + enum glsl_interp_qualifier interp_qualifier = + brw->fragment_program->InterpQualifier[attr]; + bool is_gl_Color = attr == FRAG_ATTRIB_COL0 || attr == FRAG_ATTRIB_COL1; + if (!(brw->fragment_program->Base.InputsRead & BITFIELD64_BIT(attr))) continue; @@ -87,17 +93,10 @@ 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 (interp_qualifier == INTERP_QUALIFIER_FLAT || + (shade_model_flat && is_gl_Color && + interp_qualifier == INTERP_QUALIFIER_NONE)) + 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 fc23c2e1615..ba83340bde9 100644 --- a/src/mesa/drivers/dri/i965/gen7_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen7_wm_state.c @@ -41,6 +41,9 @@ upload_wm_state(struct brw_context *brw) bool writes_depth = false; uint32_t dw1; + /* _NEW_LIGHT */ + bool flat_shade = (ctx->Light.ShadeModel == GL_FLAT); + dw1 = 0; dw1 |= GEN7_WM_STATISTICS_ENABLE; dw1 |= GEN7_WM_LINE_AA_WIDTH_1_0; @@ -61,6 +64,8 @@ upload_wm_state(struct brw_context *brw) writes_depth = true; dw1 |= GEN7_WM_PSCDEPTH_ON; } + dw1 |= brw_compute_barycentric_interp_modes(flat_shade, &fp->program) << + GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; /* _NEW_COLOR */ if (fp->program.UsesKill || ctx->Color.AlphaEnabled) @@ -72,9 +77,6 @@ upload_wm_state(struct brw_context *brw) dw1 |= GEN7_WM_DISPATCH_ENABLE; } - dw1 |= brw_compute_barycentric_interp_modes() << - GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; - BEGIN_BATCH(3); OUT_BATCH(_3DSTATE_WM << 16 | (3 - 2)); OUT_BATCH(dw1); @@ -84,7 +86,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 |