diff --git a/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Resources.cs b/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Resources.cs index d82b9c5..ce3d1f4 100644 --- a/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Resources.cs +++ b/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.Resources.cs @@ -112,6 +112,9 @@ public static partial class Gen5SpirvTranslator _usesPixelValidMask = _stage == Gen5SpirvStage.Pixel && request.Program.Instructions.Any(static instruction => instruction.Control is Gen5ExportControl { ValidMask: true }); + _pixelExecExcludesHelpers = + _stage == Gen5SpirvStage.Pixel && PixelLiveExec && + request.Program.Instructions.Any(static instruction => instruction.Opcode is "DsAppend" or "DsConsume"); _enableGraphicsSubgroupOperations = _stage == Gen5SpirvStage.Compute || request.EnableGraphicsSubgroupOperations; _waveLaneCount = request.WaveSize == 64 ? 64u : 32u; _localSizeX = Math.Max(request.LocalSizeX, 1); @@ -2043,6 +2046,11 @@ public static partial class Gen5SpirvTranslator } var active = Load(_boolType, _exec); + if (_stage == Gen5SpirvStage.Pixel) + { + active = LogicalAnd(active, _module.AddInstruction(SpirvOp.LogicalNot, _boolType, Load(_boolType, HelperInvocationInput()))); + } + var activeMask = BooleanToWaveMask(active); var activeLow = Narrow(activeMask); var activeHigh = Narrow(ShiftRightLogical64(activeMask, ULong(32))); diff --git a/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.cs b/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.cs index b7fe844..da1c589 100644 --- a/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.cs +++ b/src/SharpEmu.ShaderCompiler.Vulkan/Gen5SpirvTranslator.cs @@ -67,6 +67,10 @@ public static partial class Gen5SpirvTranslator private readonly Gen5SpirvStage _stage; private readonly IReadOnlyList _pixelOutputBindings; private readonly bool _usesPixelValidMask; + private readonly bool _pixelExecExcludesHelpers; + + private static readonly bool PixelLiveExec = !string.Equals( + Environment.GetEnvironmentVariable("SHARPEMU_PS_LIVE_EXEC"), "0", StringComparison.Ordinal); private readonly bool _enableGraphicsSubgroupOperations; private readonly uint _waveLaneCount; private readonly IWaveLowering _waveLowering; @@ -1147,6 +1151,10 @@ public static partial class Gen5SpirvTranslator Store(_pixelValidMaskActive, _module.ConstantBool(true)); } _waveLowering.InitializeMasks(); + if (_pixelExecExcludesHelpers) + { + _waveLowering.StoreWaveMask(126, _module.AddInstruction(SpirvOp.LogicalNot, _boolType, Load(_boolType, HelperInvocationInput()))); + } // Primitive (NGG) vertex programs rebuild EXEC from the merged wave info in s3: // vertex count in bits 0-7, primitive count in bits 8-15. Left at zero, EXEC @@ -7720,7 +7728,7 @@ public static partial class Gen5SpirvTranslator private bool IsExecKnownFull(uint pc) { - if (!ExecGuardElision || !_request.EnableExecGuardElision || _pairedLanes) + if (!ExecGuardElision || !_request.EnableExecGuardElision || _pairedLanes || _pixelExecExcludesHelpers) { return false; } @@ -7741,7 +7749,7 @@ public static partial class Gen5SpirvTranslator if (!_observationPlanBuilt) { _observationPlanBuilt = true; - _observationPlan = ExecSelectElimination + _observationPlan = ExecSelectElimination && !_pixelExecExcludesHelpers ? Ir.Gen5VectorObservationAnalysis.Analyze(_request.Program, wave32: _waveLaneCount == 32) : null; }