mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 19:06:15 +08:00
Vulkan: reduce guest buffer upload allocations (#301)
This commit is contained in:
@@ -4405,11 +4405,14 @@ internal static unsafe class VulkanVideoPresenter
|
|||||||
CollectCompletedGuestSubmissions(waitForOldest: false);
|
CollectCompletedGuestSubmissions(waitForOldest: false);
|
||||||
var waitedMs = (System.Diagnostics.Stopwatch.GetTimestamp() - waitStart) *
|
var waitedMs = (System.Diagnostics.Stopwatch.GetTimestamp() - waitStart) *
|
||||||
1000.0 / System.Diagnostics.Stopwatch.Frequency;
|
1000.0 / System.Diagnostics.Stopwatch.Frequency;
|
||||||
TraceVulkanShader(
|
if (_traceVulkanShaderEnabled)
|
||||||
$"vk.queue_visibility queue={_activeGuestQueue.Name} " +
|
{
|
||||||
$"submission={_activeGuestQueue.SubmissionId} " +
|
TraceVulkanShader(
|
||||||
$"target_timeline={targetTimeline} completed_timeline={_completedTimeline} " +
|
$"vk.queue_visibility queue={_activeGuestQueue.Name} " +
|
||||||
$"waited_ms={waitedMs:F3}");
|
$"submission={_activeGuestQueue.SubmissionId} " +
|
||||||
|
$"target_timeline={targetTimeline} completed_timeline={_completedTimeline} " +
|
||||||
|
$"waited_ms={waitedMs:F3}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteOrderedGuestAction(VulkanOrderedGuestAction work)
|
private void ExecuteOrderedGuestAction(VulkanOrderedGuestAction work)
|
||||||
@@ -4417,10 +4420,13 @@ internal static unsafe class VulkanVideoPresenter
|
|||||||
WaitForActiveGuestQueueSubmissionsForCpuVisibility();
|
WaitForActiveGuestQueueSubmissionsForCpuVisibility();
|
||||||
WriteBackAllDirtyGuestBuffers(_activeGuestQueue.Name);
|
WriteBackAllDirtyGuestBuffers(_activeGuestQueue.Name);
|
||||||
work.Action();
|
work.Action();
|
||||||
TraceVulkanShader(
|
if (_traceVulkanShaderEnabled)
|
||||||
$"vk.ordered_action queue={_activeGuestQueue.Name} " +
|
{
|
||||||
$"submission={_activeGuestQueue.SubmissionId} " +
|
TraceVulkanShader(
|
||||||
$"work_sequence={_activeGuestWorkSequence} name='{work.DebugName}'");
|
$"vk.ordered_action queue={_activeGuestQueue.Name} " +
|
||||||
|
$"submission={_activeGuestQueue.SubmissionId} " +
|
||||||
|
$"work_sequence={_activeGuestWorkSequence} name='{work.DebugName}'");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void ExecuteOrderedGuestFlip(VulkanOrderedGuestFlip work)
|
private void ExecuteOrderedGuestFlip(VulkanOrderedGuestFlip work)
|
||||||
@@ -7529,21 +7535,43 @@ internal static unsafe class VulkanVideoPresenter
|
|||||||
|
|
||||||
var size = (ulong)Math.Max(guestBuffer.Length, sizeof(uint));
|
var size = (ulong)Math.Max(guestBuffer.Length, sizeof(uint));
|
||||||
var endAddress = checked(guestBuffer.BaseAddress + size);
|
var endAddress = checked(guestBuffer.BaseAddress + size);
|
||||||
var allocation = _guestBufferAllocations
|
GuestBufferAllocation? allocation = null;
|
||||||
.Where(candidate =>
|
var allocationPriority = -1;
|
||||||
candidate.BaseAddress <= guestBuffer.BaseAddress &&
|
// This runs for every bound global buffer. Preserve the previous
|
||||||
candidate.BaseAddress + candidate.Size >= endAddress)
|
// stable queue preference without allocating LINQ sort state.
|
||||||
.OrderByDescending(candidate =>
|
foreach (var candidate in _guestBufferAllocations)
|
||||||
string.Equals(
|
{
|
||||||
|
if (candidate.BaseAddress > guestBuffer.BaseAddress ||
|
||||||
|
candidate.BaseAddress + candidate.Size < endAddress)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var candidatePriority = string.Equals(
|
||||||
candidate.QueueName,
|
candidate.QueueName,
|
||||||
_activeGuestQueue.Name,
|
_activeGuestQueue.Name,
|
||||||
StringComparison.Ordinal))
|
StringComparison.Ordinal)
|
||||||
.ThenByDescending(candidate =>
|
? 2
|
||||||
string.Equals(
|
: string.Equals(
|
||||||
candidate.QueueName,
|
candidate.QueueName,
|
||||||
SharedReadOnlyGuestBufferQueue,
|
SharedReadOnlyGuestBufferQueue,
|
||||||
StringComparison.Ordinal))
|
StringComparison.Ordinal)
|
||||||
.First();
|
? 1
|
||||||
|
: 0;
|
||||||
|
if (candidatePriority > allocationPriority)
|
||||||
|
{
|
||||||
|
allocation = candidate;
|
||||||
|
allocationPriority = candidatePriority;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (allocation is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException(
|
||||||
|
$"no Vulkan guest buffer allocation covers " +
|
||||||
|
$"0x{guestBuffer.BaseAddress:X16}-0x{endAddress:X16}");
|
||||||
|
}
|
||||||
|
|
||||||
var guestOffset = guestBuffer.BaseAddress - allocation.BaseAddress;
|
var guestOffset = guestBuffer.BaseAddress - allocation.BaseAddress;
|
||||||
var descriptorOffset = guestOffset &
|
var descriptorOffset = guestOffset &
|
||||||
~(GuestStorageBufferOffsetAlignment - 1);
|
~(GuestStorageBufferOffsetAlignment - 1);
|
||||||
@@ -7592,16 +7620,15 @@ internal static unsafe class VulkanVideoPresenter
|
|||||||
WaitForActiveGuestQueueSubmissionsForCpuVisibility();
|
WaitForActiveGuestQueueSubmissionsForCpuVisibility();
|
||||||
WriteBackAllDirtyGuestBuffers(_activeGuestQueue.Name);
|
WriteBackAllDirtyGuestBuffers(_activeGuestQueue.Name);
|
||||||
}
|
}
|
||||||
var live = new byte[guestBuffer.Length];
|
var mapped = new Span<byte>(
|
||||||
if (_guestMemory?.TryRead(guestBuffer.BaseAddress, live) == true)
|
(void*)(allocation.Mapped + checked((nint)guestOffset)),
|
||||||
|
guestBuffer.Length);
|
||||||
|
if (_guestMemory?.TryRead(guestBuffer.BaseAddress, mapped) != true)
|
||||||
{
|
{
|
||||||
source = live;
|
source.CopyTo(mapped);
|
||||||
}
|
}
|
||||||
|
|
||||||
source.CopyTo(new Span<byte>(
|
mapped.CopyTo(shadow);
|
||||||
(void*)(allocation.Mapped + checked((nint)guestOffset)),
|
|
||||||
source.Length));
|
|
||||||
source.CopyTo(shadow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ShouldTraceVulkanResources() &&
|
if (ShouldTraceVulkanResources() &&
|
||||||
@@ -7611,14 +7638,6 @@ internal static unsafe class VulkanVideoPresenter
|
|||||||
$"[LOADER][TRACE] vk.global_buffer base=0x{guestBuffer.BaseAddress:X16} " +
|
$"[LOADER][TRACE] vk.global_buffer base=0x{guestBuffer.BaseAddress:X16} " +
|
||||||
$"bytes={guestBuffer.Length}");
|
$"bytes={guestBuffer.Length}");
|
||||||
}
|
}
|
||||||
if (_setDebugUtilsObjectName is not null)
|
|
||||||
{
|
|
||||||
SetDebugName(
|
|
||||||
ObjectType.Buffer,
|
|
||||||
allocation.Buffer.Handle,
|
|
||||||
$"SharpEmu global 0x{guestBuffer.BaseAddress:X16} {guestBuffer.Length}b");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (guestBuffer.Pooled)
|
if (guestBuffer.Pooled)
|
||||||
{
|
{
|
||||||
GuestDataPool.Return(guestBuffer.Data);
|
GuestDataPool.Return(guestBuffer.Data);
|
||||||
@@ -9890,10 +9909,13 @@ internal static unsafe class VulkanVideoPresenter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
TraceVulkanShader(
|
if (_traceVulkanShaderEnabled)
|
||||||
$"vk.offscreen_draw mrt={targets.Length} " +
|
{
|
||||||
$"size={firstTarget.Width}x{firstTarget.Height} " +
|
TraceVulkanShader(
|
||||||
$"textures={work.Draw.Textures.Count}");
|
$"vk.offscreen_draw mrt={targets.Length} " +
|
||||||
|
$"size={firstTarget.Width}x{firstTarget.Height} " +
|
||||||
|
$"textures={work.Draw.Textures.Count}");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user