diff --git a/src/SharpEmu.Libs/Diagnostics/DccWriterTrace.cs b/src/SharpEmu.Libs/Diagnostics/DccWriterTrace.cs index 88efe4f..ed00daf 100644 --- a/src/SharpEmu.Libs/Diagnostics/DccWriterTrace.cs +++ b/src/SharpEmu.Libs/Diagnostics/DccWriterTrace.cs @@ -9,15 +9,19 @@ namespace SharpEmu.Libs.Diagnostics; internal static class DccWriterTrace { - private const int MaxReports = 64; + private const int MaxReports = 256; private const int MaxFrames = 12; private static readonly bool DccEnabled = Environment.GetEnvironmentVariable("SHARPEMU_TRACE_DCC_WRITERS") == "1"; - private static readonly ulong TargetAddress = ParseAddress(Environment.GetEnvironmentVariable("SHARPEMU_TRACE_WRITER_ADDRESS")); + private static readonly ulong[] TargetAddresses = (Environment.GetEnvironmentVariable("SHARPEMU_TRACE_WRITER_ADDRESS") ?? string.Empty) + .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) + .Select(ParseAddress) + .Where(address => address != 0) + .ToArray(); - public static readonly bool Enabled = DccEnabled || TargetAddress != 0; + public static readonly bool Enabled = DccEnabled || TargetAddresses.Length != 0; [ThreadStatic] public static ulong CurrentProgram; @@ -43,7 +47,7 @@ internal static class DccWriterTrace public static void Record(IGuestImageCache images, ulong address, ulong size) { - var targeted = TargetAddress != 0 && TargetAddress >= address && TargetAddress - address < size; + var targeted = TargetAddresses.Any(target => target >= address && target - address < size); if (_reported.Count >= MaxReports || (!targeted && !(DccEnabled && images.OverlapsDccMetadata(address, size))) || !_reported.Add((address, size, CurrentProgram))) { diff --git a/src/SharpEmu.Libs/Diagnostics/GpuReadTrace.cs b/src/SharpEmu.Libs/Diagnostics/GpuReadTrace.cs index 02b3ede..ebbf945 100644 --- a/src/SharpEmu.Libs/Diagnostics/GpuReadTrace.cs +++ b/src/SharpEmu.Libs/Diagnostics/GpuReadTrace.cs @@ -17,6 +17,30 @@ internal static class GpuReadTrace public static string? CurrentStage; private static readonly HashSet<(ulong Shader, ulong Page, bool Table)> _reported = new(); + private static readonly Dictionary _values = new(); + private static long _nextValueReport = System.Diagnostics.Stopwatch.GetTimestamp(); + + public static void RecordValue(ulong address, uint word) + { + lock (_values) + { + _values[address] = _values.TryGetValue(address, out var entry) + ? (entry.Reads + 1, entry.Changes + (entry.Last != word ? 1 : 0), word, entry.First, entry.Shader) + : (1, 0, word, word, CurrentShader); + var now = System.Diagnostics.Stopwatch.GetTimestamp(); + if (now < _nextValueReport) + { + return; + } + + _nextValueReport = now + System.Diagnostics.Stopwatch.Frequency * 5; + foreach (var (key, value) in _values.OrderByDescending(pair => pair.Value.Reads).Take(16)) + { + Console.Error.WriteLine( + $"[GPU][SYNC_READ_VALUE] address=0x{key:X16} reads={value.Reads} changes={value.Changes} first=0x{value.First:X8} last=0x{value.Last:X8} shader=0x{value.Shader:X16}"); + } + } + } public static void Record(ulong address, bool table) { diff --git a/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs b/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs index 2ff726a..e380648 100644 --- a/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs +++ b/src/SharpEmu.Libs/VideoOut/VulkanVideoPresenter.Pipelines.cs @@ -100,6 +100,7 @@ internal static unsafe partial class VulkanVideoPresenter { using var profile = ResourceMaterializationProfile.Measure(ResourceMaterializationProfile.Phase.GuestRead); word = 0; + var synchronized = false; if (IsCleanReadPage(address, sizeof(uint))) { if (TryGetAliasPointer(address, sizeof(uint), out var alias)) @@ -132,6 +133,8 @@ internal static unsafe partial class VulkanVideoPresenter { return false; } + + synchronized = true; } else { @@ -146,6 +149,11 @@ internal static unsafe partial class VulkanVideoPresenter } word = System.Buffers.Binary.BinaryPrimitives.ReadUInt32LittleEndian(bytes); + if (Diagnostics.GpuReadTrace.Enabled && synchronized) + { + Diagnostics.GpuReadTrace.RecordValue(address, word); + } + return true; }