shader: implement RDNA2 DS masked OR through shared atomic updates

Co-authored-by: shadowbeat070 <70843316+shadowbeat070@users.noreply.github.com>
This commit is contained in:
nmzik
2026-10-04 17:18:35 +04:00
parent c3f4962715
commit 98557a83b6
11 changed files with 144 additions and 28 deletions
@@ -232,6 +232,7 @@ void EmitStoreMemory(ValueEmitContext& ctx, const IR::Inst& ins
uint32_t EmitAtomic32(ValueEmitContext& ctx, const IR::Inst& inst);
uint32_t EmitBufferAtomic64(ValueEmitContext& ctx, const IR::Inst& inst);
void EmitSharedAtomic64(ValueEmitContext& ctx, const IR::Inst& inst);
void EmitSharedAtomicMaskedOr32(ValueEmitContext& ctx, const IR::Inst& inst);
uint32_t EmitBufferFloatAtomic(ValueEmitContext& ctx, const IR::Inst& inst);
void EmitSharedFloatAtomic(ValueEmitContext& ctx, const IR::Inst& inst);
uint32_t EmitSharedIncDec(ValueEmitContext& ctx, const IR::Inst& inst);
@@ -259,8 +259,14 @@ uint32_t ByteAddress(ValueEmitContext& ctx, const IR::Inst& inst, const IR::Memo
}
uint32_t DwordIndex(ValueEmitContext& ctx, const IR::Inst& inst, const IR::MemoryInfo& mem) {
auto address = ByteAddress(ctx, inst, mem);
if (mem.kind == IR::ResourceKind::Lds || mem.kind == IR::ResourceKind::Gds) {
// RDNA2 DS region addresses retain bits [15:2] after adding the byte offset.
address = Binary(ctx.state, spv::OpBitwiseAnd, TypeU32(ctx.state), address,
ConstantU32(ctx.state, 0xffffu));
}
return Binary(ctx.state, spv::OpShiftRightLogical, TypeU32(ctx.state),
ByteAddress(ctx, inst, mem), ConstantU32(ctx.state, 2));
address, ConstantU32(ctx.state, 2));
}
uint32_t LoadWordInBounds(ValueEmitContext& ctx, const MemoryResourceAccess& resource,
@@ -1415,6 +1421,15 @@ uint32_t EmitSharedIncDec(ValueEmitContext& ctx, const IR::Inst& inst) {
return EmitAtomicUpdate(ctx, inst, ctx.Memory(inst), replacement);
}
void EmitSharedAtomicMaskedOr32(ValueEmitContext& ctx, const IR::Inst& inst) {
const auto keep = Unary(ctx.state, spv::OpNot, TypeU32(ctx.state), ctx.Arg(inst, 1));
EmitAtomicUpdate(ctx, inst, ctx.Memory(inst),
[keep](EmitterState& state, uint32_t old, uint32_t value) {
return Binary(state, spv::OpBitwiseOr, TypeU32(state),
Binary(state, spv::OpBitwiseAnd, TypeU32(state), old, keep), value);
});
}
uint32_t EmitSwizzleU32(ValueEmitContext& ctx, const IR::Inst& inst) {
auto& state = ctx.state;
state.builder.AddFunction(spv::OpStore, ctx.scratch_u32_variable, ctx.Arg(inst, 0));