summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/backend/spirv
diff options
context:
space:
mode:
authorGravatar ameerj2021-03-23 20:27:17 -0400
committerGravatar ameerj2021-07-22 21:51:24 -0400
commit3d07cef009cf9e287744c7771c67166ef5761ce8 (patch)
tree78f4fea18d9facb72850b4c2fe115e96b7af8f26 /src/shader_recompiler/backend/spirv
parentvk_pipeline_cache: Fix ReleaseContents order (diff)
downloadyuzu-3d07cef009cf9e287744c7771c67166ef5761ce8.tar.gz
yuzu-3d07cef009cf9e287744c7771c67166ef5761ce8.tar.xz
yuzu-3d07cef009cf9e287744c7771c67166ef5761ce8.zip
shader: Implement VOTE
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.cpp4
-rw-r--r--src/shader_recompiler/backend/spirv/emit_context.h3
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp9
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.h4
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv_vote.cpp58
5 files changed, 77 insertions, 1 deletions
diff --git a/src/shader_recompiler/backend/spirv/emit_context.cpp b/src/shader_recompiler/backend/spirv/emit_context.cpp
index 4a4de3676..36f130781 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_context.cpp
@@ -259,6 +259,10 @@ void EmitContext::DefineInputs(const Info& info, Stage stage) {
259 if (info.uses_local_invocation_id) { 259 if (info.uses_local_invocation_id) {
260 local_invocation_id = DefineInput(*this, U32[3], spv::BuiltIn::LocalInvocationId); 260 local_invocation_id = DefineInput(*this, U32[3], spv::BuiltIn::LocalInvocationId);
261 } 261 }
262 if (profile.warp_size_potentially_larger_than_guest && info.uses_subgroup_vote) {
263 subgroup_local_invocation_id =
264 DefineInput(*this, U32[1], spv::BuiltIn::SubgroupLocalInvocationId);
265 }
262 if (info.loads_position) { 266 if (info.loads_position) {
263 const bool is_fragment{stage != Stage::Fragment}; 267 const bool is_fragment{stage != Stage::Fragment};
264 const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord}; 268 const spv::BuiltIn built_in{is_fragment ? spv::BuiltIn::Position : spv::BuiltIn::FragCoord};
diff --git a/src/shader_recompiler/backend/spirv/emit_context.h b/src/shader_recompiler/backend/spirv/emit_context.h
index 9b9e0d6b1..6e64360bf 100644
--- a/src/shader_recompiler/backend/spirv/emit_context.h
+++ b/src/shader_recompiler/backend/spirv/emit_context.h
@@ -82,6 +82,7 @@ public:
82 82
83 Id workgroup_id{}; 83 Id workgroup_id{};
84 Id local_invocation_id{}; 84 Id local_invocation_id{};
85 Id subgroup_local_invocation_id{};
85 Id instance_id{}; 86 Id instance_id{};
86 Id instance_index{}; 87 Id instance_index{};
87 Id base_instance{}; 88 Id base_instance{};
@@ -96,7 +97,7 @@ public:
96 std::array<Id, 32> output_generics{}; 97 std::array<Id, 32> output_generics{};
97 98
98 std::array<Id, 8> frag_color{}; 99 std::array<Id, 8> frag_color{};
99 Id frag_depth {}; 100 Id frag_depth{};
100 101
101 std::vector<Id> interfaces; 102 std::vector<Id> interfaces;
102 103
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 93e851133..107403912 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -224,6 +224,15 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
224 ctx.AddExtension("SPV_KHR_shader_draw_parameters"); 224 ctx.AddExtension("SPV_KHR_shader_draw_parameters");
225 ctx.AddCapability(spv::Capability::DrawParameters); 225 ctx.AddCapability(spv::Capability::DrawParameters);
226 } 226 }
227 if (info.uses_subgroup_vote && profile.support_vote) {
228 ctx.AddExtension("SPV_KHR_shader_ballot");
229 ctx.AddCapability(spv::Capability::SubgroupBallotKHR);
230 if (!profile.warp_size_potentially_larger_than_guest) {
231 // vote ops are only used when not taking the long path
232 ctx.AddExtension("SPV_KHR_subgroup_vote");
233 ctx.AddCapability(spv::Capability::SubgroupVoteKHR);
234 }
235 }
227 // TODO: Track this usage 236 // TODO: Track this usage
228 ctx.AddCapability(spv::Capability::ImageGatherExtended); 237 ctx.AddCapability(spv::Capability::ImageGatherExtended);
229} 238}
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.h b/src/shader_recompiler/backend/spirv/emit_spirv.h
index 960d022ff..ce23200f2 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.h
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.h
@@ -346,5 +346,9 @@ Id EmitImageSampleDrefImplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Va
346 Id coords, Id dref, Id bias_lc, Id offset); 346 Id coords, Id dref, Id bias_lc, Id offset);
347Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, 347Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index,
348 Id coords, Id dref, Id lod_lc, Id offset); 348 Id coords, Id dref, Id lod_lc, Id offset);
349Id EmitVoteAll(EmitContext& ctx, Id pred);
350Id EmitVoteAny(EmitContext& ctx, Id pred);
351Id EmitVoteEqual(EmitContext& ctx, Id pred);
352Id EmitSubgroupBallot(EmitContext& ctx, Id pred);
349 353
350} // namespace Shader::Backend::SPIRV 354} // namespace Shader::Backend::SPIRV
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_vote.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_vote.cpp
new file mode 100644
index 000000000..a63677ef2
--- /dev/null
+++ b/src/shader_recompiler/backend/spirv/emit_spirv_vote.cpp
@@ -0,0 +1,58 @@
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/spirv/emit_spirv.h"
6
7namespace Shader::Backend::SPIRV {
8namespace {
9Id LargeWarpBallot(EmitContext& ctx, Id ballot) {
10 const Id shift{ctx.Constant(ctx.U32[1], 5)};
11 const Id local_index{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)};
12 return ctx.OpVectorExtractDynamic(ctx.U32[1], ballot, local_index);
13}
14} // Anonymous namespace
15
16Id EmitVoteAll(EmitContext& ctx, Id pred) {
17 if (!ctx.profile.warp_size_potentially_larger_than_guest) {
18 return ctx.OpSubgroupAllKHR(ctx.U1, pred);
19 }
20 const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)};
21 const Id active_mask{LargeWarpBallot(ctx, mask_ballot)};
22 const Id ballot{LargeWarpBallot(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))};
23 const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)};
24 return ctx.OpIEqual(ctx.U1, lhs, active_mask);
25}
26
27Id EmitVoteAny(EmitContext& ctx, Id pred) {
28 if (!ctx.profile.warp_size_potentially_larger_than_guest) {
29 return ctx.OpSubgroupAnyKHR(ctx.U1, pred);
30 }
31 const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)};
32 const Id active_mask{LargeWarpBallot(ctx, mask_ballot)};
33 const Id ballot{LargeWarpBallot(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))};
34 const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)};
35 return ctx.OpINotEqual(ctx.U1, lhs, ctx.u32_zero_value);
36}
37
38Id EmitVoteEqual(EmitContext& ctx, Id pred) {
39 if (!ctx.profile.warp_size_potentially_larger_than_guest) {
40 return ctx.OpSubgroupAllEqualKHR(ctx.U1, pred);
41 }
42 const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)};
43 const Id active_mask{LargeWarpBallot(ctx, mask_ballot)};
44 const Id ballot{LargeWarpBallot(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))};
45 const Id lhs{ctx.OpBitwiseXor(ctx.U32[1], ballot, active_mask)};
46 return ctx.OpLogicalOr(ctx.U1, ctx.OpIEqual(ctx.U1, lhs, ctx.u32_zero_value),
47 ctx.OpIEqual(ctx.U1, lhs, active_mask));
48}
49
50Id EmitSubgroupBallot(EmitContext& ctx, Id pred) {
51 const Id ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], pred)};
52 if (!ctx.profile.warp_size_potentially_larger_than_guest) {
53 return ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U);
54 }
55 return LargeWarpBallot(ctx, ballot);
56}
57
58} // namespace Shader::Backend::SPIRV