summaryrefslogtreecommitdiffstats
path: root/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp
diff options
context:
space:
mode:
authorFernandoS27 <fsahmkow27@gmail.com>2021-04-19 01:03:38 +0200
committerameerj <52414509+ameerj@users.noreply.github.com>2021-07-23 03:51:29 +0200
commitb541f5e5e333a8ec8c3569e02d67e59ad14217c2 (patch)
tree5b19bdd92d74ce8e32be75cfa2c27a4612a663de /src/shader_recompiler/ir_opt/dual_vertex_pass.cpp
parentshader: Implement delegation of Exit to dispatcher on CFG (diff)
downloadyuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.tar
yuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.tar.gz
yuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.tar.bz2
yuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.tar.lz
yuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.tar.xz
yuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.tar.zst
yuzu-b541f5e5e333a8ec8c3569e02d67e59ad14217c2.zip
Diffstat (limited to 'src/shader_recompiler/ir_opt/dual_vertex_pass.cpp')
-rw-r--r--src/shader_recompiler/ir_opt/dual_vertex_pass.cpp74
1 files changed, 74 insertions, 0 deletions
diff --git a/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp
new file mode 100644
index 000000000..f35c6478a
--- /dev/null
+++ b/src/shader_recompiler/ir_opt/dual_vertex_pass.cpp
@@ -0,0 +1,74 @@
+// Copyright 2021 yuzu Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <algorithm>
+#include <ranges>
+#include <tuple>
+#include <type_traits>
+
+#include "common/bit_cast.h"
+#include "common/bit_util.h"
+#include "shader_recompiler/exception.h"
+#include "shader_recompiler/frontend/ir/ir_emitter.h"
+#include "shader_recompiler/ir_opt/passes.h"
+
+namespace Shader::Optimization {
+
+void VertexATransformPass(IR::Program& program) {
+ bool replaced_join{};
+ bool eliminated_epilogue{};
+ for (IR::Block* const block : program.post_order_blocks) {
+ for (IR::Inst& inst : block->Instructions()) {
+ switch (inst.GetOpcode()) {
+ case IR::Opcode::Return:
+ inst.ReplaceOpcode(IR::Opcode::Join);
+ replaced_join = true;
+ break;
+ case IR::Opcode::Epilogue:
+ inst.Invalidate();
+ eliminated_epilogue = true;
+ break;
+ default:
+ break;
+ }
+ if (replaced_join && eliminated_epilogue) {
+ return;
+ }
+ }
+ }
+}
+
+void VertexBTransformPass(IR::Program& program) {
+ for (IR::Block* const block : program.post_order_blocks | std::views::reverse) {
+ for (IR::Inst& inst : block->Instructions()) {
+ if (inst.GetOpcode() == IR::Opcode::Prologue) {
+ return inst.Invalidate();
+ }
+ }
+ }
+}
+
+void DualVertexJoinPass(IR::Program& program) {
+ const auto& blocks = program.blocks;
+ s64 s = static_cast<s64>(blocks.size()) - 1;
+ if (s < 1) {
+ throw NotImplementedException("Dual Vertex Join pass failed, expected atleast 2 blocks!");
+ }
+ for (s64 index = 0; index < s; index++) {
+ IR::Block* const current_block = blocks[index];
+ IR::Block* const next_block = blocks[index + 1];
+ for (IR::Inst& inst : current_block->Instructions()) {
+ if (inst.GetOpcode() == IR::Opcode::Join) {
+ IR::IREmitter ir{*current_block, IR::Block::InstructionList::s_iterator_to(inst)};
+ ir.Branch(next_block);
+ inst.Invalidate();
+ // only 1 join should exist
+ return;
+ }
+ }
+ }
+ throw NotImplementedException("Dual Vertex Join pass failed, no join present!");
+}
+
+} // namespace Shader::Optimization