[Profile] Attribute render thread GPU waits to their call sites
This commit is contained in:
parent
22ec74e085
commit
e5c2755789
|
|
@ -172,10 +172,13 @@ internal sealed unsafe class VulkanAsyncReadback : IDisposable
|
|||
PSemaphores = &semaphore,
|
||||
PValues = &signalValue,
|
||||
};
|
||||
var waitStart = VideoOut.GpuWaitSiteProfile.Begin();
|
||||
using (VideoOut.RenderPhaseProfile.MeasureDetail(VideoOut.RenderPhaseProfile.Phase.GpuCompletionWait))
|
||||
{
|
||||
Require(vk.WaitSemaphores(_device.Device, &waitInfo, ulong.MaxValue), "vkWaitSemaphores(readback)");
|
||||
}
|
||||
|
||||
VideoOut.GpuWaitSiteProfile.End(waitStart);
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
|
|
|||
|
|
@ -220,10 +220,13 @@ internal sealed unsafe class VulkanTickDevice : IGpuTickDevice
|
|||
PValues = &tick,
|
||||
};
|
||||
Result result;
|
||||
var waitStart = GpuWaitSiteProfile.Begin();
|
||||
using (RenderPhaseProfile.MeasureDetail(RenderPhaseProfile.Phase.GpuCompletionWait))
|
||||
{
|
||||
result = _vk.WaitSemaphores(_device, &waitInfo, ulong.MaxValue);
|
||||
}
|
||||
|
||||
GpuWaitSiteProfile.End(waitStart);
|
||||
failure = result.ToString();
|
||||
return result == Result.Success && WaitRetired(tick);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,96 @@
|
|||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace SharpEmu.Libs.VideoOut;
|
||||
|
||||
internal static class GpuWaitSiteProfile
|
||||
{
|
||||
private const int SiteFrames = 5;
|
||||
|
||||
private static readonly object _gate = new();
|
||||
private static readonly Dictionary<string, (long Count, long Ticks)> _sites = new(StringComparer.Ordinal);
|
||||
|
||||
private static readonly HashSet<string> PlumbingTypes = new(StringComparer.Ordinal)
|
||||
{
|
||||
"GpuWaitSiteProfile",
|
||||
"TickTimeline",
|
||||
"SubmissionScheduler",
|
||||
"VulkanTickDevice",
|
||||
"VulkanAsyncReadback",
|
||||
"GpuWorkerRelay",
|
||||
"GpuWaitSpin",
|
||||
};
|
||||
|
||||
public static long Begin() => RenderPhaseProfile.DetailMeasurementsEnabled ? Stopwatch.GetTimestamp() : 0;
|
||||
|
||||
public static void End(long start)
|
||||
{
|
||||
if (start == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var elapsed = Stopwatch.GetTimestamp() - start;
|
||||
var site = Site();
|
||||
lock (_gate)
|
||||
{
|
||||
_sites.TryGetValue(site, out var entry);
|
||||
_sites[site] = (entry.Count + 1, entry.Ticks + elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
private static string Site()
|
||||
{
|
||||
var names = new List<string>(SiteFrames);
|
||||
foreach (var frame in new StackTrace(2, false).GetFrames())
|
||||
{
|
||||
if (frame.GetMethod() is not { } method)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var type = method.DeclaringType;
|
||||
while (type is { DeclaringType: not null } && type.Name.StartsWith('<'))
|
||||
{
|
||||
type = type.DeclaringType;
|
||||
}
|
||||
|
||||
var typeName = type?.Name ?? "?";
|
||||
if (PlumbingTypes.Contains(typeName) || method.Name.StartsWith('<'))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
names.Add($"{typeName}.{method.Name}");
|
||||
if (names.Count == SiteFrames)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return string.Join(" < ", names);
|
||||
}
|
||||
|
||||
public static void Report()
|
||||
{
|
||||
List<KeyValuePair<string, (long Count, long Ticks)>> ranked;
|
||||
lock (_gate)
|
||||
{
|
||||
if (_sites.Count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ranked = _sites.OrderByDescending(pair => pair.Value.Ticks).Take(12).ToList();
|
||||
_sites.Clear();
|
||||
}
|
||||
|
||||
foreach (var (site, (count, ticks)) in ranked)
|
||||
{
|
||||
Console.Error.WriteLine(
|
||||
$"[PERF][GPU_WAIT_SITE] ms={ticks * 1000.0 / Stopwatch.Frequency:F1} n={count} site={site}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -465,6 +465,7 @@ internal static class RenderPhaseProfile
|
|||
$"[PERF][RENDER_MS] window_s={seconds:F1} frames={frames} " +
|
||||
string.Join(" ", parts.Select(part => $"{part.Phase}={part.Milliseconds:F2}ms/n{part.Entries}")));
|
||||
|
||||
GpuWaitSiteProfile.Report();
|
||||
ReportImageUploads();
|
||||
BufferUploadProfile.Report();
|
||||
Console.Error.WriteLine(SharpEmu.ShaderCompiler.Resources.ResourceMaterializationCache.TakeReport());
|
||||
|
|
|
|||
Loading…
Reference in New Issue