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 <eric@anholt.net>
This commit is contained in:
parent
102bdd26e1
commit
e04bdeae82
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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]);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
|
|
Loading…
Reference in New Issue