diff options
Diffstat (limited to 'src/shader_recompiler/ir_opt/constant_propagation_pass.cpp')
| -rw-r--r-- | src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | 76 |
1 files changed, 73 insertions, 3 deletions
diff --git a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp index 826f9a54a..4d81e9336 100644 --- a/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp +++ b/src/shader_recompiler/ir_opt/constant_propagation_pass.cpp | |||
| @@ -7,6 +7,7 @@ | |||
| 7 | #include <type_traits> | 7 | #include <type_traits> |
| 8 | 8 | ||
| 9 | #include "common/bit_cast.h" | 9 | #include "common/bit_cast.h" |
| 10 | #include "shader_recompiler/environment.h" | ||
| 10 | #include "shader_recompiler/exception.h" | 11 | #include "shader_recompiler/exception.h" |
| 11 | #include "shader_recompiler/frontend/ir/ir_emitter.h" | 12 | #include "shader_recompiler/frontend/ir/ir_emitter.h" |
| 12 | #include "shader_recompiler/frontend/ir/value.h" | 13 | #include "shader_recompiler/frontend/ir/value.h" |
| @@ -515,6 +516,9 @@ void FoldBitCast(IR::Inst& inst, IR::Opcode reverse) { | |||
| 515 | case IR::Attribute::PrimitiveId: | 516 | case IR::Attribute::PrimitiveId: |
| 516 | case IR::Attribute::InstanceId: | 517 | case IR::Attribute::InstanceId: |
| 517 | case IR::Attribute::VertexId: | 518 | case IR::Attribute::VertexId: |
| 519 | case IR::Attribute::BaseVertex: | ||
| 520 | case IR::Attribute::BaseInstance: | ||
| 521 | case IR::Attribute::DrawID: | ||
| 518 | break; | 522 | break; |
| 519 | default: | 523 | default: |
| 520 | return; | 524 | return; |
| @@ -644,7 +648,63 @@ void FoldFSwizzleAdd(IR::Block& block, IR::Inst& inst) { | |||
| 644 | } | 648 | } |
| 645 | } | 649 | } |
| 646 | 650 | ||
| 647 | void ConstantPropagation(IR::Block& block, IR::Inst& inst) { | 651 | void FoldConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst) { |
| 652 | const IR::Value bank{inst.Arg(0)}; | ||
| 653 | const IR::Value offset{inst.Arg(1)}; | ||
| 654 | if (!bank.IsImmediate() || !offset.IsImmediate()) { | ||
| 655 | return; | ||
| 656 | } | ||
| 657 | const auto bank_value = bank.U32(); | ||
| 658 | const auto offset_value = offset.U32(); | ||
| 659 | auto replacement = env.GetReplaceConstBuffer(bank_value, offset_value); | ||
| 660 | if (!replacement) { | ||
| 661 | return; | ||
| 662 | } | ||
| 663 | const auto new_attribute = [replacement]() { | ||
| 664 | switch (*replacement) { | ||
| 665 | case ReplaceConstant::BaseInstance: | ||
| 666 | return IR::Attribute::BaseInstance; | ||
| 667 | case ReplaceConstant::BaseVertex: | ||
| 668 | return IR::Attribute::BaseVertex; | ||
| 669 | case ReplaceConstant::DrawID: | ||
| 670 | return IR::Attribute::DrawID; | ||
| 671 | default: | ||
| 672 | throw NotImplementedException("Not implemented replacement variable {}", *replacement); | ||
| 673 | } | ||
| 674 | }(); | ||
| 675 | IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 676 | if (inst.GetOpcode() == IR::Opcode::GetCbufU32) { | ||
| 677 | inst.ReplaceUsesWith(ir.GetAttributeU32(new_attribute)); | ||
| 678 | } else { | ||
| 679 | inst.ReplaceUsesWith(ir.GetAttribute(new_attribute)); | ||
| 680 | } | ||
| 681 | } | ||
| 682 | |||
| 683 | void FoldDriverConstBuffer(Environment& env, IR::Block& block, IR::Inst& inst, u32 which_bank, | ||
| 684 | u32 offset_start = 0, u32 offset_end = std::numeric_limits<u16>::max()) { | ||
| 685 | const IR::Value bank{inst.Arg(0)}; | ||
| 686 | const IR::Value offset{inst.Arg(1)}; | ||
| 687 | if (!bank.IsImmediate() || !offset.IsImmediate()) { | ||
| 688 | return; | ||
| 689 | } | ||
| 690 | const auto bank_value = bank.U32(); | ||
| 691 | if (bank_value != which_bank) { | ||
| 692 | return; | ||
| 693 | } | ||
| 694 | const auto offset_value = offset.U32(); | ||
| 695 | if (offset_value < offset_start || offset_value >= offset_end) { | ||
| 696 | return; | ||
| 697 | } | ||
| 698 | IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 699 | if (inst.GetOpcode() == IR::Opcode::GetCbufU32) { | ||
| 700 | inst.ReplaceUsesWith(IR::Value{env.ReadCbufValue(bank_value, offset_value)}); | ||
| 701 | } else { | ||
| 702 | inst.ReplaceUsesWith( | ||
| 703 | IR::Value{Common::BitCast<f32>(env.ReadCbufValue(bank_value, offset_value))}); | ||
| 704 | } | ||
| 705 | } | ||
| 706 | |||
| 707 | void ConstantPropagation(Environment& env, IR::Block& block, IR::Inst& inst) { | ||
| 648 | switch (inst.GetOpcode()) { | 708 | switch (inst.GetOpcode()) { |
| 649 | case IR::Opcode::GetRegister: | 709 | case IR::Opcode::GetRegister: |
| 650 | return FoldGetRegister(inst); | 710 | return FoldGetRegister(inst); |
| @@ -789,18 +849,28 @@ void ConstantPropagation(IR::Block& block, IR::Inst& inst) { | |||
| 789 | IR::Opcode::CompositeInsertF16x4); | 849 | IR::Opcode::CompositeInsertF16x4); |
| 790 | case IR::Opcode::FSwizzleAdd: | 850 | case IR::Opcode::FSwizzleAdd: |
| 791 | return FoldFSwizzleAdd(block, inst); | 851 | return FoldFSwizzleAdd(block, inst); |
| 852 | case IR::Opcode::GetCbufF32: | ||
| 853 | case IR::Opcode::GetCbufU32: | ||
| 854 | if (env.HasHLEMacroState()) { | ||
| 855 | FoldConstBuffer(env, block, inst); | ||
| 856 | } | ||
| 857 | if (env.IsPropietaryDriver()) { | ||
| 858 | FoldDriverConstBuffer(env, block, inst, 1); | ||
| 859 | } | ||
| 860 | break; | ||
| 792 | default: | 861 | default: |
| 793 | break; | 862 | break; |
| 794 | } | 863 | } |
| 795 | } | 864 | } |
| 865 | |||
| 796 | } // Anonymous namespace | 866 | } // Anonymous namespace |
| 797 | 867 | ||
| 798 | void ConstantPropagationPass(IR::Program& program) { | 868 | void ConstantPropagationPass(Environment& env, IR::Program& program) { |
| 799 | const auto end{program.post_order_blocks.rend()}; | 869 | const auto end{program.post_order_blocks.rend()}; |
| 800 | for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { | 870 | for (auto it = program.post_order_blocks.rbegin(); it != end; ++it) { |
| 801 | IR::Block* const block{*it}; | 871 | IR::Block* const block{*it}; |
| 802 | for (IR::Inst& inst : block->Instructions()) { | 872 | for (IR::Inst& inst : block->Instructions()) { |
| 803 | ConstantPropagation(*block, inst); | 873 | ConstantPropagation(env, *block, inst); |
| 804 | } | 874 | } |
| 805 | } | 875 | } |
| 806 | } | 876 | } |