diff options
| author | PastaLaPate <pastalapate@proton.me> | 2026-11-02 20:34:15 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2026-11-02 20:34:15 +0100 |
| commit | 6f002badce45fa2fdb414043544c829e834a7e27 (patch) | |
| tree | 51c21a851fbc8218ebe7febb69fb710a891cc4fc /src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | |
| parent | 396f011ea875dfe4fdb1b0f489651ab74a505b74 (diff) | |
| parent | 046646e3514ca4950622d75609e68498f889989e (diff) | |
Merge branch 'nx2' into ci/qt-6.12.0
Diffstat (limited to 'src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp | 29 |
1 files changed, 25 insertions, 4 deletions
diff --git a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp index 329d44443e..50cff52f88 100644 --- a/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/structured_control_flow.cpp @@ -314,7 +314,8 @@ bool NeedsLift(Node goto_stmt, Node label_stmt) noexcept { class GotoPass { public: - explicit GotoPass(Flow::CFG& cfg, ObjectPool<Statement>& stmt_pool) : pool{stmt_pool} { + explicit GotoPass(Flow::CFG& cfg, ObjectPool<Statement>& stmt_pool, bool converge_exits_) + : pool{stmt_pool}, converge_exits{converge_exits_} { std::vector gotos{BuildTree(cfg)}; const auto end{gotos.rend()}; for (auto goto_stmt = gotos.rbegin(); goto_stmt != end; ++goto_stmt) { @@ -381,7 +382,17 @@ private: u32 label_id{0}; std::vector<Node> gotos; Flow::Function& first_function{cfg.Functions().front()}; - BuildTree(cfg, first_function, label_id, gotos, root_stmt.children.end(), std::nullopt); + Node insert_point{root_stmt.children.end()}; + if (converge_exits) { + // Every EXIT jumps to one return at the end, so all invocations reach the same + // epilogue (task and mesh programs emit their outputs there, after a barrier). + Tree& root{root_stmt.children}; + exit_label = root.insert(root.end(), *pool.Create(Label{}, label_id, &root_stmt)); + ++label_id; + root.insert(root.end(), *pool.Create(Return{}, &root_stmt)); + insert_point = *exit_label; + } + BuildTree(cfg, first_function, label_id, gotos, insert_point, std::nullopt); return gotos; } @@ -454,7 +465,14 @@ private: break; } case Flow::EndClass::Exit: - root.insert(ip, *pool.Create(Return{}, &root_stmt)); + if (exit_label) { + Statement* const always_cond{ + pool.Create(Identity{}, IR::Condition{true}, &root_stmt)}; + gotos.push_back(root.insert( + ip, *pool.Create(Goto{}, always_cond, *exit_label, &root_stmt))); + } else { + root.insert(ip, *pool.Create(Return{}, &root_stmt)); + } break; case Flow::EndClass::Return: { Statement* const always_cond{pool.Create(Identity{}, block.cond, &root_stmt)}; @@ -618,6 +636,8 @@ private: ObjectPool<Statement>& pool; Statement root_stmt{FunctionTag{}}; + bool converge_exits{}; + std::optional<Node> exit_label; }; [[nodiscard]] Statement* TryFindForwardBlock(Statement& stmt) { @@ -987,7 +1007,8 @@ IR::AbstractSyntaxList BuildASL(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR:: Environment& env, Flow::CFG& cfg, const HostTranslateInfo& host_info) { ObjectPool<Statement> stmt_pool{64}; - GotoPass goto_pass{cfg, stmt_pool}; + const Stage stage{env.ShaderStage()}; + GotoPass goto_pass{cfg, stmt_pool, stage == Stage::Task || stage == Stage::Mesh}; Statement& root{goto_pass.RootStatement()}; IR::AbstractSyntaxList syntax_list; TranslatePass{inst_pool, block_pool, stmt_pool, env, root, syntax_list, host_info}; |
