diff options
author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-04-09 23:41:41 +0200 |
---|---|---|
committer | ReinUsesLisp <reinuseslisp@airmail.cc> | 2019-04-16 02:16:10 +0200 |
commit | 64613db6052dfe0c056ce3d6ead21ae9a32f03ae (patch) | |
tree | 9fa4a632c8fc050b6176ebbca727c27757f95662 /src/video_core/shader | |
parent | shader_ir/decode: Reduce severity of unimplemented half-float FTZ (diff) | |
download | yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.tar yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.tar.gz yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.tar.bz2 yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.tar.lz yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.tar.xz yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.tar.zst yuzu-64613db6052dfe0c056ce3d6ead21ae9a32f03ae.zip |
Diffstat (limited to 'src/video_core/shader')
-rw-r--r-- | src/video_core/shader/decode/arithmetic_half_immediate.cpp | 6 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.cpp | 9 | ||||
-rw-r--r-- | src/video_core/shader/shader_ir.h | 3 |
3 files changed, 14 insertions, 4 deletions
diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp index 4a5b0620e..cf4bc0432 100644 --- a/src/video_core/shader/decode/arithmetic_half_immediate.cpp +++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp @@ -23,8 +23,6 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) { } else { UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None); } - UNIMPLEMENTED_IF_MSG(instr.alu_half_imm.saturate != 0, - "Half float immediate saturation not implemented"); Node op_a = GetRegister(instr.gpr8); op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a); @@ -43,10 +41,10 @@ u32 ShaderIR::DecodeArithmeticHalfImmediate(NodeBlock& bb, u32 pc) { return Immediate(0); } }(); - value = HalfMerge(GetRegister(instr.gpr0), value, instr.alu_half_imm.merge); + value = GetSaturatedHalfFloat(value, instr.alu_half_imm.saturate); + value = HalfMerge(GetRegister(instr.gpr0), value, instr.alu_half_imm.merge); SetRegister(bb, instr.gpr0, value); - return pc; } diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp index 5c1c591f8..d158b4bfd 100644 --- a/src/video_core/shader/shader_ir.cpp +++ b/src/video_core/shader/shader_ir.cpp @@ -218,6 +218,15 @@ Node ShaderIR::GetOperandAbsNegHalf(Node value, bool absolute, bool negate) { return value; } +Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) { + if (!saturate) { + return value; + } + const Node positive_zero = Immediate(std::copysignf(0, 1)); + const Node positive_one = Immediate(1.0f); + return Operation(OperationCode::HClamp, HALF_NO_PRECISE, value, positive_zero, positive_one); +} + Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = { {PredCondition::LessThan, OperationCode::LogicalFLessThan}, diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h index 0ae51389b..d329da58d 100644 --- a/src/video_core/shader/shader_ir.h +++ b/src/video_core/shader/shader_ir.h @@ -114,6 +114,7 @@ enum class OperationCode { HFma, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 HAbsolute, /// (f16vec2 a) -> f16vec2 HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 + HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 HMergeF32, /// (f16vec2 src) -> float HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 @@ -716,6 +717,8 @@ private: Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge); /// Conditionally absolute/negated half float pair. Absolute is applied first Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate); + /// Conditionally saturates a half float pair + Node GetSaturatedHalfFloat(Node value, bool saturate = true); /// Returns a predicate comparing two floats Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b); |