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
/* 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 */
# 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)
# 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)
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++;
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++;
}
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) {
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;
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]);
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";
* 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);
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;
}
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)
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) {
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;
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;
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));