mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
Keep presenter pacing out of dynamic-resolution overload signals
This commit is contained in:
@@ -213,6 +213,8 @@ on a fixed region -> next.
|
||||
|
||||
## 5. Status / Log (update every session)
|
||||
|
||||
- **2026-10-21 (BRIEF-4 presenter accounting):** Publish composer swap/slot wait separately and exclude that pacing from dynamic-resolution work backpressure. Windows and Mac real-context checks pass. Quiet fullscreen route: 60.020 Hz, four completion gaps >25ms, p99 busy 48.0%; allocation stalls remain. Raw completion and queue-wait metrics are unchanged.
|
||||
|
||||
- **2026-10-21 (BRIEF-4 GPU timing):** Split TIME_ELAPSED brackets around command starvation and presentation waits. Real-context 30ms producer-idle control reports 35.141ms with the old bracket / 5.620ms active GPU work; Windows and Mac GL fixtures and render-thread unit checks pass. Completion stalls remain; dynamic-resolution reallocations are the next target. No guest or completion-clock changes.
|
||||
|
||||
- **2026-10-21 (BRIEF-4 depth state):** Removed per-batch GL state round trips, including the mask-check exception absent in the old experiment. Real-context state restoration and image/readback controls pass on Windows and Mac. Fullscreen quiet route remains unaccepted (8 completion gaps, 53.2% p99 busy). Investigating GPU query spans that include host pacing and provoke expensive dynamic-resolution reallocations.
|
||||
|
||||
@@ -457,6 +457,7 @@ void gl_renderer_host_ledger(GlHostLedger *out);
|
||||
* gl_renderer_render_thread_measure(1) (dynamic resolution on). */
|
||||
typedef struct GlRthCosts {
|
||||
uint64_t frames, cost_ns, cpu_ns, gpu_ns, gpu_frames, dropped;
|
||||
uint64_t present_wait_ns; /* composer blocked on swap / a free present slot */
|
||||
} GlRthCosts;
|
||||
void gl_renderer_render_thread_measure(int on);
|
||||
void gl_renderer_render_thread_costs(GlRthCosts *out);
|
||||
|
||||
@@ -485,6 +485,7 @@ static int s_hd_authority_pending = 0;
|
||||
|
||||
static int rth_record_mode(void);
|
||||
/* Render-thread frame cost (dynamic resolution; defined with GL_RT_BACKEND). */
|
||||
static _Atomic uint64_t s_rth_present_wait_ns;
|
||||
static uint64_t s_rthf_swap_ns = 0; /* render thread: time in the swap */
|
||||
static uint64_t host_now_ns_rthf(void);
|
||||
/* The SW rasterizer and the HD texture residency read the same native VRAM
|
||||
@@ -10059,6 +10060,7 @@ static void gl_swap_now(int generated) {
|
||||
if (rthf_t0) {
|
||||
const uint64_t sw = host_now_ns_rthf() - rthf_t0;
|
||||
s_rthf_swap_ns += sw;
|
||||
atomic_fetch_add_explicit(&s_rth_present_wait_ns, sw, memory_order_relaxed);
|
||||
fg_note_swap(sw);
|
||||
}
|
||||
if (s_dyn_on) {
|
||||
@@ -11552,6 +11554,7 @@ void gl_renderer_render_thread_costs(GlRthCosts *out) {
|
||||
out->gpu_ns = atomic_load(&s_rthf_gpu_ns);
|
||||
out->gpu_frames = atomic_load(&s_rthf_gpu_frames);
|
||||
out->dropped = atomic_load(&s_rthf_dropped);
|
||||
out->present_wait_ns = atomic_load_explicit(&s_rth_present_wait_ns, memory_order_relaxed);
|
||||
}
|
||||
|
||||
/* ---- frame generation ([video] frame_generation) ---------------------------
|
||||
|
||||
+14
-1
@@ -10627,7 +10627,20 @@ static void dynres_tick_rt(double now_s, double wall, double period, int held,
|
||||
const int frames = (int)(co.frames - c0.frames);
|
||||
const double cost = (double)(co.cost_ns - c0.cost_ns) * 1e-9;
|
||||
const uint64_t bp_ns = rs.backpressure_ns + rs.ring_full_ns;
|
||||
const double bp = (double)(bp_ns - g_dynres.last_bp_ns) * 1e-9;
|
||||
uint64_t work_bp_ns = bp_ns - g_dynres.last_bp_ns;
|
||||
/* A bounded presenter intentionally holds the renderer at display rate.
|
||||
* That wait propagates to the guest queue even with ample render headroom;
|
||||
* it is not evidence that lowering resolution would help. GPU/CPU work
|
||||
* remains measured separately and still drives overload decisions. */
|
||||
static const bool account_present = [] {
|
||||
const char *e = std::getenv("PSX_DYNRES_PRESENT_WAIT_ACCOUNTING");
|
||||
return !(e && e[0] == '0');
|
||||
}();
|
||||
if (account_present) {
|
||||
const uint64_t present_ns = co.present_wait_ns - c0.present_wait_ns;
|
||||
work_bp_ns = work_bp_ns > present_ns ? work_bp_ns - present_ns : 0;
|
||||
}
|
||||
const double bp = (double)work_bp_ns * 1e-9;
|
||||
g_dynres.rt_acc_cpu += (double)(co.cpu_ns - c0.cpu_ns) * 1e-6;
|
||||
g_dynres.rt_acc_gpu += (double)(co.gpu_ns - c0.gpu_ns) * 1e-6;
|
||||
g_dynres.rt_acc_frames += co.frames - c0.frames;
|
||||
|
||||
@@ -359,6 +359,7 @@ int main(int argc, char **argv) {
|
||||
double gpu_ms = co.gpu_frames ? (double)co.gpu_ns / co.gpu_frames * 1e-6 : 0.0;
|
||||
printf("idle_gpu_ms=%.3f gpu_frames=%llu\n", gpu_ms, (unsigned long long)co.gpu_frames);
|
||||
check(co.gpu_frames > 0, "idle timing has completed GPU samples");
|
||||
check(co.present_wait_ns > 0, "composer wait published independently of render cost");
|
||||
if (rthf_active_segments())
|
||||
check(gpu_ms < 15.0, "GPU work excludes the 30ms producer wait");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user