From: Kenneth Graunke <kenneth@whitecape.org>
Date: Wed, 27 Jan 2016 20:21:04 +0000 (-0800)
Subject: i965: Fix SIN/COS precision problems.
X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=4acfc9effbe4513075881a045bdfbec8ad2433a4;p=mesa.git

i965: Fix SIN/COS precision problems.

Signed-off-by: Kenneth Graunke <kenneth@whitecape.org>
---

diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
index f41854c2c09..11e7c7dc102 100644
--- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp
@@ -715,15 +715,29 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr)
       inst->saturate = instr->dest.saturate;
       break;
 
-   case nir_op_fsin:
-      inst = bld.emit(SHADER_OPCODE_SIN, result, op[0]);
-      inst->saturate = instr->dest.saturate;
+   case nir_op_fsin: {
+      fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F);
+      inst = bld.emit(SHADER_OPCODE_SIN, tmp, op[0]);
+      if (instr->dest.saturate) {
+         inst->dst = result;
+         inst->saturate = true;
+      } else {
+         bld.MUL(result, tmp, brw_imm_f(0.99997));
+      }
       break;
+   }
 
-   case nir_op_fcos:
-      inst = bld.emit(SHADER_OPCODE_COS, result, op[0]);
-      inst->saturate = instr->dest.saturate;
+   case nir_op_fcos: {
+      fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F);
+      inst = bld.emit(SHADER_OPCODE_COS, tmp, op[0]);
+      if (instr->dest.saturate) {
+         inst->dst = result;
+         inst->saturate = true;
+      } else {
+         bld.MUL(result, tmp, brw_imm_f(0.99997));
+      }
       break;
+   }
 
    case nir_op_fddx:
       if (fs_key->high_quality_derivatives) {
diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
index a608dca03ff..2b261fcc952 100644
--- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
+++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp
@@ -1086,15 +1086,29 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr)
       inst->saturate = instr->dest.saturate;
       break;
 
-   case nir_op_fsin:
-      inst = emit_math(SHADER_OPCODE_SIN, dst, op[0]);
-      inst->saturate = instr->dest.saturate;
+   case nir_op_fsin: {
+      src_reg tmp = src_reg(this, glsl_type::vec4_type);
+      inst = emit_math(SHADER_OPCODE_SIN, dst_reg(tmp), op[0]);
+      if (instr->dest.saturate) {
+         inst->dst = dst;
+         inst->saturate = true;
+      } else {
+         emit(MUL(dst, tmp, brw_imm_f(0.99997)));
+      }
       break;
+   }
 
-   case nir_op_fcos:
-      inst = emit_math(SHADER_OPCODE_COS, dst, op[0]);
-      inst->saturate = instr->dest.saturate;
+   case nir_op_fcos: {
+      src_reg tmp = src_reg(this, glsl_type::vec4_type);
+      inst = emit_math(SHADER_OPCODE_COS, dst_reg(tmp), op[0]);
+      if (instr->dest.saturate) {
+         inst->dst = dst;
+         inst->saturate = true;
+      } else {
+         emit(MUL(dst, tmp, brw_imm_f(0.99997)));
+      }
       break;
+   }
 
    case nir_op_idiv:
    case nir_op_udiv: