i965/fs: Support fine/coarse derivative opcodes
authorChris Forbes <chrisf@ijw.co.nz>
Thu, 14 Aug 2014 08:59:15 +0000 (20:59 +1200)
committerChris Forbes <chrisf@ijw.co.nz>
Fri, 15 Aug 2014 06:04:04 +0000 (18:04 +1200)
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>
src/mesa/drivers/dri/i965/brw_defines.h
src/mesa/drivers/dri/i965/brw_fs.h
src/mesa/drivers/dri/i965/brw_fs_channel_expressions.cpp
src/mesa/drivers/dri/i965/brw_fs_generator.cpp
src/mesa/drivers/dri/i965/brw_fs_visitor.cpp

index 3564041e645c722e3cbd3ce11f507996deea5eb0..1322ed241b6c8a95d9cd2d88827996fe3efd414f 100644 (file)
@@ -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,
 
index 5cad50437aa039c87743d353d2e7cbf5251a7411..a838e74d8b63367631fdab5740a2456632522b39 100644 (file)
@@ -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);
index 4113f475f60d19a4b0aa71cc5a831bef4ec08edf..d98b7ebc64522e72ac7ccfc87289f3ce24df06b7 100644 (file)
@@ -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:
index 1190f1f7e666c2c698c4338e43014f14ff6e927b..6efd41cdea28f34c709ef67f6259daf0cd626495 100644 (file)
@@ -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:
index 2d5f18d448c18abecf91108239bbf4c66284aa0c..f72909e3f57057524bc33d5a480bf689c5bd83c2 100644 (file)
@@ -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: