summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--appveyor.yml2
-rw-r--r--src/video_core/engines/shader_bytecode.h42
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp80
3 files changed, 108 insertions, 16 deletions
diff --git a/appveyor.yml b/appveyor.yml
index 4f928adb5..72cda26a7 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -53,7 +53,7 @@ build_script:
53 # https://www.appveyor.com/docs/build-phase 53 # https://www.appveyor.com/docs/build-phase
54 msbuild msvc_build/yuzu.sln /maxcpucount /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll" 54 msbuild msvc_build/yuzu.sln /maxcpucount /logger:"C:\Program Files\AppVeyor\BuildAgent\Appveyor.MSBuildLogger.dll"
55 } else { 55 } else {
56 C:\msys64\usr\bin\bash.exe -lc 'mingw32-make -j4 -C mingw_build/ 2>&1' 56 C:\msys64\usr\bin\bash.exe -lc 'mingw32-make -C mingw_build/ 2>&1'
57 } 57 }
58 58
59after_build: 59after_build:
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 93654eb66..4eb507325 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -237,9 +237,22 @@ union Instruction {
237 std::memcpy(&result, &imm, sizeof(imm)); 237 std::memcpy(&result, &imm, sizeof(imm));
238 return result; 238 return result;
239 } 239 }
240
241 s32 GetSignedImm20_20() const {
242 u32 immediate = static_cast<u32>(imm20_19 | (negate_imm << 19));
243 // Sign extend the 20-bit value.
244 u32 mask = 1U << (20 - 1);
245 return static_cast<s32>((immediate ^ mask) - mask);
246 }
240 } alu; 247 } alu;
241 248
242 union { 249 union {
250 BitField<39, 5, u64> shift_amount;
251 BitField<48, 1, u64> negate_b;
252 BitField<49, 1, u64> negate_a;
253 } iscadd;
254
255 union {
243 BitField<48, 1, u64> negate_b; 256 BitField<48, 1, u64> negate_b;
244 BitField<49, 1, u64> negate_c; 257 BitField<49, 1, u64> negate_c;
245 } ffma; 258 } ffma;
@@ -328,15 +341,16 @@ union Instruction {
328 } texs; 341 } texs;
329 342
330 union { 343 union {
331 BitField<20, 5, u64> target; 344 BitField<20, 24, u64> target;
332 BitField<5, 1, u64> constant_buffer; 345 BitField<5, 1, u64> constant_buffer;
333 346
334 s32 GetBranchTarget() const { 347 s32 GetBranchTarget() const {
335 // Sign extend the branch target offset 348 // Sign extend the branch target offset
336 u32 mask = 1U << (5 - 1); 349 u32 mask = 1U << (24 - 1);
337 u32 value = static_cast<u32>(target); 350 u32 value = static_cast<u32>(target);
338 // The branch offset is relative to the next instruction, so add 1 to it. 351 // The branch offset is relative to the next instruction and is stored in bytes, so
339 return static_cast<s32>((value ^ mask) - mask) + 1; 352 // divide it by the size of an instruction and add 1 to it.
353 return static_cast<s32>((value ^ mask) - mask) / sizeof(Instruction) + 1;
340 } 354 }
341 } bra; 355 } bra;
342 356
@@ -378,6 +392,9 @@ public:
378 FMUL_R, 392 FMUL_R,
379 FMUL_IMM, 393 FMUL_IMM,
380 FMUL32_IMM, 394 FMUL32_IMM,
395 ISCADD_C, // Scale and Add
396 ISCADD_R,
397 ISCADD_IMM,
381 MUFU, // Multi-Function Operator 398 MUFU, // Multi-Function Operator
382 RRO_C, // Range Reduction Operator 399 RRO_C, // Range Reduction Operator
383 RRO_R, 400 RRO_R,
@@ -399,6 +416,9 @@ public:
399 MOV_R, 416 MOV_R,
400 MOV_IMM, 417 MOV_IMM,
401 MOV32_IMM, 418 MOV32_IMM,
419 SHL_C,
420 SHL_R,
421 SHL_IMM,
402 SHR_C, 422 SHR_C,
403 SHR_R, 423 SHR_R,
404 SHR_IMM, 424 SHR_IMM,
@@ -421,6 +441,8 @@ public:
421 Trivial, 441 Trivial,
422 Arithmetic, 442 Arithmetic,
423 Logic, 443 Logic,
444 Shift,
445 ScaledAdd,
424 Ffma, 446 Ffma,
425 Flow, 447 Flow,
426 Memory, 448 Memory,
@@ -544,6 +566,9 @@ private:
544 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"), 566 INST("0101110001101---", Id::FMUL_R, Type::Arithmetic, "FMUL_R"),
545 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"), 567 INST("0011100-01101---", Id::FMUL_IMM, Type::Arithmetic, "FMUL_IMM"),
546 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"), 568 INST("00011110--------", Id::FMUL32_IMM, Type::Arithmetic, "FMUL32_IMM"),
569 INST("0100110000011---", Id::ISCADD_C, Type::ScaledAdd, "ISCADD_C"),
570 INST("0101110000011---", Id::ISCADD_R, Type::ScaledAdd, "ISCADD_R"),
571 INST("0011100-00011---", Id::ISCADD_IMM, Type::ScaledAdd, "ISCADD_IMM"),
547 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), 572 INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"),
548 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"), 573 INST("0100110010010---", Id::RRO_C, Type::Arithmetic, "RRO_C"),
549 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"), 574 INST("0101110010010---", Id::RRO_R, Type::Arithmetic, "RRO_R"),
@@ -558,13 +583,16 @@ private:
558 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"), 583 INST("0101110010011---", Id::MOV_R, Type::Arithmetic, "MOV_R"),
559 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"), 584 INST("0011100-10011---", Id::MOV_IMM, Type::Arithmetic, "MOV_IMM"),
560 INST("000000010000----", Id::MOV32_IMM, Type::Arithmetic, "MOV32_IMM"), 585 INST("000000010000----", Id::MOV32_IMM, Type::Arithmetic, "MOV32_IMM"),
561 INST("0100110000101---", Id::SHR_C, Type::Arithmetic, "SHR_C"),
562 INST("0101110000101---", Id::SHR_R, Type::Arithmetic, "SHR_R"),
563 INST("0011100-00101---", Id::SHR_IMM, Type::Arithmetic, "SHR_IMM"),
564 INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"), 586 INST("0100110001100---", Id::FMNMX_C, Type::Arithmetic, "FMNMX_C"),
565 INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"), 587 INST("0101110001100---", Id::FMNMX_R, Type::Arithmetic, "FMNMX_R"),
566 INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"), 588 INST("0011100-01100---", Id::FMNMX_IMM, Type::Arithmetic, "FMNMX_IMM"),
567 INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"), 589 INST("000001----------", Id::LOP32I, Type::Logic, "LOP32I"),
590 INST("0100110001001---", Id::SHL_C, Type::Shift, "SHL_C"),
591 INST("0101110001001---", Id::SHL_R, Type::Shift, "SHL_R"),
592 INST("0011100-01001---", Id::SHL_IMM, Type::Shift, "SHL_IMM"),
593 INST("0100110000101---", Id::SHR_C, Type::Shift, "SHR_C"),
594 INST("0101110000101---", Id::SHR_R, Type::Shift, "SHR_R"),
595 INST("0011100-00101---", Id::SHR_IMM, Type::Shift, "SHR_IMM"),
568 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"), 596 INST("0100110011100---", Id::I2I_C, Type::Conversion, "I2I_C"),
569 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"), 597 INST("0101110011100---", Id::I2I_R, Type::Conversion, "I2I_R"),
570 INST("01110001-1000---", Id::I2I_IMM, Type::Conversion, "I2I_IMM"), 598 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 4b14bb47e..4a41e7798 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -115,7 +115,16 @@ private:
115 if (const auto opcode = OpCode::Decode(instr)) { 115 if (const auto opcode = OpCode::Decode(instr)) {
116 switch (opcode->GetId()) { 116 switch (opcode->GetId()) {
117 case OpCode::Id::EXIT: { 117 case OpCode::Id::EXIT: {
118 return exit_method = ExitMethod::AlwaysEnd; 118 // The EXIT instruction can be predicated, which means that the shader can
119 // conditionally end on this instruction. We have to consider the case where the
120 // condition is not met and check the exit method of that other basic block.
121 using Tegra::Shader::Pred;
122 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
123 return exit_method = ExitMethod::AlwaysEnd;
124 } else {
125 ExitMethod not_met = Scan(offset + 1, end, labels);
126 return exit_method = ParallelExit(ExitMethod::AlwaysEnd, not_met);
127 }
119 } 128 }
120 case OpCode::Id::BRA: { 129 case OpCode::Id::BRA: {
121 u32 target = offset + instr.bra.GetBranchTarget(); 130 u32 target = offset + instr.bra.GetBranchTarget();
@@ -645,9 +654,9 @@ private:
645 std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const { 654 std::string GetPredicateComparison(Tegra::Shader::PredCondition condition) const {
646 using Tegra::Shader::PredCondition; 655 using Tegra::Shader::PredCondition;
647 static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = { 656 static const std::unordered_map<PredCondition, const char*> PredicateComparisonStrings = {
648 {PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="}, 657 {PredCondition::LessThan, "<"}, {PredCondition::Equal, "=="},
649 {PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"}, 658 {PredCondition::LessEqual, "<="}, {PredCondition::GreaterThan, ">"},
650 {PredCondition::GreaterEqual, ">="}, 659 {PredCondition::NotEqual, "!="}, {PredCondition::GreaterEqual, ">="},
651 }; 660 };
652 661
653 auto comparison = PredicateComparisonStrings.find(condition); 662 auto comparison = PredicateComparisonStrings.find(condition);
@@ -884,6 +893,59 @@ private:
884 } 893 }
885 break; 894 break;
886 } 895 }
896
897 case OpCode::Type::Shift: {
898 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8, 0, false);
899 std::string op_b;
900
901 if (instr.is_b_imm) {
902 op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')';
903 } else {
904 if (instr.is_b_gpr) {
905 op_b += regs.GetRegisterAsInteger(instr.gpr20);
906 } else {
907 op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Integer);
908 }
909 }
910
911 switch (opcode->GetId()) {
912 case OpCode::Id::SHL_C:
913 case OpCode::Id::SHL_R:
914 case OpCode::Id::SHL_IMM:
915 regs.SetRegisterToInteger(instr.gpr0, true, 0, op_a + " << " + op_b, 1, 1);
916 break;
917 default: {
918 NGLOG_CRITICAL(HW_GPU, "Unhandled shift instruction: {}", opcode->GetName());
919 UNREACHABLE();
920 }
921 }
922 break;
923 }
924
925 case OpCode::Type::ScaledAdd: {
926 std::string op_a = regs.GetRegisterAsInteger(instr.gpr8);
927
928 if (instr.iscadd.negate_a)
929 op_a = '-' + op_a;
930
931 std::string op_b = instr.iscadd.negate_b ? "-" : "";
932
933 if (instr.is_b_imm) {
934 op_b += '(' + std::to_string(instr.alu.GetSignedImm20_20()) + ')';
935 } else {
936 if (instr.is_b_gpr) {
937 op_b += regs.GetRegisterAsInteger(instr.gpr20);
938 } else {
939 op_b += regs.GetUniform(instr.uniform, GLSLRegister::Type::Integer);
940 }
941 }
942
943 std::string shift = std::to_string(instr.iscadd.shift_amount.Value());
944
945 regs.SetRegisterToInteger(instr.gpr0, true, 0,
946 "((" + op_a + " << " + shift + ") + " + op_b + ')', 1, 1);
947 break;
948 }
887 case OpCode::Type::Ffma: { 949 case OpCode::Type::Ffma: {
888 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8); 950 std::string op_a = regs.GetRegisterAsFloat(instr.gpr8);
889 std::string op_b = instr.ffma.negate_b ? "-" : ""; 951 std::string op_b = instr.ffma.negate_b ? "-" : "";
@@ -1230,9 +1292,6 @@ private:
1230 default: { 1292 default: {
1231 switch (opcode->GetId()) { 1293 switch (opcode->GetId()) {
1232 case OpCode::Id::EXIT: { 1294 case OpCode::Id::EXIT: {
1233 ASSERT_MSG(instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex),
1234 "Predicated exits not implemented");
1235
1236 // Final color output is currently hardcoded to GPR0-3 for fragment shaders 1295 // Final color output is currently hardcoded to GPR0-3 for fragment shaders
1237 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) { 1296 if (stage == Maxwell3D::Regs::ShaderStage::Fragment) {
1238 shader.AddLine("color.r = " + regs.GetRegisterAsFloat(0) + ';'); 1297 shader.AddLine("color.r = " + regs.GetRegisterAsFloat(0) + ';');
@@ -1242,7 +1301,12 @@ private:
1242 } 1301 }
1243 1302
1244 shader.AddLine("return true;"); 1303 shader.AddLine("return true;");
1245 offset = PROGRAM_END - 1; 1304 if (instr.pred.pred_index == static_cast<u64>(Pred::UnusedIndex)) {
1305 // If this is an unconditional exit then just end processing here, otherwise we
1306 // have to account for the possibility of the condition not being met, so
1307 // continue processing the next instruction.
1308 offset = PROGRAM_END - 1;
1309 }
1246 break; 1310 break;
1247 } 1311 }
1248 case OpCode::Id::KIL: { 1312 case OpCode::Id::KIL: {