diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/video_core/engines/shader_bytecode.h | 7 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/gl_shader_decompiler.cpp | 39 |
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 | ||