diff --git a/src/mesa/drivers/dri/i965/brw_compiler.c b/src/mesa/drivers/dri/i965/brw_compiler.c index 3da6aac2cbf..6509267a52e 100644 --- a/src/mesa/drivers/dri/i965/brw_compiler.c +++ b/src/mesa/drivers/dri/i965/brw_compiler.c @@ -147,6 +147,8 @@ brw_compiler_create(void *mem_ctx, const struct brw_device_info *devinfo) brw_fs_alloc_reg_sets(compiler); brw_vec4_alloc_reg_set(compiler); + compiler->precise_trig = env_var_as_boolean("INTEL_PRECISE_TRIG", false); + compiler->scalar_stage[MESA_SHADER_VERTEX] = devinfo->gen >= 8 && !(INTEL_DEBUG & DEBUG_VEC4VS); compiler->scalar_stage[MESA_SHADER_TESS_CTRL] = false; diff --git a/src/mesa/drivers/dri/i965/brw_compiler.h b/src/mesa/drivers/dri/i965/brw_compiler.h index 27a95a3c661..231e0001d54 100644 --- a/src/mesa/drivers/dri/i965/brw_compiler.h +++ b/src/mesa/drivers/dri/i965/brw_compiler.h @@ -92,6 +92,12 @@ struct brw_compiler { bool scalar_stage[MESA_SHADER_STAGES]; struct gl_shader_compiler_options glsl_compiler_options[MESA_SHADER_STAGES]; + + /** + * Apply workarounds for SIN and COS output range problems. + * This can negatively impact performance. + */ + bool precise_trig; }; diff --git a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp index 7839428c52e..5cca91ec5b4 100644 --- a/src/mesa/drivers/dri/i965/brw_fs_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_fs_nir.cpp @@ -775,12 +775,24 @@ fs_visitor::nir_emit_alu(const fs_builder &bld, nir_alu_instr *instr) break; case nir_op_fsin: - inst = bld.emit(SHADER_OPCODE_SIN, result, op[0]); + if (!compiler->precise_trig) { + inst = bld.emit(SHADER_OPCODE_SIN, result, op[0]); + } else { + fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F); + inst = bld.emit(SHADER_OPCODE_SIN, tmp, op[0]); + inst = bld.MUL(result, tmp, brw_imm_f(0.99997)); + } inst->saturate = instr->dest.saturate; break; case nir_op_fcos: - inst = bld.emit(SHADER_OPCODE_COS, result, op[0]); + if (!compiler->precise_trig) { + inst = bld.emit(SHADER_OPCODE_COS, result, op[0]); + } else { + fs_reg tmp = bld.vgrf(BRW_REGISTER_TYPE_F); + inst = bld.emit(SHADER_OPCODE_COS, tmp, op[0]); + inst = bld.MUL(result, tmp, brw_imm_f(0.99997)); + } inst->saturate = instr->dest.saturate; break; diff --git a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp index ee6929b16a2..6c8fd06fb5e 100644 --- a/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp +++ b/src/mesa/drivers/dri/i965/brw_vec4_nir.cpp @@ -1101,12 +1101,24 @@ vec4_visitor::nir_emit_alu(nir_alu_instr *instr) break; case nir_op_fsin: - inst = emit_math(SHADER_OPCODE_SIN, dst, op[0]); + if (!compiler->precise_trig) { + inst = emit_math(SHADER_OPCODE_SIN, dst, op[0]); + } else { + src_reg tmp = src_reg(this, glsl_type::vec4_type); + inst = emit_math(SHADER_OPCODE_SIN, dst_reg(tmp), op[0]); + inst = emit(MUL(dst, tmp, brw_imm_f(0.99997))); + } inst->saturate = instr->dest.saturate; break; case nir_op_fcos: - inst = emit_math(SHADER_OPCODE_COS, dst, op[0]); + if (!compiler->precise_trig) { + inst = emit_math(SHADER_OPCODE_COS, dst, op[0]); + } else { + src_reg tmp = src_reg(this, glsl_type::vec4_type); + inst = emit_math(SHADER_OPCODE_COS, dst_reg(tmp), op[0]); + inst = emit(MUL(dst, tmp, brw_imm_f(0.99997))); + } inst->saturate = instr->dest.saturate; break;