diff options
| author | 2021-03-08 18:31:53 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:23 -0400 | |
| commit | ab463712474de5f99eec137a9c6233e55fe184f0 (patch) | |
| tree | 30d79ac64dd03d5cfafd07c0c42c2baadc82de98 /src/shader_recompiler/frontend/ir/microinstruction.cpp | |
| parent | shader: Implement R2P (diff) | |
| download | yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.gz yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.tar.xz yuzu-ab463712474de5f99eec137a9c6233e55fe184f0.zip | |
shader: Initial support for textures and TEX
Diffstat (limited to 'src/shader_recompiler/frontend/ir/microinstruction.cpp')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/microinstruction.cpp | 73 |
1 files changed, 48 insertions, 25 deletions
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index d6a9be87d..88e186f21 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp | |||
| @@ -10,26 +10,27 @@ | |||
| 10 | #include "shader_recompiler/frontend/ir/type.h" | 10 | #include "shader_recompiler/frontend/ir/type.h" |
| 11 | 11 | ||
| 12 | namespace Shader::IR { | 12 | namespace Shader::IR { |
| 13 | 13 | namespace { | |
| 14 | static void CheckPseudoInstruction(IR::Inst* inst, IR::Opcode opcode) { | 14 | void CheckPseudoInstruction(IR::Inst* inst, IR::Opcode opcode) { |
| 15 | if (inst && inst->Opcode() != opcode) { | 15 | if (inst && inst->Opcode() != opcode) { |
| 16 | throw LogicError("Invalid pseudo-instruction"); | 16 | throw LogicError("Invalid pseudo-instruction"); |
| 17 | } | 17 | } |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | static void SetPseudoInstruction(IR::Inst*& dest_inst, IR::Inst* pseudo_inst) { | 20 | void SetPseudoInstruction(IR::Inst*& dest_inst, IR::Inst* pseudo_inst) { |
| 21 | if (dest_inst) { | 21 | if (dest_inst) { |
| 22 | throw LogicError("Only one of each type of pseudo-op allowed"); | 22 | throw LogicError("Only one of each type of pseudo-op allowed"); |
| 23 | } | 23 | } |
| 24 | dest_inst = pseudo_inst; | 24 | dest_inst = pseudo_inst; |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | static void RemovePseudoInstruction(IR::Inst*& inst, IR::Opcode expected_opcode) { | 27 | void RemovePseudoInstruction(IR::Inst*& inst, IR::Opcode expected_opcode) { |
| 28 | if (inst->Opcode() != expected_opcode) { | 28 | if (inst->Opcode() != expected_opcode) { |
| 29 | throw LogicError("Undoing use of invalid pseudo-op"); | 29 | throw LogicError("Undoing use of invalid pseudo-op"); |
| 30 | } | 30 | } |
| 31 | inst = nullptr; | 31 | inst = nullptr; |
| 32 | } | 32 | } |
| 33 | } // Anonymous namespace | ||
| 33 | 34 | ||
| 34 | Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} { | 35 | Inst::Inst(IR::Opcode op_, u32 flags_) noexcept : op{op_}, flags{flags_} { |
| 35 | if (op == Opcode::Phi) { | 36 | if (op == Opcode::Phi) { |
| @@ -82,6 +83,7 @@ bool Inst::IsPseudoInstruction() const noexcept { | |||
| 82 | case Opcode::GetSignFromOp: | 83 | case Opcode::GetSignFromOp: |
| 83 | case Opcode::GetCarryFromOp: | 84 | case Opcode::GetCarryFromOp: |
| 84 | case Opcode::GetOverflowFromOp: | 85 | case Opcode::GetOverflowFromOp: |
| 86 | case Opcode::GetSparseFromOp: | ||
| 85 | return true; | 87 | return true; |
| 86 | default: | 88 | default: |
| 87 | return false; | 89 | return false; |
| @@ -96,25 +98,26 @@ bool Inst::AreAllArgsImmediates() const { | |||
| 96 | [](const IR::Value& value) { return value.IsImmediate(); }); | 98 | [](const IR::Value& value) { return value.IsImmediate(); }); |
| 97 | } | 99 | } |
| 98 | 100 | ||
| 99 | bool Inst::HasAssociatedPseudoOperation() const noexcept { | ||
| 100 | return zero_inst || sign_inst || carry_inst || overflow_inst; | ||
| 101 | } | ||
| 102 | |||
| 103 | Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) { | 101 | Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) { |
| 104 | // This is faster than doing a search through the block. | 102 | if (!associated_insts) { |
| 103 | return nullptr; | ||
| 104 | } | ||
| 105 | switch (opcode) { | 105 | switch (opcode) { |
| 106 | case Opcode::GetZeroFromOp: | 106 | case Opcode::GetZeroFromOp: |
| 107 | CheckPseudoInstruction(zero_inst, Opcode::GetZeroFromOp); | 107 | CheckPseudoInstruction(associated_insts->zero_inst, Opcode::GetZeroFromOp); |
| 108 | return zero_inst; | 108 | return associated_insts->zero_inst; |
| 109 | case Opcode::GetSignFromOp: | 109 | case Opcode::GetSignFromOp: |
| 110 | CheckPseudoInstruction(sign_inst, Opcode::GetSignFromOp); | 110 | CheckPseudoInstruction(associated_insts->sign_inst, Opcode::GetSignFromOp); |
| 111 | return sign_inst; | 111 | return associated_insts->sign_inst; |
| 112 | case Opcode::GetCarryFromOp: | 112 | case Opcode::GetCarryFromOp: |
| 113 | CheckPseudoInstruction(carry_inst, Opcode::GetCarryFromOp); | 113 | CheckPseudoInstruction(associated_insts->carry_inst, Opcode::GetCarryFromOp); |
| 114 | return carry_inst; | 114 | return associated_insts->carry_inst; |
| 115 | case Opcode::GetOverflowFromOp: | 115 | case Opcode::GetOverflowFromOp: |
| 116 | CheckPseudoInstruction(overflow_inst, Opcode::GetOverflowFromOp); | 116 | CheckPseudoInstruction(associated_insts->overflow_inst, Opcode::GetOverflowFromOp); |
| 117 | return overflow_inst; | 117 | return associated_insts->overflow_inst; |
| 118 | case Opcode::GetSparseFromOp: | ||
| 119 | CheckPseudoInstruction(associated_insts->sparse_inst, Opcode::GetSparseFromOp); | ||
| 120 | return associated_insts->sparse_inst; | ||
| 118 | default: | 121 | default: |
| 119 | throw InvalidArgument("{} is not a pseudo-instruction", opcode); | 122 | throw InvalidArgument("{} is not a pseudo-instruction", opcode); |
| 120 | } | 123 | } |
| @@ -220,22 +223,37 @@ void Inst::ReplaceOpcode(IR::Opcode opcode) { | |||
| 220 | op = opcode; | 223 | op = opcode; |
| 221 | } | 224 | } |
| 222 | 225 | ||
| 226 | void AllocAssociatedInsts(std::unique_ptr<AssociatedInsts>& associated_insts) { | ||
| 227 | if (!associated_insts) { | ||
| 228 | associated_insts = std::make_unique<AssociatedInsts>(); | ||
| 229 | } | ||
| 230 | } | ||
| 231 | |||
| 223 | void Inst::Use(const Value& value) { | 232 | void Inst::Use(const Value& value) { |
| 224 | Inst* const inst{value.Inst()}; | 233 | Inst* const inst{value.Inst()}; |
| 225 | ++inst->use_count; | 234 | ++inst->use_count; |
| 226 | 235 | ||
| 236 | std::unique_ptr<AssociatedInsts>& assoc_inst{inst->associated_insts}; | ||
| 227 | switch (op) { | 237 | switch (op) { |
| 228 | case Opcode::GetZeroFromOp: | 238 | case Opcode::GetZeroFromOp: |
| 229 | SetPseudoInstruction(inst->zero_inst, this); | 239 | AllocAssociatedInsts(assoc_inst); |
| 240 | SetPseudoInstruction(assoc_inst->zero_inst, this); | ||
| 230 | break; | 241 | break; |
| 231 | case Opcode::GetSignFromOp: | 242 | case Opcode::GetSignFromOp: |
| 232 | SetPseudoInstruction(inst->sign_inst, this); | 243 | AllocAssociatedInsts(assoc_inst); |
| 244 | SetPseudoInstruction(assoc_inst->sign_inst, this); | ||
| 233 | break; | 245 | break; |
| 234 | case Opcode::GetCarryFromOp: | 246 | case Opcode::GetCarryFromOp: |
| 235 | SetPseudoInstruction(inst->carry_inst, this); | 247 | AllocAssociatedInsts(assoc_inst); |
| 248 | SetPseudoInstruction(assoc_inst->carry_inst, this); | ||
| 236 | break; | 249 | break; |
| 237 | case Opcode::GetOverflowFromOp: | 250 | case Opcode::GetOverflowFromOp: |
| 238 | SetPseudoInstruction(inst->overflow_inst, this); | 251 | AllocAssociatedInsts(assoc_inst); |
| 252 | SetPseudoInstruction(assoc_inst->overflow_inst, this); | ||
| 253 | break; | ||
| 254 | case Opcode::GetSparseFromOp: | ||
| 255 | AllocAssociatedInsts(assoc_inst); | ||
| 256 | SetPseudoInstruction(assoc_inst->sparse_inst, this); | ||
| 239 | break; | 257 | break; |
| 240 | default: | 258 | default: |
| 241 | break; | 259 | break; |
| @@ -246,18 +264,23 @@ void Inst::UndoUse(const Value& value) { | |||
| 246 | Inst* const inst{value.Inst()}; | 264 | Inst* const inst{value.Inst()}; |
| 247 | --inst->use_count; | 265 | --inst->use_count; |
| 248 | 266 | ||
| 267 | std::unique_ptr<AssociatedInsts>& assoc_inst{inst->associated_insts}; | ||
| 249 | switch (op) { | 268 | switch (op) { |
| 250 | case Opcode::GetZeroFromOp: | 269 | case Opcode::GetZeroFromOp: |
| 251 | RemovePseudoInstruction(inst->zero_inst, Opcode::GetZeroFromOp); | 270 | AllocAssociatedInsts(assoc_inst); |
| 271 | RemovePseudoInstruction(assoc_inst->zero_inst, Opcode::GetZeroFromOp); | ||
| 252 | break; | 272 | break; |
| 253 | case Opcode::GetSignFromOp: | 273 | case Opcode::GetSignFromOp: |
| 254 | RemovePseudoInstruction(inst->sign_inst, Opcode::GetSignFromOp); | 274 | AllocAssociatedInsts(assoc_inst); |
| 275 | RemovePseudoInstruction(assoc_inst->sign_inst, Opcode::GetSignFromOp); | ||
| 255 | break; | 276 | break; |
| 256 | case Opcode::GetCarryFromOp: | 277 | case Opcode::GetCarryFromOp: |
| 257 | RemovePseudoInstruction(inst->carry_inst, Opcode::GetCarryFromOp); | 278 | AllocAssociatedInsts(assoc_inst); |
| 279 | RemovePseudoInstruction(assoc_inst->carry_inst, Opcode::GetCarryFromOp); | ||
| 258 | break; | 280 | break; |
| 259 | case Opcode::GetOverflowFromOp: | 281 | case Opcode::GetOverflowFromOp: |
| 260 | RemovePseudoInstruction(inst->overflow_inst, Opcode::GetOverflowFromOp); | 282 | AllocAssociatedInsts(assoc_inst); |
| 283 | RemovePseudoInstruction(assoc_inst->overflow_inst, Opcode::GetOverflowFromOp); | ||
| 261 | break; | 284 | break; |
| 262 | default: | 285 | default: |
| 263 | break; | 286 | break; |