diff options
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 51 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 153 |
2 files changed, 190 insertions, 14 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index a57b90632..8d4ea3401 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -156,6 +156,13 @@ enum class PredOperation : u64 { | |||
| 156 | Xor = 2, | 156 | Xor = 2, |
| 157 | }; | 157 | }; |
| 158 | 158 | ||
| 159 | enum class LogicOperation : u64 { | ||
| 160 | And = 0, | ||
| 161 | Or = 1, | ||
| 162 | Xor = 2, | ||
| 163 | PassB = 3, | ||
| 164 | }; | ||
| 165 | |||
| 159 | enum class SubOp : u64 { | 166 | enum class SubOp : u64 { |
| 160 | Cos = 0x0, | 167 | Cos = 0x0, |
| 161 | Sin = 0x1, | 168 | Sin = 0x1, |
| @@ -202,6 +209,12 @@ union Instruction { | |||
| 202 | BitField<42, 1, u64> negate_pred; | 209 | BitField<42, 1, u64> negate_pred; |
| 203 | } fmnmx; | 210 | } fmnmx; |
| 204 | 211 | ||
| 212 | union { | ||
| 213 | BitField<53, 2, LogicOperation> operation; | ||
| 214 | BitField<55, 1, u64> invert_a; | ||
| 215 | BitField<56, 1, u64> invert_b; | ||
| 216 | } lop; | ||
| 217 | |||
| 205 | float GetImm20_19() const { | 218 | float GetImm20_19() const { |
| 206 | float result{}; | 219 | float result{}; |
| 207 | u32 imm{static_cast<u32>(imm20_19)}; | 220 | u32 imm{static_cast<u32>(imm20_19)}; |
| @@ -220,6 +233,22 @@ union Instruction { | |||
| 220 | } alu; | 233 | } alu; |
| 221 | 234 | ||
| 222 | union { | 235 | union { |
| 236 | BitField<39, 5, u64> shift_amount; | ||
| 237 | BitField<20, 19, u64> immediate_low; | ||
| 238 | BitField<56, 1, u64> immediate_high; | ||
| 239 | BitField<48, 1, u64> negate_b; | ||
| 240 | BitField<49, 1, u64> negate_a; | ||
| 241 | |||
| 242 | s32 GetImmediate() const { | ||
| 243 | u32 immediate = static_cast<u32>(immediate_low | (immediate_high << 19)); | ||
| 244 | // Sign extend the 20-bit value. | ||
| 245 | u32 mask = 1U << (20 - 1); | ||
| 246 | return static_cast<s32>((immediate ^ mask) - mask); | ||
| 247 | } | ||
| 248 | |||
| 249 | } iscadd; | ||
| 250 | |||
| 251 | union { | ||
| 223 | BitField<48, 1, u64> negate_b; | 252 | BitField<48, 1, u64> negate_b; |
| 224 | BitField<49, 1, u64> negate_c; | 253 | BitField<49, 1, u64> negate_c; |
| 225 | } ffma; | 254 | } ffma; |
| @@ -239,15 +268,25 @@ union Instruction { | |||
| 239 | } fsetp; | 268 | } fsetp; |
| 240 | 269 | ||
| 241 | union { | 270 | union { |
| 271 | BitField<0, 3, u64> pred0; | ||
| 272 | BitField<3, 3, u64> pred3; | ||
| 273 | BitField<39, 3, u64> pred39; | ||
| 274 | BitField<42, 1, u64> neg_pred; | ||
| 275 | BitField<45, 2, PredOperation> op; | ||
| 276 | BitField<48, 1, u64> is_signed; | ||
| 277 | BitField<49, 3, PredCondition> cond; | ||
| 278 | } isetp; | ||
| 279 | |||
| 280 | union { | ||
| 242 | BitField<39, 3, u64> pred39; | 281 | BitField<39, 3, u64> pred39; |
| 243 | BitField<42, 1, u64> neg_pred; | 282 | BitField<42, 1, u64> neg_pred; |
| 244 | BitField<43, 1, u64> neg_a; | 283 | BitField<43, 1, u64> neg_a; |
| 245 | BitField<44, 1, u64> abs_b; | 284 | BitField<44, 1, u64> abs_b; |
| 246 | BitField<45, 2, PredOperation> op; | 285 | BitField<45, 2, PredOperation> op; |
| 247 | BitField<48, 4, PredCondition> cond; | 286 | BitField<48, 4, PredCondition> cond; |
| 287 | BitField<52, 1, u64> bf; | ||
| 248 | BitField<53, 1, u64> neg_b; | 288 | BitField<53, 1, u64> neg_b; |
| 249 | BitField<54, 1, u64> abs_a; | 289 | BitField<54, 1, u64> abs_a; |
| 250 | BitField<52, 1, u64> bf; | ||
| 251 | BitField<55, 1, u64> ftz; | 290 | BitField<55, 1, u64> ftz; |
| 252 | BitField<56, 1, u64> neg_imm; | 291 | BitField<56, 1, u64> neg_imm; |
| 253 | } fset; | 292 | } fset; |
| @@ -339,6 +378,9 @@ public: | |||
| 339 | FMUL_R, | 378 | FMUL_R, |
| 340 | FMUL_IMM, | 379 | FMUL_IMM, |
| 341 | FMUL32_IMM, | 380 | FMUL32_IMM, |
| 381 | ISCADD_C, // Scale and Add | ||
| 382 | ISCADD_R, | ||
| 383 | ISCADD_IMM, | ||
| 342 | MUFU, // Multi-Function Operator | 384 | MUFU, // Multi-Function Operator |
| 343 | RRO_C, // Range Reduction Operator | 385 | RRO_C, // Range Reduction Operator |
| 344 | RRO_R, | 386 | RRO_R, |
| @@ -381,6 +423,8 @@ public: | |||
| 381 | enum class Type { | 423 | enum class Type { |
| 382 | Trivial, | 424 | Trivial, |
| 383 | Arithmetic, | 425 | Arithmetic, |
| 426 | Logic, | ||
| 427 | ScaledAdd, | ||
| 384 | Ffma, | 428 | Ffma, |
| 385 | Flow, | 429 | Flow, |
| 386 | Memory, | 430 | Memory, |
| @@ -504,6 +548,9 @@ private: | |||
| 504 | INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"), | 548 | INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"), |
| 505 | INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), | 549 | INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), |
| 506 | INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), | 550 | INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), |
| 551 | INST("0100110000011---", Id::ISCADD_C, Type::ScaledAdd, "ISCADD_C"), | ||
| 552 | INST("0101110000011---", Id::ISCADD_R, Type::ScaledAdd, "ISCADD_R"), | ||
| 553 | INST("0011100-00011---", Id::ISCADD_IMM, Type::ScaledAdd, "ISCADD_IMM"), | ||
| 507 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | 554 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), |
| 508 | INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), | 555 | INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), |
| 509 | INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), | 556 | INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), |
| @@ -514,7 +561,6 @@ private: | |||
| 514 | INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), | 561 | INST("0100110010110---", Id::F2I_C, Type::Arithmetic, "F2I_C"), |
| 515 | INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), | 562 | INST("0101110010110---", Id::F2I_R, Type::Arithmetic, "F2I_R"), |
| 516 | INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), | 563 | INST("0011100-10110---", Id::F2I_IMM, Type::Arithmetic, "F2I_IMM"), |
| 517 | INST("000001----------", Id::LOP32I, Type::Arithmetic, "LOP32I"), | ||
| 518 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), | 564 | INST("0100110010011---", Id::MOV_C, Type::Arithmetic, "MOV_C"), |
| 519 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), | 565 | INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), |
| 520 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), | 566 | INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), |
| @@ -525,6 +571,7 @@ private: | |||
| 525 | INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), | 571 | INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), |
| 526 | INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), | 572 | INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), |
| 527 | INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), | 573 | INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), |
| 574 | INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), | ||
| 528 | INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), | 575 | INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), |
| 529 | INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), | 576 | INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), |
| 530 | INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), | 577 | INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 6391f1ad4..eb8d37c9b 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -228,6 +228,11 @@ public: | |||
| 228 | return active_type == Type::Integer; | 228 | return active_type == Type::Integer; |
| 229 | } | 229 | } |
| 230 | 230 | ||
| 231 | /// Returns the current active type of the register | ||
| 232 | Type GetActiveType() const { | ||
| 233 | return active_type; | ||
| 234 | } | ||
| 235 | |||
| 231 | /// Returns the index of the register | 236 | /// Returns the index of the register |
| 232 | size_t GetIndex() const { | 237 | size_t GetIndex() const { |
| 233 | return index; | 238 | return index; |
| @@ -359,22 +364,28 @@ public: | |||
| 359 | shader.AddLine(dest + " = " + src + ';'); | 364 | shader.AddLine(dest + " = " + src + ';'); |
| 360 | } | 365 | } |
| 361 | 366 | ||
| 362 | /// Generates code representing a uniform (C buffer) register. | 367 | /// Generates code representing a uniform (C buffer) register, interpreted as the input type. |
| 363 | std::string GetUniform(const Uniform& uniform, const Register& dest_reg) { | 368 | std::string GetUniform(const Uniform& uniform, GLSLRegister::Type type) { |
| 364 | declr_const_buffers[uniform.index].MarkAsUsed(static_cast<unsigned>(uniform.index), | 369 | declr_const_buffers[uniform.index].MarkAsUsed(static_cast<unsigned>(uniform.index), |
| 365 | static_cast<unsigned>(uniform.offset), stage); | 370 | static_cast<unsigned>(uniform.offset), stage); |
| 366 | std::string value = | 371 | std::string value = |
| 367 | 'c' + std::to_string(uniform.index) + '[' + std::to_string(uniform.offset) + ']'; | 372 | 'c' + std::to_string(uniform.index) + '[' + std::to_string(uniform.offset) + ']'; |
| 368 | 373 | ||
| 369 | if (regs[dest_reg].IsFloat()) { | 374 | if (type == GLSLRegister::Type::Float) { |
| 370 | return value; | 375 | return value; |
| 371 | } else if (regs[dest_reg].IsInteger()) { | 376 | } else if (type == GLSLRegister::Type::Integer) { |
| 372 | return "floatBitsToInt(" + value + ')'; | 377 | return "floatBitsToInt(" + value + ')'; |
| 373 | } else { | 378 | } else { |
| 374 | UNREACHABLE(); | 379 | UNREACHABLE(); |
| 375 | } | 380 | } |
| 376 | } | 381 | } |
| 377 | 382 | ||
| 383 | /// Generates code representing a uniform (C buffer) register, interpreted as the type of the | ||
| 384 | /// destination register. | ||
| 385 | std::string GetUniform(const Uniform& uniform, const Register& dest_reg) { | ||
| 386 | return GetUniform(uniform, regs[dest_reg].GetActiveType()); | ||
| 387 | } | ||
| 388 | |||
| 378 | /// Add declarations for registers | 389 | /// Add declarations for registers |
| 379 | void GenerateDeclarations() { | 390 | void GenerateDeclarations() { |
| 380 | for (const auto& reg : regs) { | 391 | for (const auto& reg : regs) { |
| @@ -643,9 +654,9 @@ private: | |||
| 643 | std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const { | 654 | std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const { |
| 644 | using Tegra::Shader::PredCondition; | 655 | using Tegra::Shader::PredCondition; |
| 645 | static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = { | 656 | static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = { |
| 646 | {PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="}, | 657 | {PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="}, |
| 647 | {PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"}, | 658 | {PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"}, |
| 648 | {PredCondition::GreaterEqual, ">="}, | 659 | {PredCondition::NotEqual, "!="}, {PredCondition::GreaterEqual, ">="}, |
| 649 | }; | 660 | }; |
| 650 | 661 | ||
| 651 | auto comparison = PredicateComparisonStrings.find(condition); | 662 | auto comparison = PredicateComparisonStrings.find(condition); |
| @@ -839,6 +850,73 @@ private: | |||
| 839 | } | 850 | } |
| 840 | break; | 851 | break; |
| 841 | } | 852 | } |
| 853 | case OpCode::Type::Logic: { | ||
| 854 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false); | ||
| 855 | |||
| 856 | if (instr.alu.lop.invert_a) | ||
| 857 | op_a = "~(" + op_a + ')'; | ||
| 858 | |||
| 859 | switch (opcode->GetId()) { | ||
| 860 | case OpCode::Id::LOP32I: { | ||
| 861 | u32 imm = static_cast<u32>(instr.alu.imm20_32.Value()); | ||
| 862 | |||
| 863 | if (instr.alu.lop.invert_b) | ||
| 864 | imm = ~imm; | ||
| 865 | |||
| 866 | switch (instr.alu.lop.operation) { | ||
| 867 | case Tegra::Shader::LogicOperation::And: { | ||
| 868 | regs.SetRegisterToInteger(instr.gpr0, false, 0, | ||
| 869 | '(' + op_a + " & " + std::to_string(imm) + ')', 1, 1); | ||
| 870 | break; | ||
| 871 | } | ||
| 872 | case Tegra::Shader::LogicOperation::Or: { | ||
| 873 | regs.SetRegisterToInteger(instr.gpr0, false, 0, | ||
| 874 | '(' + op_a + " | " + std::to_string(imm) + ')', 1, 1); | ||
| 875 | break; | ||
| 876 | } | ||
| 877 | case Tegra::Shader::LogicOperation::Xor: { | ||
| 878 | regs.SetRegisterToInteger(instr.gpr0, false, 0, | ||
| 879 | '(' + op_a + " ^ " + std::to_string(imm) + ')', 1, 1); | ||
| 880 | break; | ||
| 881 | } | ||
| 882 | default: | ||
| 883 | NGLOG_CRITICAL(HW_GPU, "Unimplemented lop32i operation: {}", | ||
| 884 | static_cast<u32>(instr.alu.lop.operation.Value())); | ||
| 885 | UNREACHABLE(); | ||
| 886 | } | ||
| 887 | break; | ||
| 888 | } | ||
| 889 | default: { | ||
| 890 | NGLOG_CRITICAL(HW_GPU, "Unhandled logic instruction: {}", opcode->GetName()); | ||
| 891 | UNREACHABLE(); | ||
| 892 | } | ||
| 893 | } | ||
| 894 | break; | ||
| 895 | } | ||
| 896 | case OpCode::Type::ScaledAdd: { | ||
| 897 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8); | ||
| 898 | |||
| 899 | if (instr.iscadd.negate_a) | ||
| 900 | op_a = '-' + op_a; | ||
| 901 | |||
| 902 | std::string op_b = instr.iscadd.negate_b ? "-" : ""; | ||
| 903 | |||
| 904 | if (instr.is_b_imm) { | ||
| 905 | op_b += '(' + std::to_string(instr.iscadd.GetImmediate()) + ')'; | ||
| 906 | } else { | ||
| 907 | if (instr.is_b_gpr) { | ||
| 908 | op_b += regs.GetRegisterAsInteger(instr.gpr20); | ||
| 909 | } else { | ||
| 910 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | ||
| 911 | } | ||
| 912 | } | ||
| 913 | |||
| 914 | std::string shift = std::to_string(instr.iscadd.shift_amount.Value()); | ||
| 915 | |||
| 916 | regs.SetRegisterToInteger(instr.gpr0, true, 0, | ||
| 917 | "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1); | ||
| 918 | break; | ||
| 919 | } | ||
| 842 | case OpCode::Type::Ffma: { | 920 | case OpCode::Type::Ffma: { |
| 843 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); | 921 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); |
| 844 | std::string op_b = instr.ffma.negate_b ? "-" : ""; | 922 | std::string op_b = instr.ffma.negate_b ? "-" : ""; |
| @@ -880,8 +958,7 @@ private: | |||
| 880 | ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); | 958 | ASSERT_MSG(!instr.conversion.saturate_a, "Unimplemented"); |
| 881 | 959 | ||
| 882 | switch (opcode->GetId()) { | 960 | switch (opcode->GetId()) { |
| 883 | case OpCode::Id::I2I_R: | 961 | case OpCode::Id::I2I_R: { |
| 884 | case OpCode::Id::I2F_R: { | ||
| 885 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); | 962 | ASSERT_MSG(!instr.conversion.selector, "Unimplemented"); |
| 886 | 963 | ||
| 887 | std::string op_a = | 964 | std::string op_a = |
| @@ -894,6 +971,17 @@ private: | |||
| 894 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); | 971 | regs.SetRegisterToInteger(instr.gpr0, instr.conversion.is_signed, 0, op_a, 1, 1); |
| 895 | break; | 972 | break; |
| 896 | } | 973 | } |
| 974 | case OpCode::Id::I2F_R: { | ||
| 975 | std::string op_a = | ||
| 976 | regs.GetRegisterAsInteger(instr.gpr20, 0, instr.conversion.is_signed); | ||
| 977 | |||
| 978 | if (instr.conversion.abs_a) { | ||
| 979 | op_a = "abs(" + op_a + ')'; | ||
| 980 | } | ||
| 981 | |||
| 982 | regs.SetRegisterToFloat(instr.gpr0, 0, op_a, 1, 1); | ||
| 983 | break; | ||
| 984 | } | ||
| 897 | case OpCode::Id::F2F_R: { | 985 | case OpCode::Id::F2F_R: { |
| 898 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); | 986 | std::string op_a = regs.GetRegisterAsFloat(instr.gpr20); |
| 899 | 987 | ||
| @@ -1017,7 +1105,7 @@ private: | |||
| 1017 | if (instr.is_b_gpr) { | 1105 | if (instr.is_b_gpr) { |
| 1018 | op_b += regs.GetRegisterAsFloat(instr.gpr20); | 1106 | op_b += regs.GetRegisterAsFloat(instr.gpr20); |
| 1019 | } else { | 1107 | } else { |
| 1020 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | 1108 | op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Float); |
| 1021 | } | 1109 | } |
| 1022 | } | 1110 | } |
| 1023 | 1111 | ||
| @@ -1048,6 +1136,42 @@ private: | |||
| 1048 | } | 1136 | } |
| 1049 | break; | 1137 | break; |
| 1050 | } | 1138 | } |
| 1139 | case OpCode::Type::IntegerSetPredicate: { | ||
| 1140 | std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, instr.isetp.is_signed); | ||
| 1141 | |||
| 1142 | std::string op_b{}; | ||
| 1143 | |||
| 1144 | ASSERT_MSG(!instr.is_b_imm, "ISETP_IMM not implemented"); | ||
| 1145 | |||
| 1146 | if (instr.is_b_gpr) { | ||
| 1147 | op_b += regs.GetRegisterAsInteger(instr.gpr20, 0, instr.isetp.is_signed); | ||
| 1148 | } else { | ||
| 1149 | op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Integer); | ||
| 1150 | } | ||
| 1151 | |||
| 1152 | using Tegra::Shader::Pred; | ||
| 1153 | // We can't use the constant predicate as destination. | ||
| 1154 | ASSERT(instr.isetp.pred3 != static_cast<u64>(Pred::UnusedIndex)); | ||
| 1155 | |||
| 1156 | std::string second_pred = | ||
| 1157 | GetPredicateCondition(instr.isetp.pred39, instr.isetp.neg_pred != 0); | ||
| 1158 | |||
| 1159 | std::string comparator = GetPredicateComparison(instr.isetp.cond); | ||
| 1160 | std::string combiner = GetPredicateCombiner(instr.isetp.op); | ||
| 1161 | |||
| 1162 | std::string predicate = '(' + op_a + ") " + comparator + " (" + op_b + ')'; | ||
| 1163 | // Set the primary predicate to the result of Predicate OP SecondPredicate | ||
| 1164 | SetPredicate(instr.isetp.pred3, | ||
| 1165 | '(' + predicate + ") " + combiner + " (" + second_pred + ')'); | ||
| 1166 | |||
| 1167 | if (instr.isetp.pred0 != static_cast<u64>(Pred::UnusedIndex)) { | ||
| 1168 | // Set the secondary predicate to the result of !Predicate OP SecondPredicate, | ||
| 1169 | // if enabled | ||
| 1170 | SetPredicate(instr.isetp.pred0, | ||
| 1171 | "!(" + predicate + ") " + combiner + " (" + second_pred + ')'); | ||
| 1172 | } | ||
| 1173 | break; | ||
| 1174 | } | ||
| 1051 | case OpCode::Type::FloatSet: { | 1175 | case OpCode::Type::FloatSet: { |
| 1052 | std::string op_a = instr.fset.neg_a ? "-" : ""; | 1176 | std::string op_a = instr.fset.neg_a ? "-" : ""; |
| 1053 | op_a += regs.GetRegisterAsFloat(instr.gpr8); | 1177 | op_a += regs.GetRegisterAsFloat(instr.gpr8); |
| @@ -1068,7 +1192,7 @@ private: | |||
| 1068 | if (instr.is_b_gpr) { | 1192 | if (instr.is_b_gpr) { |
| 1069 | op_b += regs.GetRegisterAsFloat(instr.gpr20); | 1193 | op_b += regs.GetRegisterAsFloat(instr.gpr20); |
| 1070 | } else { | 1194 | } else { |
| 1071 | op_b += regs.GetUniform(instr.uniform, instr.gpr0); | 1195 | op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Float); |
| 1072 | } | 1196 | } |
| 1073 | } | 1197 | } |
| 1074 | 1198 | ||
| @@ -1087,7 +1211,12 @@ private: | |||
| 1087 | std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " + | 1211 | std::string predicate = "(((" + op_a + ") " + comparator + " (" + op_b + ")) " + |
| 1088 | combiner + " (" + second_pred + "))"; | 1212 | combiner + " (" + second_pred + "))"; |
| 1089 | 1213 | ||
| 1090 | regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); | 1214 | if (instr.fset.bf) { |
| 1215 | regs.SetRegisterToFloat(instr.gpr0, 0, predicate + " ? 1.0 : 0.0", 1, 1); | ||
| 1216 | } else { | ||
| 1217 | regs.SetRegisterToInteger(instr.gpr0, false, 0, predicate + " ? 0xFFFFFFFF : 0", 1, | ||
| 1218 | 1); | ||
| 1219 | } | ||
| 1091 | break; | 1220 | break; |
| 1092 | } | 1221 | } |
| 1093 | default: { | 1222 | default: { |