diff options
| author | 2021-05-10 18:21:28 -0300 | |
|---|---|---|
| committer | 2021-07-22 21:51:31 -0400 | |
| commit | c4fd6b55bc9acd06b2fc89f84fd175d78e14110a (patch) | |
| tree | c246a1c64f4826faedcf5c93be778116e48caf85 /src/shader_recompiler/backend/glasm | |
| parent | glasm: Add MUFU instructions to GLASM (diff) | |
| download | yuzu-c4fd6b55bc9acd06b2fc89f84fd175d78e14110a.tar.gz yuzu-c4fd6b55bc9acd06b2fc89f84fd175d78e14110a.tar.xz yuzu-c4fd6b55bc9acd06b2fc89f84fd175d78e14110a.zip | |
glasm: Implement shuffle and vote instructions on GLASM
Diffstat (limited to 'src/shader_recompiler/backend/glasm')
6 files changed, 158 insertions, 97 deletions
diff --git a/src/shader_recompiler/backend/glasm/emit_context.cpp b/src/shader_recompiler/backend/glasm/emit_context.cpp index 9f839f3bf..f9d83dd91 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.cpp +++ b/src/shader_recompiler/backend/glasm/emit_context.cpp | |||
| @@ -25,6 +25,23 @@ EmitContext::EmitContext(IR::Program& program) { | |||
| 25 | if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { | 25 | if (const size_t num = program.info.storage_buffers_descriptors.size(); num > 0) { |
| 26 | Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); | 26 | Add("PARAM c[{}]={{program.local[0..{}]}};", num, num - 1); |
| 27 | } | 27 | } |
| 28 | switch (program.stage) { | ||
| 29 | case Stage::VertexA: | ||
| 30 | case Stage::VertexB: | ||
| 31 | stage_name = "vertex"; | ||
| 32 | break; | ||
| 33 | case Stage::TessellationControl: | ||
| 34 | case Stage::TessellationEval: | ||
| 35 | case Stage::Geometry: | ||
| 36 | stage_name = "primitive"; | ||
| 37 | break; | ||
| 38 | case Stage::Fragment: | ||
| 39 | stage_name = "fragment"; | ||
| 40 | break; | ||
| 41 | case Stage::Compute: | ||
| 42 | stage_name = "compute"; | ||
| 43 | break; | ||
| 44 | } | ||
| 28 | } | 45 | } |
| 29 | 46 | ||
| 30 | } // namespace Shader::Backend::GLASM | 47 | } // namespace Shader::Backend::GLASM |
diff --git a/src/shader_recompiler/backend/glasm/emit_context.h b/src/shader_recompiler/backend/glasm/emit_context.h index 37663c1c8..4efe42ada 100644 --- a/src/shader_recompiler/backend/glasm/emit_context.h +++ b/src/shader_recompiler/backend/glasm/emit_context.h | |||
| @@ -45,6 +45,8 @@ public: | |||
| 45 | 45 | ||
| 46 | std::string code; | 46 | std::string code; |
| 47 | RegAlloc reg_alloc{*this}; | 47 | RegAlloc reg_alloc{*this}; |
| 48 | |||
| 49 | std::string_view stage_name = "invalid"; | ||
| 48 | }; | 50 | }; |
| 49 | 51 | ||
| 50 | } // namespace Shader::Backend::GLASM | 52 | } // namespace Shader::Backend::GLASM |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index ad27b8b06..8b42cbf79 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -189,6 +189,12 @@ void SetupOptions(std::string& header, Info info) { | |||
| 189 | if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) { | 189 | if (info.uses_atomic_f16x2_add || info.uses_atomic_f16x2_min || info.uses_atomic_f16x2_max) { |
| 190 | header += "OPTION NV_shader_atomic_fp16_vector;"; | 190 | header += "OPTION NV_shader_atomic_fp16_vector;"; |
| 191 | } | 191 | } |
| 192 | if (info.uses_subgroup_invocation_id || info.uses_subgroup_mask) { | ||
| 193 | header += "OPTION NV_shader_thread_group;"; | ||
| 194 | } | ||
| 195 | if (info.uses_subgroup_shuffles) { | ||
| 196 | header += "OPTION NV_shader_thread_shuffle;"; | ||
| 197 | } | ||
| 192 | } | 198 | } |
| 193 | } // Anonymous namespace | 199 | } // Anonymous namespace |
| 194 | 200 | ||
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h index 1bbd02022..75613571f 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h +++ b/src/shader_recompiler/backend/glasm/emit_glasm_instructions.h | |||
| @@ -584,24 +584,24 @@ void EmitImageAtomicXor32(EmitContext& ctx, IR::Inst& inst, const IR::Value& ind | |||
| 584 | ScalarU32 value); | 584 | ScalarU32 value); |
| 585 | void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, | 585 | void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, |
| 586 | Register coords, ScalarU32 value); | 586 | Register coords, ScalarU32 value); |
| 587 | void EmitLaneId(EmitContext& ctx); | 587 | void EmitLaneId(EmitContext& ctx, IR::Inst& inst); |
| 588 | void EmitVoteAll(EmitContext& ctx, ScalarS32 pred); | 588 | void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); |
| 589 | void EmitVoteAny(EmitContext& ctx, ScalarS32 pred); | 589 | void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); |
| 590 | void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred); | 590 | void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); |
| 591 | void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred); | 591 | void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred); |
| 592 | void EmitSubgroupEqMask(EmitContext& ctx); | 592 | void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst); |
| 593 | void EmitSubgroupLtMask(EmitContext& ctx); | 593 | void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst); |
| 594 | void EmitSubgroupLeMask(EmitContext& ctx); | 594 | void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst); |
| 595 | void EmitSubgroupGtMask(EmitContext& ctx); | 595 | void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst); |
| 596 | void EmitSubgroupGeMask(EmitContext& ctx); | 596 | void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst); |
| 597 | void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | 597 | void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, |
| 598 | ScalarU32 clamp, ScalarU32 segmentation_mask); | 598 | const IR::Value& clamp, const IR::Value& segmentation_mask); |
| 599 | void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | 599 | void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, |
| 600 | ScalarU32 clamp, ScalarU32 segmentation_mask); | 600 | const IR::Value& clamp, const IR::Value& segmentation_mask); |
| 601 | void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | 601 | void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, |
| 602 | ScalarU32 clamp, ScalarU32 segmentation_mask); | 602 | const IR::Value& clamp, const IR::Value& segmentation_mask); |
| 603 | void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | 603 | void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, |
| 604 | ScalarU32 clamp, ScalarU32 segmentation_mask); | 604 | const IR::Value& clamp, const IR::Value& segmentation_mask); |
| 605 | void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); | 605 | void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); |
| 606 | void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a); | 606 | void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a); |
| 607 | void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a); | 607 | void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a); |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp index 85110bcc9..3c0a74e3c 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp | |||
| @@ -21,9 +21,7 @@ void EmitPhi(EmitContext& ctx, IR::Inst& inst) { | |||
| 21 | NotImplemented(); | 21 | NotImplemented(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | void EmitVoid(EmitContext& ctx) { | 24 | void EmitVoid(EmitContext&) {} |
| 25 | NotImplemented(); | ||
| 26 | } | ||
| 27 | 25 | ||
| 28 | void EmitBranch(EmitContext& ctx) { | 26 | void EmitBranch(EmitContext& ctx) { |
| 29 | NotImplemented(); | 27 | NotImplemented(); |
| @@ -636,84 +634,4 @@ void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value | |||
| 636 | NotImplemented(); | 634 | NotImplemented(); |
| 637 | } | 635 | } |
| 638 | 636 | ||
| 639 | void EmitLaneId(EmitContext& ctx) { | ||
| 640 | NotImplemented(); | ||
| 641 | } | ||
| 642 | |||
| 643 | void EmitVoteAll(EmitContext& ctx, ScalarS32 pred) { | ||
| 644 | NotImplemented(); | ||
| 645 | } | ||
| 646 | |||
| 647 | void EmitVoteAny(EmitContext& ctx, ScalarS32 pred) { | ||
| 648 | NotImplemented(); | ||
| 649 | } | ||
| 650 | |||
| 651 | void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred) { | ||
| 652 | NotImplemented(); | ||
| 653 | } | ||
| 654 | |||
| 655 | void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred) { | ||
| 656 | NotImplemented(); | ||
| 657 | } | ||
| 658 | |||
| 659 | void EmitSubgroupEqMask(EmitContext& ctx) { | ||
| 660 | NotImplemented(); | ||
| 661 | } | ||
| 662 | |||
| 663 | void EmitSubgroupLtMask(EmitContext& ctx) { | ||
| 664 | NotImplemented(); | ||
| 665 | } | ||
| 666 | |||
| 667 | void EmitSubgroupLeMask(EmitContext& ctx) { | ||
| 668 | NotImplemented(); | ||
| 669 | } | ||
| 670 | |||
| 671 | void EmitSubgroupGtMask(EmitContext& ctx) { | ||
| 672 | NotImplemented(); | ||
| 673 | } | ||
| 674 | |||
| 675 | void EmitSubgroupGeMask(EmitContext& ctx) { | ||
| 676 | NotImplemented(); | ||
| 677 | } | ||
| 678 | |||
| 679 | void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 680 | ScalarU32 clamp, ScalarU32 segmentation_mask) { | ||
| 681 | NotImplemented(); | ||
| 682 | } | ||
| 683 | |||
| 684 | void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 685 | ScalarU32 clamp, ScalarU32 segmentation_mask) { | ||
| 686 | NotImplemented(); | ||
| 687 | } | ||
| 688 | |||
| 689 | void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 690 | ScalarU32 clamp, ScalarU32 segmentation_mask) { | ||
| 691 | NotImplemented(); | ||
| 692 | } | ||
| 693 | |||
| 694 | void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 695 | ScalarU32 clamp, ScalarU32 segmentation_mask) { | ||
| 696 | NotImplemented(); | ||
| 697 | } | ||
| 698 | |||
| 699 | void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle) { | ||
| 700 | NotImplemented(); | ||
| 701 | } | ||
| 702 | |||
| 703 | void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a) { | ||
| 704 | NotImplemented(); | ||
| 705 | } | ||
| 706 | |||
| 707 | void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a) { | ||
| 708 | NotImplemented(); | ||
| 709 | } | ||
| 710 | |||
| 711 | void EmitDPdxCoarse(EmitContext& ctx, ScalarF32 op_a) { | ||
| 712 | NotImplemented(); | ||
| 713 | } | ||
| 714 | |||
| 715 | void EmitDPdyCoarse(EmitContext& ctx, ScalarF32 op_a) { | ||
| 716 | NotImplemented(); | ||
| 717 | } | ||
| 718 | |||
| 719 | } // namespace Shader::Backend::GLASM | 637 | } // namespace Shader::Backend::GLASM |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp index e69de29bb..37eb577cd 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp | |||
| @@ -0,0 +1,118 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "shader_recompiler/backend/glasm/emit_context.h" | ||
| 6 | #include "shader_recompiler/backend/glasm/emit_glasm_instructions.h" | ||
| 7 | #include "shader_recompiler/frontend/ir/value.h" | ||
| 8 | |||
| 9 | namespace Shader::Backend::GLASM { | ||
| 10 | |||
| 11 | void EmitLaneId(EmitContext& ctx, IR::Inst& inst) { | ||
| 12 | ctx.Add("MOV.S {}.x,{}.threadid;", inst, ctx.stage_name); | ||
| 13 | } | ||
| 14 | |||
| 15 | void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 16 | ctx.Add("TGALL.S {}.x,{};", inst, pred); | ||
| 17 | } | ||
| 18 | |||
| 19 | void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 20 | ctx.Add("TGANY.S {}.x,{};", inst, pred); | ||
| 21 | } | ||
| 22 | |||
| 23 | void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 24 | ctx.Add("TGEQ.S {}.x,{};", inst, pred); | ||
| 25 | } | ||
| 26 | |||
| 27 | void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) { | ||
| 28 | ctx.Add("TGBALLOT {}.x,{};", inst, pred); | ||
| 29 | } | ||
| 30 | |||
| 31 | void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 32 | ctx.Add("MOV.U {},{}.threadeqmask;", inst, ctx.stage_name); | ||
| 33 | } | ||
| 34 | |||
| 35 | void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 36 | ctx.Add("MOV.U {},{}.threadltmask;", inst, ctx.stage_name); | ||
| 37 | } | ||
| 38 | |||
| 39 | void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 40 | ctx.Add("MOV.U {},{}.threadlemask;", inst, ctx.stage_name); | ||
| 41 | } | ||
| 42 | |||
| 43 | void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 44 | ctx.Add("MOV.U {},{}.threadgtmask;", inst, ctx.stage_name); | ||
| 45 | } | ||
| 46 | |||
| 47 | void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) { | ||
| 48 | ctx.Add("MOV.U {},{}.threadgemask;", inst, ctx.stage_name); | ||
| 49 | } | ||
| 50 | |||
| 51 | static void Shuffle(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 52 | const IR::Value& clamp, const IR::Value& segmentation_mask, | ||
| 53 | std::string_view op) { | ||
| 54 | std::string mask; | ||
| 55 | if (clamp.IsImmediate() && segmentation_mask.IsImmediate()) { | ||
| 56 | mask = fmt::to_string(clamp.U32() | (segmentation_mask.U32() << 8)); | ||
| 57 | } else { | ||
| 58 | mask = "RC"; | ||
| 59 | ctx.Add("BFI.U RC.x,{{5,8,0,0}},{},{};", | ||
| 60 | ScalarU32{ctx.reg_alloc.Consume(segmentation_mask)}, | ||
| 61 | ScalarU32{ctx.reg_alloc.Consume(clamp)}); | ||
| 62 | } | ||
| 63 | const Register value_ret{ctx.reg_alloc.Define(inst)}; | ||
| 64 | IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)}; | ||
| 65 | if (in_bounds) { | ||
| 66 | const Register bounds_ret{ctx.reg_alloc.Define(*in_bounds)}; | ||
| 67 | ctx.Add("SHF{}.U {},{},{},{};" | ||
| 68 | "MOV.U {}.x,{}.y;", | ||
| 69 | op, bounds_ret, value, index, mask, value_ret, bounds_ret); | ||
| 70 | in_bounds->Invalidate(); | ||
| 71 | } else { | ||
| 72 | ctx.Add("SHF{}.U {},{},{},{};" | ||
| 73 | "MOV.U {}.x,{}.y;", | ||
| 74 | op, value_ret, value, index, mask, value_ret, value_ret); | ||
| 75 | } | ||
| 76 | } | ||
| 77 | |||
| 78 | void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 79 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 80 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "IDX"); | ||
| 81 | } | ||
| 82 | |||
| 83 | void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 84 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 85 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "UP"); | ||
| 86 | } | ||
| 87 | |||
| 88 | void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 89 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 90 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "DOWN"); | ||
| 91 | } | ||
| 92 | |||
| 93 | void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, | ||
| 94 | const IR::Value& clamp, const IR::Value& segmentation_mask) { | ||
| 95 | Shuffle(ctx, inst, value, index, clamp, segmentation_mask, "XOR"); | ||
| 96 | } | ||
| 97 | |||
| 98 | void EmitFSwizzleAdd(EmitContext&, ScalarF32, ScalarF32, ScalarU32) { | ||
| 99 | throw NotImplementedException("GLASM instruction"); | ||
| 100 | } | ||
| 101 | |||
| 102 | void EmitDPdxFine(EmitContext&, ScalarF32) { | ||
| 103 | throw NotImplementedException("GLASM instruction"); | ||
| 104 | } | ||
| 105 | |||
| 106 | void EmitDPdyFine(EmitContext&, ScalarF32) { | ||
| 107 | throw NotImplementedException("GLASM instruction"); | ||
| 108 | } | ||
| 109 | |||
| 110 | void EmitDPdxCoarse(EmitContext&, ScalarF32) { | ||
| 111 | throw NotImplementedException("GLASM instruction"); | ||
| 112 | } | ||
| 113 | |||
| 114 | void EmitDPdyCoarse(EmitContext&, ScalarF32) { | ||
| 115 | throw NotImplementedException("GLASM instruction"); | ||
| 116 | } | ||
| 117 | |||
| 118 | } // namespace Shader::Backend::GLASM | ||