From a39622452069b76f7562472cc15ddefd2db4b503 Mon Sep 17 00:00:00 2001 From: Chris Forbes Date: Thu, 14 Aug 2014 20:59:15 +1200 Subject: [PATCH] i965/fs: Support fine/coarse derivative opcodes The quality level (fine/coarse/dont-care) is plumbed through to the generator as a constant in src1. Signed-off-by: Chris Forbes Reviewed-by: Matt Turner --- src/mesa/drivers/dri/i965/brw_defines.h | 6 +++++ src/mesa/drivers/dri/i965/brw_fs.h | 4 ++-- .../dri/i965/brw_fs_channel_expressions.cpp | 4 ++++ .../drivers/dri/i965/brw_fs_generator.cpp | 24 ++++++++++++++----- src/mesa/drivers/dri/i965/brw_fs_visitor.cpp | 16 +++++++++++-- 5 files changed, 44 insertions(+), 10 deletions(-) diff --git a/src/mesa/drivers/dri/i965/brw_defines.h b/src/mesa/drivers/dri/i965/brw_defines.h index 3564041e645..1322ed241b6 100644 --- a/src/mesa/drivers/dri/i965/brw_defines.h +++ b/src/mesa/drivers/dri/i965/brw_defines.h @@ -1004,6 +1004,12 @@ enum opcode { GS_OPCODE_GET_INSTANCE_ID, }; +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, diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h index 5cad50437aa..a838e74d8b6 100644 --- a/src/mesa/drivers/dri/i965/brw_fs.h +++ b/src/mesa/drivers/dri/i965/brw_fs.h @@ -604,9 +604,9 @@ private: 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); + 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, - bool negate_value); + struct brw_reg quality, 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); diff --git a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp index 4113f475f60..d98b7ebc645 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp @@ -237,7 +237,11 @@ ir_channel_expressions_visitor::visit_leave(ir_assignment *ir) case ir_unop_sin_reduced: case ir_unop_cos_reduced: case ir_unop_dFdx: + case ir_unop_dFdx_coarse: + case ir_unop_dFdx_fine: case ir_unop_dFdy: + case ir_unop_dFdy_coarse: + case ir_unop_dFdy_fine: case ir_unop_bitfield_reverse: case ir_unop_bit_count: case ir_unop_find_msb: diff --git a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp index 1190f1f7e66..6efd41cdea2 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_generator.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_generator.cpp @@ -644,11 +644,17 @@ fs_generator::generate_tex(fs_inst *inst, struct brw_reg dst, struct brw_reg src * appropriate swizzling. */ void -fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src) +fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src, + struct brw_reg quality) { unsigned vstride, width; + assert(quality.file == BRW_IMMEDIATE_VALUE); + assert(quality.type == BRW_REGISTER_TYPE_D); - if (key->high_quality_derivatives) { + int quality_value = quality.dw1.d; + + if (quality_value == BRW_DERIVATIVE_FINE || + (key->high_quality_derivatives && quality_value != BRW_DERIVATIVE_COARSE)) { /* produce accurate derivatives */ vstride = BRW_VERTICAL_STRIDE_2; width = BRW_WIDTH_2; @@ -680,9 +686,15 @@ fs_generator::generate_ddx(fs_inst *inst, struct brw_reg dst, struct brw_reg src */ void fs_generator::generate_ddy(fs_inst *inst, struct brw_reg dst, struct brw_reg src, - bool negate_value) + struct brw_reg quality, bool negate_value) { - if (key->high_quality_derivatives) { + assert(quality.file == BRW_IMMEDIATE_VALUE); + assert(quality.type == BRW_REGISTER_TYPE_D); + + int quality_value = quality.dw1.d; + + if (quality_value == BRW_DERIVATIVE_FINE || + (key->high_quality_derivatives && quality_value != BRW_DERIVATIVE_COARSE)) { /* From the Ivy Bridge PRM, volume 4 part 3, section 3.3.9 (Register * Region Restrictions): * @@ -1655,14 +1667,14 @@ fs_generator::generate_code(exec_list *instructions) generate_tex(inst, dst, src[0], src[1]); break; case FS_OPCODE_DDX: - generate_ddx(inst, dst, src[0]); + generate_ddx(inst, dst, src[0], src[1]); break; case FS_OPCODE_DDY: /* Make sure fp->UsesDFdy flag got set (otherwise there's no * guarantee that key->render_to_fbo is set). */ assert(fp->UsesDFdy); - generate_ddy(inst, dst, src[0], key->render_to_fbo); + generate_ddy(inst, dst, src[0], src[1], key->render_to_fbo); break; case SHADER_OPCODE_GEN4_SCRATCH_WRITE: diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp index 2d5f18d448c..f72909e3f57 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp @@ -593,10 +593,22 @@ fs_visitor::visit(ir_expression *ir) break; case ir_unop_dFdx: - emit(FS_OPCODE_DDX, this->result, op[0]); + emit(FS_OPCODE_DDX, this->result, op[0], fs_reg(BRW_DERIVATIVE_BY_HINT)); + break; + case ir_unop_dFdx_coarse: + emit(FS_OPCODE_DDX, this->result, op[0], fs_reg(BRW_DERIVATIVE_COARSE)); + break; + case ir_unop_dFdx_fine: + emit(FS_OPCODE_DDX, this->result, op[0], fs_reg(BRW_DERIVATIVE_FINE)); break; case ir_unop_dFdy: - emit(FS_OPCODE_DDY, this->result, op[0]); + emit(FS_OPCODE_DDY, this->result, op[0], fs_reg(BRW_DERIVATIVE_BY_HINT)); + break; + case ir_unop_dFdy_coarse: + emit(FS_OPCODE_DDY, this->result, op[0], fs_reg(BRW_DERIVATIVE_COARSE)); + break; + case ir_unop_dFdy_fine: + emit(FS_OPCODE_DDY, this->result, op[0], fs_reg(BRW_DERIVATIVE_FINE)); break; case ir_binop_add: -- 2.30.2