[Mesa-dev] [PATCH 05/16] i965: Fix bitcast operations with negate

Eduardo Lima Mitev elima at igalia.com
Thu Dec 11 14:34:11 PST 2014


From: Iago Toral Quiroga <itoral at igalia.com>

For code such as this in a vertex or fragment shader:

uniform float in0;
flat out float out0;
...
out0 = ceil(in0)

We generate this IR:

(assign  (x) (var_ref packed:out0)
   (expression int bitcast_f2i
       (expression float ceil (var_ref in0) ) ) )

In i965, this would eventually become:

rndd(8)         g14<1>.xF       -g3<0,4,1>.xF
mov(8)          g6<1>.xD        -g14<4,4,1>.xD
mov(8)          g116<1>D        g6<4,4,1>D

which does not produce the expected result.

The problem has to do with the second instruction, that changes the
type to D at the same time it does the negate. For this to work we
need to negate first with the original type, then change the type
to the bitcast destination so we produce code like this instead:

rndd(8)         g14<1>.xF       -g3<0,4,1>.xF
mov(8)          g6<1>.xF        -g14<4,4,1>.xF
mov(8)          g116<1>D        g6<4,4,1>D

Fixes the following 42 dEQP tests:
dEQP-GLES3.functional.shaders.builtin_functions.common.ceil.*_vertex
dEQP-GLES3.functional.shaders.builtin_functions.common.ceil.*_fragment
dEQP-GLES3.functional.shaders.builtin_functions.precision.ceil._*vertex.*
dEQP-GLES3.functional.shaders.builtin_functions.precision.ceil._*fragment.*
---
 src/mesa/drivers/dri/i965/brw_fs_visitor.cpp   | 41 +++++++++++++++++++++++---
 src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp | 40 +++++++++++++++++++++----
 2 files changed, 71 insertions(+), 10 deletions(-)

diff --git a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
index 399e772..ecd6398 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_visitor.cpp
@@ -909,20 +909,53 @@ fs_visitor::visit(ir_expression *ir)
       break;
 
    case ir_unop_bitcast_i2f:
+      if (!op[0].negate) {
+         op[0].type = BRW_REGISTER_TYPE_F;
+         this->result = op[0];
+      } else {
+         this->result.type = BRW_REGISTER_TYPE_D;
+         emit(MOV(this->result, op[0]));
+         this->result.type = BRW_REGISTER_TYPE_F;
+      }
+      break;
    case ir_unop_bitcast_u2f:
-      op[0].type = BRW_REGISTER_TYPE_F;
-      this->result = op[0];
+      if (!op[0].negate) {
+         op[0].type = BRW_REGISTER_TYPE_F;
+         this->result = op[0];
+      } else {
+         this->result.type = BRW_REGISTER_TYPE_UD;
+         emit(MOV(this->result, op[0]));
+         this->result.type = BRW_REGISTER_TYPE_F;
+      }
       break;
    case ir_unop_i2u:
-   case ir_unop_bitcast_f2u:
       op[0].type = BRW_REGISTER_TYPE_UD;
       this->result = op[0];
       break;
+   case ir_unop_bitcast_f2u:
+      if (!op[0].negate) {
+         op[0].type = BRW_REGISTER_TYPE_UD;
+         this->result = op[0];
+      } else {
+         this->result.type = BRW_REGISTER_TYPE_F;
+         emit(MOV(this->result, op[0]));
+         this->result.type = BRW_REGISTER_TYPE_UD;
+      }
+      break;
    case ir_unop_u2i:
-   case ir_unop_bitcast_f2i:
       op[0].type = BRW_REGISTER_TYPE_D;
       this->result = op[0];
       break;
+   case ir_unop_bitcast_f2i:
+      if (!op[0].negate) {
+         op[0].type = BRW_REGISTER_TYPE_D;
+         this->result = op[0];
+      } else {
+         this->result.type = BRW_REGISTER_TYPE_F;
+         emit(MOV(this->result, op[0]));
+         this->result.type = BRW_REGISTER_TYPE_D;
+      }
+      break;
    case ir_unop_i2f:
    case ir_unop_u2f:
    case ir_unop_f2i:
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
index 7238788..a5e46a2 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_visitor.cpp
@@ -1604,19 +1604,47 @@ vec4_visitor::visit(ir_expression *ir)
       break;
 
    case ir_unop_bitcast_i2f:
+      if (!op[0].negate) {
+         this->result = op[0];
+         this->result.type = BRW_REGISTER_TYPE_F;
+      } else {
+         result_dst.type = BRW_REGISTER_TYPE_D;
+         emit(MOV(result_dst, op[0]));
+         result_dst.type = BRW_REGISTER_TYPE_F;
+      }
+      break;
+
    case ir_unop_bitcast_u2f:
-      this->result = op[0];
-      this->result.type = BRW_REGISTER_TYPE_F;
+      if (!op[0].negate) {
+         this->result = op[0];
+         this->result.type = BRW_REGISTER_TYPE_F;
+      } else {
+         result_dst.type = BRW_REGISTER_TYPE_UD;
+         emit(MOV(result_dst, op[0]));
+         result_dst.type = BRW_REGISTER_TYPE_F;
+      }
       break;
 
    case ir_unop_bitcast_f2i:
-      this->result = op[0];
-      this->result.type = BRW_REGISTER_TYPE_D;
+      if (!op[0].negate) {
+         this->result = op[0];
+         this->result.type = BRW_REGISTER_TYPE_D;
+      } else {
+         result_dst.type = BRW_REGISTER_TYPE_F;
+         emit(MOV(result_dst, op[0]));
+         result_dst.type = BRW_REGISTER_TYPE_D;
+      }
       break;
 
    case ir_unop_bitcast_f2u:
-      this->result = op[0];
-      this->result.type = BRW_REGISTER_TYPE_UD;
+      if (!op[0].negate) {
+         this->result = op[0];
+         this->result.type = BRW_REGISTER_TYPE_UD;
+      } else {
+         result_dst.type = BRW_REGISTER_TYPE_F;
+         emit(MOV(result_dst, op[0]));
+         result_dst.type = BRW_REGISTER_TYPE_UD;
+      }
       break;
 
    case ir_unop_i2f:
-- 
2.1.3



More information about the mesa-dev mailing list