Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
116 commits
Select commit Hold shift + click to select a range
f9b24e5
video_core, vulkan: AMD and split GPU thread fixes for Ocarina of Time
sanchodecuba11-del Nov 7, 2026
7a85ecc
Merge remote-tracking branch 'origin/nx2' into lichii/oot-amd-pr-update
sanchodecuba11-del Nov 7, 2026
249eaa7
Address review: semaphore writes, texture cache budget, pool shutdown
sanchodecuba11-del Nov 7, 2026
07287cc
puller: drop the early semaphore acquire from this PR
sanchodecuba11-del Nov 7, 2026
6e26139
vk_query_cache: resolve AMD samples queries from their availability
sanchodecuba11-del Nov 7, 2026
5a83bd8
Merge origin/nx2 (#679) into oot-amd-fixes; drop the texture cache cap
sanchodecuba11-del Nov 8, 2026
59d39a4
kepler_compute: don't shadow the state member (MSVC C4458 as error)
sanchodecuba11-del Nov 8, 2026
deb527e
vk_query_cache: drop the rest of the preset method left by the merge
sanchodecuba11-del Nov 8, 2026
0534753
vk_query_cache: resolve availability on AMD's proprietary driver unco…
sanchodecuba11-del Nov 8, 2026
a2178a6
vk_query_cache: keep gap slots at zero through the availability resolve
sanchodecuba11-del Nov 8, 2026
fc42430
TEST: log every 10 s how long guest threads wait for the GPU
jpkto Nov 7, 2026
d86bffd
video_core: serve a guest read's flush on the split's back after its …
jpkto Nov 7, 2026
6229487
video_core: wait for a command list's writers only up to the last hos…
jpkto Nov 7, 2026
4a143da
TEST: count what the split's front would miss without its waits (EDEN…
jpkto Nov 7, 2026
fb4d4e4
video_core: check Switch 2 semaphore acquires without draining the sp…
jpkto Nov 7, 2026
3465946
TEST: verify acquires decided without the drain (EDEN_NX2_DRAIN_CHECK)
jpkto Nov 7, 2026
1d9b6ef
video_core: wait only for the work that writes what a macro DMA reads
jpkto Nov 7, 2026
936c05e
video_core: check macro DMA reads against a drained split (EDEN_NX2_D…
jpkto Nov 7, 2026
1072d4a
video_core: let the reading thread wait for its downloads
jpkto Nov 7, 2026
f6fc343
TEST: compare read downloads with a synchronous flush (EDEN_NX2_READ_…
jpkto Nov 7, 2026
4c6864a
video_core: land read downloads under query results, outdate them for…
jpkto Nov 7, 2026
7693bb2
TEST: read download check: compare kept bytes as they landed
jpkto Nov 7, 2026
783a9a3
video_core: download read-back pages right behind their GPU writes
jpkto Nov 7, 2026
00a62b9
TEST: read trace and read check for early read downloads
jpkto Nov 8, 2026
739a6ed
vulkan: cast the LSFG mip level binding count to u32
jpkto Nov 7, 2026
a442c38
video_core: run the macros that read memory on the split's back
jpkto Nov 7, 2026
0ba2026
TEST: check back macros against the old way (EDEN_NX2_BACK_MACRO_VERIFY)
jpkto Nov 7, 2026
34656e8
video_core: command lists on GPU-written pages wait only for the word…
jpkto Nov 7, 2026
3a665f9
TEST: command list read stats and a check against the old reads (EDEN…
jpkto Nov 7, 2026
188baa1
video_core: decide Switch 2 acquires from the split's semaphore view
jpkto Nov 7, 2026
557a132
TEST: verify and count the semaphore view's acquire decisions
jpkto Nov 7, 2026
87a44cc
video_core: share one ring position wait between back macros and acqu…
jpkto Nov 7, 2026
e11c916
TEST: time the host GPU's work outside draws and dispatches (EDEN_NX2…
jpkto Nov 8, 2026
bd737eb
video_core: value QMD releases on the split's front, publish sooner a…
jpkto Nov 8, 2026
2c59c7b
TEST: check the QMD view's releases, count it and the late publishes
jpkto Nov 8, 2026
4edd776
TEST: classify uploads only with EDEN_NX2_GPU_COST=2
jpkto Nov 8, 2026
d612710
vulkan: one command and one pair of barriers for a run of in-order up…
jpkto Nov 8, 2026
1457bd0
vulkan: keep a deferred clear's render pass for the draws after it
jpkto Nov 8, 2026
b62f491
vulkan: record a dispatch's barrier in the dispatch's own command
jpkto Nov 8, 2026
8b5be87
vulkan: order later transfers after a copy that asked for barriers
jpkto Nov 8, 2026
62db242
video_core: publish to the split's back once it waits, copy fewer lis…
jpkto Nov 8, 2026
78f08ae
video_core: keep the split front's QMD view in sync, place copies and…
jpkto Nov 8, 2026
3319c78
TEST: check the QMD view's descriptors and table, count why it stops
jpkto Nov 8, 2026
b964e6b
video_core: profile the 3D methods on the path unprofiled runs take
jpkto Nov 8, 2026
47af075
engines: write 3D state registers in one call
jpkto Nov 8, 2026
7c38230
buffer_cache: compare a small uniform buffer where it lies in guest m…
jpkto Nov 8, 2026
20628c9
video_core: leave TickWork without its lock when every sync request ran
jpkto Nov 8, 2026
20eba75
TEST: fine profile zones for the split's back (EDEN_NX2_GPU_PROFILE=2)
jpkto Nov 8, 2026
90e3342
video_core: mark the buffer uses of indirect draws, obtained buffers …
jpkto Nov 8, 2026
3406508
TEST: mark the read check's own download copy as a use of its bytes
jpkto Nov 8, 2026
ddf01f5
vulkan: put uploads ahead of a submission's work unless that work use…
jpkto Nov 8, 2026
a0ecdb0
TEST: check each upload's place against an exact model of buffer uses…
jpkto Nov 8, 2026
d4e8d85
video_core: command entries don't wait for the writers before the las…
jpkto Nov 8, 2026
f7d4131
TEST: check the command entries parsed without waiting for GPU work (…
jpkto Nov 8, 2026
4942eb8
core, video_core: let guest writes wait for a download landing under …
jpkto Nov 8, 2026
cf3c7f0
TEST: count guest writes held by download landings, explain check dif…
jpkto Nov 8, 2026
758b5aa
video_core: release threads waiting for sync operations once the GPU …
jpkto Nov 8, 2026
15efb11
video_core: keep a QMD entry from the split's back until the front no…
jpkto Nov 8, 2026
3cee6b6
video_core: keep the split's placed writes apart where their granules…
jpkto Nov 8, 2026
3c7cfea
video_core: have a QMD signal the front can't read yet wait, not lose…
jpkto Nov 8, 2026
b57e486
TEST: check the QMD view's late valuing and publish hold, name what i…
jpkto Nov 8, 2026
a59f7dc
video_core: let the host GPU keep GPU-written compute list words
jpkto Nov 8, 2026
9e0cd4f
TEST: count and check the GPU-written list words the host GPU keeps
jpkto Nov 8, 2026
f3702f3
cmake: reuse a cached CI package when its checksum can't be downloaded
jpkto Nov 8, 2026
443eee0
Merge nx2 into perf/nx2-split-chain
jpkto Nov 8, 2026
611a09d
video_core: have the QMD view read a descriptor only once the back ra…
jpkto Nov 8, 2026
0a6bd6e
vulkan: recycle images instead of creating and freeing them every fra…
burakcakay Nov 8, 2026
eb64bfb
TEST: read download check: leave out landed bytes newer writes replaced
jpkto Nov 8, 2026
f9f3bc6
TEST: explain Outdated read download check results
jpkto Nov 8, 2026
59f05ab
Merge nx2 into perf/nx2-split-chain
jpkto Nov 8, 2026
d4e91e8
vulkan: align a command chunk's data for every command it holds
jpkto Nov 8, 2026
a5cb088
vulkan: let the image recycler keep images of a new allocator at a cl…
burakcakay Nov 8, 2026
d8988e7
core: give device memory translations generations no other manager has
jpkto Nov 8, 2026
f01be63
TEST: read download check: leave out landed bytes an upload took from…
jpkto Nov 8, 2026
894a9e8
gpu_split: count fence-flagged releases in memory once their fence ran
jpkto Nov 8, 2026
969cc05
decoders: cap the unswizzle threads by the spare physical cores
sanchodecuba11-del Nov 8, 2026
57bc26a
vk_query_cache: wait on each run's newest query before the availabili…
sanchodecuba11-del Nov 8, 2026
802c5e4
gpu_split: decide acquires on a word with a pending fenced release by…
jpkto Nov 8, 2026
a8db170
Merge nx2 into perf/nx2-split-chain
jpkto Nov 8, 2026
0758309
gpu_thread: publish what the front sent before it sleeps on suspended…
jpkto Nov 8, 2026
34621dc
gpu: take the applied writes out of applying_writes on every exit
jpkto Nov 8, 2026
ecfef2c
Merge #573: AMD and split GPU thread fixes for Ocarina of Time
Copilot Nov 9, 2026
b2304fa
texture_cache: don't prepare the null image for views of empty descri…
Copilot Nov 9, 2026
74a38bc
query_cache: keep fence-flagged payload releases synchronized at low …
tibzejoker Nov 8, 2026
630416a
query_cache: drop the [[likely]] hints on the synced checks (docs/Cod…
tibzejoker Nov 9, 2026
f837a66
gpu_split: synced payload releases land as the back runs them (#874 w…
Copilot Nov 9, 2026
2d4c50c
Merge #836: recycle images instead of creating and freeing them every…
Copilot Nov 9, 2026
762b7cd
vulkan: free compute IR before a synchronous driver compile (precache…
zortos293 Nov 8, 2026
05bea62
nx2 video: pick libdav1d for AV1 explicitly, cap its threads, log the…
zortos293 Nov 8, 2026
8c42de0
shader_recompiler: remove static clip_distance_written data race in S…
zortos293 Nov 8, 2026
ec32c7a
texture_cache: don't prepare the null image on a texture memo hit (Oc…
atk3001 Nov 8, 2026
6a049eb
common: make Log2Ceil(0) the smallest bucket instead of wrapping (#918)
zortos293 Nov 8, 2026
8014ba8
video_core: give GetSubmappedDeviceRange's min one type (macOS build)…
zortos293 Nov 8, 2026
d9d8e11
common: reserve the last page table level from the range's last byte …
zortos293 Nov 9, 2026
dc9f79d
file_sys: harden PFS0, RomFS, NCA and XCI parsers against malformed f…
zortos293 Nov 9, 2026
0fb6b9b
common: trim all-zero guest pages unconditionally (builds on #431) (#…
zortos293 Nov 9, 2026
8c7aad9
buffer_cache: skip the once-a-frame native bank upload for Ocarina of…
the-cashman Nov 8, 2026
42dcc24
buffer_cache: keep the resolved index buffer while its range, mapping…
robertveloso Nov 8, 2026
088f53b
buffer_cache: no index buffer memo with accurate GPU fences
robertveloso Nov 8, 2026
139d936
video_core: read texture descriptors without flushing during shader t…
El-Sashok Nov 9, 2026
e64b407
common: keep a faulting stack walk from taking the sampler's process …
hellasleeper108 Nov 9, 2026
cccac7b
texture_cache: keep the TIC and TSC lookup maps in flat hash maps
JuliusBairaktaris Nov 8, 2026
0593fd7
kepler_compute: return a program's image handles by reference
JuliusBairaktaris Nov 8, 2026
d5c9589
vulkan_device: reuse the device memory usage for 50 ms
JuliusBairaktaris Nov 8, 2026
58144d2
fence_manager: don't flush again after queueing a fence
JuliusBairaktaris Nov 8, 2026
6ec2433
video_core: align delta draws and memo image preparation (port of nx2…
Copilot Nov 9, 2026
a21232a
video_core: keep uniforms and replay delta image descriptors (partial…
Copilot Nov 9, 2026
aa4b58a
video_core: keep vertex_id_base writes from breaking fast draws
mstampfli Nov 9, 2026
8a452bc
video_core: keep counter resets and render enable writes from breakin…
mstampfli Nov 9, 2026
d252c5b
video_core: keep per-draw reports from breaking fast draws
mstampfli Nov 9, 2026
90e3ad1
Merge nx2 (0ab7736df9) into the #805 integration branch
Copilot Nov 9, 2026
9bf7c43
video_core: keep synced payloads out of deferred report tracking
Copilot Nov 9, 2026
84dea2f
Merge nx2 (1a5e995a38) into the #805 integration branch
Copilot Nov 9, 2026
94621e1
tests: extend the existing synced-writer regression
Copilot Nov 9, 2026
1b67697
Merge nx2 (c215653cc5) into the #805 integration branch
Copilot Nov 9, 2026
3d5789e
Merge nx2 (7afad5494e) into the #805 integration branch
Copilot Nov 9, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ Use these before guessing. All are off unless the variable is set; pass them as
| A newly lowered program changes the image | `EDEN_NX2_REJECT_HASH=<hash>,...` (native program keys from shader dump file names, or shader hashes from the frame dump) | Those programs are rejected as if unsupported; the log shows `rejected by EDEN_NX2_REJECT_HASH` per hit. Bisect by halving the list. The key covers the captured code, so recompute it when the capture rules change. |
| Draw and render-state questions | `EDEN_NX2_RENDER_TRACE=1`, filter `*:Info HW.GPU:Debug Render.Vulkan:Debug Shader:Debug` | Per-draw state, rejected stages and zero-format texture descriptors. |
| Video playback | `EDEN_NX2_VDEC_TRACE=1`, `EDEN_NX2_VDEC_DUMP=<dir>` | Decoder submit, decode and composite trace; decoded frames. |
| Performance and frame pacing | `EDEN_NX2_GPU_PROFILE=1`, `EDEN_DKB_FRAME_TRACE=1` | GPU thread, back thread and Vulkan worker time per second by zone, GPU waits by the zone they happen in, waits for the back by site, and spin mutex contention; per-present interval, CPU and fence timing. The profile also logs `Async read-back per second` every 10 s: guest reads of GPU-written memory, their waits, and macro DMA reads that waited for the split's back or drained it. |
| Performance and frame pacing | `EDEN_NX2_GPU_PROFILE=1`, `EDEN_DKB_FRAME_TRACE=1` | GPU thread, back thread and Vulkan worker time per second by zone, GPU waits by the zone they happen in, waits for the back by site, and spin mutex contention; per-present interval, CPU and fence timing. The #805 integration also logs `GPU waits in ... s` every 10 s with guest reads, reactive flushes and front/back waits; it retains #805's read tracing rather than the port's duplicate async-readback counters. |
| HostTiming CPU or timer lateness (late guest timers, audio or vsync jitter) | `EDEN_NX2_HOSTTIMING_STATS=1`, or live with the debug server's `host_timing {"stats": true}` | One `HostTiming wait` line per second: waits, waits woken by newly scheduled events, OS sleep and `WaitFor` time (ms/s), how late timed waits ended and how late events fired (p50/p99/max µs), and the thread's CPU %. |
| Shader stutter or not, boot and cache costs | `EDEN_NX2_STUTTER_TRACE=1` | One `Nx2Stutter` line per frame presented over 33 ms after the last, with its top cause (gfx/compute pipeline built on the GPU thread, pipeline wait, shader capture, texture, buffer, query/fence, present, other) and each GPU thread's ms; `Nx2StutterSummary` every 10 s (frame-time histogram, builds, cache lookups, cache file size); `Nx2Boot` boot phases with commit and peak commit. Frames over `EDEN_NX2_STUTTER_DETAIL_MS` (default 50) also get `Nx2StutterDetail`: each GPU thread's eight largest zones (ms/calls) and the rare sites that ran (device memory allocate/free, staging, buffer and image create/delete/GC, synchronous downloads, `Scheduler::Finish`), with each run over 2 ms by thread; the summary adds the sites per 10 s. The category totals in the summary are every frame's steady cost, not hitch time. `python3 -I tools/nx2/cache_metrics.py parse <log>` turns a log into JSON, `compare` A/B runs; `tools/nx2/cache_bench.py` runs the cold/warm matrix on the PC. |
| Command corruption or pop-in | `EDEN_NX2_PB_CHECK=1`; A/B with `EDEN_NX2_PB_SNAPSHOT=0` or `EDEN_NX2_FETCH_DRAIN=1` | How many pushbuffer entries change between submit and parse. |
Expand Down
77 changes: 77 additions & 0 deletions NX2_GPU_THREAD_SPLIT.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,3 +61,80 @@ with stage 2, 50,000-66,500 with stage 3. The front waits ~4,000-5,000 times a s
acquires, MME DMA reads); the back still spends ~200 ms a second outside its zones (ring dispatch,
method sink). Clean A/B (NX2_NOTES row 145): 1.46x throughput, frames 17% shorter; on by
default since. The back is ~92% busy, ~53% of it draw setup: the next step is there, not the ring.

## Fast draw ports on the #805 performance branch (2026-11-09)

The port of nx2 `1c25fbdfb4` (#921) makes full resolves and texture memo hits use
the same image-preparation predicate. Empty descriptor views backed by the null
image are excluded even when their view id is not the null view id. Delta draws
fall back when a sampled image needs an upload or alias synchronization, or when
the draw's serial, mappings, command buffer or render pass changed before the
caches were locked. Rescaling ends the chain too.

Only the uniform-keep and image-descriptor replay portions of nx2 `a4f6287327`
(#949) are ported: `6b38851501`, `ee98215f14`, and the CPU-write follow-up
`3e86407514`. The test-runtime support in `b2375cff7f` already exists on #805.
Its semaphore, waiter and acquire/drain replacements are not included; #805
retains its own implementations. The subsequent nx2 merge keeps the independent
scheduler-owner guard on buffer-cache writes from CPU/service threads, without
replacing #805's back-owned `Run` operations with nx2's `back_quiet` drain scheme.

Small streamed uniforms can reuse the previous allocation without rereading
guest memory when the stage, slot, device range and command-buffer tick still
match, and no overlapping inline data, notified CPU write, GPU write or buffer
deletion invalidated it. More than eight notified writes between draws disable
keeps for the next draw. Unsynchronized CPU writes unknown to the caches remain
an assumption to check on the game. Per-stage image descriptor entries and
rescaling words are replayed until the views are recaptured or the scale epoch
changes; buffer descriptors still bind on every draw.

Validate a fixed scene with these diagnostics separately (set each to `1`):

- `EDEN_NX2_TEXTURE_MEMO_VERIFY`: compare views, samplers and prepared image sets.
- `EDEN_NX2_FAST_DRAW_VERIFY`: full-resolve comparison; this deliberately bypasses
delta draws, so it does not exercise uniform keeps or descriptor replay.
- `EDEN_NX2_UBO_KEEP_VERIFY`: reread would-be kept uniforms and report changed bytes.
- `EDEN_NX2_DELTA_DESCRIPTORS_VERIFY`: regenerate and compare image descriptors
and rescaling words.
- `EDEN_NX2_GPU_PROFILE`: report keep/replay counts and draw fallback reasons;
value `2` also retains #805's fine uniform-binding counters.

After building the test target, run `tests.exe "[buffer_ports]"`,
`tests.exe "[video_core][texture_cache]"`, and
`tests.exe "Uniform stream*"`. These ports were reviewed without building on
the porting machine; compilation, runtime verification and visual A/B testing
are still required. #949's reported Bananza gain (+8–9%, back thread about
56.0 to 52.2 ms/frame on a Ryzen 9 5900X) includes its acquire changes and does
not predict the gain of this partial port in Ocarina of Time.

## nx2 integration through 1a5e995a38

- #1028 does not replace #805's read downloads, write tracking, sampled method
profiling or diagnostics. Its correctness fixes are retained: discard/DMA
destinations first land overlapping read downloads, and older deferred query
results cannot mark newer GPU writes clean. Synced #874 payload callbacks still
do not advance `fenced_landed` or retire an older deferred report's tracking;
`FencedPayloadLanding` remains authoritative.
- #979/#1014 retain every registered semaphore region and the direct-release
shadow. Mirrored releases are emitted only when `ViewApplies()` is false
(unsplit, back macros, or delayed/high-accuracy releases). The full #805 front
view continues to decide from the original releases, never a second mirrored
counter. Its unbounded, source-tracking waiter collection is retained.
- Shader cache v2 replaces the legacy Vulkan cache. #970's no-flush TIC reads
apply to worker translation too, so no pool-wide flush is introduced before
launching workers. As with #970, pending GPU writes to descriptors remain a
runtime validation risk. AMD shader exceptions, the image recycler and memory
usage caching are unchanged.
- #965/#1039 add stutter sites, GPU waits by zone, queue/present waits, contention
and opt-in live-read comparisons around the existing split. Method profiling
still takes the fast path and samples timing, rather than timing every write.
- #1056's macro-on-back port arrived during integration. Keep #805's full effect
analysis and back-macro machinery, but take the review fixes: recheck command
pages even when the writer wait did not block, and remember the actual last
writer at each host sync rather than waiting through unrelated intervening work.

In-game validation should cover low/default and high/delayed fence modes,
cross-channel semaphore waits, concurrent CPU read-back, cold/migrated/warm v2
caches, and the fast-draw checks above. The integration build disables
`BUILD_TESTING`; the updated C++ regression sources must be run separately in a
test-enabled build.
43 changes: 37 additions & 6 deletions src/common/nx2_sampler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ constexpr size_t MaxDepth = 40;
struct Sample {
unsigned thread;
unsigned depth;
bool faulted; ///< the walk stopped at an access violation
std::array<DWORD64, MaxDepth> frames;
};

Expand Down Expand Up @@ -146,15 +147,15 @@ std::vector<Target> FindThreads(const std::vector<std::string>& patterns) {
// could be paused holding the heap lock. A wrong unwind step (code with missing or wrong unwind
// data) leaves a garbage stack pointer: reading through it crashed the process, so the walk
// stops once the stack pointer leaves the thread's stack.
unsigned Walk(CONTEXT context, std::array<DWORD64, MaxDepth>& frames, const NT_TIB* tib) {
void Walk(CONTEXT context, std::array<DWORD64, MaxDepth>& frames, const NT_TIB* tib,
unsigned& depth) {
if (tib == nullptr) {
return 0;
return;
}
const auto on_stack = [tib](DWORD64 rsp) {
return rsp >= reinterpret_cast<DWORD64>(tib->StackLimit) &&
rsp + 8 <= reinterpret_cast<DWORD64>(tib->StackBase) && (rsp & 7) == 0;
};
unsigned depth = 0;
while (depth < MaxDepth && context.Rip != 0 && on_stack(context.Rsp)) {
frames[depth++] = context.Rip;
DWORD64 image_base{};
Expand All @@ -174,6 +175,26 @@ unsigned Walk(CONTEXT context, std::array<DWORD64, MaxDepth>& frames, const NT_T
RtlVirtualUnwind(UNW_FLAG_NHANDLER, image_base, context.Rip, function, &context,
&handler_data, &establisher_frame, nullptr);
}
}

// RtlVirtualUnwind also reads through the frame register, which the stack check above doesn't
// cover: a thread paused in a fiber switch with Rbp 0 made it read address 0, and the access
// violation took the process down (EDEN_NX2_SAMPLE=CPUCore_*). Such a walk keeps the frames it
// found.
unsigned GuardedWalk(const CONTEXT& context, std::array<DWORD64, MaxDepth>& frames,
const NT_TIB* tib, bool& faulted) {
unsigned depth = 0;
faulted = false;
#ifdef _MSC_VER
__try {
Walk(context, frames, tib, depth);
} __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ? EXCEPTION_EXECUTE_HANDLER
: EXCEPTION_CONTINUE_SEARCH) {
faulted = true;
}
#else
Walk(context, frames, tib, depth);
#endif
return depth;
}

Expand Down Expand Up @@ -257,8 +278,15 @@ std::string Report(const std::vector<Target>& targets, const std::vector<Sample>
std::map<std::string, unsigned> inclusive;
std::map<std::string, unsigned> self_caller;
unsigned total = 0;
unsigned faulted = 0;
unsigned empty = 0;
for (const Sample& sample : samples) {
if (sample.thread != thread || sample.depth == 0) {
if (sample.thread != thread) {
continue;
}
faulted += sample.faulted ? 1 : 0;
if (sample.depth == 0) {
++empty;
continue;
}
++total;
Expand Down Expand Up @@ -289,7 +317,9 @@ std::string Report(const std::vector<Target>& targets, const std::vector<Sample>
sorted[i].second.c_str());
}
};
text += fmt::format("=== thread \"{}\": {} samples\n", targets[thread].name, total);
text += fmt::format("=== thread \"{}\": {} samples ({} without a stack, {} walks stopped "
"by a fault)\n",
targets[thread].name, total, empty, faulted);
print("self (where the thread is)", self, 60);
// The hottest instructions as module offsets, for llvm-symbolizer --relative-address
// (which line of a function, inlined code included).
Expand Down Expand Up @@ -371,7 +401,8 @@ std::string SampleThreads(const std::vector<std::string>& patterns, double secon
if (GetThreadContext(handle, &context)) {
Sample& sample = samples.emplace_back();
sample.thread = i;
sample.depth = Walk(context, sample.frames, targets[i].tib);
sample.depth =
GuardedWalk(context, sample.frames, targets[i].tib, sample.faulted);
}
ResumeThread(handle);
}
Expand Down
2 changes: 2 additions & 0 deletions src/core/hle/service/nx2_gsv.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
#include "core/frontend/framebuffer_layout.h"
#include "core/perf_stats.h"
#include "video_core/gpu.h"
#include "video_core/gpu_wait_stats.h"
#include "video_core/framebuffer_config.h"
#include "core/core_timing.h"
#include "core/hle/kernel/k_client_session.h"
Expand Down Expand Up @@ -1802,6 +1803,7 @@ class INx2Vi2Session final : public ServiceFramework<INx2Vi2Session> {
m_vsync->trace_present.store(m_presents, std::memory_order_relaxed);
}
const u64 present = Core::g_nx2_present_count.fetch_add(1, std::memory_order_relaxed) + 1;
VideoCommon::GpuWaitStats::NotePresent();
if (Core::g_nx2_present_time_services.load(std::memory_order_relaxed) != 0) {
const u64 present_ns = std::chrono::duration_cast<std::chrono::nanoseconds>(
std::chrono::steady_clock::now().time_since_epoch())
Expand Down
6 changes: 6 additions & 0 deletions src/core/memory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include "core/hle/kernel/k_process.h"
#include "core/memory.h"
#include "video_core/gpu.h"
#include "video_core/gpu_wait_stats.h"
#include "video_core/host1x/gpu_device_memory_manager.h"
#include "video_core/host1x/host1x.h"
#include "video_core/rasterizer_download_area.h"
Expand Down Expand Up @@ -891,6 +892,7 @@ struct Memory::Impl {
return;
}
const size_t core = system.GetCurrentHostThreadID();
VideoCommon::GpuWaitStats::CountRasterizerRead(core);
if (core >= Core::Hardware::NUM_CPU_CORES) {
// A service thread has no slot in the arrays below, and it does not use a slot of a
// core. It keeps no area, so it asks on each read.
Expand Down Expand Up @@ -943,6 +945,7 @@ struct Memory::Impl {
sys_core_guard.unlock();
}
};
VideoCommon::GpuWaitStats::CountRasterizerWrite(core);
gpu_device_memory->ApplyOpOnPointer(p, scratch_buffers[core], [&](DAddr address) {
auto& current_area = rasterizer_write_areas[core];
PAddr subaddress = address >> YUZU_PAGEBITS;
Expand All @@ -952,8 +955,11 @@ struct Memory::Impl {
// we should let the compiler just do it's thing...
if (current_area.last_address != subaddress) {
// Short circuit the need to check for address/size
const u64 check_start = VideoCommon::GpuWaitStats::Now();
auto const do_collection = (address != 0 && size != 0)
&& system.GPU().OnCPUWrite(address, size);
VideoCommon::GpuWaitStats::AddWriteCheck(core, VideoCommon::GpuWaitStats::Now() -
check_start);
if (do_collection) {
current_area.last_address = subaddress;
} else {
Expand Down
1 change: 1 addition & 0 deletions src/tests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ add_executable(tests
video_core/turing_macro_effects.cpp
video_core/turing_macro_ram.cpp
video_core/uniform_stream_reuse.cpp
video_core/upload_order.cpp
video_core/usage_tracker.cpp
video_core/shader_invalidation.cpp
video_core/descriptor_table.cpp
Expand Down
Loading