diff options
| author | 2021-03-23 20:27:17 -0400 | |
|---|---|---|
| committer | 2021-07-22 21:51:24 -0400 | |
| commit | 3d07cef009cf9e287744c7771c67166ef5761ce8 (patch) | |
| tree | 78f4fea18d9facb72850b4c2fe115e96b7af8f26 /src/shader_recompiler/backend/spirv | |
| parent | vk_pipeline_cache: Fix ReleaseContents order (diff) | |
| download | yuzu-3d07cef009cf9e287744c7771c67166ef5761ce8.tar.gz yuzu-3d07cef009cf9e287744c7771c67166ef5761ce8.tar.xz yuzu-3d07cef009cf9e287744c7771c67166ef5761ce8.zip | |
shader: Implement VOTE
Diffstat (limited to 'src/shader_recompiler/backend/spirv')
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); |
| 347 | Id EmitImageSampleDrefExplicitLod(EmitContext& ctx, IR::Inst* inst, const IR::Value& index, | 347 | Id 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); |
| 349 | Id EmitVoteAll(EmitContext& ctx, Id pred); | ||
| 350 | Id EmitVoteAny(EmitContext& ctx, Id pred); | ||
| 351 | Id EmitVoteEqual(EmitContext& ctx, Id pred); | ||
| 352 | Id 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 | |||
| 7 | namespace Shader::Backend::SPIRV { | ||
| 8 | namespace { | ||
| 9 | Id 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 | |||
| 16 | Id 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 | |||
| 27 | Id 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 | |||
| 38 | Id 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 | |||
| 50 | Id 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 | ||