diff options
Diffstat (limited to 'src/video_core/shader/decode.cpp')
| -rw-r--r-- | src/video_core/shader/decode.cpp | 70 |
1 files changed, 68 insertions, 2 deletions
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp index 381e87415..e7e0903f6 100644 --- a/src/video_core/shader/decode.cpp +++ b/src/video_core/shader/decode.cpp | |||
| @@ -35,10 +35,73 @@ constexpr bool IsSchedInstruction(u32 offset, u32 main_offset) { | |||
| 35 | 35 | ||
| 36 | } // namespace | 36 | } // namespace |
| 37 | 37 | ||
| 38 | class ASTDecoder { | ||
| 39 | public: | ||
| 40 | ASTDecoder(ShaderIR& ir) : ir(ir) {} | ||
| 41 | |||
| 42 | void operator()(ASTProgram& ast) { | ||
| 43 | ASTNode current = ast.nodes.GetFirst(); | ||
| 44 | while (current) { | ||
| 45 | Visit(current); | ||
| 46 | current = current->GetNext(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | void operator()(ASTIfThen& ast) { | ||
| 51 | ASTNode current = ast.nodes.GetFirst(); | ||
| 52 | while (current) { | ||
| 53 | Visit(current); | ||
| 54 | current = current->GetNext(); | ||
| 55 | } | ||
| 56 | } | ||
| 57 | |||
| 58 | void operator()(ASTIfElse& ast) { | ||
| 59 | ASTNode current = ast.nodes.GetFirst(); | ||
| 60 | while (current) { | ||
| 61 | Visit(current); | ||
| 62 | current = current->GetNext(); | ||
| 63 | } | ||
| 64 | } | ||
| 65 | |||
| 66 | void operator()(ASTBlockEncoded& ast) {} | ||
| 67 | |||
| 68 | void operator()(ASTBlockDecoded& ast) {} | ||
| 69 | |||
| 70 | void operator()(ASTVarSet& ast) {} | ||
| 71 | |||
| 72 | void operator()(ASTLabel& ast) {} | ||
| 73 | |||
| 74 | void operator()(ASTGoto& ast) {} | ||
| 75 | |||
| 76 | void operator()(ASTDoWhile& ast) { | ||
| 77 | ASTNode current = ast.nodes.GetFirst(); | ||
| 78 | while (current) { | ||
| 79 | Visit(current); | ||
| 80 | current = current->GetNext(); | ||
| 81 | } | ||
| 82 | } | ||
| 83 | |||
| 84 | void operator()(ASTReturn& ast) {} | ||
| 85 | |||
| 86 | void operator()(ASTBreak& ast) {} | ||
| 87 | |||
| 88 | void Visit(ASTNode& node) { | ||
| 89 | std::visit(*this, *node->GetInnerData()); | ||
| 90 | if (node->IsBlockEncoded()) { | ||
| 91 | auto block = std::get_if<ASTBlockEncoded>(node->GetInnerData()); | ||
| 92 | NodeBlock bb = ir.DecodeRange(block->start, block->end); | ||
| 93 | node->TransformBlockEncoded(bb); | ||
| 94 | } | ||
| 95 | } | ||
| 96 | |||
| 97 | private: | ||
| 98 | ShaderIR& ir; | ||
| 99 | }; | ||
| 100 | |||
| 38 | void ShaderIR::Decode() { | 101 | void ShaderIR::Decode() { |
| 39 | std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); | 102 | std::memcpy(&header, program_code.data(), sizeof(Tegra::Shader::Header)); |
| 40 | 103 | ||
| 41 | disable_flow_stack = false; | 104 | decompiled = false; |
| 42 | const auto info = | 105 | const auto info = |
| 43 | ScanFlow(program_code, program_size, main_offset, program_manager); | 106 | ScanFlow(program_code, program_size, main_offset, program_manager); |
| 44 | if (info) { | 107 | if (info) { |
| @@ -46,7 +109,10 @@ void ShaderIR::Decode() { | |||
| 46 | coverage_begin = shader_info.start; | 109 | coverage_begin = shader_info.start; |
| 47 | coverage_end = shader_info.end; | 110 | coverage_end = shader_info.end; |
| 48 | if (shader_info.decompiled) { | 111 | if (shader_info.decompiled) { |
| 49 | disable_flow_stack = true; | 112 | decompiled = true; |
| 113 | ASTDecoder decoder{*this}; | ||
| 114 | ASTNode program = GetASTProgram(); | ||
| 115 | decoder.Visit(program); | ||
| 50 | return; | 116 | return; |
| 51 | } | 117 | } |
| 52 | LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method"); | 118 | LOG_WARNING(HW_GPU, "Flow Stack Removing Failed! Falling back to old method"); |