summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp6
-rw-r--r--src/video_core/shader/decode/arithmetic_half_immediate.cpp6
-rw-r--r--src/video_core/shader/shader_ir.cpp9
-rw-r--r--src/video_core/shader/shader_ir.h3
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
221Node 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
221Node ShaderIR::GetPredicateComparisonFloat(PredCondition condition, Node op_a, Node op_b) { 230Node 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);