diff options
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 15 | ||||
| -rw-r--r-- | src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | 6 | ||||
| -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 |
5 files changed, 31 insertions, 8 deletions
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index cbaa4dceb..9c972fd3a 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -617,13 +617,11 @@ private: | |||
| 617 | } | 617 | } |
| 618 | 618 | ||
| 619 | std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) { | 619 | std::string VisitOperand(Operation operation, std::size_t operand_index, Type type) { |
| 620 | std::string value = VisitOperand(operation, operand_index); | 620 | const std::string value = VisitOperand(operation, operand_index); |
| 621 | switch (type) { | 621 | switch (type) { |
| 622 | case Type::HalfFloat: { | 622 | case Type::HalfFloat: { |
| 623 | const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta()); | 623 | const auto half_meta = std::get_if<MetaHalfArithmetic>(&operation.GetMeta()); |
| 624 | if (!half_meta) { | 624 | ASSERT(half_meta); |
| 625 | value = "toHalf2(" + value + ')'; | ||
| 626 | } | ||
| 627 | 625 | ||
| 628 | switch (half_meta->types.at(operand_index)) { | 626 | switch (half_meta->types.at(operand_index)) { |
| 629 | case Tegra::Shader::HalfType::H0_H1: | 627 | case Tegra::Shader::HalfType::H0_H1: |
| @@ -1067,6 +1065,14 @@ private: | |||
| 1067 | return BitwiseCastResult(value, Type::HalfFloat); | 1065 | return BitwiseCastResult(value, Type::HalfFloat); |
| 1068 | } | 1066 | } |
| 1069 | 1067 | ||
| 1068 | std::string HClamp(Operation operation) { | ||
| 1069 | const std::string value = VisitOperand(operation, 0, Type::HalfFloat); | ||
| 1070 | const std::string min = VisitOperand(operation, 1, Type::Float); | ||
| 1071 | const std::string max = VisitOperand(operation, 2, Type::Float); | ||
| 1072 | const std::string clamped = "clamp(" + value + ", vec2(" + min + "), vec2(" + max + "))"; | ||
| 1073 | return ApplyPrecise(operation, BitwiseCastResult(clamped, Type::HalfFloat)); | ||
| 1074 | } | ||
| 1075 | |||
| 1070 | std::string HMergeF32(Operation operation) { | 1076 | std::string HMergeF32(Operation operation) { |
| 1071 | return "float(toHalf2(" + Visit(operation[0]) + ")[0])"; | 1077 | return "float(toHalf2(" + Visit(operation[0]) + ")[0])"; |
| 1072 | } | 1078 | } |
| @@ -1501,6 +1507,7 @@ private: | |||
| 1501 | &GLSLDecompiler::Fma<Type::HalfFloat>, | 1507 | &GLSLDecompiler::Fma<Type::HalfFloat>, |
| 1502 | &GLSLDecompiler::Absolute<Type::HalfFloat>, | 1508 | &GLSLDecompiler::Absolute<Type::HalfFloat>, |
| 1503 | &GLSLDecompiler::HNegate, | 1509 | &GLSLDecompiler::HNegate, |
| 1510 | &GLSLDecompiler::HClamp, | ||
| 1504 | &GLSLDecompiler::HMergeF32, | 1511 | &GLSLDecompiler::HMergeF32, |
| 1505 | &GLSLDecompiler::HMergeH0, | 1512 | &GLSLDecompiler::HMergeH0, |
| 1506 | &GLSLDecompiler::HMergeH1, | 1513 | &GLSLDecompiler::HMergeH1, |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index e0a6f5e87..6ecb0bcb0 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -744,6 +744,11 @@ private: | |||
| 744 | return {}; | 744 | return {}; |
| 745 | } | 745 | } |
| 746 | 746 | ||
| 747 | Id HClamp(Operation operation) { | ||
| 748 | UNIMPLEMENTED(); | ||
| 749 | return {}; | ||
| 750 | } | ||
| 751 | |||
| 747 | Id HMergeF32(Operation operation) { | 752 | Id HMergeF32(Operation operation) { |
| 748 | UNIMPLEMENTED(); | 753 | UNIMPLEMENTED(); |
| 749 | return {}; | 754 | return {}; |
| @@ -1216,6 +1221,7 @@ private: | |||
| 1216 | &SPIRVDecompiler::Ternary<&Module::OpFma, Type::HalfFloat>, | 1221 | &SPIRVDecompiler::Ternary<&Module::OpFma, Type::HalfFloat>, |
| 1217 | &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>, | 1222 | &SPIRVDecompiler::Unary<&Module::OpFAbs, Type::HalfFloat>, |
| 1218 | &SPIRVDecompiler::HNegate, | 1223 | &SPIRVDecompiler::HNegate, |
| 1224 | &SPIRVDecompiler::HClamp, | ||
| 1219 | &SPIRVDecompiler::HMergeF32, | 1225 | &SPIRVDecompiler::HMergeF32, |
| 1220 | &SPIRVDecompiler::HMergeH0, | 1226 | &SPIRVDecompiler::HMergeH0, |
| 1221 | &SPIRVDecompiler::HMergeH1, | 1227 | &SPIRVDecompiler::HMergeH1, |
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) { | |||
| 23 | } else { | 23 | } else { |
| 24 | UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None); | 24 | UNIMPLEMENTED_IF(instr.alu_half_imm.precision != Tegra::Shader::HalfPrecision::None); |
| 25 | } | 25 | } |
| 26 | UNIMPLEMENTED_IF_MSG(instr.alu_half_imm.saturate != 0, | ||
| 27 | "Half float immediate saturation not implemented"); | ||
| 28 | 26 | ||
| 29 | Node op_a = GetRegister(instr.gpr8); | 27 | Node op_a = GetRegister(instr.gpr8); |
| 30 | op_a = GetOperandAbsNegHalf(op_a, instr.alu_half_imm.abs_a, instr.alu_half_imm.negate_a); | 28 | 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) { | |||
| 43 | return Immediate(0); | 41 | return Immediate(0); |
| 44 | } | 42 | } |
| 45 | }(); | 43 | }(); |
| 46 | value = HalfMerge(GetRegister(instr.gpr0), value, instr.alu_half_imm.merge); | ||
| 47 | 44 | ||
| 45 | value = GetSaturatedHalfFloat(value, instr.alu_half_imm.saturate); | ||
| 46 | value = HalfMerge(GetRegister(instr.gpr0), value, instr.alu_half_imm.merge); | ||
| 48 | SetRegister(bb, instr.gpr0, value); | 47 | SetRegister(bb, instr.gpr0, value); |
| 49 | |||
| 50 | return pc; | 48 | return pc; |
| 51 | } | 49 | } |
| 52 | 50 | ||
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) { | |||
| 218 | return value; | 218 | return value; |
| 219 | } | 219 | } |
| 220 | 220 | ||
| 221 | Node ShaderIR::GetSaturatedHalfFloat(Node value, bool saturate) { | ||
| 222 | if (!saturate) { | ||
| 223 | return value; | ||
| 224 | } | ||
| 225 | const Node positive_zero = Immediate(std::copysignf(0, 1)); | ||
| 226 | const Node positive_one = Immediate(1.0f); | ||
| 227 | return Operation(OperationCode::HClamp, HALF_NO_PRECISE, value, positive_zero, positive_one); | ||
| 228 | } | ||
| 229 | |||
| 221 | Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { | 230 | Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { |
| 222 | const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = { | 231 | const std::unordered_map<PredCondition, OperationCode> PredicateComparisonTable = { |
| 223 | {PredCondition::LessThan, OperationCode::LogicalFLessThan}, | 232 | {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 { | |||
| 114 | HFma, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 | 114 | HFma, /// (MetaHalfArithmetic, f16vec2 a, f16vec2 b, f16vec2 c) -> f16vec2 |
| 115 | HAbsolute, /// (f16vec2 a) -> f16vec2 | 115 | HAbsolute, /// (f16vec2 a) -> f16vec2 |
| 116 | HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 | 116 | HNegate, /// (f16vec2 a, bool first, bool second) -> f16vec2 |
| 117 | HClamp, /// (f16vec2 src, float min, float max) -> f16vec2 | ||
| 117 | HMergeF32, /// (f16vec2 src) -> float | 118 | HMergeF32, /// (f16vec2 src) -> float |
| 118 | HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | 119 | HMergeH0, /// (f16vec2 dest, f16vec2 src) -> f16vec2 |
| 119 | HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 | 120 | HMergeH1, /// (f16vec2 dest, f16vec2 src) -> f16vec2 |
| @@ -716,6 +717,8 @@ private: | |||
| 716 | Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge); | 717 | Node HalfMerge(Node dest, Node src, Tegra::Shader::HalfMerge merge); |
| 717 | /// Conditionally absolute/negated half float pair. Absolute is applied first | 718 | /// Conditionally absolute/negated half float pair. Absolute is applied first |
| 718 | Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate); | 719 | Node GetOperandAbsNegHalf(Node value, bool absolute, bool negate); |
| 720 | /// Conditionally saturates a half float pair | ||
| 721 | Node GetSaturatedHalfFloat(Node value, bool saturate = true); | ||
| 719 | 722 | ||
| 720 | /// Returns a predicate comparing two floats | 723 | /// Returns a predicate comparing two floats |
| 721 | Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b); | 724 | Node GetPredicateComparisonFloat(Tegra::Shader::PredCondition condition, Node op_a, Node op_b); |