From 8cc5f5364a97ad8bda500be09592f6a49111aeca Mon Sep 17 00:00:00 2001 From: nmzik Date: Tue, 20 Oct 2026 22:32:48 +0200 Subject: [PATCH] shader: share SMEM load results across emulated wave64 halves --- .../backend/spirv/spirvEmitterProgram.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp index 3a6df4256..03470687e 100644 --- a/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp +++ b/src/graphics/shader/recompiler/backend/spirv/spirvEmitterProgram.cpp @@ -233,14 +233,17 @@ void Invoke(Return (*emit)(Context&, Args...), ValueEmitContext& ctx, const IR:: } void EmitDirectInstruction(ValueEmitContext& ctx, const IR::Inst& inst) { - if (ctx.half != 0 && (inst.GetOpcode() == IR::ValueOpcode::Ballot || - inst.GetOpcode() == IR::ValueOpcode::ReadFirstLane || - inst.GetOpcode() == IR::ValueOpcode::SubgroupUMinU32)) { - // These operations combine both emulated halves into one whole-wave result. + using Op = IR::ValueOpcode; + const auto op = inst.GetOpcode(); + if (ctx.half != 0 && + (op == Op::Ballot || op == Op::ReadFirstLane || op == Op::SubgroupUMinU32 || + op == Op::ReadConstBuffer || + (op == Op::LoadAddressU32 && ctx.Memory(inst).kind == IR::ResourceKind::ScalarAddress))) { + // Whole-wave results and SMEM loads (SGPR operands, no EXEC) are identical in both halves. ctx.Define(inst, ctx.other_half->Result(inst)); return; } - switch (inst.GetOpcode()) { + switch (op) { #define VALUE_OPCODE(name, ...) \ case IR::ValueOpcode::name: return Invoke(Emit##name, ctx, inst); #include "graphics/shader/recompiler/ir/opcodes/ValueOpcodes.inc"