From 92497689ab90f6b456ebe963e13f77f0fe2c8ae6 Mon Sep 17 00:00:00 2001 From: kostyaff Date: Thu, 16 Jul 2026 00:25:59 +0300 Subject: [PATCH] [AGC] Fix VOP3 decode for V_READLANE_B32 and V_WRITELANE_B32 (#232) PR #200 moved shader files from SharpEmu.Libs/Agc/ to new projects SharpEmu.ShaderCompiler and SharpEmu.ShaderCompiler.Vulkan. This re-ports the VOP3 decode fix from PR #226 to the new file paths. Decode table (Gen5ShaderTranslator.cs): - 0x360: VMadU32U16 -> VReadlaneB32 (per RDNA2 ISA) - 0x361: VMulLoU32 -> VWritelaneB32 (0x361 was a duplicate of 0x169) - 0x373: added VMadU32U16 at its correct opcode Emission (Gen5SpirvTranslator.Alu.cs): - VWritelaneB32: per-lane conditional write via IEqual+Select, stores with guardWithExec:false (writelane bypasses exec mask) - VReadlaneB32: kept as GetRawSource(instruction, 0) simplification (correct emission with src1 lane select is a follow-up) Verified: dotnet build 0 errors/0 warnings, 26/26 tests pass, ShaderDump all programs behaved as expected. --- .../Gen5SpirvTranslator.Alu.cs | 27 +++++++++++++++++++ .../Gen5ShaderTranslator.cs | 5 ++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Alu.cs b/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Alu.cs index 6fbf059..76a054e 100644 --- a/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Alu.cs +++ b/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Alu.cs @@ -38,6 +38,33 @@ public static partial class Gen5SpirvTranslator case "VReadfirstlaneB32": result = GetRawSource(instruction, 0); break; + case "VWritelaneB32": + { + // vdst[lane(src1)] = src0 + // Per-lane: if current lane == src1, write src0, else keep old value. + var oldValue = LoadV(destination); + var src0 = GetRawSource(instruction, 0); + var laneSelect = GetRawSource(instruction, 1); + var currentLane = _subgroupInvocationIdInput != 0 + ? BitwiseAnd( + Load(_uintType, _subgroupInvocationIdInput), + UInt(RdnaWaveLaneCount - 1)) + : UInt(0); + var isTargetLane = _module.AddInstruction( + SpirvOp.IEqual, + _boolType, + currentLane, + laneSelect); + result = _module.AddInstruction( + SpirvOp.Select, + _uintType, + isTargetLane, + src0, + oldValue); + // Writelane writes to a specific lane regardless of exec mask. + StoreV(destination, result, guardWithExec: false); + return true; + } case "VCndmaskB32": { var condition = instruction.Sources.Count > 2 diff --git a/src/SharpEmu.ShaderCompiler/Gen5ShaderTranslator.cs b/src/SharpEmu.ShaderCompiler/Gen5ShaderTranslator.cs index 90df507..c4155bd 100644 --- a/src/SharpEmu.ShaderCompiler/Gen5ShaderTranslator.cs +++ b/src/SharpEmu.ShaderCompiler/Gen5ShaderTranslator.cs @@ -911,9 +911,10 @@ public static class Gen5ShaderTranslator 0x16A => "VMulHiU32", 0x16B => "VMulLoI32", 0x16C => "VMulHiI32", - 0x360 => "VMadU32U16", - 0x361 => "VMulLoU32", + 0x360 => "VReadlaneB32", + 0x361 => "VWritelaneB32", 0x362 => "VLdexpF32", + 0x373 => "VMadU32U16", 0x346 => "VLshlAddU32", 0x347 => "VAddLshlU32", 0x36D => "VAdd3U32",