fix(agc): skip CB metadata draws for EliminateFastClear/Fmask/DCC

CB_COLOR_CONTROL modes 2/5/6 are colour-buffer metadata ops; applying
the bound shader as a normal colour draw corrupts subsequent composites.
Decode MODE from bits [6:4] and return before translate.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
MarcelMediaDev
2026-07-23 00:52:39 +01:00
parent 4e1b5606d5
commit b7a461757e
+51 -2
View File
@@ -299,6 +299,7 @@ public static partial class AgcExports
private static int _tracedVertexRangeCount; private static int _tracedVertexRangeCount;
private static long _dcbWaitRegMemTraceCount; private static long _dcbWaitRegMemTraceCount;
private static long _createShaderTraceCount; private static long _createShaderTraceCount;
private static long _cbMetadataSkipTraceCount;
private static long _packetPayloadTraceCount; private static long _packetPayloadTraceCount;
private static bool _tracedMissingPixelShaderBindings; private static bool _tracedMissingPixelShaderBindings;
private static long _unsatisfiedWaitTraceCount; private static long _unsatisfiedWaitTraceCount;
@@ -5670,6 +5671,25 @@ public static partial class AgcExports
} }
state.TranslatedDraw = null; state.TranslatedDraw = null;
state.GuestDrawKind = GuestDrawKind.None; state.GuestDrawKind = GuestDrawKind.None;
// CB modes EliminateFastClear / FmaskDecompress / DccDecompress run
// colour-buffer metadata ops. The bound shader is only a vehicle and
// must not be applied as a normal colour draw.
if (TryGetCbColorControlMode(state.CxRegisters, out var cbMode) &&
IsCbMetadataColorMode(cbMode))
{
if (_traceAgcShader || ShouldTraceHotPath(ref _cbMetadataSkipTraceCount))
{
TraceAgcShader(
$"agc.cb_metadata_skip seq={drawSequence} mode={cbMode} " +
$"es=0x{(hasExportShader ? exportShaderAddress : 0):X16} " +
$"ps=0x{(hasPixelShader ? pixelShaderAddress : 0):X16} " +
$"vertices={vertexCount}");
}
return;
}
foreach (var target in renderTargets) foreach (var target in renderTargets)
{ {
state.KnownRenderTargets[target.Address] = target; state.KnownRenderTargets[target.Address] = target;
@@ -7281,6 +7301,35 @@ public static partial class AgcExports
return hash; return hash;
} }
private enum CbColorMode : byte
{
Disable = 0,
Normal = 1,
EliminateFastClear = 2,
Resolve = 3,
FmaskDecompress = 5,
DccDecompress = 6,
}
private static bool TryGetCbColorControlMode(
IReadOnlyDictionary<uint, uint> registers,
out uint mode)
{
mode = 0;
if (!registers.TryGetValue(CbColorControl, out var colorControl))
{
return false;
}
mode = (colorControl >> 4) & 0x7u;
return true;
}
private static bool IsCbMetadataColorMode(uint mode) =>
mode is (uint)CbColorMode.EliminateFastClear or
(uint)CbColorMode.FmaskDecompress or
(uint)CbColorMode.DccDecompress;
private static bool TryGetHardwareColorResolveTargets( private static bool TryGetHardwareColorResolveTargets(
IReadOnlyDictionary<uint, uint> registers, IReadOnlyDictionary<uint, uint> registers,
out RenderTargetDescriptor source, out RenderTargetDescriptor source,
@@ -7288,8 +7337,8 @@ public static partial class AgcExports
{ {
source = default; source = default;
destination = default; destination = default;
if (!registers.TryGetValue(CbColorControl, out var colorControl) || if (!TryGetCbColorControlMode(registers, out var mode) ||
((colorControl >> 4) & 0x7u) != 3u) mode != (uint)CbColorMode.Resolve)
{ {
return false; return false;
} }