18 changed files with 182 additions and 6 deletions
-
2src/shader_recompiler/CMakeLists.txt
-
4src/shader_recompiler/backend/spirv/emit_context.cpp
-
3src/shader_recompiler/backend/spirv/emit_context.h
-
9src/shader_recompiler/backend/spirv/emit_spirv.cpp
-
4src/shader_recompiler/backend/spirv/emit_spirv.h
-
58src/shader_recompiler/backend/spirv/emit_spirv_vote.cpp
-
16src/shader_recompiler/frontend/ir/ir_emitter.cpp
-
5src/shader_recompiler/frontend/ir/ir_emitter.h
-
6src/shader_recompiler/frontend/ir/opcodes.inc
-
4src/shader_recompiler/frontend/maxwell/translate/impl/not_implemented.cpp
-
52src/shader_recompiler/frontend/maxwell/translate/impl/vote.cpp
-
6src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp
-
2src/shader_recompiler/profile.h
-
1src/shader_recompiler/shader_info.h
-
7src/video_core/renderer_vulkan/vk_compute_pipeline.cpp
-
2src/video_core/renderer_vulkan/vk_pipeline_cache.cpp
-
1src/video_core/vulkan_common/vulkan_device.cpp
-
6src/video_core/vulkan_common/vulkan_device.h
@ -0,0 +1,58 @@ |
|||
// Copyright 2021 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include "shader_recompiler/backend/spirv/emit_spirv.h"
|
|||
|
|||
namespace Shader::Backend::SPIRV { |
|||
namespace { |
|||
Id LargeWarpBallot(EmitContext& ctx, Id ballot) { |
|||
const Id shift{ctx.Constant(ctx.U32[1], 5)}; |
|||
const Id local_index{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; |
|||
return ctx.OpVectorExtractDynamic(ctx.U32[1], ballot, local_index); |
|||
} |
|||
} // Anonymous namespace
|
|||
|
|||
Id EmitVoteAll(EmitContext& ctx, Id pred) { |
|||
if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
|||
return ctx.OpSubgroupAllKHR(ctx.U1, pred); |
|||
} |
|||
const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)}; |
|||
const Id active_mask{LargeWarpBallot(ctx, mask_ballot)}; |
|||
const Id ballot{LargeWarpBallot(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))}; |
|||
const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)}; |
|||
return ctx.OpIEqual(ctx.U1, lhs, active_mask); |
|||
} |
|||
|
|||
Id EmitVoteAny(EmitContext& ctx, Id pred) { |
|||
if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
|||
return ctx.OpSubgroupAnyKHR(ctx.U1, pred); |
|||
} |
|||
const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)}; |
|||
const Id active_mask{LargeWarpBallot(ctx, mask_ballot)}; |
|||
const Id ballot{LargeWarpBallot(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))}; |
|||
const Id lhs{ctx.OpBitwiseAnd(ctx.U32[1], ballot, active_mask)}; |
|||
return ctx.OpINotEqual(ctx.U1, lhs, ctx.u32_zero_value); |
|||
} |
|||
|
|||
Id EmitVoteEqual(EmitContext& ctx, Id pred) { |
|||
if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
|||
return ctx.OpSubgroupAllEqualKHR(ctx.U1, pred); |
|||
} |
|||
const Id mask_ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], ctx.true_value)}; |
|||
const Id active_mask{LargeWarpBallot(ctx, mask_ballot)}; |
|||
const Id ballot{LargeWarpBallot(ctx, ctx.OpSubgroupBallotKHR(ctx.U32[4], pred))}; |
|||
const Id lhs{ctx.OpBitwiseXor(ctx.U32[1], ballot, active_mask)}; |
|||
return ctx.OpLogicalOr(ctx.U1, ctx.OpIEqual(ctx.U1, lhs, ctx.u32_zero_value), |
|||
ctx.OpIEqual(ctx.U1, lhs, active_mask)); |
|||
} |
|||
|
|||
Id EmitSubgroupBallot(EmitContext& ctx, Id pred) { |
|||
const Id ballot{ctx.OpSubgroupBallotKHR(ctx.U32[4], pred)}; |
|||
if (!ctx.profile.warp_size_potentially_larger_than_guest) { |
|||
return ctx.OpCompositeExtract(ctx.U32[1], ballot, 0U); |
|||
} |
|||
return LargeWarpBallot(ctx, ballot); |
|||
} |
|||
|
|||
} // namespace Shader::Backend::SPIRV
|
|||
@ -0,0 +1,52 @@ |
|||
// Copyright 2021 yuzu Emulator Project
|
|||
// Licensed under GPLv2 or any later version
|
|||
// Refer to the license.txt file included.
|
|||
|
|||
#include <optional>
|
|||
|
|||
#include "common/bit_field.h"
|
|||
#include "common/common_types.h"
|
|||
#include "shader_recompiler/frontend/maxwell/translate/impl/impl.h"
|
|||
|
|||
namespace Shader::Maxwell { |
|||
namespace { |
|||
enum class VoteOp : u64 { |
|||
ALL, |
|||
ANY, |
|||
EQ, |
|||
}; |
|||
|
|||
[[nodiscard]] IR::U1 VoteOperation(IR::IREmitter& ir, const IR::U1& pred, VoteOp vote_op) { |
|||
switch (vote_op) { |
|||
case VoteOp::ALL: |
|||
return ir.VoteAll(pred); |
|||
case VoteOp::ANY: |
|||
return ir.VoteAny(pred); |
|||
case VoteOp::EQ: |
|||
return ir.VoteEqual(pred); |
|||
default: |
|||
throw NotImplementedException("Invalid VOTE op {}", vote_op); |
|||
} |
|||
} |
|||
|
|||
void Vote(TranslatorVisitor& v, u64 insn) { |
|||
union { |
|||
u64 insn; |
|||
BitField<0, 8, IR::Reg> dest_reg; |
|||
BitField<39, 3, IR::Pred> pred_a; |
|||
BitField<42, 1, u64> neg_pred_a; |
|||
BitField<45, 3, IR::Pred> pred_b; |
|||
BitField<48, 2, VoteOp> vote_op; |
|||
} const vote{insn}; |
|||
|
|||
const IR::U1 vote_pred{v.ir.GetPred(vote.pred_a, vote.neg_pred_a != 0)}; |
|||
v.ir.SetPred(vote.pred_b, VoteOperation(v.ir, vote_pred, vote.vote_op)); |
|||
v.X(vote.dest_reg, v.ir.SubgroupBallot(vote_pred)); |
|||
} |
|||
} // Anonymous namespace
|
|||
|
|||
void TranslatorVisitor::VOTE(u64 insn) { |
|||
Vote(*this, insn); |
|||
} |
|||
|
|||
} // namespace Shader::Maxwell
|
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue