diff options
| author | 2021-07-25 22:20:56 -0300 | |
|---|---|---|
| committer | 2021-11-16 22:11:28 +0100 | |
| commit | 01379c5e3cd1181c7c7d37a672364fbcad627fb0 (patch) | |
| tree | 9dfc52e3e4793f24cdc1d0c1d071f21605cb2bac /src/shader_recompiler | |
| parent | shader: Add IsTextureScaled opcode (diff) | |
| download | yuzu-01379c5e3cd1181c7c7d37a672364fbcad627fb0.tar.gz yuzu-01379c5e3cd1181c7c7d37a672364fbcad627fb0.tar.xz yuzu-01379c5e3cd1181c7c7d37a672364fbcad627fb0.zip | |
shader/rescaling_pass: Patch more instructions
Diffstat (limited to 'src/shader_recompiler')
| -rw-r--r-- | src/shader_recompiler/ir_opt/rescaling_pass.cpp | 105 |
1 files changed, 101 insertions, 4 deletions
diff --git a/src/shader_recompiler/ir_opt/rescaling_pass.cpp b/src/shader_recompiler/ir_opt/rescaling_pass.cpp index f8d04b6e3..d5b98ae6e 100644 --- a/src/shader_recompiler/ir_opt/rescaling_pass.cpp +++ b/src/shader_recompiler/ir_opt/rescaling_pass.cpp | |||
| @@ -22,6 +22,105 @@ void PatchFragCoord(IR::Block& block, IR::Inst& inst) { | |||
| 22 | inst.ReplaceUsesWith(downscaled_frag_coord); | 22 | inst.ReplaceUsesWith(downscaled_frag_coord); |
| 23 | } | 23 | } |
| 24 | 24 | ||
| 25 | [[nodiscard]] IR::U32 Scale(IR::IREmitter& ir, const IR::U1& is_scaled, const IR::U32& value) { | ||
| 26 | IR::U32 scaled_value{value}; | ||
| 27 | bool changed{}; | ||
| 28 | if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { | ||
| 29 | scaled_value = ir.IMul(value, ir.Imm32(up_scale)); | ||
| 30 | changed = true; | ||
| 31 | } | ||
| 32 | if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { | ||
| 33 | scaled_value = ir.ShiftRightArithmetic(value, ir.Imm32(down_shift)); | ||
| 34 | changed = true; | ||
| 35 | } | ||
| 36 | if (changed) { | ||
| 37 | return IR::U32{ir.Select(is_scaled, scaled_value, value)}; | ||
| 38 | } else { | ||
| 39 | return value; | ||
| 40 | } | ||
| 41 | } | ||
| 42 | |||
| 43 | [[nodiscard]] IR::U32 DownScale(IR::IREmitter& ir, IR::U32 value) { | ||
| 44 | if (const u32 down_shift = Settings::values.resolution_info.down_shift; down_shift != 0) { | ||
| 45 | value = ir.ShiftLeftLogical(value, ir.Imm32(down_shift)); | ||
| 46 | } | ||
| 47 | if (const u32 up_scale = Settings::values.resolution_info.up_scale; up_scale != 1) { | ||
| 48 | value = ir.IDiv(value, ir.Imm32(up_scale)); | ||
| 49 | } | ||
| 50 | return value; | ||
| 51 | } | ||
| 52 | |||
| 53 | void PatchImageQueryDimensions(IR::Block& block, IR::Inst& inst) { | ||
| 54 | const auto it{IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 55 | IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 56 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | ||
| 57 | switch (info.type) { | ||
| 58 | case TextureType::Color1D: | ||
| 59 | case TextureType::ColorArray1D: { | ||
| 60 | const IR::Value new_inst{&*block.PrependNewInst(it, inst)}; | ||
| 61 | const IR::U32 width{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 0)})}; | ||
| 62 | const IR::Value replacement{ir.CompositeConstruct(width, ir.CompositeExtract(new_inst, 1), | ||
| 63 | ir.CompositeExtract(new_inst, 2), | ||
| 64 | ir.CompositeExtract(new_inst, 3))}; | ||
| 65 | inst.ReplaceUsesWith(replacement); | ||
| 66 | break; | ||
| 67 | } | ||
| 68 | case TextureType::Color2D: | ||
| 69 | case TextureType::ColorArray2D: { | ||
| 70 | const IR::Value new_inst{&*block.PrependNewInst(it, inst)}; | ||
| 71 | const IR::U32 width{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 0)})}; | ||
| 72 | const IR::U32 height{DownScale(ir, IR::U32{ir.CompositeExtract(new_inst, 1)})}; | ||
| 73 | const IR::Value replacement{ir.CompositeConstruct( | ||
| 74 | width, height, ir.CompositeExtract(new_inst, 2), ir.CompositeExtract(new_inst, 3))}; | ||
| 75 | inst.ReplaceUsesWith(replacement); | ||
| 76 | break; | ||
| 77 | } | ||
| 78 | case TextureType::Color3D: | ||
| 79 | case TextureType::ColorCube: | ||
| 80 | case TextureType::ColorArrayCube: | ||
| 81 | case TextureType::Buffer: | ||
| 82 | // Nothing to patch here | ||
| 83 | break; | ||
| 84 | } | ||
| 85 | } | ||
| 86 | |||
| 87 | void PatchImageFetch(IR::Block& block, IR::Inst& inst) { | ||
| 88 | IR::IREmitter ir{block, IR::Block::InstructionList::s_iterator_to(inst)}; | ||
| 89 | const auto info{inst.Flags<IR::TextureInstInfo>()}; | ||
| 90 | const IR::U1 is_scaled{ir.IsTextureScaled(ir.Imm32(info.descriptor_index))}; | ||
| 91 | const IR::Value coord{inst.Arg(1)}; | ||
| 92 | switch (info.type) { | ||
| 93 | case TextureType::Color1D: | ||
| 94 | inst.SetArg(1, Scale(ir, is_scaled, IR::U32{coord})); | ||
| 95 | break; | ||
| 96 | case TextureType::ColorArray1D: { | ||
| 97 | const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; | ||
| 98 | const IR::U32 y{ir.CompositeExtract(coord, 1)}; | ||
| 99 | inst.SetArg(1, ir.CompositeConstruct(x, y)); | ||
| 100 | break; | ||
| 101 | } | ||
| 102 | case TextureType::Color2D: { | ||
| 103 | const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; | ||
| 104 | const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; | ||
| 105 | inst.SetArg(1, ir.CompositeConstruct(x, y)); | ||
| 106 | break; | ||
| 107 | } | ||
| 108 | case TextureType::ColorArray2D: { | ||
| 109 | const IR::U32 x{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 0)})}; | ||
| 110 | const IR::U32 y{Scale(ir, is_scaled, IR::U32{ir.CompositeExtract(coord, 1)})}; | ||
| 111 | const IR::U32 z{ir.CompositeExtract(coord, 2)}; | ||
| 112 | inst.SetArg(1, ir.CompositeConstruct(x, y, z)); | ||
| 113 | break; | ||
| 114 | } | ||
| 115 | case TextureType::Color3D: | ||
| 116 | case TextureType::ColorCube: | ||
| 117 | case TextureType::ColorArrayCube: | ||
| 118 | case TextureType::Buffer: | ||
| 119 | // Nothing to patch here | ||
| 120 | break; | ||
| 121 | } | ||
| 122 | } | ||
| 123 | |||
| 25 | void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { | 124 | void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { |
| 26 | const bool is_fragment_shader{program.stage == Stage::Fragment}; | 125 | const bool is_fragment_shader{program.stage == Stage::Fragment}; |
| 27 | switch (inst.GetOpcode()) { | 126 | switch (inst.GetOpcode()) { |
| @@ -40,12 +139,10 @@ void Visit(const IR::Program& program, IR::Block& block, IR::Inst& inst) { | |||
| 40 | break; | 139 | break; |
| 41 | } | 140 | } |
| 42 | case IR::Opcode::ImageQueryDimensions: | 141 | case IR::Opcode::ImageQueryDimensions: |
| 142 | PatchImageQueryDimensions(block, inst); | ||
| 43 | break; | 143 | break; |
| 44 | case IR::Opcode::ImageFetch: | 144 | case IR::Opcode::ImageFetch: |
| 45 | break; | 145 | PatchImageFetch(block, inst); |
| 46 | case IR::Opcode::ImageRead: | ||
| 47 | break; | ||
| 48 | case IR::Opcode::ImageWrite: | ||
| 49 | break; | 146 | break; |
| 50 | default: | 147 | default: |
| 51 | break; | 148 | break; |