summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChris Forbes <chrisf@ijw.co.nz>2014-08-14 20:59:15 +1200
committerChris Forbes <chrisf@ijw.co.nz>2014-08-15 18:04:04 +1200
commita39622452069b76f7562472cc15ddefd2db4b503 (patch)
tree0d681685daa40add9fd0eecd4d4e9a64585b4f80
parent587e6e78984cd7490ac68b83d0b751bf23256595 (diff)
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 <chrisf@ijw.co.nz> Reviewed-by: Matt Turner <mattst88@gmail.com>
-rw-r--r--src/mesa/drivers/dri/i965/brw_defines.h6
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs.h4
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp4
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_generator.cpp24
-rw-r--r--src/mesa/drivers/dri/i965/brw_fs_visitor.cpp16
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: