diff options
| author | 2021-03-25 11:31:37 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:24 -0400 | |
| commit | 32c5483beb2f79f5d55eb2906f2bfdfa1698bca3 (patch) | |
| tree | bca00dad85f6823746aee66f43dc0cbe2f337481 /src/shader_recompiler/frontend/ir | |
| parent | shader: Track first bindless argument instead of the instruction itself (diff) | |
| download | yuzu-32c5483beb2f79f5d55eb2906f2bfdfa1698bca3.tar.gz yuzu-32c5483beb2f79f5d55eb2906f2bfdfa1698bca3.tar.xz yuzu-32c5483beb2f79f5d55eb2906f2bfdfa1698bca3.zip | |
shader: Implement SHFL
Diffstat (limited to 'src/shader_recompiler/frontend/ir')
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.cpp | 23 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/ir_emitter.h | 12 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/microinstruction.cpp | 12 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/microinstruction.h | 1 | ||||
| -rw-r--r-- | src/shader_recompiler/frontend/ir/opcodes.inc | 7 |
5 files changed, 53 insertions, 2 deletions
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 6280c08f6..418b7f5ac 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -374,6 +374,10 @@ U1 IREmitter::GetSparseFromOp(const Value& op) { | |||
| 374 | return Inst<U1>(Opcode::GetSparseFromOp, op); | 374 | return Inst<U1>(Opcode::GetSparseFromOp, op); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | U1 IREmitter::GetInBoundsFromOp(const Value& op) { | ||
| 378 | return Inst<U1>(Opcode::GetInBoundsFromOp, op); | ||
| 379 | } | ||
| 380 | |||
| 377 | F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { | 381 | F16F32F64 IREmitter::FPAdd(const F16F32F64& a, const F16F32F64& b, FpControl control) { |
| 378 | if (a.Type() != b.Type()) { | 382 | if (a.Type() != b.Type()) { |
| 379 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); | 383 | throw InvalidArgument("Mismatching types {} and {}", a.Type(), b.Type()); |
| @@ -1486,4 +1490,23 @@ U32 IREmitter::SubgroupBallot(const U1& value) { | |||
| 1486 | return Inst<U32>(Opcode::SubgroupBallot, value); | 1490 | return Inst<U32>(Opcode::SubgroupBallot, value); |
| 1487 | } | 1491 | } |
| 1488 | 1492 | ||
| 1493 | U32 IREmitter::ShuffleIndex(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 1494 | const IR::U32& seg_mask) { | ||
| 1495 | return Inst<U32>(Opcode::ShuffleIndex, value, index, clamp, seg_mask); | ||
| 1496 | } | ||
| 1497 | |||
| 1498 | U32 IREmitter::ShuffleUp(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 1499 | const IR::U32& seg_mask) { | ||
| 1500 | return Inst<U32>(Opcode::ShuffleUp, value, index, clamp, seg_mask); | ||
| 1501 | } | ||
| 1502 | |||
| 1503 | U32 IREmitter::ShuffleDown(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 1504 | const IR::U32& seg_mask) { | ||
| 1505 | return Inst<U32>(Opcode::ShuffleDown, value, index, clamp, seg_mask); | ||
| 1506 | } | ||
| 1507 | |||
| 1508 | U32 IREmitter::ShuffleButterfly(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 1509 | const IR::U32& seg_mask) { | ||
| 1510 | return Inst<U32>(Opcode::ShuffleButterfly, value, index, clamp, seg_mask); | ||
| 1511 | } | ||
| 1489 | } // namespace Shader::IR | 1512 | } // namespace Shader::IR |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index ebbda78a9..64738735e 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -104,6 +104,7 @@ public: | |||
| 104 | [[nodiscard]] U1 GetCarryFromOp(const Value& op); | 104 | [[nodiscard]] U1 GetCarryFromOp(const Value& op); |
| 105 | [[nodiscard]] U1 GetOverflowFromOp(const Value& op); | 105 | [[nodiscard]] U1 GetOverflowFromOp(const Value& op); |
| 106 | [[nodiscard]] U1 GetSparseFromOp(const Value& op); | 106 | [[nodiscard]] U1 GetSparseFromOp(const Value& op); |
| 107 | [[nodiscard]] U1 GetInBoundsFromOp(const Value& op); | ||
| 107 | 108 | ||
| 108 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); | 109 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2); |
| 109 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); | 110 | [[nodiscard]] Value CompositeConstruct(const Value& e1, const Value& e2, const Value& e3); |
| @@ -147,7 +148,8 @@ public: | |||
| 147 | [[nodiscard]] F32F64 FPRecipSqrt(const F32F64& value); | 148 | [[nodiscard]] F32F64 FPRecipSqrt(const F32F64& value); |
| 148 | [[nodiscard]] F32 FPSqrt(const F32& value); | 149 | [[nodiscard]] F32 FPSqrt(const F32& value); |
| 149 | [[nodiscard]] F16F32F64 FPSaturate(const F16F32F64& value); | 150 | [[nodiscard]] F16F32F64 FPSaturate(const F16F32F64& value); |
| 150 | [[nodiscard]] F16F32F64 FPClamp(const F16F32F64& value, const F16F32F64& min_value, const F16F32F64& max_value); | 151 | [[nodiscard]] F16F32F64 FPClamp(const F16F32F64& value, const F16F32F64& min_value, |
| 152 | const F16F32F64& max_value); | ||
| 151 | [[nodiscard]] F16F32F64 FPRoundEven(const F16F32F64& value, FpControl control = {}); | 153 | [[nodiscard]] F16F32F64 FPRoundEven(const F16F32F64& value, FpControl control = {}); |
| 152 | [[nodiscard]] F16F32F64 FPFloor(const F16F32F64& value, FpControl control = {}); | 154 | [[nodiscard]] F16F32F64 FPFloor(const F16F32F64& value, FpControl control = {}); |
| 153 | [[nodiscard]] F16F32F64 FPCeil(const F16F32F64& value, FpControl control = {}); | 155 | [[nodiscard]] F16F32F64 FPCeil(const F16F32F64& value, FpControl control = {}); |
| @@ -242,6 +244,14 @@ public: | |||
| 242 | [[nodiscard]] U1 VoteAny(const U1& value); | 244 | [[nodiscard]] U1 VoteAny(const U1& value); |
| 243 | [[nodiscard]] U1 VoteEqual(const U1& value); | 245 | [[nodiscard]] U1 VoteEqual(const U1& value); |
| 244 | [[nodiscard]] U32 SubgroupBallot(const U1& value); | 246 | [[nodiscard]] U32 SubgroupBallot(const U1& value); |
| 247 | [[nodiscard]] U32 ShuffleIndex(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 248 | const IR::U32& seg_mask); | ||
| 249 | [[nodiscard]] U32 ShuffleUp(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 250 | const IR::U32& seg_mask); | ||
| 251 | [[nodiscard]] U32 ShuffleDown(const IR::U32& value, const IR::U32& index, const IR::U32& clamp, | ||
| 252 | const IR::U32& seg_mask); | ||
| 253 | [[nodiscard]] U32 ShuffleButterfly(const IR::U32& value, const IR::U32& index, | ||
| 254 | const IR::U32& clamp, const IR::U32& seg_mask); | ||
| 245 | 255 | ||
| 246 | private: | 256 | private: |
| 247 | IR::Block::iterator insertion_point; | 257 | IR::Block::iterator insertion_point; |
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.cpp b/src/shader_recompiler/frontend/ir/microinstruction.cpp index ba3968056..be8eb4d4c 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.cpp +++ b/src/shader_recompiler/frontend/ir/microinstruction.cpp | |||
| @@ -89,6 +89,7 @@ bool Inst::IsPseudoInstruction() const noexcept { | |||
| 89 | case Opcode::GetCarryFromOp: | 89 | case Opcode::GetCarryFromOp: |
| 90 | case Opcode::GetOverflowFromOp: | 90 | case Opcode::GetOverflowFromOp: |
| 91 | case Opcode::GetSparseFromOp: | 91 | case Opcode::GetSparseFromOp: |
| 92 | case Opcode::GetInBoundsFromOp: | ||
| 92 | return true; | 93 | return true; |
| 93 | default: | 94 | default: |
| 94 | return false; | 95 | return false; |
| @@ -123,6 +124,9 @@ Inst* Inst::GetAssociatedPseudoOperation(IR::Opcode opcode) { | |||
| 123 | case Opcode::GetSparseFromOp: | 124 | case Opcode::GetSparseFromOp: |
| 124 | CheckPseudoInstruction(associated_insts->sparse_inst, Opcode::GetSparseFromOp); | 125 | CheckPseudoInstruction(associated_insts->sparse_inst, Opcode::GetSparseFromOp); |
| 125 | return associated_insts->sparse_inst; | 126 | return associated_insts->sparse_inst; |
| 127 | case Opcode::GetInBoundsFromOp: | ||
| 128 | CheckPseudoInstruction(associated_insts->in_bounds_inst, Opcode::GetInBoundsFromOp); | ||
| 129 | return associated_insts->in_bounds_inst; | ||
| 126 | default: | 130 | default: |
| 127 | throw InvalidArgument("{} is not a pseudo-instruction", opcode); | 131 | throw InvalidArgument("{} is not a pseudo-instruction", opcode); |
| 128 | } | 132 | } |
| @@ -262,6 +266,10 @@ void Inst::Use(const Value& value) { | |||
| 262 | AllocAssociatedInsts(assoc_inst); | 266 | AllocAssociatedInsts(assoc_inst); |
| 263 | SetPseudoInstruction(assoc_inst->sparse_inst, this); | 267 | SetPseudoInstruction(assoc_inst->sparse_inst, this); |
| 264 | break; | 268 | break; |
| 269 | case Opcode::GetInBoundsFromOp: | ||
| 270 | AllocAssociatedInsts(assoc_inst); | ||
| 271 | SetPseudoInstruction(assoc_inst->in_bounds_inst, this); | ||
| 272 | break; | ||
| 265 | default: | 273 | default: |
| 266 | break; | 274 | break; |
| 267 | } | 275 | } |
| @@ -289,6 +297,10 @@ void Inst::UndoUse(const Value& value) { | |||
| 289 | AllocAssociatedInsts(assoc_inst); | 297 | AllocAssociatedInsts(assoc_inst); |
| 290 | RemovePseudoInstruction(assoc_inst->overflow_inst, Opcode::GetOverflowFromOp); | 298 | RemovePseudoInstruction(assoc_inst->overflow_inst, Opcode::GetOverflowFromOp); |
| 291 | break; | 299 | break; |
| 300 | case Opcode::GetInBoundsFromOp: | ||
| 301 | AllocAssociatedInsts(assoc_inst); | ||
| 302 | RemovePseudoInstruction(assoc_inst->in_bounds_inst, Opcode::GetInBoundsFromOp); | ||
| 303 | break; | ||
| 292 | default: | 304 | default: |
| 293 | break; | 305 | break; |
| 294 | } | 306 | } |
diff --git a/src/shader_recompiler/frontend/ir/microinstruction.h b/src/shader_recompiler/frontend/ir/microinstruction.h index d5336c438..770bbd550 100644 --- a/src/shader_recompiler/frontend/ir/microinstruction.h +++ b/src/shader_recompiler/frontend/ir/microinstruction.h | |||
| @@ -134,6 +134,7 @@ static_assert(sizeof(Inst) <= 128, "Inst size unintentionally increased"); | |||
| 134 | 134 | ||
| 135 | struct AssociatedInsts { | 135 | struct AssociatedInsts { |
| 136 | union { | 136 | union { |
| 137 | Inst* in_bounds_inst; | ||
| 137 | Inst* sparse_inst; | 138 | Inst* sparse_inst; |
| 138 | Inst* zero_inst{}; | 139 | Inst* zero_inst{}; |
| 139 | }; | 140 | }; |
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index dd17212a1..a2479c46a 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -159,6 +159,7 @@ OPCODE(GetSignFromOp, U1, Opaq | |||
| 159 | OPCODE(GetCarryFromOp, U1, Opaque, ) | 159 | OPCODE(GetCarryFromOp, U1, Opaque, ) |
| 160 | OPCODE(GetOverflowFromOp, U1, Opaque, ) | 160 | OPCODE(GetOverflowFromOp, U1, Opaque, ) |
| 161 | OPCODE(GetSparseFromOp, U1, Opaque, ) | 161 | OPCODE(GetSparseFromOp, U1, Opaque, ) |
| 162 | OPCODE(GetInBoundsFromOp, U1, Opaque, ) | ||
| 162 | 163 | ||
| 163 | // Floating-point operations | 164 | // Floating-point operations |
| 164 | OPCODE(FPAbs16, F16, F16, ) | 165 | OPCODE(FPAbs16, F16, F16, ) |
| @@ -363,8 +364,12 @@ OPCODE(ImageSampleExplicitLod, F32x4, U32, | |||
| 363 | OPCODE(ImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) | 364 | OPCODE(ImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) |
| 364 | OPCODE(ImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) | 365 | OPCODE(ImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) |
| 365 | 366 | ||
| 366 | // Vote operations | 367 | // Warp operations |
| 367 | OPCODE(VoteAll, U1, U1, ) | 368 | OPCODE(VoteAll, U1, U1, ) |
| 368 | OPCODE(VoteAny, U1, U1, ) | 369 | OPCODE(VoteAny, U1, U1, ) |
| 369 | OPCODE(VoteEqual, U1, U1, ) | 370 | OPCODE(VoteEqual, U1, U1, ) |
| 370 | OPCODE(SubgroupBallot, U32, U1, ) | 371 | OPCODE(SubgroupBallot, U32, U1, ) |
| 372 | OPCODE(ShuffleIndex, U32, U32, U32, U32, U32, ) | ||
| 373 | OPCODE(ShuffleUp, U32, U32, U32, U32, U32, ) | ||
| 374 | OPCODE(ShuffleDown, U32, U32, U32, U32, U32, ) | ||
| 375 | OPCODE(ShuffleButterfly, U32, U32, U32, U32, U32, ) | ||