Browse Source

[spir-v] Added fallback for unsupported quads + shader-stage checks

vk-experiments4
CamilleLaVey 1 month ago
committed by crueter
parent
commit
2e1f4cb84b
  1. 6
      src/shader_recompiler/backend/spirv/emit_spirv.cpp
  2. 8
      src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp
  3. 10
      src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp

6
src/shader_recompiler/backend/spirv/emit_spirv.cpp

@ -446,8 +446,10 @@ void SetupCapabilities(const Profile& profile, const Info& info, EmitContext& ct
ctx.AddCapability(spv::Capability::GroupNonUniformVote);
}
}
if (info.uses_quad_shuffles && profile.support_quad_shuffles) {
ctx.AddCapability(spv::Capability::GroupNonUniformQuad);
if (info.uses_quad_shuffles) {
if (profile.support_quad_shuffles) {
ctx.AddCapability(spv::Capability::GroupNonUniformQuad);
}
ctx.AddCapability(spv::Capability::GroupNonUniformShuffle);
}
if (info.uses_int64_bit_atomics && profile.support_int64_atomics) {

8
src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp

@ -224,7 +224,13 @@ Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id
}
Id EmitQuadBroadcast(EmitContext& ctx, Id value, Id lane) {
return ctx.OpGroupNonUniformQuadBroadcast(ctx.U32[1], SubgroupScope(ctx), value, lane);
if (ctx.profile.support_quad_shuffles) {
return ctx.OpGroupNonUniformQuadBroadcast(ctx.U32[1], SubgroupScope(ctx), value, lane);
}
const Id base{ctx.OpBitwiseAnd(ctx.U32[1], GetThreadId(ctx), ctx.Const(~3u))};
const Id local_lane{ctx.OpBitwiseAnd(ctx.U32[1], lane, ctx.Const(3u))};
const Id src_thread_id{ctx.OpBitwiseOr(ctx.U32[1], base, local_lane)};
return ctx.OpGroupNonUniformShuffle(ctx.U32[1], SubgroupScope(ctx), value, src_thread_id);
}
Id EmitQuadSwap(EmitContext& ctx, Id value, Id direction) {

10
src/shader_recompiler/frontend/maxwell/translate/impl/warp_shuffle.cpp

@ -36,9 +36,7 @@ enum class ShuffleMode : u64 {
}
}
// SHFL mask encoding for quad-constrained operations:
// bits [0:4] = clamp = 3, bits [8:12] = seg_mask = 28 (0x1C)
constexpr u32 QUAD_MASK = (28u << 8) | 3u; // 0x1C03
constexpr u32 QUAD_MASK = (28u << 8) | 3u;
void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32& mask,
bool index_is_imm, u32 index_imm, bool mask_is_imm, u32 mask_imm) {
@ -50,15 +48,15 @@ void Shuffle(TranslatorVisitor& v, u64 insn, const IR::U32& index, const IR::U32
BitField<48, 3, IR::Pred> pred;
} const shfl{insn};
if (mask_is_imm && mask_imm == QUAD_MASK && index_is_imm) {
const bool is_quad_candidate{mask_is_imm && mask_imm == QUAD_MASK && index_is_imm &&
v.env.ShaderStage() == Stage::Fragment};
if (is_quad_candidate) {
if (shfl.mode == ShuffleMode::IDX && index_imm <= 3) {
// SHFL IDX with lane 0-3 in a quad → QuadBroadcast
v.X(shfl.dest_reg, v.ir.QuadBroadcast(v.X(shfl.src_reg), v.ir.Imm32(index_imm)));
v.ir.SetPred(shfl.pred, v.ir.Imm1(true));
return;
}
if (shfl.mode == ShuffleMode::BFLY && index_imm >= 1 && index_imm <= 3) {
// SHFL BFLY index 1/2/3 in a quad → QuadSwap direction 0/1/2
v.X(shfl.dest_reg, v.ir.QuadSwap(v.X(shfl.src_reg), v.ir.Imm32(index_imm - 1)));
v.ir.SetPred(shfl.pred, v.ir.Imm1(true));
return;

Loading…
Cancel
Save