VEC4_OPCODE_PACK_BYTES,
- FS_OPCODE_DDX,
- FS_OPCODE_DDY,
+ FS_OPCODE_DDX_COARSE,
+ FS_OPCODE_DDX_FINE,
+ FS_OPCODE_DDY_COARSE,
+ FS_OPCODE_DDY_FINE,
FS_OPCODE_PIXEL_X,
FS_OPCODE_PIXEL_Y,
FS_OPCODE_CINTERP,
GS_OPCODE_FF_SYNC_SET_PRIMITIVES,
};
-enum brw_derivative_quality {
- BRW_DERIVATIVE_BY_HINT = 0,
- BRW_DERIVATIVE_FINE = 1,
- BRW_DERIVATIVE_COARSE = 2,
-};
-
enum brw_urb_write_flags {
BRW_URB_WRITE_NO_FLAGS = 0,
void generate_math_g45(fs_inst *inst,
struct brw_reg dst,
struct brw_reg src);
- void generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src, struct brw_reg quality);
- void generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
- struct brw_reg quality, bool negate_value);
+ void generate_ddx(enum opcode op, struct brw_reg dst, struct brw_reg src);
+ void generate_ddy(enum opcode op, struct brw_reg dst, struct brw_reg src,
+ bool negate_value);
void generate_scratch_write(fs_inst *inst, struct brw_reg src);
void generate_scratch_read(fs_inst *inst, struct brw_reg dst);
void generate_scratch_read_gen7(fs_inst *inst, struct brw_reg dst);
* appropriate swizzling.
*/
void
-fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
- struct brw_reg quality)
+fs_generator::generate_ddx(enum opcode opcode,
+ struct brw_reg dst, struct brw_reg src)
{
unsigned vstride, width;
- assert(quality.file == BRW_IMMEDIATE_VALUE);
- assert(quality.type == BRW_REGISTER_TYPE_D);
- assert(stage == MESA_SHADER_FRAGMENT);
- const brw_wm_prog_key * const key = (brw_wm_prog_key * const) this->key;
-
- int quality_value = quality.dw1.d;
-
- if (quality_value == BRW_DERIVATIVE_FINE ||
- (key->high_quality_derivatives && quality_value != BRW_DERIVATIVE_COARSE)) {
+ if (opcode == FS_OPCODE_DDX_FINE) {
/* produce accurate derivatives */
vstride = BRW_VERTICAL_STRIDE_2;
width = BRW_WIDTH_2;
- }
- else {
+ } else {
/* replicate the derivative at the top-left pixel to other pixels */
vstride = BRW_VERTICAL_STRIDE_4;
width = BRW_WIDTH_4;
* left.
*/
void
-fs_generator::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src,
- struct brw_reg quality, bool negate_value)
+fs_generator::generate_ddy(enum opcode opcode,
+ struct brw_reg dst, struct brw_reg src,
+ bool negate_value)
{
- assert(quality.file == BRW_IMMEDIATE_VALUE);
- assert(quality.type == BRW_REGISTER_TYPE_D);
-
- assert(stage == MESA_SHADER_FRAGMENT);
- const brw_wm_prog_key * const key = (brw_wm_prog_key * const) this->key;
-
- int quality_value = quality.dw1.d;
-
- if (quality_value == BRW_DERIVATIVE_FINE ||
- (key->high_quality_derivatives && quality_value != BRW_DERIVATIVE_COARSE)) {
+ if (opcode == FS_OPCODE_DDY_FINE) {
/* From the Ivy Bridge PRM, volume 4 part 3, section 3.3.9 (Register
* Region Restrictions):
*
case SHADER_OPCODE_TG4_OFFSET:
generate_tex(inst, dst, src[0], src[1]);
break;
- case FS_OPCODE_DDX:
- generate_ddx(inst, dst, src[0], src[1]);
- break;
- case FS_OPCODE_DDY:
+ case FS_OPCODE_DDX_COARSE:
+ case FS_OPCODE_DDX_FINE:
+ generate_ddx(inst->opcode, dst, src[0]);
+ break;
+ case FS_OPCODE_DDY_COARSE:
+ case FS_OPCODE_DDY_FINE:
/* Make sure fp->UsesDFdy flag got set (otherwise there's no
* guarantee that key->render_to_fbo is set).
*/
assert(stage == MESA_SHADER_FRAGMENT &&
((gl_fragment_program *) prog)->UsesDFdy);
- generate_ddy(inst, dst, src[0], src[1],
+ generate_ddy(inst->opcode, dst, src[0],
((brw_wm_prog_key * const) this->key)->render_to_fbo);
break;
unsigned int operand;
fs_reg op[3], temp;
fs_inst *inst;
+ struct brw_wm_prog_key *fs_key = (struct brw_wm_prog_key *) this->key;
assert(ir->get_num_operands() <= 3);
break;
case ir_unop_dFdx:
- emit(FS_OPCODE_DDX, this->result, op[0], fs_reg(BRW_DERIVATIVE_BY_HINT));
+ /* Select one of the two opcodes based on the glHint value. */
+ if (fs_key->high_quality_derivatives)
+ emit(FS_OPCODE_DDX_FINE, this->result, op[0]);
+ else
+ emit(FS_OPCODE_DDX_COARSE, this->result, op[0]);
break;
+
case ir_unop_dFdx_coarse:
- emit(FS_OPCODE_DDX, this->result, op[0], fs_reg(BRW_DERIVATIVE_COARSE));
+ emit(FS_OPCODE_DDX_COARSE, this->result, op[0]);
break;
+
case ir_unop_dFdx_fine:
- emit(FS_OPCODE_DDX, this->result, op[0], fs_reg(BRW_DERIVATIVE_FINE));
+ emit(FS_OPCODE_DDX_FINE, this->result, op[0]);
break;
+
case ir_unop_dFdy:
- emit(FS_OPCODE_DDY, this->result, op[0], fs_reg(BRW_DERIVATIVE_BY_HINT));
+ /* Select one of the two opcodes based on the glHint value. */
+ if (fs_key->high_quality_derivatives)
+ emit(FS_OPCODE_DDY_FINE, this->result, op[0]);
+ else
+ emit(FS_OPCODE_DDY_COARSE, this->result, op[0]);
break;
+
case ir_unop_dFdy_coarse:
- emit(FS_OPCODE_DDY, this->result, op[0], fs_reg(BRW_DERIVATIVE_COARSE));
+ emit(FS_OPCODE_DDY_COARSE, this->result, op[0]);
break;
+
case ir_unop_dFdy_fine:
- emit(FS_OPCODE_DDY, this->result, op[0], fs_reg(BRW_DERIVATIVE_FINE));
+ emit(FS_OPCODE_DDY_FINE, this->result, op[0]);
break;
case ir_binop_add:
case VEC4_OPCODE_PACK_BYTES:
return "pack_bytes";
- case FS_OPCODE_DDX:
- return "ddx";
- case FS_OPCODE_DDY:
- return "ddy";
+ case FS_OPCODE_DDX_COARSE:
+ return "ddx_coarse";
+ case FS_OPCODE_DDX_FINE:
+ return "ddx_fine";
+ case FS_OPCODE_DDY_COARSE:
+ return "ddy_coarse";
+ case FS_OPCODE_DDY_FINE:
+ return "ddy_fine";
case FS_OPCODE_PIXEL_X:
return "pixel_x";
return writes_accumulator ||
(brw->gen < 6 &&
((opcode >= BRW_OPCODE_ADD && opcode < BRW_OPCODE_NOP) ||
- (opcode >= FS_OPCODE_DDX && opcode <= FS_OPCODE_LINTERP &&
+ (opcode >= FS_OPCODE_DDX_COARSE && opcode <= FS_OPCODE_LINTERP &&
opcode != FS_OPCODE_CINTERP)));
}