mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 10:56:20 +08:00
AGC: reduce inactive trace and draw allocations (#308)
This commit is contained in:
@@ -3729,13 +3729,16 @@ public static partial class AgcExports
|
|||||||
_labelProducers.Add(producer);
|
_labelProducers.Add(producer);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var waiting in GpuWaitRegistry.SnapshotInRange(memory, address, length))
|
if (_traceAgc)
|
||||||
{
|
{
|
||||||
TraceAgc(
|
foreach (var waiting in GpuWaitRegistry.SnapshotInRange(memory, address, length))
|
||||||
$"agc.wait_producer_scheduled label=0x{waiting.Address:X16} " +
|
{
|
||||||
$"waiters={waiting.Count} producer_seq={producer.Sequence} " +
|
TraceAgc(
|
||||||
$"queue={producer.QueueName} submission={producer.SubmissionId} " +
|
$"agc.wait_producer_scheduled label=0x{waiting.Address:X16} " +
|
||||||
$"packet=0x{packetAddress:X16} action='{debugName}'");
|
$"waiters={waiting.Count} producer_seq={producer.Sequence} " +
|
||||||
|
$"queue={producer.QueueName} submission={producer.SubmissionId} " +
|
||||||
|
$"packet=0x{packetAddress:X16} action='{debugName}'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return producer;
|
return producer;
|
||||||
@@ -3753,16 +3756,19 @@ public static partial class AgcExports
|
|||||||
producer.Completed = true;
|
producer.Completed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var waiting in GpuWaitRegistry.SnapshotInRange(
|
if (_traceAgc)
|
||||||
producer.Memory,
|
|
||||||
producer.Address,
|
|
||||||
producer.Length))
|
|
||||||
{
|
{
|
||||||
TraceAgc(
|
foreach (var waiting in GpuWaitRegistry.SnapshotInRange(
|
||||||
$"agc.wait_producer_completed label=0x{waiting.Address:X16} " +
|
producer.Memory,
|
||||||
$"waiters={waiting.Count} producer_seq={producer.Sequence} " +
|
producer.Address,
|
||||||
$"queue={producer.QueueName} submission={producer.SubmissionId} " +
|
producer.Length))
|
||||||
$"action='{producer.DebugName}'");
|
{
|
||||||
|
TraceAgc(
|
||||||
|
$"agc.wait_producer_completed label=0x{waiting.Address:X16} " +
|
||||||
|
$"waiters={waiting.Count} producer_seq={producer.Sequence} " +
|
||||||
|
$"queue={producer.QueueName} submission={producer.SubmissionId} " +
|
||||||
|
$"action='{producer.DebugName}'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3807,6 +3813,14 @@ public static partial class AgcExports
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Producer-backed waits are trace-only. Keep the producer lookup above
|
||||||
|
// because producerless waits are always warned, but do not build the
|
||||||
|
// detailed condition strings when AGC tracing is disabled.
|
||||||
|
if (producer is not null && !_traceAgc)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
var prefix = stale ? "agc.wait_stale" : "agc.wait_suspended";
|
var prefix = stale ? "agc.wait_stale" : "agc.wait_suspended";
|
||||||
var current = currentValue.HasValue
|
var current = currentValue.HasValue
|
||||||
? $"0x{currentValue.Value:X16}"
|
? $"0x{currentValue.Value:X16}"
|
||||||
@@ -6088,54 +6102,39 @@ public static partial class AgcExports
|
|||||||
_graphicsShaderCache.TryAdd(shaderKey, compiled);
|
_graphicsShaderCache.TryAdd(shaderKey, compiled);
|
||||||
}
|
}
|
||||||
|
|
||||||
var imageBindings = pixelEvaluation.ImageBindings
|
|
||||||
.Concat(exportEvaluation.ImageBindings);
|
|
||||||
var textures = new List<TranslatedImageBinding>(
|
var textures = new List<TranslatedImageBinding>(
|
||||||
pixelEvaluation.ImageBindings.Count +
|
pixelEvaluation.ImageBindings.Count +
|
||||||
exportEvaluation.ImageBindings.Count);
|
exportEvaluation.ImageBindings.Count);
|
||||||
foreach (var binding in imageBindings)
|
if (!TryAppendTranslatedImageBindings(
|
||||||
|
pixelEvaluation.ImageBindings,
|
||||||
|
textures,
|
||||||
|
pixelShaderAddress,
|
||||||
|
exportShaderAddress,
|
||||||
|
out error) ||
|
||||||
|
!TryAppendTranslatedImageBindings(
|
||||||
|
exportEvaluation.ImageBindings,
|
||||||
|
textures,
|
||||||
|
pixelShaderAddress,
|
||||||
|
exportShaderAddress,
|
||||||
|
out error))
|
||||||
{
|
{
|
||||||
if (!TryDecodeTextureDescriptor(binding.ResourceDescriptor, out var texture))
|
ReturnPooledEvaluationArrays(exportEvaluation);
|
||||||
{
|
ReturnPooledEvaluationArrays(pixelEvaluation);
|
||||||
// A garbage/zeroed texture descriptor (from a per-draw descriptor
|
return false;
|
||||||
// setup race — the same root as scalar-load-failed) would drop
|
|
||||||
// the whole draw, so Demon's Souls' deferred-lighting/composite
|
|
||||||
// passes that produce the composite's feeder targets never run
|
|
||||||
// and the frame stays black. Substitute a 1x1 fallback binding so
|
|
||||||
// the pass still renders (that one sampled texture reads black)
|
|
||||||
// rather than dropping it entirely. STRICT reverts.
|
|
||||||
if (_strictShaderDescriptors)
|
|
||||||
{
|
|
||||||
error = $"invalid texture descriptor at pc=0x{binding.Pc:X}";
|
|
||||||
ReturnPooledEvaluationArrays(exportEvaluation);
|
|
||||||
ReturnPooledEvaluationArrays(pixelEvaluation);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
texture = new TextureDescriptor(
|
|
||||||
0, 1, 1, Gen5TextureFormatR8G8B8A8Unorm, 0, 0, 0, 0, 0, 1, 0xFAC);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_traceAgcShader || _tracePixelShaderAddress == pixelShaderAddress)
|
|
||||||
{
|
|
||||||
Console.Error.WriteLine(
|
|
||||||
"[LOADER][TRACE] " +
|
|
||||||
$"agc.texture_binding ps=0x{pixelShaderAddress:X16} es=0x{exportShaderAddress:X16} " +
|
|
||||||
$"pc=0x{binding.Pc:X} op={binding.Opcode} storage={(Gen5ShaderTranslator.IsStorageImageOperation(binding.Opcode) ? 1 : 0)} " +
|
|
||||||
$"decoded={FormatTextureDescriptor(texture)} " +
|
|
||||||
$"raw={FormatShaderDwords(binding.ResourceDescriptor)} sampler={FormatShaderDwords(binding.SamplerDescriptor)}");
|
|
||||||
}
|
|
||||||
textures.Add(
|
|
||||||
new TranslatedImageBinding(
|
|
||||||
texture,
|
|
||||||
Gen5ShaderTranslator.IsStorageImageOperation(binding.Opcode),
|
|
||||||
binding.MipLevel ?? 0,
|
|
||||||
binding.SamplerDescriptor));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var globalMemoryBindings = pixelEvaluation.GlobalMemoryBindings
|
var globalMemoryBindings = new Gen5GlobalMemoryBinding[
|
||||||
.Concat(exportEvaluation.GlobalMemoryBindings)
|
pixelEvaluation.GlobalMemoryBindings.Count +
|
||||||
.ToArray();
|
exportEvaluation.GlobalMemoryBindings.Count];
|
||||||
|
for (var index = 0; index < pixelEvaluation.GlobalMemoryBindings.Count; index++)
|
||||||
|
{
|
||||||
|
globalMemoryBindings[index] = pixelEvaluation.GlobalMemoryBindings[index];
|
||||||
|
}
|
||||||
|
for (var index = 0; index < exportEvaluation.GlobalMemoryBindings.Count; index++)
|
||||||
|
{
|
||||||
|
globalMemoryBindings[pixelEvaluation.GlobalMemoryBindings.Count + index] =
|
||||||
|
exportEvaluation.GlobalMemoryBindings[index];
|
||||||
|
}
|
||||||
IReadOnlyList<Gen5VertexInputBinding> vertexInputs =
|
IReadOnlyList<Gen5VertexInputBinding> vertexInputs =
|
||||||
exportEvaluation.VertexInputs ?? [];
|
exportEvaluation.VertexInputs ?? [];
|
||||||
state.UcRegisters.TryGetValue(VgtPrimitiveType, out var primitiveType);
|
state.UcRegisters.TryGetValue(VgtPrimitiveType, out var primitiveType);
|
||||||
@@ -6150,6 +6149,13 @@ public static partial class AgcExports
|
|||||||
renderTargets[index].NumberType);
|
renderTargets[index].NumberType);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var pixelUserDataCount = Math.Min(pixelEvaluation.InitialScalarRegisters.Count, 8);
|
||||||
|
var pixelUserData = new uint[pixelUserDataCount];
|
||||||
|
for (var index = 0; index < pixelUserDataCount; index++)
|
||||||
|
{
|
||||||
|
pixelUserData[index] = pixelEvaluation.InitialScalarRegisters[index];
|
||||||
|
}
|
||||||
|
|
||||||
draw = new TranslatedGuestDraw(
|
draw = new TranslatedGuestDraw(
|
||||||
exportShaderAddress,
|
exportShaderAddress,
|
||||||
pixelShaderAddress,
|
pixelShaderAddress,
|
||||||
@@ -6171,7 +6177,7 @@ public static partial class AgcExports
|
|||||||
textures,
|
textures,
|
||||||
vertexInputs,
|
vertexInputs,
|
||||||
pixelEvaluation.InitialScalarRegisters),
|
pixelEvaluation.InitialScalarRegisters),
|
||||||
pixelEvaluation.InitialScalarRegisters.Take(8).ToArray(),
|
pixelUserData,
|
||||||
state.CxRegisters.TryGetValue(CbBlend0Control, out var rawBlend) ? rawBlend : 0,
|
state.CxRegisters.TryGetValue(CbBlend0Control, out var rawBlend) ? rawBlend : 0,
|
||||||
state.CxRegisters.TryGetValue(
|
state.CxRegisters.TryGetValue(
|
||||||
CbColor0Info + renderTargets.FirstOrDefault().Slot * CbColorRegisterStride,
|
CbColor0Info + renderTargets.FirstOrDefault().Slot * CbColorRegisterStride,
|
||||||
@@ -6183,6 +6189,55 @@ public static partial class AgcExports
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool TryAppendTranslatedImageBindings(
|
||||||
|
IReadOnlyList<Gen5ImageBinding> bindings,
|
||||||
|
List<TranslatedImageBinding> textures,
|
||||||
|
ulong pixelShaderAddress,
|
||||||
|
ulong exportShaderAddress,
|
||||||
|
out string error)
|
||||||
|
{
|
||||||
|
foreach (var binding in bindings)
|
||||||
|
{
|
||||||
|
if (!TryDecodeTextureDescriptor(binding.ResourceDescriptor, out var texture))
|
||||||
|
{
|
||||||
|
// A garbage/zeroed texture descriptor (from a per-draw descriptor
|
||||||
|
// setup race — the same root as scalar-load-failed) would drop
|
||||||
|
// the whole draw, so deferred-lighting/composite passes that
|
||||||
|
// produce the composite's feeder targets never run. Keep the
|
||||||
|
// existing 1x1 fallback unless strict diagnostics are requested.
|
||||||
|
if (_strictShaderDescriptors)
|
||||||
|
{
|
||||||
|
error = $"invalid texture descriptor at pc=0x{binding.Pc:X}";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
texture = new TextureDescriptor(
|
||||||
|
0, 1, 1, Gen5TextureFormatR8G8B8A8Unorm, 0, 0, 0, 0, 0, 1, 0xFAC);
|
||||||
|
}
|
||||||
|
|
||||||
|
var isStorage =
|
||||||
|
Gen5ShaderTranslator.IsStorageImageOperation(binding.Opcode);
|
||||||
|
if (_traceAgcShader || _tracePixelShaderAddress == pixelShaderAddress)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine(
|
||||||
|
"[LOADER][TRACE] " +
|
||||||
|
$"agc.texture_binding ps=0x{pixelShaderAddress:X16} es=0x{exportShaderAddress:X16} " +
|
||||||
|
$"pc=0x{binding.Pc:X} op={binding.Opcode} storage={(isStorage ? 1 : 0)} " +
|
||||||
|
$"decoded={FormatTextureDescriptor(texture)} " +
|
||||||
|
$"raw={FormatShaderDwords(binding.ResourceDescriptor)} sampler={FormatShaderDwords(binding.SamplerDescriptor)}");
|
||||||
|
}
|
||||||
|
textures.Add(
|
||||||
|
new TranslatedImageBinding(
|
||||||
|
texture,
|
||||||
|
isStorage,
|
||||||
|
binding.MipLevel ?? 0,
|
||||||
|
binding.SamplerDescriptor));
|
||||||
|
}
|
||||||
|
|
||||||
|
error = string.Empty;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
private static int _tracedAstroTitlePixelGlobals;
|
private static int _tracedAstroTitlePixelGlobals;
|
||||||
private static int _tracedAstroTitlePixelGlobalProbe;
|
private static int _tracedAstroTitlePixelGlobalProbe;
|
||||||
|
|
||||||
@@ -6621,16 +6676,21 @@ public static partial class AgcExports
|
|||||||
|
|
||||||
var target = targets[0];
|
var target = targets[0];
|
||||||
var scissor = DecodeScissor(registers, target.Width, target.Height);
|
var scissor = DecodeScissor(registers, target.Width, target.Height);
|
||||||
return new GuestRenderState(
|
var blends = new GuestBlendState[targets.Count];
|
||||||
targets.Select(target =>
|
for (var index = 0; index < targets.Count; index++)
|
||||||
|
{
|
||||||
|
var blend = DecodeBlendState(registers, targets[index].Slot);
|
||||||
|
blends[index] = blend with
|
||||||
{
|
{
|
||||||
var blend = DecodeBlendState(registers, target.Slot);
|
WriteMask = blend.WriteMask &
|
||||||
return blend with
|
GetPixelColorExportMask(
|
||||||
{
|
pixelColorExportMasks,
|
||||||
WriteMask = blend.WriteMask &
|
targets[index].Slot),
|
||||||
GetPixelColorExportMask(pixelColorExportMasks, target.Slot),
|
};
|
||||||
};
|
}
|
||||||
}).ToArray(),
|
|
||||||
|
return new GuestRenderState(
|
||||||
|
blends,
|
||||||
scissor,
|
scissor,
|
||||||
DecodeViewport(registers, target.Width, target.Height, scissor),
|
DecodeViewport(registers, target.Width, target.Height, scissor),
|
||||||
DecodeRasterState(registers),
|
DecodeRasterState(registers),
|
||||||
|
|||||||
Reference in New Issue
Block a user