[Mesa-dev] [WIP 19/25] i965/fs: Collect results for double precision conditionals

Topi Pohjolainen topi.pohjolainen at intel.com
Thu Oct 16 05:24:31 PDT 2014


Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_fs.cpp | 43 ++++++++++++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_fs.h   |  3 +++
 2 files changed, 46 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index 71729be..37e7cbd 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -320,6 +320,40 @@ fs_visitor::IF(const fs_reg &src0, const fs_reg &src1,
    return inst;
 }
 
+fs_inst *
+fs_visitor::emit_double_precision_cmp(fs_reg dst, fs_reg src0, fs_reg src1,
+                                      enum brw_conditional_mod condition)
+{
+
+   fs_reg res_df(this, glsl_type::double_type);
+   fs_inst *inst = emit(BRW_OPCODE_CMP, res_df, src0, src1);
+   inst->conditional_mod = condition;
+
+   if (dst.file == GRF) {
+      dst.type = BRW_REGISTER_TYPE_F;
+      return emit(FS_OPCODE_D2F_MOV_LOW_32BITS, dst, res_df);
+   }
+
+   assert(dst.fixed_hw_reg.nr == BRW_ARF_NULL);
+
+   /* Convert the double precision results into single precision, and
+    * issue another comparison writing the flag register appropiately.
+    *
+    * TODO: Skip the conversion by using twice the stride in res_f. This
+    *       requires the optimization passes to be taught about the need
+    *       for the second hw register.
+    *       Or convert the results directly into the flag register avoiding
+    *       the need for the additional comparison. This requires changes in
+    *       the optimization passes as well.
+    */
+   fs_reg res_f(this, glsl_type::float_type);
+   emit(FS_OPCODE_D2F_MOV_LOW_32BITS, res_f, res_df);
+   inst = new(mem_ctx) fs_inst(BRW_OPCODE_CMP, dst, res_f, fs_reg(0.0f));
+   inst->conditional_mod = BRW_CONDITIONAL_NZ;
+
+   return inst;
+}
+
 /**
  * CMP: Sets the low bit of the destination channels with the result
  * of the comparison, while the upper bits are undefined, and updates
@@ -331,6 +365,15 @@ fs_visitor::CMP(fs_reg dst, fs_reg src0, fs_reg src1,
 {
    fs_inst *inst;
 
+   if (src0.type == BRW_REGISTER_TYPE_DF) {
+      assert(src1.type == BRW_REGISTER_TYPE_DF);
+      if (dst.file != GRF || dst.type != BRW_REGISTER_TYPE_DF)
+         return emit_double_precision_cmp(dst, src0, src1, condition);
+   } else {
+      assert(src1.type != BRW_REGISTER_TYPE_DF);
+      assert(dst.type != BRW_REGISTER_TYPE_DF);
+   }
+
    /* Take the instruction:
     *
     * CMP null<d> src0<f> src1<f>
diff --git a/src/mesa/drivers/dri/i965/brw_fs.h b/src/mesa/drivers/dri/i965/brw_fs.h
index 9637b90..0f47464 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.h
+++ b/src/mesa/drivers/dri/i965/brw_fs.h
@@ -550,6 +550,9 @@ public:
 
    void emit_pack32(ir_expression *ir);
 
+   fs_inst *emit_double_precision_cmp(fs_reg dst, fs_reg src0, fs_reg src1,
+                                      enum brw_conditional_mod condition);
+
    bool try_rewrite_rhs_to_dst(ir_assignment *ir,
 			       fs_reg dst,
 			       fs_reg src,
-- 
1.8.3.1



More information about the mesa-dev mailing list