summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2019-06-04 22:44:06 -0300
committerGravatar ReinUsesLisp2019-06-05 20:41:52 -0300
commitbf4dfb3ad4c6419216e8154c970f5577bc1bc475 (patch)
treefc03ece18cae31f3a855d6702878027bd1f6134a /src
parentMerge pull request #2520 from ReinUsesLisp/vulkan-refresh (diff)
downloadyuzu-bf4dfb3ad4c6419216e8154c970f5577bc1bc475.tar.gz
yuzu-bf4dfb3ad4c6419216e8154c970f5577bc1bc475.tar.xz
yuzu-bf4dfb3ad4c6419216e8154c970f5577bc1bc475.zip
shader: Use shared_ptr to store nodes and move initialization to file
Instead of having a vector of unique_ptr stored in a vector and returning star pointers to this, use shared_ptr. While changing initialization code, move it to a separate file when possible. This is a first step to allow code analysis and node generation beyond the ShaderIR class.
Diffstat (limited to 'src')
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp62
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp50
-rw-r--r--src/video_core/shader/decode.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic_half.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic_half_immediate.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic_immediate.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp1
-rw-r--r--src/video_core/shader/decode/arithmetic_integer_immediate.cpp1
-rw-r--r--src/video_core/shader/decode/bfe.cpp1
-rw-r--r--src/video_core/shader/decode/bfi.cpp1
-rw-r--r--src/video_core/shader/decode/conversion.cpp1
-rw-r--r--src/video_core/shader/decode/ffma.cpp1
-rw-r--r--src/video_core/shader/decode/float_set.cpp1
-rw-r--r--src/video_core/shader/decode/float_set_predicate.cpp1
-rw-r--r--src/video_core/shader/decode/half_set.cpp1
-rw-r--r--src/video_core/shader/decode/half_set_predicate.cpp1
-rw-r--r--src/video_core/shader/decode/hfma2.cpp1
-rw-r--r--src/video_core/shader/decode/integer_set.cpp1
-rw-r--r--src/video_core/shader/decode/integer_set_predicate.cpp1
-rw-r--r--src/video_core/shader/decode/memory.cpp9
-rw-r--r--src/video_core/shader/decode/other.cpp1
-rw-r--r--src/video_core/shader/decode/predicate_set_predicate.cpp1
-rw-r--r--src/video_core/shader/decode/predicate_set_register.cpp1
-rw-r--r--src/video_core/shader/decode/register_set_predicate.cpp1
-rw-r--r--src/video_core/shader/decode/shift.cpp1
-rw-r--r--src/video_core/shader/decode/texture.cpp9
-rw-r--r--src/video_core/shader/decode/video.cpp1
-rw-r--r--src/video_core/shader/decode/xmad.cpp1
-rw-r--r--src/video_core/shader/node_helper.cpp99
-rw-r--r--src/video_core/shader/node_helper.h60
-rw-r--r--src/video_core/shader/shader_ir.cpp102
-rw-r--r--src/video_core/shader/shader_ir.h108
-rw-r--r--src/video_core/shader/track.cpp18
35 files changed, 296 insertions, 248 deletions
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 1e010e4da..fa80c3814 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -102,6 +102,8 @@ add_library(video_core STATIC
102 shader/decode/xmad.cpp 102 shader/decode/xmad.cpp
103 shader/decode/other.cpp 103 shader/decode/other.cpp
104 shader/decode.cpp 104 shader/decode.cpp
105 shader/node_helper.cpp
106 shader/node_helper.h
105 shader/shader_ir.cpp 107 shader/shader_ir.cpp
106 shader/shader_ir.h 108 shader/shader_ir.h
107 shader/track.cpp 109 shader/track.cpp
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 29de5c9db..f2d0722af 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -123,8 +123,8 @@ bool IsPrecise(Operation operand) {
123 return false; 123 return false;
124} 124}
125 125
126bool IsPrecise(Node node) { 126bool IsPrecise(const Node& node) {
127 if (const auto operation = std::get_if<OperationNode>(node)) { 127 if (const auto operation = std::get_if<OperationNode>(&*node)) {
128 return IsPrecise(*operation); 128 return IsPrecise(*operation);
129 } 129 }
130 return false; 130 return false;
@@ -497,15 +497,15 @@ private:
497 } 497 }
498 498
499 void VisitBlock(const NodeBlock& bb) { 499 void VisitBlock(const NodeBlock& bb) {
500 for (const Node node : bb) { 500 for (const auto& node : bb) {
501 if (const std::string expr = Visit(node); !expr.empty()) { 501 if (const std::string expr = Visit(node); !expr.empty()) {
502 code.AddLine(expr); 502 code.AddLine(expr);
503 } 503 }
504 } 504 }
505 } 505 }
506 506
507 std::string Visit(Node node) { 507 std::string Visit(const Node& node) {
508 if (const auto operation = std::get_if<OperationNode>(node)) { 508 if (const auto operation = std::get_if<OperationNode>(&*node)) {
509 const auto operation_index = static_cast<std::size_t>(operation->GetCode()); 509 const auto operation_index = static_cast<std::size_t>(operation->GetCode());
510 if (operation_index >= operation_decompilers.size()) { 510 if (operation_index >= operation_decompilers.size()) {
511 UNREACHABLE_MSG("Out of bounds operation: {}", operation_index); 511 UNREACHABLE_MSG("Out of bounds operation: {}", operation_index);
@@ -519,7 +519,7 @@ private:
519 return (this->*decompiler)(*operation); 519 return (this->*decompiler)(*operation);
520 } 520 }
521 521
522 if (const auto gpr = std::get_if<GprNode>(node)) { 522 if (const auto gpr = std::get_if<GprNode>(&*node)) {
523 const u32 index = gpr->GetIndex(); 523 const u32 index = gpr->GetIndex();
524 if (index == Register::ZeroIndex) { 524 if (index == Register::ZeroIndex) {
525 return "0"; 525 return "0";
@@ -527,7 +527,7 @@ private:
527 return GetRegister(index); 527 return GetRegister(index);
528 } 528 }
529 529
530 if (const auto immediate = std::get_if<ImmediateNode>(node)) { 530 if (const auto immediate = std::get_if<ImmediateNode>(&*node)) {
531 const u32 value = immediate->GetValue(); 531 const u32 value = immediate->GetValue();
532 if (value < 10) { 532 if (value < 10) {
533 // For eyecandy avoid using hex numbers on single digits 533 // For eyecandy avoid using hex numbers on single digits
@@ -536,7 +536,7 @@ private:
536 return fmt::format("utof(0x{:x}u)", immediate->GetValue()); 536 return fmt::format("utof(0x{:x}u)", immediate->GetValue());
537 } 537 }
538 538
539 if (const auto predicate = std::get_if<PredicateNode>(node)) { 539 if (const auto predicate = std::get_if<PredicateNode>(&*node)) {
540 const auto value = [&]() -> std::string { 540 const auto value = [&]() -> std::string {
541 switch (const auto index = predicate->GetIndex(); index) { 541 switch (const auto index = predicate->GetIndex(); index) {
542 case Tegra::Shader::Pred::UnusedIndex: 542 case Tegra::Shader::Pred::UnusedIndex:
@@ -553,7 +553,7 @@ private:
553 return value; 553 return value;
554 } 554 }
555 555
556 if (const auto abuf = std::get_if<AbufNode>(node)) { 556 if (const auto abuf = std::get_if<AbufNode>(&*node)) {
557 UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry, 557 UNIMPLEMENTED_IF_MSG(abuf->IsPhysicalBuffer() && stage == ShaderStage::Geometry,
558 "Physical attributes in geometry shaders are not implemented"); 558 "Physical attributes in geometry shaders are not implemented");
559 if (abuf->IsPhysicalBuffer()) { 559 if (abuf->IsPhysicalBuffer()) {
@@ -563,9 +563,9 @@ private:
563 return ReadAttribute(abuf->GetIndex(), abuf->GetElement(), abuf->GetBuffer()); 563 return ReadAttribute(abuf->GetIndex(), abuf->GetElement(), abuf->GetBuffer());
564 } 564 }
565 565
566 if (const auto cbuf = std::get_if<CbufNode>(node)) { 566 if (const auto cbuf = std::get_if<CbufNode>(&*node)) {
567 const Node offset = cbuf->GetOffset(); 567 const Node offset = cbuf->GetOffset();
568 if (const auto immediate = std::get_if<ImmediateNode>(offset)) { 568 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) {
569 // Direct access 569 // Direct access
570 const u32 offset_imm = immediate->GetValue(); 570 const u32 offset_imm = immediate->GetValue();
571 ASSERT_MSG(offset_imm % 4 == 0, "Unaligned cbuf direct access"); 571 ASSERT_MSG(offset_imm % 4 == 0, "Unaligned cbuf direct access");
@@ -601,22 +601,22 @@ private:
601 UNREACHABLE_MSG("Unmanaged offset node type"); 601 UNREACHABLE_MSG("Unmanaged offset node type");
602 } 602 }
603 603
604 if (const auto gmem = std::get_if<GmemNode>(node)) { 604 if (const auto gmem = std::get_if<GmemNode>(&*node)) {
605 const std::string real = Visit(gmem->GetRealAddress()); 605 const std::string real = Visit(gmem->GetRealAddress());
606 const std::string base = Visit(gmem->GetBaseAddress()); 606 const std::string base = Visit(gmem->GetBaseAddress());
607 const std::string final_offset = fmt::format("(ftou({}) - ftou({})) / 4", real, base); 607 const std::string final_offset = fmt::format("(ftou({}) - ftou({})) / 4", real, base);
608 return fmt::format("{}[{}]", GetGlobalMemory(gmem->GetDescriptor()), final_offset); 608 return fmt::format("{}[{}]", GetGlobalMemory(gmem->GetDescriptor()), final_offset);
609 } 609 }
610 610
611 if (const auto lmem = std::get_if<LmemNode>(node)) { 611 if (const auto lmem = std::get_if<LmemNode>(&*node)) {
612 return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); 612 return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
613 } 613 }
614 614
615 if (const auto internal_flag = std::get_if<InternalFlagNode>(node)) { 615 if (const auto internal_flag = std::get_if<InternalFlagNode>(&*node)) {
616 return GetInternalFlag(internal_flag->GetFlag()); 616 return GetInternalFlag(internal_flag->GetFlag());
617 } 617 }
618 618
619 if (const auto conditional = std::get_if<ConditionalNode>(node)) { 619 if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
620 // It's invalid to call conditional on nested nodes, use an operation instead 620 // It's invalid to call conditional on nested nodes, use an operation instead
621 code.AddLine("if ({}) {{", Visit(conditional->GetCondition())); 621 code.AddLine("if ({}) {{", Visit(conditional->GetCondition()));
622 ++code.scope; 622 ++code.scope;
@@ -628,7 +628,7 @@ private:
628 return {}; 628 return {};
629 } 629 }
630 630
631 if (const auto comment = std::get_if<CommentNode>(node)) { 631 if (const auto comment = std::get_if<CommentNode>(&*node)) {
632 return "// " + comment->GetText(); 632 return "// " + comment->GetText();
633 } 633 }
634 634
@@ -636,7 +636,7 @@ private:
636 return {}; 636 return {};
637 } 637 }
638 638
639 std::string ReadAttribute(Attribute::Index attribute, u32 element, Node buffer = {}) { 639 std::string ReadAttribute(Attribute::Index attribute, u32 element, const Node& buffer = {}) {
640 const auto GeometryPass = [&](std::string_view name) { 640 const auto GeometryPass = [&](std::string_view name) {
641 if (stage == ShaderStage::Geometry && buffer) { 641 if (stage == ShaderStage::Geometry && buffer) {
642 // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games 642 // TODO(Rodrigo): Guard geometry inputs against out of bound reads. Some games
@@ -872,7 +872,7 @@ private:
872 std::string expr = ", "; 872 std::string expr = ", ";
873 switch (type) { 873 switch (type) {
874 case Type::Int: 874 case Type::Int:
875 if (const auto immediate = std::get_if<ImmediateNode>(operand)) { 875 if (const auto immediate = std::get_if<ImmediateNode>(&*operand)) {
876 // Inline the string as an immediate integer in GLSL (some extra arguments are 876 // Inline the string as an immediate integer in GLSL (some extra arguments are
877 // required to be constant) 877 // required to be constant)
878 expr += std::to_string(static_cast<s32>(immediate->GetValue())); 878 expr += std::to_string(static_cast<s32>(immediate->GetValue()));
@@ -904,7 +904,7 @@ private:
904 904
905 for (std::size_t index = 0; index < aoffi.size(); ++index) { 905 for (std::size_t index = 0; index < aoffi.size(); ++index) {
906 const auto operand{aoffi.at(index)}; 906 const auto operand{aoffi.at(index)};
907 if (const auto immediate = std::get_if<ImmediateNode>(operand)) { 907 if (const auto immediate = std::get_if<ImmediateNode>(&*operand)) {
908 // Inline the string as an immediate integer in GLSL (AOFFI arguments are required 908 // Inline the string as an immediate integer in GLSL (AOFFI arguments are required
909 // to be constant by the standard). 909 // to be constant by the standard).
910 expr += std::to_string(static_cast<s32>(immediate->GetValue())); 910 expr += std::to_string(static_cast<s32>(immediate->GetValue()));
@@ -925,17 +925,17 @@ private:
925 } 925 }
926 926
927 std::string Assign(Operation operation) { 927 std::string Assign(Operation operation) {
928 const Node dest = operation[0]; 928 const Node& dest = operation[0];
929 const Node src = operation[1]; 929 const Node& src = operation[1];
930 930
931 std::string target; 931 std::string target;
932 if (const auto gpr = std::get_if<GprNode>(dest)) { 932 if (const auto gpr = std::get_if<GprNode>(&*dest)) {
933 if (gpr->GetIndex() == Register::ZeroIndex) { 933 if (gpr->GetIndex() == Register::ZeroIndex) {
934 // Writing to Register::ZeroIndex is a no op 934 // Writing to Register::ZeroIndex is a no op
935 return {}; 935 return {};
936 } 936 }
937 target = GetRegister(gpr->GetIndex()); 937 target = GetRegister(gpr->GetIndex());
938 } else if (const auto abuf = std::get_if<AbufNode>(dest)) { 938 } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) {
939 UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer()); 939 UNIMPLEMENTED_IF(abuf->IsPhysicalBuffer());
940 940
941 target = [&]() -> std::string { 941 target = [&]() -> std::string {
@@ -957,9 +957,9 @@ private:
957 return "0"; 957 return "0";
958 } 958 }
959 }(); 959 }();
960 } else if (const auto lmem = std::get_if<LmemNode>(dest)) { 960 } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) {
961 target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); 961 target = fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
962 } else if (const auto gmem = std::get_if<GmemNode>(dest)) { 962 } else if (const auto gmem = std::get_if<GmemNode>(&*dest)) {
963 const std::string real = Visit(gmem->GetRealAddress()); 963 const std::string real = Visit(gmem->GetRealAddress());
964 const std::string base = Visit(gmem->GetBaseAddress()); 964 const std::string base = Visit(gmem->GetBaseAddress());
965 const std::string final_offset = fmt::format("(ftou({}) - ftou({})) / 4", real, base); 965 const std::string final_offset = fmt::format("(ftou({}) - ftou({})) / 4", real, base);
@@ -1236,12 +1236,12 @@ private:
1236 } 1236 }
1237 1237
1238 std::string LogicalAssign(Operation operation) { 1238 std::string LogicalAssign(Operation operation) {
1239 const Node dest = operation[0]; 1239 const Node& dest = operation[0];
1240 const Node src = operation[1]; 1240 const Node& src = operation[1];
1241 1241
1242 std::string target; 1242 std::string target;
1243 1243
1244 if (const auto pred = std::get_if<PredicateNode>(dest)) { 1244 if (const auto pred = std::get_if<PredicateNode>(&*dest)) {
1245 ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment"); 1245 ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment");
1246 1246
1247 const auto index = pred->GetIndex(); 1247 const auto index = pred->GetIndex();
@@ -1252,7 +1252,7 @@ private:
1252 return {}; 1252 return {};
1253 } 1253 }
1254 target = GetPredicate(index); 1254 target = GetPredicate(index);
1255 } else if (const auto flag = std::get_if<InternalFlagNode>(dest)) { 1255 } else if (const auto flag = std::get_if<InternalFlagNode>(&*dest)) {
1256 target = GetInternalFlag(flag->GetFlag()); 1256 target = GetInternalFlag(flag->GetFlag());
1257 } 1257 }
1258 1258
@@ -1429,7 +1429,7 @@ private:
1429 } 1429 }
1430 1430
1431 std::string Branch(Operation operation) { 1431 std::string Branch(Operation operation) {
1432 const auto target = std::get_if<ImmediateNode>(operation[0]); 1432 const auto target = std::get_if<ImmediateNode>(&*operation[0]);
1433 UNIMPLEMENTED_IF(!target); 1433 UNIMPLEMENTED_IF(!target);
1434 1434
1435 code.AddLine("jmp_to = 0x{:x}u;", target->GetValue()); 1435 code.AddLine("jmp_to = 0x{:x}u;", target->GetValue());
@@ -1438,7 +1438,7 @@ private:
1438 } 1438 }
1439 1439
1440 std::string PushFlowStack(Operation operation) { 1440 std::string PushFlowStack(Operation operation) {
1441 const auto target = std::get_if<ImmediateNode>(operation[0]); 1441 const auto target = std::get_if<ImmediateNode>(&*operation[0]);
1442 UNIMPLEMENTED_IF(!target); 1442 UNIMPLEMENTED_IF(!target);
1443 1443
1444 code.AddLine("flow_stack[flow_stack_top++] = 0x{:x}u;", target->GetValue()); 1444 code.AddLine("flow_stack[flow_stack_top++] = 0x{:x}u;", target->GetValue());
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
index a85fcae5a..547883425 100644
--- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
+++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp
@@ -481,13 +481,13 @@ private:
481 } 481 }
482 482
483 void VisitBasicBlock(const NodeBlock& bb) { 483 void VisitBasicBlock(const NodeBlock& bb) {
484 for (const Node node : bb) { 484 for (const auto& node : bb) {
485 static_cast<void>(Visit(node)); 485 static_cast<void>(Visit(node));
486 } 486 }
487 } 487 }
488 488
489 Id Visit(Node node) { 489 Id Visit(const Node& node) {
490 if (const auto operation = std::get_if<OperationNode>(node)) { 490 if (const auto operation = std::get_if<OperationNode>(&*node)) {
491 const auto operation_index = static_cast<std::size_t>(operation->GetCode()); 491 const auto operation_index = static_cast<std::size_t>(operation->GetCode());
492 const auto decompiler = operation_decompilers[operation_index]; 492 const auto decompiler = operation_decompilers[operation_index];
493 if (decompiler == nullptr) { 493 if (decompiler == nullptr) {
@@ -495,17 +495,17 @@ private:
495 } 495 }
496 return (this->*decompiler)(*operation); 496 return (this->*decompiler)(*operation);
497 497
498 } else if (const auto gpr = std::get_if<GprNode>(node)) { 498 } else if (const auto gpr = std::get_if<GprNode>(&*node)) {
499 const u32 index = gpr->GetIndex(); 499 const u32 index = gpr->GetIndex();
500 if (index == Register::ZeroIndex) { 500 if (index == Register::ZeroIndex) {
501 return Constant(t_float, 0.0f); 501 return Constant(t_float, 0.0f);
502 } 502 }
503 return Emit(OpLoad(t_float, registers.at(index))); 503 return Emit(OpLoad(t_float, registers.at(index)));
504 504
505 } else if (const auto immediate = std::get_if<ImmediateNode>(node)) { 505 } else if (const auto immediate = std::get_if<ImmediateNode>(&*node)) {
506 return BitcastTo<Type::Float>(Constant(t_uint, immediate->GetValue())); 506 return BitcastTo<Type::Float>(Constant(t_uint, immediate->GetValue()));
507 507
508 } else if (const auto predicate = std::get_if<PredicateNode>(node)) { 508 } else if (const auto predicate = std::get_if<PredicateNode>(&*node)) {
509 const auto value = [&]() -> Id { 509 const auto value = [&]() -> Id {
510 switch (const auto index = predicate->GetIndex(); index) { 510 switch (const auto index = predicate->GetIndex(); index) {
511 case Tegra::Shader::Pred::UnusedIndex: 511 case Tegra::Shader::Pred::UnusedIndex:
@@ -521,7 +521,7 @@ private:
521 } 521 }
522 return value; 522 return value;
523 523
524 } else if (const auto abuf = std::get_if<AbufNode>(node)) { 524 } else if (const auto abuf = std::get_if<AbufNode>(&*node)) {
525 const auto attribute = abuf->GetIndex(); 525 const auto attribute = abuf->GetIndex();
526 const auto element = abuf->GetElement(); 526 const auto element = abuf->GetElement();
527 527
@@ -571,8 +571,8 @@ private:
571 } 571 }
572 UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute)); 572 UNIMPLEMENTED_MSG("Unhandled input attribute: {}", static_cast<u32>(attribute));
573 573
574 } else if (const auto cbuf = std::get_if<CbufNode>(node)) { 574 } else if (const auto cbuf = std::get_if<CbufNode>(&*node)) {
575 const Node offset = cbuf->GetOffset(); 575 const Node& offset = cbuf->GetOffset();
576 const Id buffer_id = constant_buffers.at(cbuf->GetIndex()); 576 const Id buffer_id = constant_buffers.at(cbuf->GetIndex());
577 577
578 Id pointer{}; 578 Id pointer{};
@@ -584,7 +584,7 @@ private:
584 } else { 584 } else {
585 Id buffer_index{}; 585 Id buffer_index{};
586 Id buffer_element{}; 586 Id buffer_element{};
587 if (const auto immediate = std::get_if<ImmediateNode>(offset)) { 587 if (const auto immediate = std::get_if<ImmediateNode>(&*offset)) {
588 // Direct access 588 // Direct access
589 const u32 offset_imm = immediate->GetValue(); 589 const u32 offset_imm = immediate->GetValue();
590 ASSERT(offset_imm % 4 == 0); 590 ASSERT(offset_imm % 4 == 0);
@@ -606,7 +606,7 @@ private:
606 } 606 }
607 return Emit(OpLoad(t_float, pointer)); 607 return Emit(OpLoad(t_float, pointer));
608 608
609 } else if (const auto gmem = std::get_if<GmemNode>(node)) { 609 } else if (const auto gmem = std::get_if<GmemNode>(&*node)) {
610 const Id gmem_buffer = global_buffers.at(gmem->GetDescriptor()); 610 const Id gmem_buffer = global_buffers.at(gmem->GetDescriptor());
611 const Id real = BitcastTo<Type::Uint>(Visit(gmem->GetRealAddress())); 611 const Id real = BitcastTo<Type::Uint>(Visit(gmem->GetRealAddress()));
612 const Id base = BitcastTo<Type::Uint>(Visit(gmem->GetBaseAddress())); 612 const Id base = BitcastTo<Type::Uint>(Visit(gmem->GetBaseAddress()));
@@ -616,7 +616,7 @@ private:
616 return Emit(OpLoad(t_float, Emit(OpAccessChain(t_gmem_float, gmem_buffer, 616 return Emit(OpLoad(t_float, Emit(OpAccessChain(t_gmem_float, gmem_buffer,
617 Constant(t_uint, 0u), offset)))); 617 Constant(t_uint, 0u), offset))));
618 618
619 } else if (const auto conditional = std::get_if<ConditionalNode>(node)) { 619 } else if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
620 // It's invalid to call conditional on nested nodes, use an operation instead 620 // It's invalid to call conditional on nested nodes, use an operation instead
621 const Id true_label = OpLabel(); 621 const Id true_label = OpLabel();
622 const Id skip_label = OpLabel(); 622 const Id skip_label = OpLabel();
@@ -631,7 +631,7 @@ private:
631 Emit(skip_label); 631 Emit(skip_label);
632 return {}; 632 return {};
633 633
634 } else if (const auto comment = std::get_if<CommentNode>(node)) { 634 } else if (const auto comment = std::get_if<CommentNode>(&*node)) {
635 Name(Emit(OpUndef(t_void)), comment->GetText()); 635 Name(Emit(OpUndef(t_void)), comment->GetText());
636 return {}; 636 return {};
637 } 637 }
@@ -699,18 +699,18 @@ private:
699 } 699 }
700 700
701 Id Assign(Operation operation) { 701 Id Assign(Operation operation) {
702 const Node dest = operation[0]; 702 const Node& dest = operation[0];
703 const Node src = operation[1]; 703 const Node& src = operation[1];
704 704
705 Id target{}; 705 Id target{};
706 if (const auto gpr = std::get_if<GprNode>(dest)) { 706 if (const auto gpr = std::get_if<GprNode>(&*dest)) {
707 if (gpr->GetIndex() == Register::ZeroIndex) { 707 if (gpr->GetIndex() == Register::ZeroIndex) {
708 // Writing to Register::ZeroIndex is a no op 708 // Writing to Register::ZeroIndex is a no op
709 return {}; 709 return {};
710 } 710 }
711 target = registers.at(gpr->GetIndex()); 711 target = registers.at(gpr->GetIndex());
712 712
713 } else if (const auto abuf = std::get_if<AbufNode>(dest)) { 713 } else if (const auto abuf = std::get_if<AbufNode>(&*dest)) {
714 target = [&]() -> Id { 714 target = [&]() -> Id {
715 switch (const auto attribute = abuf->GetIndex(); attribute) { 715 switch (const auto attribute = abuf->GetIndex(); attribute) {
716 case Attribute::Index::Position: 716 case Attribute::Index::Position:
@@ -735,7 +735,7 @@ private:
735 } 735 }
736 }(); 736 }();
737 737
738 } else if (const auto lmem = std::get_if<LmemNode>(dest)) { 738 } else if (const auto lmem = std::get_if<LmemNode>(&*dest)) {
739 Id address = BitcastTo<Type::Uint>(Visit(lmem->GetAddress())); 739 Id address = BitcastTo<Type::Uint>(Visit(lmem->GetAddress()));
740 address = Emit(OpUDiv(t_uint, address, Constant(t_uint, 4))); 740 address = Emit(OpUDiv(t_uint, address, Constant(t_uint, 4)));
741 target = Emit(OpAccessChain(t_prv_float, local_memory, {address})); 741 target = Emit(OpAccessChain(t_prv_float, local_memory, {address}));
@@ -781,11 +781,11 @@ private:
781 } 781 }
782 782
783 Id LogicalAssign(Operation operation) { 783 Id LogicalAssign(Operation operation) {
784 const Node dest = operation[0]; 784 const Node& dest = operation[0];
785 const Node src = operation[1]; 785 const Node& src = operation[1];
786 786
787 Id target{}; 787 Id target{};
788 if (const auto pred = std::get_if<PredicateNode>(dest)) { 788 if (const auto pred = std::get_if<PredicateNode>(&*dest)) {
789 ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment"); 789 ASSERT_MSG(!pred->IsNegated(), "Negating logical assignment");
790 790
791 const auto index = pred->GetIndex(); 791 const auto index = pred->GetIndex();
@@ -797,7 +797,7 @@ private:
797 } 797 }
798 target = predicates.at(index); 798 target = predicates.at(index);
799 799
800 } else if (const auto flag = std::get_if<InternalFlagNode>(dest)) { 800 } else if (const auto flag = std::get_if<InternalFlagNode>(&*dest)) {
801 target = internal_flags.at(static_cast<u32>(flag->GetFlag())); 801 target = internal_flags.at(static_cast<u32>(flag->GetFlag()));
802 } 802 }
803 803
@@ -883,7 +883,7 @@ private:
883 } else { 883 } else {
884 u32 component_value = 0; 884 u32 component_value = 0;
885 if (meta->component) { 885 if (meta->component) {
886 const auto component = std::get_if<ImmediateNode>(meta->component); 886 const auto component = std::get_if<ImmediateNode>(&*meta->component);
887 ASSERT_MSG(component, "Component is not an immediate value"); 887 ASSERT_MSG(component, "Component is not an immediate value");
888 component_value = component->GetValue(); 888 component_value = component->GetValue();
889 } 889 }
@@ -940,7 +940,7 @@ private:
940 } 940 }
941 941
942 Id Branch(Operation operation) { 942 Id Branch(Operation operation) {
943 const auto target = std::get_if<ImmediateNode>(operation[0]); 943 const auto target = std::get_if<ImmediateNode>(&*operation[0]);
944 UNIMPLEMENTED_IF(!target); 944 UNIMPLEMENTED_IF(!target);
945 945
946 Emit(OpStore(jmp_to, Constant(t_uint, target->GetValue()))); 946 Emit(OpStore(jmp_to, Constant(t_uint, target->GetValue())));
@@ -949,7 +949,7 @@ private:
949 } 949 }
950 950
951 Id PushFlowStack(Operation operation) { 951 Id PushFlowStack(Operation operation) {
952 const auto target = std::get_if<ImmediateNode>(operation[0]); 952 const auto target = std::get_if<ImmediateNode>(&*operation[0]);
953 ASSERT(target); 953 ASSERT(target);
954 954
955 const Id current = Emit(OpLoad(t_uint, flow_stack_top)); 955 const Id current = Emit(OpLoad(t_uint, flow_stack_top));
diff --git a/src/video_core/shader/decode.cpp b/src/video_core/shader/decode.cpp
index 2da595c0d..a0554c97e 100644
--- a/src/video_core/shader/decode.cpp
+++ b/src/video_core/shader/decode.cpp
@@ -11,6 +11,7 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "video_core/engines/shader_bytecode.h" 12#include "video_core/engines/shader_bytecode.h"
13#include "video_core/engines/shader_header.h" 13#include "video_core/engines/shader_header.h"
14#include "video_core/shader/node_helper.h"
14#include "video_core/shader/shader_ir.h" 15#include "video_core/shader/shader_ir.h"
15 16
16namespace VideoCommon::Shader { 17namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/arithmetic.cpp b/src/video_core/shader/decode/arithmetic.cpp
index b4859bc1e..87d8fecaa 100644
--- a/src/video_core/shader/decode/arithmetic.cpp
+++ b/src/video_core/shader/decode/arithmetic.cpp
@@ -6,6 +6,7 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "video_core/engines/shader_bytecode.h" 8#include "video_core/engines/shader_bytecode.h"
9#include "video_core/shader/node_helper.h"
9#include "video_core/shader/shader_ir.h" 10#include "video_core/shader/shader_ir.h"
10 11
11namespace VideoCommon::Shader { 12namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/arithmetic_half.cpp b/src/video_core/shader/decode/arithmetic_half.cpp
index 3a29c4a46..b06cbe441 100644
--- a/src/video_core/shader/decode/arithmetic_half.cpp
+++ b/src/video_core/shader/decode/arithmetic_half.cpp
@@ -6,6 +6,7 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "video_core/engines/shader_bytecode.h" 8#include "video_core/engines/shader_bytecode.h"
9#include "video_core/shader/node_helper.h"
9#include "video_core/shader/shader_ir.h" 10#include "video_core/shader/shader_ir.h"
10 11
11namespace VideoCommon::Shader { 12namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/arithmetic_half_immediate.cpp b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
index 5341e460f..7bcf38f23 100644
--- a/src/video_core/shader/decode/arithmetic_half_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_half_immediate.cpp
@@ -6,6 +6,7 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "video_core/engines/shader_bytecode.h" 8#include "video_core/engines/shader_bytecode.h"
9#include "video_core/shader/node_helper.h"
9#include "video_core/shader/shader_ir.h" 10#include "video_core/shader/shader_ir.h"
10 11
11namespace VideoCommon::Shader { 12namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/arithmetic_immediate.cpp b/src/video_core/shader/decode/arithmetic_immediate.cpp
index 3095f2fd4..f1875967c 100644
--- a/src/video_core/shader/decode/arithmetic_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_immediate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp
index 9fd4b273e..c8c1a7f40 100644
--- a/src/video_core/shader/decode/arithmetic_integer.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp
index 679ac0d4e..73880db0e 100644
--- a/src/video_core/shader/decode/arithmetic_integer_immediate.cpp
+++ b/src/video_core/shader/decode/arithmetic_integer_immediate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/bfe.cpp b/src/video_core/shader/decode/bfe.cpp
index 1ae192c6a..e02bcd097 100644
--- a/src/video_core/shader/decode/bfe.cpp
+++ b/src/video_core/shader/decode/bfe.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/bfi.cpp b/src/video_core/shader/decode/bfi.cpp
index 0b12a0d08..8be1119df 100644
--- a/src/video_core/shader/decode/bfi.cpp
+++ b/src/video_core/shader/decode/bfi.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/conversion.cpp b/src/video_core/shader/decode/conversion.cpp
index b5ec9a6f5..4221f0c58 100644
--- a/src/video_core/shader/decode/conversion.cpp
+++ b/src/video_core/shader/decode/conversion.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/ffma.cpp b/src/video_core/shader/decode/ffma.cpp
index a1d04c6e5..29be25ca3 100644
--- a/src/video_core/shader/decode/ffma.cpp
+++ b/src/video_core/shader/decode/ffma.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/float_set.cpp b/src/video_core/shader/decode/float_set.cpp
index cc522f1de..f5013e44a 100644
--- a/src/video_core/shader/decode/float_set.cpp
+++ b/src/video_core/shader/decode/float_set.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/float_set_predicate.cpp b/src/video_core/shader/decode/float_set_predicate.cpp
index 9d2322a1d..2323052b0 100644
--- a/src/video_core/shader/decode/float_set_predicate.cpp
+++ b/src/video_core/shader/decode/float_set_predicate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp
index 755f2ec44..48ca7a4af 100644
--- a/src/video_core/shader/decode/half_set.cpp
+++ b/src/video_core/shader/decode/half_set.cpp
@@ -8,6 +8,7 @@
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "video_core/engines/shader_bytecode.h" 10#include "video_core/engines/shader_bytecode.h"
11#include "video_core/shader/node_helper.h"
11#include "video_core/shader/shader_ir.h" 12#include "video_core/shader/shader_ir.h"
12 13
13namespace VideoCommon::Shader { 14namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/half_set_predicate.cpp b/src/video_core/shader/decode/half_set_predicate.cpp
index fba44d714..d59d15bd8 100644
--- a/src/video_core/shader/decode/half_set_predicate.cpp
+++ b/src/video_core/shader/decode/half_set_predicate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/hfma2.cpp b/src/video_core/shader/decode/hfma2.cpp
index a425f9eb7..c3bcf1ae9 100644
--- a/src/video_core/shader/decode/hfma2.cpp
+++ b/src/video_core/shader/decode/hfma2.cpp
@@ -7,6 +7,7 @@
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "video_core/engines/shader_bytecode.h" 9#include "video_core/engines/shader_bytecode.h"
10#include "video_core/shader/node_helper.h"
10#include "video_core/shader/shader_ir.h" 11#include "video_core/shader/shader_ir.h"
11 12
12namespace VideoCommon::Shader { 13namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/integer_set.cpp b/src/video_core/shader/decode/integer_set.cpp
index a4cdaf74d..46e3d5905 100644
--- a/src/video_core/shader/decode/integer_set.cpp
+++ b/src/video_core/shader/decode/integer_set.cpp
@@ -4,6 +4,7 @@
4 4
5#include "common/common_types.h" 5#include "common/common_types.h"
6#include "video_core/engines/shader_bytecode.h" 6#include "video_core/engines/shader_bytecode.h"
7#include "video_core/shader/node_helper.h"
7#include "video_core/shader/shader_ir.h" 8#include "video_core/shader/shader_ir.h"
8 9
9namespace VideoCommon::Shader { 10namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/integer_set_predicate.cpp b/src/video_core/shader/decode/integer_set_predicate.cpp
index a6a1fb632..dd20775d7 100644
--- a/src/video_core/shader/decode/integer_set_predicate.cpp
+++ b/src/video_core/shader/decode/integer_set_predicate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index e6a010a7d..80fc0ccfc 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -10,6 +10,7 @@
10#include "common/common_types.h" 10#include "common/common_types.h"
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "video_core/engines/shader_bytecode.h" 12#include "video_core/engines/shader_bytecode.h"
13#include "video_core/shader/node_helper.h"
13#include "video_core/shader/shader_ir.h" 14#include "video_core/shader/shader_ir.h"
14 15
15namespace VideoCommon::Shader { 16namespace VideoCommon::Shader {
@@ -169,7 +170,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
169 const Node it_offset = Immediate(i * 4); 170 const Node it_offset = Immediate(i * 4);
170 const Node real_address = 171 const Node real_address =
171 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); 172 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
172 const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor)); 173 const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
173 174
174 SetTemporal(bb, i, gmem); 175 SetTemporal(bb, i, gmem);
175 } 176 }
@@ -262,7 +263,7 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) {
262 const Node it_offset = Immediate(i * 4); 263 const Node it_offset = Immediate(i * 4);
263 const Node real_address = 264 const Node real_address =
264 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset); 265 Operation(OperationCode::UAdd, NO_PRECISE, real_address_base, it_offset);
265 const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor)); 266 const Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor);
266 267
267 bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1))); 268 bb.push_back(Operation(OperationCode::Assign, gmem, GetTemporal(i + 1)));
268 } 269 }
@@ -298,9 +299,9 @@ std::tuple<Node, Node, GlobalMemoryBase> ShaderIR::TrackAndGetGlobalMemory(NodeB
298 299
299 const Node base_address{ 300 const Node base_address{
300 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))}; 301 TrackCbuf(addr_register, global_code, static_cast<s64>(global_code.size()))};
301 const auto cbuf = std::get_if<CbufNode>(base_address); 302 const auto cbuf = std::get_if<CbufNode>(&*base_address);
302 ASSERT(cbuf != nullptr); 303 ASSERT(cbuf != nullptr);
303 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset()); 304 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset());
304 ASSERT(cbuf_offset_imm != nullptr); 305 ASSERT(cbuf_offset_imm != nullptr);
305 const auto cbuf_offset = cbuf_offset_imm->GetValue(); 306 const auto cbuf_offset = cbuf_offset_imm->GetValue();
306 307
diff --git a/src/video_core/shader/decode/other.cpp b/src/video_core/shader/decode/other.cpp
index a6c123573..6fc07f213 100644
--- a/src/video_core/shader/decode/other.cpp
+++ b/src/video_core/shader/decode/other.cpp
@@ -6,6 +6,7 @@
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "common/logging/log.h" 7#include "common/logging/log.h"
8#include "video_core/engines/shader_bytecode.h" 8#include "video_core/engines/shader_bytecode.h"
9#include "video_core/shader/node_helper.h"
9#include "video_core/shader/shader_ir.h" 10#include "video_core/shader/shader_ir.h"
10 11
11namespace VideoCommon::Shader { 12namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/predicate_set_predicate.cpp b/src/video_core/shader/decode/predicate_set_predicate.cpp
index 71844c42b..9290d22eb 100644
--- a/src/video_core/shader/decode/predicate_set_predicate.cpp
+++ b/src/video_core/shader/decode/predicate_set_predicate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/predicate_set_register.cpp b/src/video_core/shader/decode/predicate_set_register.cpp
index 387491bd3..febbfeb50 100644
--- a/src/video_core/shader/decode/predicate_set_register.cpp
+++ b/src/video_core/shader/decode/predicate_set_register.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/register_set_predicate.cpp b/src/video_core/shader/decode/register_set_predicate.cpp
index f8659e48e..e6c9d287e 100644
--- a/src/video_core/shader/decode/register_set_predicate.cpp
+++ b/src/video_core/shader/decode/register_set_predicate.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/shift.cpp b/src/video_core/shader/decode/shift.cpp
index 44ae87ece..2ac16eeb0 100644
--- a/src/video_core/shader/decode/shift.cpp
+++ b/src/video_core/shader/decode/shift.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/texture.cpp b/src/video_core/shader/decode/texture.cpp
index 5b033126d..4a356dbd4 100644
--- a/src/video_core/shader/decode/texture.cpp
+++ b/src/video_core/shader/decode/texture.cpp
@@ -11,6 +11,7 @@
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "common/logging/log.h" 12#include "common/logging/log.h"
13#include "video_core/engines/shader_bytecode.h" 13#include "video_core/engines/shader_bytecode.h"
14#include "video_core/shader/node_helper.h"
14#include "video_core/shader/shader_ir.h" 15#include "video_core/shader/shader_ir.h"
15 16
16namespace VideoCommon::Shader { 17namespace VideoCommon::Shader {
@@ -291,8 +292,8 @@ const Sampler& ShaderIR::GetBindlessSampler(const Tegra::Shader::Register& reg,
291 const Node sampler_register = GetRegister(reg); 292 const Node sampler_register = GetRegister(reg);
292 const Node base_sampler = 293 const Node base_sampler =
293 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size())); 294 TrackCbuf(sampler_register, global_code, static_cast<s64>(global_code.size()));
294 const auto cbuf = std::get_if<CbufNode>(base_sampler); 295 const auto cbuf = std::get_if<CbufNode>(&*base_sampler);
295 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset()); 296 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(&*cbuf->GetOffset());
296 ASSERT(cbuf_offset_imm != nullptr); 297 ASSERT(cbuf_offset_imm != nullptr);
297 const auto cbuf_offset = cbuf_offset_imm->GetValue(); 298 const auto cbuf_offset = cbuf_offset_imm->GetValue();
298 const auto cbuf_index = cbuf->GetIndex(); 299 const auto cbuf_index = cbuf->GetIndex();
@@ -388,8 +389,8 @@ Node4 ShaderIR::GetTextureCode(Instruction instr, TextureType texture_type,
388 Node array, Node depth_compare, u32 bias_offset, 389 Node array, Node depth_compare, u32 bias_offset,
389 std::vector<Node> aoffi, 390 std::vector<Node> aoffi,
390 std::optional<Tegra::Shader::Register> bindless_reg) { 391 std::optional<Tegra::Shader::Register> bindless_reg) {
391 const bool is_array = array; 392 const auto is_array = static_cast<bool>(array);
392 const bool is_shadow = depth_compare; 393 const auto is_shadow = static_cast<bool>(depth_compare);
393 const bool is_bindless = bindless_reg.has_value(); 394 const bool is_bindless = bindless_reg.has_value();
394 395
395 UNIMPLEMENTED_IF_MSG((texture_type == TextureType::Texture3D && (is_array || is_shadow)) || 396 UNIMPLEMENTED_IF_MSG((texture_type == TextureType::Texture3D && (is_array || is_shadow)) ||
diff --git a/src/video_core/shader/decode/video.cpp b/src/video_core/shader/decode/video.cpp
index cb9ab72b1..97fc6f9b1 100644
--- a/src/video_core/shader/decode/video.cpp
+++ b/src/video_core/shader/decode/video.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/decode/xmad.cpp b/src/video_core/shader/decode/xmad.cpp
index 04a776398..93dee77d1 100644
--- a/src/video_core/shader/decode/xmad.cpp
+++ b/src/video_core/shader/decode/xmad.cpp
@@ -5,6 +5,7 @@
5#include "common/assert.h" 5#include "common/assert.h"
6#include "common/common_types.h" 6#include "common/common_types.h"
7#include "video_core/engines/shader_bytecode.h" 7#include "video_core/engines/shader_bytecode.h"
8#include "video_core/shader/node_helper.h"
8#include "video_core/shader/shader_ir.h" 9#include "video_core/shader/shader_ir.h"
9 10
10namespace VideoCommon::Shader { 11namespace VideoCommon::Shader {
diff --git a/src/video_core/shader/node_helper.cpp b/src/video_core/shader/node_helper.cpp
new file mode 100644
index 000000000..6fccbbba3
--- /dev/null
+++ b/src/video_core/shader/node_helper.cpp
@@ -0,0 +1,99 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <cstring>
6#include <vector>
7
8#include "common/common_types.h"
9#include "video_core/shader/node_helper.h"
10#include "video_core/shader/shader_ir.h"
11
12namespace VideoCommon::Shader {
13
14Node Conditional(Node condition, std::vector<Node> code) {
15 return MakeNode<ConditionalNode>(condition, std::move(code));
16}
17
18Node Comment(std::string text) {
19 return MakeNode<CommentNode>(std::move(text));
20}
21
22Node Immediate(u32 value) {
23 return MakeNode<ImmediateNode>(value);
24}
25
26Node Immediate(s32 value) {
27 return Immediate(static_cast<u32>(value));
28}
29
30Node Immediate(f32 value) {
31 u32 integral;
32 std::memcpy(&integral, &value, sizeof(u32));
33 return Immediate(integral);
34}
35
36OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed) {
37 if (is_signed) {
38 return operation_code;
39 }
40 switch (operation_code) {
41 case OperationCode::FCastInteger:
42 return OperationCode::FCastUInteger;
43 case OperationCode::IAdd:
44 return OperationCode::UAdd;
45 case OperationCode::IMul:
46 return OperationCode::UMul;
47 case OperationCode::IDiv:
48 return OperationCode::UDiv;
49 case OperationCode::IMin:
50 return OperationCode::UMin;
51 case OperationCode::IMax:
52 return OperationCode::UMax;
53 case OperationCode::ICastFloat:
54 return OperationCode::UCastFloat;
55 case OperationCode::ICastUnsigned:
56 return OperationCode::UCastSigned;
57 case OperationCode::ILogicalShiftLeft:
58 return OperationCode::ULogicalShiftLeft;
59 case OperationCode::ILogicalShiftRight:
60 return OperationCode::ULogicalShiftRight;
61 case OperationCode::IArithmeticShiftRight:
62 return OperationCode::UArithmeticShiftRight;
63 case OperationCode::IBitwiseAnd:
64 return OperationCode::UBitwiseAnd;
65 case OperationCode::IBitwiseOr:
66 return OperationCode::UBitwiseOr;
67 case OperationCode::IBitwiseXor:
68 return OperationCode::UBitwiseXor;
69 case OperationCode::IBitwiseNot:
70 return OperationCode::UBitwiseNot;
71 case OperationCode::IBitfieldInsert:
72 return OperationCode::UBitfieldInsert;
73 case OperationCode::IBitCount:
74 return OperationCode::UBitCount;
75 case OperationCode::LogicalILessThan:
76 return OperationCode::LogicalULessThan;
77 case OperationCode::LogicalIEqual:
78 return OperationCode::LogicalUEqual;
79 case OperationCode::LogicalILessEqual:
80 return OperationCode::LogicalULessEqual;
81 case OperationCode::LogicalIGreaterThan:
82 return OperationCode::LogicalUGreaterThan;
83 case OperationCode::LogicalINotEqual:
84 return OperationCode::LogicalUNotEqual;
85 case OperationCode::LogicalIGreaterEqual:
86 return OperationCode::LogicalUGreaterEqual;
87 case OperationCode::INegate:
88 UNREACHABLE_MSG("Can't negate an unsigned integer");
89 return {};
90 case OperationCode::IAbsolute:
91 UNREACHABLE_MSG("Can't apply absolute to an unsigned integer");
92 return {};
93 default:
94 UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast<u32>(operation_code));
95 return {};
96 }
97}
98
99} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/node_helper.h b/src/video_core/shader/node_helper.h
new file mode 100644
index 000000000..70547a03d
--- /dev/null
+++ b/src/video_core/shader/node_helper.h
@@ -0,0 +1,60 @@
1// Copyright 2019 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <string>
9#include <tuple>
10#include <type_traits>
11#include <utility>
12#include <vector>
13
14#include "common/common_types.h"
15#include "video_core/shader/shader_ir.h"
16
17namespace VideoCommon::Shader {
18
19/// Creates a conditional node
20Node Conditional(Node condition, std::vector<Node> code);
21
22/// Creates a commentary node
23Node Comment(std::string text);
24
25/// Creates an u32 immediate
26Node Immediate(u32 value);
27
28/// Creates a s32 immediate
29Node Immediate(s32 value);
30
31/// Creates a f32 immediate
32Node Immediate(f32 value);
33
34/// Converts an signed operation code to an unsigned operation code
35OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed);
36
37template <typename T, typename... Args>
38Node MakeNode(Args&&... args) {
39 static_assert(std::is_convertible_v<T, NodeData>);
40 return std::make_shared<NodeData>(T(std::forward<Args>(args)...));
41}
42
43template <typename... Args>
44Node Operation(OperationCode code, Args&&... args) {
45 if constexpr (sizeof...(args) == 0) {
46 return MakeNode<OperationNode>(code);
47 } else if constexpr (std::is_convertible_v<std::tuple_element_t<0, std::tuple<Args...>>,
48 Meta>) {
49 return MakeNode<OperationNode>(code, std::forward<Args>(args)...);
50 } else {
51 return MakeNode<OperationNode>(code, Meta{}, std::forward<Args>(args)...);
52 }
53}
54
55template <typename... Args>
56Node SignedOperation(OperationCode code, bool is_signed, Args&&... args) {
57 return Operation(SignedToUnsignedCode(code, is_signed), std::forward<Args>(args)...);
58}
59
60} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/shader_ir.cpp b/src/video_core/shader/shader_ir.cpp
index 8a6ee5cf5..11b545cca 100644
--- a/src/video_core/shader/shader_ir.cpp
+++ b/src/video_core/shader/shader_ir.cpp
@@ -9,6 +9,7 @@
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "video_core/engines/shader_bytecode.h" 11#include "video_core/engines/shader_bytecode.h"
12#include "video_core/shader/node_helper.h"
12#include "video_core/shader/shader_ir.h" 13#include "video_core/shader/shader_ir.h"
13 14
14namespace VideoCommon::Shader { 15namespace VideoCommon::Shader {
@@ -28,30 +29,11 @@ ShaderIR::ShaderIR(const ProgramCode& program_code, u32 main_offset)
28 29
29ShaderIR::~ShaderIR() = default; 30ShaderIR::~ShaderIR() = default;
30 31
31Node ShaderIR::StoreNode(NodeData&& node_data) {
32 auto store = std::make_unique<NodeData>(node_data);
33 const Node node = store.get();
34 stored_nodes.push_back(std::move(store));
35 return node;
36}
37
38Node ShaderIR::Conditional(Node condition, std::vector<Node>&& code) {
39 return StoreNode(ConditionalNode(condition, std::move(code)));
40}
41
42Node ShaderIR::Comment(std::string text) {
43 return StoreNode(CommentNode(std::move(text)));
44}
45
46Node ShaderIR::Immediate(u32 value) {
47 return StoreNode(ImmediateNode(value));
48}
49
50Node ShaderIR::GetRegister(Register reg) { 32Node ShaderIR::GetRegister(Register reg) {
51 if (reg != Register::ZeroIndex) { 33 if (reg != Register::ZeroIndex) {
52 used_registers.insert(static_cast<u32>(reg)); 34 used_registers.insert(static_cast<u32>(reg));
53 } 35 }
54 return StoreNode(GprNode(reg)); 36 return MakeNode<GprNode>(reg);
55} 37}
56 38
57Node ShaderIR::GetImmediate19(Instruction instr) { 39Node ShaderIR::GetImmediate19(Instruction instr) {
@@ -69,7 +51,7 @@ Node ShaderIR::GetConstBuffer(u64 index_, u64 offset_) {
69 const auto [entry, is_new] = used_cbufs.try_emplace(index); 51 const auto [entry, is_new] = used_cbufs.try_emplace(index);
70 entry->second.MarkAsUsed(offset); 52 entry->second.MarkAsUsed(offset);
71 53
72 return StoreNode(CbufNode(index, Immediate(offset))); 54 return MakeNode<CbufNode>(index, Immediate(offset));
73} 55}
74 56
75Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) { 57Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) {
@@ -80,7 +62,7 @@ Node ShaderIR::GetConstBufferIndirect(u64 index_, u64 offset_, Node node) {
80 entry->second.MarkAsUsedIndirect(); 62 entry->second.MarkAsUsedIndirect();
81 63
82 const Node final_offset = Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset)); 64 const Node final_offset = Operation(OperationCode::UAdd, NO_PRECISE, node, Immediate(offset));
83 return StoreNode(CbufNode(index, final_offset)); 65 return MakeNode<CbufNode>(index, final_offset);
84} 66}
85 67
86Node ShaderIR::GetPredicate(u64 pred_, bool negated) { 68Node ShaderIR::GetPredicate(u64 pred_, bool negated) {
@@ -89,7 +71,7 @@ Node ShaderIR::GetPredicate(u64 pred_, bool negated) {
89 used_predicates.insert(pred); 71 used_predicates.insert(pred);
90 } 72 }
91 73
92 return StoreNode(PredicateNode(pred, negated)); 74 return MakeNode<PredicateNode>(pred, negated);
93} 75}
94 76
95Node ShaderIR::GetPredicate(bool immediate) { 77Node ShaderIR::GetPredicate(bool immediate) {
@@ -98,12 +80,12 @@ Node ShaderIR::GetPredicate(bool immediate) {
98 80
99Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) { 81Node ShaderIR::GetInputAttribute(Attribute::Index index, u64 element, Node buffer) {
100 used_input_attributes.emplace(index); 82 used_input_attributes.emplace(index);
101 return StoreNode(AbufNode(index, static_cast<u32>(element), buffer)); 83 return MakeNode<AbufNode>(index, static_cast<u32>(element), buffer);
102} 84}
103 85
104Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) { 86Node ShaderIR::GetPhysicalInputAttribute(Tegra::Shader::Register physical_address, Node buffer) {
105 uses_physical_attributes = true; 87 uses_physical_attributes = true;
106 return StoreNode(AbufNode(GetRegister(physical_address), buffer)); 88 return MakeNode<AbufNode>(GetRegister(physical_address), buffer);
107} 89}
108 90
109Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) { 91Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buffer) {
@@ -115,11 +97,11 @@ Node ShaderIR::GetOutputAttribute(Attribute::Index index, u64 element, Node buff
115 } 97 }
116 used_output_attributes.insert(index); 98 used_output_attributes.insert(index);
117 99
118 return StoreNode(AbufNode(index, static_cast<u32>(element), buffer)); 100 return MakeNode<AbufNode>(index, static_cast<u32>(element), buffer);
119} 101}
120 102
121Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) { 103Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) {
122 const Node node = StoreNode(InternalFlagNode(flag)); 104 const Node node = MakeNode<InternalFlagNode>(flag);
123 if (negated) { 105 if (negated) {
124 return Operation(OperationCode::LogicalNegate, node); 106 return Operation(OperationCode::LogicalNegate, node);
125 } 107 }
@@ -127,7 +109,7 @@ Node ShaderIR::GetInternalFlag(InternalFlag flag, bool negated) {
127} 109}
128 110
129Node ShaderIR::GetLocalMemory(Node address) { 111Node ShaderIR::GetLocalMemory(Node address) {
130 return StoreNode(LmemNode(address)); 112 return MakeNode<LmemNode>(address);
131} 113}
132 114
133Node ShaderIR::GetTemporal(u32 id) { 115Node ShaderIR::GetTemporal(u32 id) {
@@ -393,68 +375,4 @@ Node ShaderIR::BitfieldExtract(Node value, u32 offset, u32 bits) {
393 Immediate(bits)); 375 Immediate(bits));
394} 376}
395 377
396/*static*/ OperationCode ShaderIR::SignedToUnsignedCode(OperationCode operation_code,
397 bool is_signed) {
398 if (is_signed) {
399 return operation_code;
400 }
401 switch (operation_code) {
402 case OperationCode::FCastInteger:
403 return OperationCode::FCastUInteger;
404 case OperationCode::IAdd:
405 return OperationCode::UAdd;
406 case OperationCode::IMul:
407 return OperationCode::UMul;
408 case OperationCode::IDiv:
409 return OperationCode::UDiv;
410 case OperationCode::IMin:
411 return OperationCode::UMin;
412 case OperationCode::IMax:
413 return OperationCode::UMax;
414 case OperationCode::ICastFloat:
415 return OperationCode::UCastFloat;
416 case OperationCode::ICastUnsigned:
417 return OperationCode::UCastSigned;
418 case OperationCode::ILogicalShiftLeft:
419 return OperationCode::ULogicalShiftLeft;
420 case OperationCode::ILogicalShiftRight:
421 return OperationCode::ULogicalShiftRight;
422 case OperationCode::IArithmeticShiftRight:
423 return OperationCode::UArithmeticShiftRight;
424 case OperationCode::IBitwiseAnd:
425 return OperationCode::UBitwiseAnd;
426 case OperationCode::IBitwiseOr:
427 return OperationCode::UBitwiseOr;
428 case OperationCode::IBitwiseXor:
429 return OperationCode::UBitwiseXor;
430 case OperationCode::IBitwiseNot:
431 return OperationCode::UBitwiseNot;
432 case OperationCode::IBitfieldInsert:
433 return OperationCode::UBitfieldInsert;
434 case OperationCode::IBitCount:
435 return OperationCode::UBitCount;
436 case OperationCode::LogicalILessThan:
437 return OperationCode::LogicalULessThan;
438 case OperationCode::LogicalIEqual:
439 return OperationCode::LogicalUEqual;
440 case OperationCode::LogicalILessEqual:
441 return OperationCode::LogicalULessEqual;
442 case OperationCode::LogicalIGreaterThan:
443 return OperationCode::LogicalUGreaterThan;
444 case OperationCode::LogicalINotEqual:
445 return OperationCode::LogicalUNotEqual;
446 case OperationCode::LogicalIGreaterEqual:
447 return OperationCode::LogicalUGreaterEqual;
448 case OperationCode::INegate:
449 UNREACHABLE_MSG("Can't negate an unsigned integer");
450 return {};
451 case OperationCode::IAbsolute:
452 UNREACHABLE_MSG("Can't apply absolute to an unsigned integer");
453 return {};
454 default:
455 UNREACHABLE_MSG("Unknown signed operation with code={}", static_cast<u32>(operation_code));
456 return {};
457 }
458}
459
460} // namespace VideoCommon::Shader 378} // namespace VideoCommon::Shader
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index ff7472e30..1b2745c23 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -38,7 +38,7 @@ using ProgramCode = std::vector<u64>;
38using NodeData = 38using NodeData =
39 std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode, 39 std::variant<OperationNode, ConditionalNode, GprNode, ImmediateNode, InternalFlagNode,
40 PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>; 40 PredicateNode, AbufNode, CbufNode, LmemNode, GmemNode, CommentNode>;
41using Node = const NodeData*; 41using Node = std::shared_ptr<NodeData>;
42using Node4 = std::array<Node, 4>; 42using Node4 = std::array<Node, 4>;
43using NodeBlock = std::vector<Node>; 43using NodeBlock = std::vector<Node>;
44 44
@@ -342,23 +342,20 @@ using Meta = std::variant<MetaArithmetic, MetaTexture, Tegra::Shader::HalfType>;
342/// Holds any kind of operation that can be done in the IR 342/// Holds any kind of operation that can be done in the IR
343class OperationNode final { 343class OperationNode final {
344public: 344public:
345 explicit OperationNode(OperationCode code) : code{code} {} 345 explicit OperationNode(OperationCode code) : OperationNode(code, Meta{}) {}
346 346
347 explicit OperationNode(OperationCode code, Meta&& meta) : code{code}, meta{std::move(meta)} {} 347 explicit OperationNode(OperationCode code, Meta meta)
348 : OperationNode(code, meta, std::vector<Node>{}) {}
348 349
349 template <typename... T> 350 explicit OperationNode(OperationCode code, std::vector<Node> operands)
350 explicit OperationNode(OperationCode code, const T*... operands) 351 : OperationNode(code, Meta{}, std::move(operands)) {}
351 : OperationNode(code, {}, operands...) {}
352 352
353 template <typename... T> 353 explicit OperationNode(OperationCode code, Meta meta, std::vector<Node> operands)
354 explicit OperationNode(OperationCode code, Meta&& meta, const T*... operands_) 354 : code{code}, meta{std::move(meta)}, operands{std::move(operands)} {}
355 : code{code}, meta{std::move(meta)}, operands{operands_...} {}
356 355
357 explicit OperationNode(OperationCode code, Meta&& meta, std::vector<Node>&& operands) 356 template <typename... Args>
358 : code{code}, meta{meta}, operands{std::move(operands)} {} 357 explicit OperationNode(OperationCode code, Meta meta, Args&&... operands)
359 358 : code{code}, meta{std::move(meta)}, operands{operands...} {}
360 explicit OperationNode(OperationCode code, std::vector<Node>&& operands)
361 : code{code}, operands{std::move(operands)} {}
362 359
363 OperationCode GetCode() const { 360 OperationCode GetCode() const {
364 return code; 361 return code;
@@ -372,13 +369,13 @@ public:
372 return operands.size(); 369 return operands.size();
373 } 370 }
374 371
375 Node operator[](std::size_t operand_index) const { 372 const Node& operator[](std::size_t operand_index) const {
376 return operands.at(operand_index); 373 return operands.at(operand_index);
377 } 374 }
378 375
379private: 376private:
380 const OperationCode code; 377 OperationCode code{};
381 const Meta meta; 378 Meta meta{};
382 std::vector<Node> operands; 379 std::vector<Node> operands;
383}; 380};
384 381
@@ -463,13 +460,12 @@ private:
463class AbufNode final { 460class AbufNode final {
464public: 461public:
465 // Initialize for standard attributes (index is explicit). 462 // Initialize for standard attributes (index is explicit).
466 explicit constexpr AbufNode(Tegra::Shader::Attribute::Index index, u32 element, 463 explicit AbufNode(Tegra::Shader::Attribute::Index index, u32 element, Node buffer = {})
467 Node buffer = {}) 464 : buffer{std::move(buffer)}, index{index}, element{element} {}
468 : buffer{buffer}, index{index}, element{element} {}
469 465
470 // Initialize for physical attributes (index is a variable value). 466 // Initialize for physical attributes (index is a variable value).
471 explicit constexpr AbufNode(Node physical_address, Node buffer = {}) 467 explicit AbufNode(Node physical_address, Node buffer = {})
472 : physical_address{physical_address}, buffer{buffer} {} 468 : physical_address{physical_address}, buffer{std::move(buffer)} {}
473 469
474 Tegra::Shader::Attribute::Index GetIndex() const { 470 Tegra::Shader::Attribute::Index GetIndex() const {
475 return index; 471 return index;
@@ -484,16 +480,16 @@ public:
484 } 480 }
485 481
486 bool IsPhysicalBuffer() const { 482 bool IsPhysicalBuffer() const {
487 return physical_address != nullptr; 483 return static_cast<bool>(physical_address);
488 } 484 }
489 485
490 Node GetPhysicalAddress() const { 486 const Node& GetPhysicalAddress() const {
491 return physical_address; 487 return physical_address;
492 } 488 }
493 489
494private: 490private:
495 Node physical_address{}; 491 Node physical_address;
496 Node buffer{}; 492 Node buffer;
497 Tegra::Shader::Attribute::Index index{}; 493 Tegra::Shader::Attribute::Index index{};
498 u32 element{}; 494 u32 element{};
499}; 495};
@@ -501,7 +497,7 @@ private:
501/// Constant buffer node, usually mapped to uniform buffers in GLSL 497/// Constant buffer node, usually mapped to uniform buffers in GLSL
502class CbufNode final { 498class CbufNode final {
503public: 499public:
504 explicit constexpr CbufNode(u32 index, Node offset) : index{index}, offset{offset} {} 500 explicit CbufNode(u32 index, Node offset) : index{index}, offset{offset} {}
505 501
506 u32 GetIndex() const { 502 u32 GetIndex() const {
507 return index; 503 return index;
@@ -519,7 +515,7 @@ private:
519/// Local memory node 515/// Local memory node
520class LmemNode final { 516class LmemNode final {
521public: 517public:
522 explicit constexpr LmemNode(Node address) : address{address} {} 518 explicit LmemNode(Node address) : address{address} {}
523 519
524 Node GetAddress() const { 520 Node GetAddress() const {
525 return address; 521 return address;
@@ -532,8 +528,7 @@ private:
532/// Global memory node 528/// Global memory node
533class GmemNode final { 529class GmemNode final {
534public: 530public:
535 explicit constexpr GmemNode(Node real_address, Node base_address, 531 explicit GmemNode(Node real_address, Node base_address, const GlobalMemoryBase& descriptor)
536 const GlobalMemoryBase& descriptor)
537 : real_address{real_address}, base_address{base_address}, descriptor{descriptor} {} 532 : real_address{real_address}, base_address{base_address}, descriptor{descriptor} {}
538 533
539 Node GetRealAddress() const { 534 Node GetRealAddress() const {
@@ -663,26 +658,6 @@ private:
663 u32 DecodeXmad(NodeBlock& bb, u32 pc); 658 u32 DecodeXmad(NodeBlock& bb, u32 pc);
664 u32 DecodeOther(NodeBlock& bb, u32 pc); 659 u32 DecodeOther(NodeBlock& bb, u32 pc);
665 660
666 /// Internalizes node's data and returns a managed pointer to a clone of that node
667 Node StoreNode(NodeData&& node_data);
668
669 /// Creates a conditional node
670 Node Conditional(Node condition, std::vector<Node>&& code);
671 /// Creates a commentary
672 Node Comment(std::string text);
673 /// Creates an u32 immediate
674 Node Immediate(u32 value);
675 /// Creates a s32 immediate
676 Node Immediate(s32 value) {
677 return Immediate(static_cast<u32>(value));
678 }
679 /// Creates a f32 immediate
680 Node Immediate(f32 value) {
681 u32 integral;
682 std::memcpy(&integral, &value, sizeof(u32));
683 return Immediate(integral);
684 }
685
686 /// Generates a node for a passed register. 661 /// Generates a node for a passed register.
687 Node GetRegister(Tegra::Shader::Register reg); 662 Node GetRegister(Tegra::Shader::Register reg);
688 /// Generates a node representing a 19-bit immediate value 663 /// Generates a node representing a 19-bit immediate value
@@ -827,37 +802,6 @@ private:
827 std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory( 802 std::tuple<Node, Node, GlobalMemoryBase> TrackAndGetGlobalMemory(
828 NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write); 803 NodeBlock& bb, Tegra::Shader::Instruction instr, bool is_write);
829 804
830 template <typename... T>
831 Node Operation(OperationCode code, const T*... operands) {
832 return StoreNode(OperationNode(code, operands...));
833 }
834
835 template <typename... T>
836 Node Operation(OperationCode code, Meta&& meta, const T*... operands) {
837 return StoreNode(OperationNode(code, std::move(meta), operands...));
838 }
839
840 Node Operation(OperationCode code, std::vector<Node>&& operands) {
841 return StoreNode(OperationNode(code, std::move(operands)));
842 }
843
844 Node Operation(OperationCode code, Meta&& meta, std::vector<Node>&& operands) {
845 return StoreNode(OperationNode(code, std::move(meta), std::move(operands)));
846 }
847
848 template <typename... T>
849 Node SignedOperation(OperationCode code, bool is_signed, const T*... operands) {
850 return StoreNode(OperationNode(SignedToUnsignedCode(code, is_signed), operands...));
851 }
852
853 template <typename... T>
854 Node SignedOperation(OperationCode code, bool is_signed, Meta&& meta, const T*... operands) {
855 return StoreNode(
856 OperationNode(SignedToUnsignedCode(code, is_signed), std::move(meta), operands...));
857 }
858
859 static OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed);
860
861 const ProgramCode& program_code; 805 const ProgramCode& program_code;
862 const u32 main_offset; 806 const u32 main_offset;
863 807
@@ -868,8 +812,6 @@ private:
868 std::map<u32, NodeBlock> basic_blocks; 812 std::map<u32, NodeBlock> basic_blocks;
869 NodeBlock global_code; 813 NodeBlock global_code;
870 814
871 std::vector<std::unique_ptr<NodeData>> stored_nodes;
872
873 std::set<u32> used_registers; 815 std::set<u32> used_registers;
874 std::set<Tegra::Shader::Pred> used_predicates; 816 std::set<Tegra::Shader::Pred> used_predicates;
875 std::set<Tegra::Shader::Attribute::Index> used_input_attributes; 817 std::set<Tegra::Shader::Attribute::Index> used_input_attributes;
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
index 19ede1eb9..fc957d980 100644
--- a/src/video_core/shader/track.cpp
+++ b/src/video_core/shader/track.cpp
@@ -16,12 +16,12 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
16 OperationCode operation_code) { 16 OperationCode operation_code) {
17 for (; cursor >= 0; --cursor) { 17 for (; cursor >= 0; --cursor) {
18 const Node node = code.at(cursor); 18 const Node node = code.at(cursor);
19 if (const auto operation = std::get_if<OperationNode>(node)) { 19 if (const auto operation = std::get_if<OperationNode>(&*node)) {
20 if (operation->GetCode() == operation_code) { 20 if (operation->GetCode() == operation_code) {
21 return {node, cursor}; 21 return {node, cursor};
22 } 22 }
23 } 23 }
24 if (const auto conditional = std::get_if<ConditionalNode>(node)) { 24 if (const auto conditional = std::get_if<ConditionalNode>(&*node)) {
25 const auto& conditional_code = conditional->GetCode(); 25 const auto& conditional_code = conditional->GetCode();
26 const auto [found, internal_cursor] = FindOperation( 26 const auto [found, internal_cursor] = FindOperation(
27 conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code); 27 conditional_code, static_cast<s64>(conditional_code.size() - 1), operation_code);
@@ -35,11 +35,11 @@ std::pair<Node, s64> FindOperation(const NodeBlock& code, s64 cursor,
35} // namespace 35} // namespace
36 36
37Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const { 37Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const {
38 if (const auto cbuf = std::get_if<CbufNode>(tracked)) { 38 if (const auto cbuf = std::get_if<CbufNode>(&*tracked)) {
39 // Cbuf found, but it has to be immediate 39 // Cbuf found, but it has to be immediate
40 return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr; 40 return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
41 } 41 }
42 if (const auto gpr = std::get_if<GprNode>(tracked)) { 42 if (const auto gpr = std::get_if<GprNode>(&*tracked)) {
43 if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) { 43 if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) {
44 return nullptr; 44 return nullptr;
45 } 45 }
@@ -51,7 +51,7 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const
51 } 51 }
52 return TrackCbuf(source, code, new_cursor); 52 return TrackCbuf(source, code, new_cursor);
53 } 53 }
54 if (const auto operation = std::get_if<OperationNode>(tracked)) { 54 if (const auto operation = std::get_if<OperationNode>(&*tracked)) {
55 for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) { 55 for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) {
56 if (const auto found = TrackCbuf((*operation)[i], code, cursor)) { 56 if (const auto found = TrackCbuf((*operation)[i], code, cursor)) {
57 // Cbuf found in operand 57 // Cbuf found in operand
@@ -60,7 +60,7 @@ Node ShaderIR::TrackCbuf(Node tracked, const NodeBlock& code, s64 cursor) const
60 } 60 }
61 return nullptr; 61 return nullptr;
62 } 62 }
63 if (const auto conditional = std::get_if<ConditionalNode>(tracked)) { 63 if (const auto conditional = std::get_if<ConditionalNode>(&*tracked)) {
64 const auto& conditional_code = conditional->GetCode(); 64 const auto& conditional_code = conditional->GetCode();
65 return TrackCbuf(tracked, conditional_code, static_cast<s64>(conditional_code.size())); 65 return TrackCbuf(tracked, conditional_code, static_cast<s64>(conditional_code.size()));
66 } 66 }
@@ -75,7 +75,7 @@ std::optional<u32> ShaderIR::TrackImmediate(Node tracked, const NodeBlock& code,
75 if (!found) { 75 if (!found) {
76 return {}; 76 return {};
77 } 77 }
78 if (const auto immediate = std::get_if<ImmediateNode>(found)) { 78 if (const auto immediate = std::get_if<ImmediateNode>(&*found)) {
79 return immediate->GetValue(); 79 return immediate->GetValue();
80 } 80 }
81 return {}; 81 return {};
@@ -88,11 +88,11 @@ std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const NodeB
88 if (!found_node) { 88 if (!found_node) {
89 return {}; 89 return {};
90 } 90 }
91 const auto operation = std::get_if<OperationNode>(found_node); 91 const auto operation = std::get_if<OperationNode>(&*found_node);
92 ASSERT(operation); 92 ASSERT(operation);
93 93
94 const auto& target = (*operation)[0]; 94 const auto& target = (*operation)[0];
95 if (const auto gpr_target = std::get_if<GprNode>(target)) { 95 if (const auto gpr_target = std::get_if<GprNode>(&*target)) {
96 if (gpr_target->GetIndex() == tracked->GetIndex()) { 96 if (gpr_target->GetIndex() == tracked->GetIndex()) {
97 return {(*operation)[1], new_cursor}; 97 return {(*operation)[1], new_cursor};
98 } 98 }