From: Paul Berry Date: Sat, 22 Oct 2011 00:20:32 +0000 (-0700) Subject: i965/gen6+: Parameterize barycentric interpolation modes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=e04bdeae82797dbdcf6f544a997a4626fdfd4aee;p=mesa.git i965/gen6+: Parameterize barycentric interpolation modes. This patch modifies the fragment shader back-end so that instead of using a single delta_x/delta_y register pair to store barycentric coordinates, it uses an array of such register pairs, one for each possible intepolation mode. When setting up the WM, we intstruct it to only provide the barycentric coordinates that are actually needed by the fragment shader--that is computed by brw_compute_barycentric_interp_modes(). Currently this function returns just BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC, because this is the only interpolation mode we support. However, that will change in a later patch. 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 ff25b093b47..4ae8580ac57 100644 --- a/src/mesa/drivers/dri/i965/brw_context.h +++ b/src/mesa/drivers/dri/i965/brw_context.h @@ -976,6 +976,11 @@ void brw_compute_vue_map(struct brw_vue_map *vue_map, GLbitfield64 outputs_written); gl_clip_plane *brw_select_clip_planes(struct gl_context *ctx); +/* brw_wm.c */ +unsigned +brw_compute_barycentric_interp_modes(void); + + /*====================================================================== * Inline conversion functions. These are better-typed than the diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 61a739c3a98..d302a61cdbc 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -1215,6 +1215,16 @@ enum brw_message_target { /* DW12: attr 0-7 wrap shortest enables */ /* DW13: attr 8-16 wrap shortest enables */ +enum brw_wm_barycentric_interp_mode { + BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC = 0, + BRW_WM_PERSPECTIVE_CENTROID_BARYCENTRIC = 1, + BRW_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC = 2, + BRW_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC = 3, + BRW_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC = 4, + BRW_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC = 5, + BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT = 6 +}; + #define _3DSTATE_WM 0x7814 /* GEN6+ */ /* DW1: kernel pointer */ /* DW2 */ @@ -1269,6 +1279,7 @@ enum brw_message_target { # define GEN6_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 12) # define GEN6_WM_PERSPECTIVE_CENTROID_BARYCENTRIC (1 << 11) # define GEN6_WM_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 10) +# define GEN6_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT 10 # define GEN6_WM_POINT_RASTRULE_UPPER_RIGHT (1 << 9) # define GEN6_WM_MSRAST_OFF_PIXEL (0 << 1) # define GEN6_WM_MSRAST_OFF_PATTERN (1 << 1) @@ -1306,12 +1317,7 @@ enum brw_message_target { # define GEN7_WM_POSITION_ZW_PIXEL (0 << 17) # define GEN7_WM_POSITION_ZW_CENTROID (2 << 17) # define GEN7_WM_POSITION_ZW_SAMPLE (3 << 17) -# define GEN7_WM_NONPERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 16) -# define GEN7_WM_NONPERSPECTIVE_CENTROID_BARYCENTRIC (1 << 15) -# define GEN7_WM_NONPERSPECTIVE_PIXEL_BARYCENTRIC (1 << 14) -# define GEN7_WM_PERSPECTIVE_SAMPLE_BARYCENTRIC (1 << 13) -# define GEN7_WM_PERSPECTIVE_CENTROID_BARYCENTRIC (1 << 12) -# define GEN7_WM_PERSPECTIVE_PIXEL_BARYCENTRIC (1 << 11) +# define GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT 11 # define GEN7_WM_USES_INPUT_COVERAGE_MASK (1 << 10) # define GEN7_WM_LINE_END_CAP_AA_WIDTH_0_5 (0 << 8) # define GEN7_WM_LINE_END_CAP_AA_WIDTH_1_0 (1 << 8) diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp index 3848915cf80..b3ad505b71e 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs.cpp @@ -407,8 +407,10 @@ fs_visitor::emit_fragcoord_interpolation(ir_variable *ir) emit(BRW_OPCODE_MOV, wpos, fs_reg(brw_vec8_grf(c->source_depth_reg, 0))); } else { - emit(FS_OPCODE_LINTERP, wpos, this->delta_x, this->delta_y, - interp_reg(FRAG_ATTRIB_WPOS, 2)); + emit(FS_OPCODE_LINTERP, wpos, + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], + this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], + interp_reg(FRAG_ATTRIB_WPOS, 2)); } wpos.reg_offset++; @@ -481,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); - emit(FS_OPCODE_LINTERP, attr, - this->delta_x, this->delta_y, fs_reg(interp)); + brw_wm_barycentric_interp_mode barycoord_mode = + BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; + emit(FS_OPCODE_LINTERP, attr, + this->delta_x[barycoord_mode], + this->delta_y[barycoord_mode], fs_reg(interp)); } attr.reg_offset++; } @@ -768,9 +773,15 @@ fs_visitor::split_virtual_grfs() split_grf[i] = false; } - if (brw->has_pln && this->delta_x.file == GRF) { - /* PLN opcodes rely on the delta_xy being contiguous. */ - split_grf[this->delta_x.reg] = false; + if (brw->has_pln && + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].file == GRF) { + /* PLN opcodes rely on the delta_xy being contiguous. We only have to + * check this for BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC, because prior to + * Gen6, that was the only supported interpolation mode, and since Gen6, + * delta_x and delta_y are in fixed hardware registers. + */ + split_grf[this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].reg] = + false; } foreach_list(node, &this->instructions) { diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index f5af9ea936a..e2ad6499e95 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -594,8 +594,8 @@ public: fs_reg pixel_y; fs_reg wpos_w; fs_reg pixel_w; - fs_reg delta_x; - fs_reg delta_y; + fs_reg delta_x[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT]; + fs_reg delta_y[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT]; fs_reg reg_null_cmp; int grf_used; diff --git a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp index 6e38cc250e8..3f875cc63d9 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_reg_allocate.cpp @@ -202,8 +202,17 @@ fs_visitor::assign_regs() for (int i = 0; i < this->virtual_grf_next; i++) { for (int c = 0; c < class_count; c++) { if (class_sizes[c] == this->virtual_grf_sizes[i]) { + /* Special case: on pre-GEN6 hardware that supports PLN, the + * second operand of a PLN instruction needs to be an + * even-numbered register, so we have a special register class + * wm_aligned_pairs_class to handle this case. pre-GEN6 always + * uses this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] as the + * second operand of a PLN instruction (since it doesn't support + * any other interpolation modes). So all we need to do is find + * that register and set it to the appropriate class. + */ if (brw->wm.aligned_pairs_class >= 0 && - this->delta_x.reg == i) { + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].reg == i) { ra_set_node_class(g, i, brw->wm.aligned_pairs_class); } else { ra_set_node_class(g, i, brw->wm.classes[c]); diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 215cdcdb022..2f95014d2a2 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -1754,16 +1754,20 @@ fs_visitor::emit_interpolation_setup_gen4() this->current_annotation = "compute pixel deltas from v0"; if (brw->has_pln) { - this->delta_x = fs_reg(this, glsl_type::vec2_type); - this->delta_y = this->delta_x; - this->delta_y.reg_offset++; + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = + fs_reg(this, glsl_type::vec2_type); + this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC]; + this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC].reg_offset++; } else { - this->delta_x = fs_reg(this, glsl_type::float_type); - this->delta_y = fs_reg(this, glsl_type::float_type); + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = + fs_reg(this, glsl_type::float_type); + this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC] = + fs_reg(this, glsl_type::float_type); } - emit(BRW_OPCODE_ADD, this->delta_x, + emit(BRW_OPCODE_ADD, this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], this->pixel_x, fs_reg(negate(brw_vec1_grf(1, 0)))); - emit(BRW_OPCODE_ADD, this->delta_y, + emit(BRW_OPCODE_ADD, this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], this->pixel_y, fs_reg(negate(brw_vec1_grf(1, 1)))); this->current_annotation = "compute pos.w and 1/pos.w"; @@ -1771,7 +1775,9 @@ fs_visitor::emit_interpolation_setup_gen4() * interpolate the other attributes. */ this->wpos_w = fs_reg(this, glsl_type::float_type); - emit(FS_OPCODE_LINTERP, wpos_w, this->delta_x, this->delta_y, + emit(FS_OPCODE_LINTERP, wpos_w, + this->delta_x[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], + this->delta_y[BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC], interp_reg(FRAG_ATTRIB_WPOS, 3)); /* Compute the pixel 1/W value from wpos.w. */ this->pixel_w = fs_reg(this, glsl_type::float_type); @@ -1814,8 +1820,11 @@ fs_visitor::emit_interpolation_setup_gen6() this->wpos_w = fs_reg(this, glsl_type::float_type); emit_math(SHADER_OPCODE_RCP, this->wpos_w, this->pixel_w); - this->delta_x = fs_reg(brw_vec8_grf(2, 0)); - this->delta_y = fs_reg(brw_vec8_grf(3, 0)); + for (int i = 0; i < BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT; ++i) { + uint8_t reg = c->barycentric_coord_reg[i]; + this->delta_x[i] = fs_reg(brw_vec8_grf(reg, 0)); + this->delta_y[i] = fs_reg(brw_vec8_grf(reg + 1, 0)); + } this->current_annotation = NULL; } diff --git a/src/mesa/drivers/dri/i965/brw_wm.c b/src/mesa/drivers/dri/i965/brw_wm.c index b60173ed4bf..81dad4f76da 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.c +++ b/src/mesa/drivers/dri/i965/brw_wm.c @@ -123,6 +123,19 @@ brw_wm_non_glsl_emit(struct brw_context *brw, struct brw_wm_compile *c) brw_wm_emit(c); } + +/** + * Return a bitfield where bit n is set if barycentric interpolation mode n + * (see enum brw_wm_barycentric_interp_mode) is needed by the fragment shader. + */ +unsigned +brw_compute_barycentric_interp_modes(void) +{ + /* At the moment the only interpolation mode we support is perspective. */ + return (1 << BRW_WM_PERSPECTIVE_PIXEL_BARYCENTRIC); +} + + void brw_wm_payload_setup(struct brw_context *brw, struct brw_wm_compile *c) @@ -130,22 +143,31 @@ brw_wm_payload_setup(struct brw_context *brw, struct intel_context *intel = &brw->intel; bool uses_depth = (c->fp->program.Base.InputsRead & (1 << FRAG_ATTRIB_WPOS)) != 0; + unsigned barycentric_interp_modes = + brw_compute_barycentric_interp_modes(); + int i; if (intel->gen >= 6) { /* R0-1: masks, pixel X/Y coordinates. */ c->nr_payload_regs = 2; /* R2: only for 32-pixel dispatch.*/ - /* R3-4: perspective pixel location barycentric */ - c->nr_payload_regs += 2; - /* R5-6: perspective pixel location bary for dispatch width != 8 */ - if (c->dispatch_width == 16) { - c->nr_payload_regs += 2; + + /* R3-26: barycentric interpolation coordinates. These appear in the + * same order that they appear in the brw_wm_barycentric_interp_mode + * enum. Each set of coordinates occupies 2 registers if dispatch width + * == 8 and 4 registers if dispatch width == 16. Coordinates only + * appear if they were enabled using the "Barycentric Interpolation + * Mode" bits in WM_STATE. + */ + for (i = 0; i < BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT; ++i) { + if (barycentric_interp_modes & (1 << i)) { + c->barycentric_coord_reg[i] = c->nr_payload_regs; + c->nr_payload_regs += 2; + if (c->dispatch_width == 16) { + c->nr_payload_regs += 2; + } + } } - /* R7-10: perspective centroid barycentric */ - /* R11-14: perspective sample barycentric */ - /* R15-18: linear pixel location barycentric */ - /* R19-22: linear centroid barycentric */ - /* R23-26: linear sample barycentric */ /* R27: interpolated depth if uses source depth */ if (uses_depth) { diff --git a/src/mesa/drivers/dri/i965/brw_wm.h b/src/mesa/drivers/dri/i965/brw_wm.h index efd18e96bec..76cf4533b56 100644 --- a/src/mesa/drivers/dri/i965/brw_wm.h +++ b/src/mesa/drivers/dri/i965/brw_wm.h @@ -215,6 +215,7 @@ struct brw_wm_compile { uint8_t source_w_reg; uint8_t aa_dest_stencil_reg; uint8_t dest_depth_reg; + uint8_t barycentric_coord_reg[BRW_WM_BARYCENTRIC_INTERP_MODE_COUNT]; uint8_t nr_payload_regs; GLuint computes_depth:1; /* could be derived from program string */ GLuint source_depth_to_render_target:1; diff --git a/src/mesa/drivers/dri/i965/gen6_wm_state.c b/src/mesa/drivers/dri/i965/gen6_wm_state.c index 24fc81dd240..178375f4133 100644 --- a/src/mesa/drivers/dri/i965/gen6_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen6_wm_state.c @@ -178,7 +178,8 @@ upload_wm_state(struct brw_context *brw) dw5 |= GEN6_WM_DISPATCH_ENABLE; } - dw6 |= GEN6_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; + 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; diff --git a/src/mesa/drivers/dri/i965/gen7_wm_state.c b/src/mesa/drivers/dri/i965/gen7_wm_state.c index aae3c1164fb..fc23c2e1615 100644 --- a/src/mesa/drivers/dri/i965/gen7_wm_state.c +++ b/src/mesa/drivers/dri/i965/gen7_wm_state.c @@ -72,7 +72,8 @@ upload_wm_state(struct brw_context *brw) dw1 |= GEN7_WM_DISPATCH_ENABLE; } - dw1 |= GEN7_WM_PERSPECTIVE_PIXEL_BARYCENTRIC; + dw1 |= brw_compute_barycentric_interp_modes() << + GEN7_WM_BARYCENTRIC_INTERPOLATION_MODE_SHIFT; BEGIN_BATCH(3); OUT_BATCH(_3DSTATE_WM << 16 | (3 - 2));