summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/video_core/engines/shader_bytecode.h7
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp39
2 files changed, 38 insertions, 8 deletions
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index 3e409c2e1..6cb7bea1c 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -597,6 +597,13 @@ public:
597 Unknown, 597 Unknown,
598 }; 598 };
599 599
600 /// Returns whether an opcode has an execution predicate field or not (ie, whether it can be
601 /// conditionally executed).
602 static bool IsPredicatedInstruction(Id opcode) {
603 // TODO(Subv): Add the rest of unpredicated instructions.
604 return opcode != Id::SSY;
605 }
606
600 class Matcher { 607 class Matcher {
601 public: 608 public:
602 Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type) 609 Matcher(const char* const name, u16 mask, u16 expected, OpCode::Id id, OpCode::Type type)
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 32f06f409..8954deb81 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -141,6 +141,15 @@ private:
141 ExitMethod jmp = Scan(target, end, labels); 141 ExitMethod jmp = Scan(target, end, labels);
142 return exit_method = ParallelExit(no_jmp, jmp); 142 return exit_method = ParallelExit(no_jmp, jmp);
143 } 143 }
144 case OpCode::Id::SSY: {
145 // The SSY instruction uses a similar encoding as the BRA instruction.
146 ASSERT_MSG(instr.bra.constant_buffer == 0,
147 "Constant buffer SSY is not supported");
148 u32 target = offset + instr.bra.GetBranchTarget();
149 labels.insert(target);
150 // Continue scanning for an exit method.
151 break;
152 }
144 } 153 }
145 } 154 }
146 } 155 }
@@ -828,7 +837,11 @@ private:
828 ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute, 837 ASSERT_MSG(instr.pred.full_pred != Pred::NeverExecute,
829 "NeverExecute predicate not implemented"); 838 "NeverExecute predicate not implemented");
830 839
831 if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) { 840 // Some instructions (like SSY) don't have a predicate field, they are always
841 // unconditionally executed.
842 bool can_be_predicated = OpCode::IsPredicatedInstruction(opcode->GetId());
843
844 if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
832 shader.AddLine("if (" + 845 shader.AddLine("if (" +
833 GetPredicateCondition(instr.pred.pred_index, instr.negate_pred != 0) + 846 GetPredicateCondition(instr.pred.pred_index, instr.negate_pred != 0) +
834 ')'); 847 ')');
@@ -1668,16 +1681,25 @@ private:
1668 break; 1681 break;
1669 } 1682 }
1670 case OpCode::Id::SSY: { 1683 case OpCode::Id::SSY: {
1671 // The SSY opcode tells the GPU where to re-converge divergent execution paths, we 1684 // The SSY opcode tells the GPU where to re-converge divergent execution paths, it
1672 // can ignore this when generating GLSL code. 1685 // sets the target of the jump that the SYNC instruction will make. The SSY opcode
1686 // has a similar structure to the BRA opcode.
1687 ASSERT_MSG(instr.bra.constant_buffer == 0, "Constant buffer SSY is not supported");
1688
1689 u32 target = offset + instr.bra.GetBranchTarget();
1690 shader.AddLine("ssy_target = " + std::to_string(target) + "u;");
1673 break; 1691 break;
1674 } 1692 }
1675 case OpCode::Id::SYNC: 1693 case OpCode::Id::SYNC: {
1694 // The SYNC opcode jumps to the address previously set by the SSY opcode
1676 ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always); 1695 ASSERT(instr.flow.cond == Tegra::Shader::FlowCondition::Always);
1696 shader.AddLine("{ jmp_to = ssy_target; break; }");
1697 break;
1698 }
1677 case OpCode::Id::DEPBAR: { 1699 case OpCode::Id::DEPBAR: {
1678 // TODO(Subv): Find out if we actually have to care about these instructions or if 1700 // TODO(Subv): Find out if we actually have to care about this instruction or if
1679 // the GLSL compiler takes care of that for us. 1701 // the GLSL compiler takes care of that for us.
1680 LOG_WARNING(HW_GPU, "DEPBAR/SYNC instruction is stubbed"); 1702 LOG_WARNING(HW_GPU, "DEPBAR instruction is stubbed");
1681 break; 1703 break;
1682 } 1704 }
1683 default: { 1705 default: {
@@ -1691,7 +1713,7 @@ private:
1691 } 1713 }
1692 1714
1693 // Close the predicate condition scope. 1715 // Close the predicate condition scope.
1694 if (instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) { 1716 if (can_be_predicated && instr.pred.pred_index != static_cast<u64>(Pred::UnusedIndex)) {
1695 --shader.scope; 1717 --shader.scope;
1696 shader.AddLine('}'); 1718 shader.AddLine('}');
1697 } 1719 }
@@ -1742,6 +1764,7 @@ private:
1742 } else { 1764 } else {
1743 labels.insert(subroutine.begin); 1765 labels.insert(subroutine.begin);
1744 shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;"); 1766 shader.AddLine("uint jmp_to = " + std::to_string(subroutine.begin) + "u;");
1767 shader.AddLine("uint ssy_target = 0u;");
1745 shader.AddLine("while (true) {"); 1768 shader.AddLine("while (true) {");
1746 ++shader.scope; 1769 ++shader.scope;
1747 1770
@@ -1757,7 +1780,7 @@ private:
1757 u32 compile_end = CompileRange(label, next_label); 1780 u32 compile_end = CompileRange(label, next_label);
1758 if (compile_end > next_label && compile_end != PROGRAM_END) { 1781 if (compile_end > next_label && compile_end != PROGRAM_END) {
1759 // This happens only when there is a label inside a IF/LOOP block 1782 // This happens only when there is a label inside a IF/LOOP block
1760 shader.AddLine("{ jmp_to = " + std::to_string(compile_end) + "u; break; }"); 1783 shader.AddLine(" jmp_to = " + std::to_string(compile_end) + "u; break; }");
1761 labels.emplace(compile_end); 1784 labels.emplace(compile_end);
1762 } 1785 }
1763 1786