mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-31 23:19:44 +08:00
Sdl backend (#670)
* [audio] added sdl audio backend and in-tree atrac9 decoder * [input] replaced per-platform pad readers with sdl gamepad input * [video] added sdl window and host display plumbing * [gui] added host display options and per-game render settings * [bink] synced host movie playback to the guest audio clock * [cpu] hooked windows write faults into guest image tracking * [perf] added guest and render profiling, reserved host cpu lanes * [kernel] fixed stale pthread mutex handle alias * [host] wired the sdl session, save-data paths and project references * [audio] hoisted ajm trace stackalloc out of its loop * [video] Add guest image sync setting * [build] Strip native symbols * reuse
This commit is contained in:
@@ -5314,7 +5314,7 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
||||
var hostCpu = processorCount < 8
|
||||
? guestCpu % processorCount
|
||||
: processorCount >= 16
|
||||
? guestCpu * 2
|
||||
? MapGuestCpuAcrossSmtLanes(guestCpu, processorCount)
|
||||
: guestCpu;
|
||||
if (hostCpu < processorCount)
|
||||
{
|
||||
@@ -5325,6 +5325,45 @@ public sealed unsafe partial class DirectExecutionBackend : INativeCpuBackend, I
|
||||
return hostAffinityMask;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Places guest CPUs on distinct physical cores first, then wraps onto the
|
||||
/// SMT siblings. Doubling the index alone only works while the title stays
|
||||
/// inside the first half of the guest CPU set: beyond that every mapped lane
|
||||
/// lands past the host's processor count and gets dropped, which silently
|
||||
/// leaves those threads unpinned. Demon's Souls asks for CPUs 0-12 and keeps
|
||||
/// its renderer on 9 and 11, so dropping the overflow un-pinned both the
|
||||
/// renderer and a third of its job pool onto every core at once.
|
||||
/// </summary>
|
||||
private static int MapGuestCpuAcrossSmtLanes(int guestCpu, int processorCount)
|
||||
{
|
||||
// Reserve the top lanes for the emulator itself. A title sized for a
|
||||
// console's dedicated cores will happily keep a worker per guest CPU
|
||||
// spinning on an empty queue — Demon's Souls' job pool runs ~90% busy
|
||||
// doing nothing — and spreading those across every host lane leaves the
|
||||
// GPU translation and present threads fighting them for a slice. Packing
|
||||
// near-idle spinners tighter costs them almost nothing and buys back
|
||||
// whole cores for the work that actually produces frames.
|
||||
var usableLanes = Math.Max(processorCount - EmulatorReservedLanes, 2);
|
||||
var physicalCores = usableLanes / 2;
|
||||
var lane = guestCpu % usableLanes;
|
||||
return lane < physicalCores
|
||||
? lane * 2
|
||||
: ((lane - physicalCores) * 2) + 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Host lanes kept away from guest threads. Measured on a 16-lane host with
|
||||
/// Demon's Souls: reserving 0/4/6/8 lanes gave 6.08/6.78/7.20/5.62 fps, so
|
||||
/// the useful range is a bit over a third of the machine — too few and the
|
||||
/// emulator is crowded out, too many and the guest cannot make progress.
|
||||
/// </summary>
|
||||
private static readonly int EmulatorReservedLanes =
|
||||
int.TryParse(
|
||||
Environment.GetEnvironmentVariable("SHARPEMU_RESERVED_HOST_LANES"),
|
||||
out var reserved) && reserved >= 0
|
||||
? reserved
|
||||
: Math.Max(2, Environment.ProcessorCount * 3 / 8);
|
||||
|
||||
public bool TrySetGuestThreadPriority(ulong guestThreadHandle, int guestPriority)
|
||||
{
|
||||
lock (_guestThreadGate)
|
||||
|
||||
Reference in New Issue
Block a user