diff options
Diffstat (limited to 'src')
18 files changed, 182 insertions, 6 deletions
diff --git a/src/shader_recompiler/CMakeLists.txt b/src/shader_recompiler/CMakeLists.txt index 23cb523a8..086bdf8d0 100644 --- a/src/shader_recompiler/CMakeLists.txt +++ b/src/shader_recompiler/CMakeLists.txt | |||
| @@ -15,6 +15,7 @@ add_library(shader_recompiler STATIC | |||
| 15 | backend/spirv/emit_spirv_memory.cpp | 15 | backend/spirv/emit_spirv_memory.cpp |
| 16 | backend/spirv/emit_spirv_select.cpp | 16 | backend/spirv/emit_spirv_select.cpp |
| 17 | backend/spirv/emit_spirv_undefined.cpp | 17 | backend/spirv/emit_spirv_undefined.cpp |
| 18 | backend/spirv/emit_spirv_vote.cpp | ||
| 18 | environment.h | 19 | environment.h |
| 19 | exception.h | 20 | exception.h |
| 20 | file_environment.cpp | 21 | file_environment.cpp |
| @@ -122,6 +123,7 @@ add_library(shader_recompiler STATIC | |||
| 122 | frontend/maxwell/translate/impl/select_source_with_predicate.cpp | 123 | frontend/maxwell/translate/impl/select_source_with_predicate.cpp |
| 123 | frontend/maxwell/translate/impl/texture_fetch.cpp | 124 | frontend/maxwell/translate/impl/texture_fetch.cpp |
| 124 | frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp | 125 | frontend/maxwell/translate/impl/texture_fetch_swizzled.cpp |
| 126 | frontend/maxwell/translate/impl/vote.cpp | ||
| 125 | frontend/maxwell/translate/translate.cpp | 127 | frontend/maxwell/translate/translate.cpp |
| 126 | frontend/maxwell/translate/translate.h | 128 | frontend/maxwell/translate/translate.h |
| 127 | ir_opt/collect_shader_info_pass.cpp | 129 | ir_opt/collect_shader_info_pass.cpp |
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 | ||
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.cpp b/src/shader_recompiler/frontend/ir/ir_emitter.cpp index 432dd29a5..ff2970125 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.cpp +++ b/src/shader_recompiler/frontend/ir/ir_emitter.cpp | |||
| @@ -1444,4 +1444,20 @@ F32 IREmitter::ImageSampleDrefExplicitLod(const Value& handle, const Value& coor | |||
| 1444 | return Inst<F32>(op, Flags{info}, handle, coords, dref, lod_lc, offset); | 1444 | return Inst<F32>(op, Flags{info}, handle, coords, dref, lod_lc, offset); |
| 1445 | } | 1445 | } |
| 1446 | 1446 | ||
| 1447 | U1 IREmitter::VoteAll(const U1& value) { | ||
| 1448 | return Inst<U1>(Opcode::VoteAll, value); | ||
| 1449 | } | ||
| 1450 | |||
| 1451 | U1 IREmitter::VoteAny(const U1& value) { | ||
| 1452 | return Inst<U1>(Opcode::VoteAny, value); | ||
| 1453 | } | ||
| 1454 | |||
| 1455 | U1 IREmitter::VoteEqual(const U1& value) { | ||
| 1456 | return Inst<U1>(Opcode::VoteEqual, value); | ||
| 1457 | } | ||
| 1458 | |||
| 1459 | U32 IREmitter::SubgroupBallot(const U1& value) { | ||
| 1460 | return Inst<U32>(Opcode::SubgroupBallot, value); | ||
| 1461 | } | ||
| 1462 | |||
| 1447 | } // namespace Shader::IR | 1463 | } // namespace Shader::IR |
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 346cef3ab..1708be3ef 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -234,6 +234,11 @@ public: | |||
| 234 | const Value& offset, const F32& lod_clamp, | 234 | const Value& offset, const F32& lod_clamp, |
| 235 | TextureInstInfo info); | 235 | TextureInstInfo info); |
| 236 | 236 | ||
| 237 | [[nodiscard]] U1 VoteAll(const U1& value); | ||
| 238 | [[nodiscard]] U1 VoteAny(const U1& value); | ||
| 239 | [[nodiscard]] U1 VoteEqual(const U1& value); | ||
| 240 | [[nodiscard]] U32 SubgroupBallot(const U1& value); | ||
| 241 | |||
| 237 | private: | 242 | private: |
| 238 | IR::Block::iterator insertion_point; | 243 | IR::Block::iterator insertion_point; |
| 239 | 244 | ||
diff --git a/src/shader_recompiler/frontend/ir/opcodes.inc b/src/shader_recompiler/frontend/ir/opcodes.inc index bdc07b9a7..fe888b8b2 100644 --- a/src/shader_recompiler/frontend/ir/opcodes.inc +++ b/src/shader_recompiler/frontend/ir/opcodes.inc | |||
| @@ -355,3 +355,9 @@ OPCODE(ImageSampleImplicitLod, F32x4, U32, | |||
| 355 | OPCODE(ImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) | 355 | OPCODE(ImageSampleExplicitLod, F32x4, U32, Opaque, Opaque, Opaque, ) |
| 356 | OPCODE(ImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) | 356 | OPCODE(ImageSampleDrefImplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) |
| 357 | OPCODE(ImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) | 357 | OPCODE(ImageSampleDrefExplicitLod, F32, U32, Opaque, F32, Opaque, Opaque, ) |
| 358 | |||
| 359 | // Vote operations | ||
| 360 | OPCODE(VoteAll, U1, U1, ) | ||
| 361 | OPCODE(VoteAny, U1, U1, ) | ||
| 362 | OPCODE(VoteEqual, U1, U1, ) | ||
| 363 | OPCODE(SubgroupBallot, U32, U1, ) | ||
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp index 27b12ff3c..c0e36a7e2 100644 --- a/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp | |||
| @@ -417,10 +417,6 @@ void TranslatorVisitor::VMNMX(u64) { | |||
| 417 | ThrowNotImplemented(Opcode::VMNMX); | 417 | ThrowNotImplemented(Opcode::VMNMX); |
| 418 | } | 418 | } |
| 419 | 419 | ||
| 420 | void TranslatorVisitor::VOTE(u64) { | ||
| 421 | ThrowNotImplemented(Opcode::VOTE); | ||
| 422 | } | ||
| 423 | |||
| 424 | void TranslatorVisitor::VOTE_vtg(u64) { | 420 | void TranslatorVisitor::VOTE_vtg(u64) { |
| 425 | ThrowNotImplemented(Opcode::VOTE_vtg); | 421 | ThrowNotImplemented(Opcode::VOTE_vtg); |
| 426 | } | 422 | } |
diff --git a/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp b/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp new file mode 100644 index 000000000..a88894a7e --- /dev/null +++ b/src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp | |||
| @@ -0,0 +1,52 @@ | |||
| 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 <optional> | ||
| 6 | |||
| 7 | #include "common/bit_field.h" | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||
| 10 | |||
| 11 | namespace Shader::Maxwell { | ||
| 12 | namespace { | ||
| 13 | enum class VoteOp : u64 { | ||
| 14 | ALL, | ||
| 15 | ANY, | ||
| 16 | EQ, | ||
| 17 | }; | ||
| 18 | |||
| 19 | [[nodiscard]] IR::U1 VoteOperation(IR::IREmitter& ir, const IR::U1& pred, VoteOp vote_op) { | ||
| 20 | switch (vote_op) { | ||
| 21 | case VoteOp::ALL: | ||
| 22 | return ir.VoteAll(pred); | ||
| 23 | case VoteOp::ANY: | ||
| 24 | return ir.VoteAny(pred); | ||
| 25 | case VoteOp::EQ: | ||
| 26 | return ir.VoteEqual(pred); | ||
| 27 | default: | ||
| 28 | throw NotImplementedException("Invalid VOTE op {}", vote_op); | ||
| 29 | } | ||
| 30 | } | ||
| 31 | |||
| 32 | void Vote(TranslatorVisitor& v, u64 insn) { | ||
| 33 | union { | ||
| 34 | u64 insn; | ||
| 35 | BitField<0, 8, IR::Reg> dest_reg; | ||
| 36 | BitField<39, 3, IR::Pred> pred_a; | ||
| 37 | BitField<42, 1, u64> neg_pred_a; | ||
| 38 | BitField<45, 3, IR::Pred> pred_b; | ||
| 39 | BitField<48, 2, VoteOp> vote_op; | ||
| 40 | } const vote{insn}; | ||
| 41 | |||
| 42 | const IR::U1 vote_pred{v.ir.GetPred(vote.pred_a, vote.neg_pred_a != 0)}; | ||
| 43 | v.ir.SetPred(vote.pred_b, VoteOperation(v.ir, vote_pred, vote.vote_op)); | ||
| 44 | v.X(vote.dest_reg, v.ir.SubgroupBallot(vote_pred)); | ||
| 45 | } | ||
| 46 | } // Anonymous namespace | ||
| 47 | |||
| 48 | void TranslatorVisitor::VOTE(u64 insn) { | ||
| 49 | Vote(*this, insn); | ||
| 50 | } | ||
| 51 | |||
| 52 | } // namespace Shader::Maxwell | ||
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index f44eac5d8..db5138e4d 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -359,6 +359,12 @@ void VisitUsages(Info& info, IR::Inst& inst) { | |||
| 359 | inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr; | 359 | inst.GetAssociatedPseudoOperation(IR::Opcode::GetSparseFromOp) != nullptr; |
| 360 | break; | 360 | break; |
| 361 | } | 361 | } |
| 362 | case IR::Opcode::VoteAll: | ||
| 363 | case IR::Opcode::VoteAny: | ||
| 364 | case IR::Opcode::VoteEqual: | ||
| 365 | case IR::Opcode::SubgroupBallot: | ||
| 366 | info.uses_subgroup_vote = true; | ||
| 367 | break; | ||
| 362 | default: | 368 | default: |
| 363 | break; | 369 | break; |
| 364 | } | 370 | } |
diff --git a/src/shader_recompiler/profile.h b/src/shader_recompiler/profile.h index 3181c79fb..b57cbc310 100644 --- a/src/shader_recompiler/profile.h +++ b/src/shader_recompiler/profile.h | |||
| @@ -19,6 +19,8 @@ struct Profile { | |||
| 19 | bool support_fp16_signed_zero_nan_preserve{}; | 19 | bool support_fp16_signed_zero_nan_preserve{}; |
| 20 | bool support_fp32_signed_zero_nan_preserve{}; | 20 | bool support_fp32_signed_zero_nan_preserve{}; |
| 21 | bool support_fp64_signed_zero_nan_preserve{}; | 21 | bool support_fp64_signed_zero_nan_preserve{}; |
| 22 | bool support_vote{}; | ||
| 23 | bool warp_size_potentially_larger_than_guest{}; | ||
| 22 | 24 | ||
| 23 | // FClamp is broken and OpFMax + OpFMin should be used instead | 25 | // FClamp is broken and OpFMax + OpFMin should be used instead |
| 24 | bool has_broken_spirv_clamp{}; | 26 | bool has_broken_spirv_clamp{}; |
diff --git a/src/shader_recompiler/shader_info.h b/src/shader_recompiler/shader_info.h index f97730b34..3d9f04d1a 100644 --- a/src/shader_recompiler/shader_info.h +++ b/src/shader_recompiler/shader_info.h | |||
| @@ -80,6 +80,7 @@ struct Info { | |||
| 80 | bool uses_sampled_1d{}; | 80 | bool uses_sampled_1d{}; |
| 81 | bool uses_sparse_residency{}; | 81 | bool uses_sparse_residency{}; |
| 82 | bool uses_demote_to_helper_invocation{}; | 82 | bool uses_demote_to_helper_invocation{}; |
| 83 | bool uses_subgroup_vote{}; | ||
| 83 | 84 | ||
| 84 | IR::Type used_constant_buffer_types{}; | 85 | IR::Type used_constant_buffer_types{}; |
| 85 | 86 | ||
diff --git a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp index 6684d37a6..8e544d745 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pipeline.cpp | |||
| @@ -36,13 +36,18 @@ ComputePipeline::ComputePipeline(const Device& device, VKDescriptorPool& descrip | |||
| 36 | descriptor_update_template = std::move(tuple.descriptor_update_template); | 36 | descriptor_update_template = std::move(tuple.descriptor_update_template); |
| 37 | descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); | 37 | descriptor_allocator = DescriptorAllocator(descriptor_pool, *descriptor_set_layout); |
| 38 | 38 | ||
| 39 | const VkPipelineShaderStageRequiredSubgroupSizeCreateInfoEXT subgroup_size_ci{ | ||
| 40 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_REQUIRED_SUBGROUP_SIZE_CREATE_INFO_EXT, | ||
| 41 | .pNext = nullptr, | ||
| 42 | .requiredSubgroupSize = GuestWarpSize, | ||
| 43 | }; | ||
| 39 | pipeline = device.GetLogical().CreateComputePipeline({ | 44 | pipeline = device.GetLogical().CreateComputePipeline({ |
| 40 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, | 45 | .sType = VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO, |
| 41 | .pNext = nullptr, | 46 | .pNext = nullptr, |
| 42 | .flags = 0, | 47 | .flags = 0, |
| 43 | .stage{ | 48 | .stage{ |
| 44 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, | 49 | .sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO, |
| 45 | .pNext = nullptr, | 50 | .pNext = device.IsExtSubgroupSizeControlSupported() ? &subgroup_size_ci : nullptr, |
| 46 | .flags = 0, | 51 | .flags = 0, |
| 47 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, | 52 | .stage = VK_SHADER_STAGE_COMPUTE_BIT, |
| 48 | .module = *spv_module, | 53 | .module = *spv_module, |
diff --git a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp index 41fc9588f..bdbc8dd1e 100644 --- a/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_pipeline_cache.cpp | |||
| @@ -455,6 +455,8 @@ PipelineCache::PipelineCache(RasterizerVulkan& rasterizer_, Tegra::GPU& gpu_, | |||
| 455 | float_control.shaderSignedZeroInfNanPreserveFloat32 != VK_FALSE, | 455 | float_control.shaderSignedZeroInfNanPreserveFloat32 != VK_FALSE, |
| 456 | .support_fp64_signed_zero_nan_preserve = | 456 | .support_fp64_signed_zero_nan_preserve = |
| 457 | float_control.shaderSignedZeroInfNanPreserveFloat64 != VK_FALSE, | 457 | float_control.shaderSignedZeroInfNanPreserveFloat64 != VK_FALSE, |
| 458 | .support_vote = true, | ||
| 459 | .warp_size_potentially_larger_than_guest = device.IsWarpSizePotentiallyBiggerThanGuest(), | ||
| 458 | .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR, | 460 | .has_broken_spirv_clamp = driver_id == VK_DRIVER_ID_INTEL_PROPRIETARY_WINDOWS_KHR, |
| 459 | }; | 461 | }; |
| 460 | } | 462 | } |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index f0e5b098c..009b74f12 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -737,6 +737,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) { | |||
| 737 | subgroup_properties.maxSubgroupSize >= GuestWarpSize) { | 737 | subgroup_properties.maxSubgroupSize >= GuestWarpSize) { |
| 738 | extensions.push_back(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); | 738 | extensions.push_back(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME); |
| 739 | guest_warp_stages = subgroup_properties.requiredSubgroupSizeStages; | 739 | guest_warp_stages = subgroup_properties.requiredSubgroupSizeStages; |
| 740 | ext_subgroup_size_control = true; | ||
| 740 | } | 741 | } |
| 741 | } else { | 742 | } else { |
| 742 | is_warp_potentially_bigger = true; | 743 | is_warp_potentially_bigger = true; |
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h index 82bccc8f0..c268a4f8d 100644 --- a/src/video_core/vulkan_common/vulkan_device.h +++ b/src/video_core/vulkan_common/vulkan_device.h | |||
| @@ -193,6 +193,11 @@ public: | |||
| 193 | return ext_shader_viewport_index_layer; | 193 | return ext_shader_viewport_index_layer; |
| 194 | } | 194 | } |
| 195 | 195 | ||
| 196 | /// Returns true if the device supports VK_EXT_subgroup_size_control. | ||
| 197 | bool IsExtSubgroupSizeControlSupported() const { | ||
| 198 | return ext_subgroup_size_control; | ||
| 199 | } | ||
| 200 | |||
| 196 | /// Returns true if the device supports VK_EXT_transform_feedback. | 201 | /// Returns true if the device supports VK_EXT_transform_feedback. |
| 197 | bool IsExtTransformFeedbackSupported() const { | 202 | bool IsExtTransformFeedbackSupported() const { |
| 198 | return ext_transform_feedback; | 203 | return ext_transform_feedback; |
| @@ -297,6 +302,7 @@ private: | |||
| 297 | bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted. | 302 | bool ext_depth_range_unrestricted{}; ///< Support for VK_EXT_depth_range_unrestricted. |
| 298 | bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer. | 303 | bool ext_shader_viewport_index_layer{}; ///< Support for VK_EXT_shader_viewport_index_layer. |
| 299 | bool ext_tooling_info{}; ///< Support for VK_EXT_tooling_info. | 304 | bool ext_tooling_info{}; ///< Support for VK_EXT_tooling_info. |
| 305 | bool ext_subgroup_size_control{}; ///< Support for VK_EXT_subgroup_size_control. | ||
| 300 | bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback. | 306 | bool ext_transform_feedback{}; ///< Support for VK_EXT_transform_feedback. |
| 301 | bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color. | 307 | bool ext_custom_border_color{}; ///< Support for VK_EXT_custom_border_color. |
| 302 | bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state. | 308 | bool ext_extended_dynamic_state{}; ///< Support for VK_EXT_extended_dynamic_state. |