summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler/backend')
-rw-r--r--src/shader_recompiler/backend/glasm/emit_context.cpp17
-rw-r--r--src/shader_recompiler/backend/glasm/emit_context.h2
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm.cpp6
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_instructions.h28
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_not_implemented.cpp84
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_warp.cpp118
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp2
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp4
8 files changed, 162 insertions, 99 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);
585void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index, 585void EmitImageAtomicExchange32(EmitContext& ctx, IR::Inst& inst, const IR::Value& index,
586 Register coords, ScalarU32 value); 586 Register coords, ScalarU32 value);
587void EmitLaneId(EmitContext& ctx); 587void EmitLaneId(EmitContext& ctx, IR::Inst& inst);
588void EmitVoteAll(EmitContext& ctx, ScalarS32 pred); 588void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred);
589void EmitVoteAny(EmitContext& ctx, ScalarS32 pred); 589void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred);
590void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred); 590void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred);
591void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred); 591void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred);
592void EmitSubgroupEqMask(EmitContext& ctx); 592void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst);
593void EmitSubgroupLtMask(EmitContext& ctx); 593void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst);
594void EmitSubgroupLeMask(EmitContext& ctx); 594void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst);
595void EmitSubgroupGtMask(EmitContext& ctx); 595void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst);
596void EmitSubgroupGeMask(EmitContext& ctx); 596void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst);
597void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, 597void 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);
599void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, 599void 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);
601void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, 601void 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);
603void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index, 603void 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);
605void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle); 605void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle);
606void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a); 606void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a);
607void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a); 607void 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
24void EmitVoid(EmitContext& ctx) { 24void EmitVoid(EmitContext&) {}
25 NotImplemented();
26}
27 25
28void EmitBranch(EmitContext& ctx) { 26void 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
639void EmitLaneId(EmitContext& ctx) {
640 NotImplemented();
641}
642
643void EmitVoteAll(EmitContext& ctx, ScalarS32 pred) {
644 NotImplemented();
645}
646
647void EmitVoteAny(EmitContext& ctx, ScalarS32 pred) {
648 NotImplemented();
649}
650
651void EmitVoteEqual(EmitContext& ctx, ScalarS32 pred) {
652 NotImplemented();
653}
654
655void EmitSubgroupBallot(EmitContext& ctx, ScalarS32 pred) {
656 NotImplemented();
657}
658
659void EmitSubgroupEqMask(EmitContext& ctx) {
660 NotImplemented();
661}
662
663void EmitSubgroupLtMask(EmitContext& ctx) {
664 NotImplemented();
665}
666
667void EmitSubgroupLeMask(EmitContext& ctx) {
668 NotImplemented();
669}
670
671void EmitSubgroupGtMask(EmitContext& ctx) {
672 NotImplemented();
673}
674
675void EmitSubgroupGeMask(EmitContext& ctx) {
676 NotImplemented();
677}
678
679void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
680 ScalarU32 clamp, ScalarU32 segmentation_mask) {
681 NotImplemented();
682}
683
684void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
685 ScalarU32 clamp, ScalarU32 segmentation_mask) {
686 NotImplemented();
687}
688
689void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
690 ScalarU32 clamp, ScalarU32 segmentation_mask) {
691 NotImplemented();
692}
693
694void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, ScalarU32 value, ScalarU32 index,
695 ScalarU32 clamp, ScalarU32 segmentation_mask) {
696 NotImplemented();
697}
698
699void EmitFSwizzleAdd(EmitContext& ctx, ScalarF32 op_a, ScalarF32 op_b, ScalarU32 swizzle) {
700 NotImplemented();
701}
702
703void EmitDPdxFine(EmitContext& ctx, ScalarF32 op_a) {
704 NotImplemented();
705}
706
707void EmitDPdyFine(EmitContext& ctx, ScalarF32 op_a) {
708 NotImplemented();
709}
710
711void EmitDPdxCoarse(EmitContext& ctx, ScalarF32 op_a) {
712 NotImplemented();
713}
714
715void 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
9namespace Shader::Backend::GLASM {
10
11void EmitLaneId(EmitContext& ctx, IR::Inst& inst) {
12 ctx.Add("MOV.S {}.x,{}.threadid;", inst, ctx.stage_name);
13}
14
15void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
16 ctx.Add("TGALL.S {}.x,{};", inst, pred);
17}
18
19void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
20 ctx.Add("TGANY.S {}.x,{};", inst, pred);
21}
22
23void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
24 ctx.Add("TGEQ.S {}.x,{};", inst, pred);
25}
26
27void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, ScalarS32 pred) {
28 ctx.Add("TGBALLOT {}.x,{};", inst, pred);
29}
30
31void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) {
32 ctx.Add("MOV.U {},{}.threadeqmask;", inst, ctx.stage_name);
33}
34
35void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) {
36 ctx.Add("MOV.U {},{}.threadltmask;", inst, ctx.stage_name);
37}
38
39void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) {
40 ctx.Add("MOV.U {},{}.threadlemask;", inst, ctx.stage_name);
41}
42
43void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) {
44 ctx.Add("MOV.U {},{}.threadgtmask;", inst, ctx.stage_name);
45}
46
47void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) {
48 ctx.Add("MOV.U {},{}.threadgemask;", inst, ctx.stage_name);
49}
50
51static 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
78void 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
83void 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
88void 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
93void 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
98void EmitFSwizzleAdd(EmitContext&, ScalarF32, ScalarF32, ScalarU32) {
99 throw NotImplementedException("GLASM instruction");
100}
101
102void EmitDPdxFine(EmitContext&, ScalarF32) {
103 throw NotImplementedException("GLASM instruction");
104}
105
106void EmitDPdyFine(EmitContext&, ScalarF32) {
107 throw NotImplementedException("GLASM instruction");
108}
109
110void EmitDPdxCoarse(EmitContext&, ScalarF32) {
111 throw NotImplementedException("GLASM instruction");
112}
113
114void EmitDPdyCoarse(EmitContext&, ScalarF32) {
115 throw NotImplementedException("GLASM instruction");
116}
117
118} // namespace Shader::Backend::GLASM
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index be88b76f7..9759591bd 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -1168,7 +1168,7 @@ void EmitContext::DefineInputs(const Info& info) {
1168 subgroup_mask_gt = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGtMaskKHR); 1168 subgroup_mask_gt = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGtMaskKHR);
1169 subgroup_mask_ge = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGeMaskKHR); 1169 subgroup_mask_ge = DefineInput(*this, U32[4], false, spv::BuiltIn::SubgroupGeMaskKHR);
1170 } 1170 }
1171 if (info.uses_subgroup_invocation_id || 1171 if (info.uses_subgroup_invocation_id || info.uses_subgroup_shuffles ||
1172 (profile.warp_size_potentially_larger_than_guest && 1172 (profile.warp_size_potentially_larger_than_guest &&
1173 (info.uses_subgroup_vote || info.uses_subgroup_mask))) { 1173 (info.uses_subgroup_vote || info.uses_subgroup_mask))) {
1174 subgroup_local_invocation_id = 1174 subgroup_local_invocation_id =
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 0681dfd16..2dad87e87 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -318,7 +318,9 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
318 ctx.AddExtension("SPV_KHR_shader_draw_parameters"); 318 ctx.AddExtension("SPV_KHR_shader_draw_parameters");
319 ctx.AddCapability(spv::Capability::DrawParameters); 319 ctx.AddCapability(spv::Capability::DrawParameters);
320 } 320 }
321 if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id) && profile.support_vote) { 321 if ((info.uses_subgroup_vote || info.uses_subgroup_invocation_id ||
322 info.uses_subgroup_shuffles) &&
323 profile.support_vote) {
322 ctx.AddExtension("SPV_KHR_shader_ballot"); 324 ctx.AddExtension("SPV_KHR_shader_ballot");
323 ctx.AddCapability(spv::Capability::SubgroupBallotKHR); 325 ctx.AddCapability(spv::Capability::SubgroupBallotKHR);
324 if (!profile.warp_size_potentially_larger_than_guest) { 326 if (!profile.warp_size_potentially_larger_than_guest) {