mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 02:11:36 -04:00
Elide identity VRAM copies without draining deferred scenes
This commit is contained in:
committed by
Matthew Stanley
parent
d60b859646
commit
2547f1bb61
@@ -571,7 +571,7 @@ int gl_renderer_perf_aggregate(int wide_filter, double out[18]);
|
||||
/* Bounded benchmark attribution. CPU spans require PSX_GL_CPU_PERF=1;
|
||||
* reading drains the render queue, so read outside the measured interval. */
|
||||
typedef struct {
|
||||
uint64_t counts[9];
|
||||
uint64_t counts[10];
|
||||
uint64_t calls[8], ticks[8], max_ticks[8], frequency;
|
||||
uint64_t prior_ticks[8], prior_max_ticks[8];
|
||||
} GlRenderWorkStats;
|
||||
|
||||
@@ -5410,8 +5410,28 @@ static void gpu_fill(int x,int y,int w,int h,uint16_t c) {
|
||||
/* VRAM->VRAM copy: blit the source region to the scratch texture (resolves
|
||||
* overlap), then draw it back at the destination through the BLIT program so
|
||||
* mask set/check and the stencil mirror apply, exactly like sw_copy_rect. */
|
||||
static uint64_t s_identity_copies;
|
||||
static int identity_copy_fast(void) {
|
||||
static int enabled = -1;
|
||||
if (enabled < 0) {
|
||||
const char *e = getenv("PSX_GL_IDENTITY_COPY_FAST");
|
||||
enabled = !(e && e[0] == '0');
|
||||
}
|
||||
return enabled;
|
||||
}
|
||||
static void gpu_copy_rect(int sx,int sy,int dx,int dy,int w,int h) {
|
||||
if (w <= 0 || h <= 0) return;
|
||||
if (identity_copy_fast() && sx == dx && sy == dy && !s_mask_set &&
|
||||
sx >= 0 && sy >= 0 && sx < VRAM_W && sy < VRAM_H) {
|
||||
/* No pixel can change. Retain the existing primitive batch boundary
|
||||
* (PGXP's two-pass depth policy is batch-sensitive), but don't drain
|
||||
* deferred high-resolution scenes or stage identical pixels.
|
||||
* The guest GPU command and its scheduled device timing still run. */
|
||||
flush_flat_batch();
|
||||
flush_tex_batch();
|
||||
s_identity_copies++;
|
||||
return;
|
||||
}
|
||||
if (gl_cpu_mode()) {
|
||||
static int seen[32][6], used;
|
||||
int key[6] = {sx,sy,dx,dy,w,h}, i;
|
||||
@@ -6903,6 +6923,7 @@ void gl_renderer_work_stats(GlRenderWorkStats *out) {
|
||||
out->counts[4] = s_hq_center_pruned;
|
||||
out->counts[5] = s_tc_hits; out->counts[6] = s_tc_misses; out->counts[7] = s_tc_evictions;
|
||||
out->counts[8] = s_hiw_copy_blits;
|
||||
out->counts[9] = s_identity_copies;
|
||||
}
|
||||
void gl_renderer_shutdown(void) {
|
||||
gl_renderer_render_thread_stop(); /* drains; the context comes back to this thread */
|
||||
|
||||
@@ -5081,8 +5081,8 @@ static void input_replay_frontend_tick(uint64_t frame) {
|
||||
f = std::fopen(path.c_str(), "w");
|
||||
if (!f) throw std::runtime_error("cannot write input replay render report");
|
||||
std::fputs("stat,count,total_us,max_us\n", f);
|
||||
const char *counts[9] = {"queue_uploads", "replay_draws", "bloom_fused", "coverage_depth", "centre_pruned", "texel_cache_hits", "texel_cache_misses", "texel_cache_evictions", "hiw_copy_blits"};
|
||||
for (int i=0; i<9; ++i) std::fprintf(f, "%s,%llu,0,0\n", counts[i], (unsigned long long)stats.counts[i]);
|
||||
const char *counts[10] = {"queue_uploads", "replay_draws", "bloom_fused", "coverage_depth", "centre_pruned", "texel_cache_hits", "texel_cache_misses", "texel_cache_evictions", "hiw_copy_blits", "identity_copies"};
|
||||
for (int i=0; i<10; ++i) std::fprintf(f, "%s,%llu,0,0\n", counts[i], (unsigned long long)stats.counts[i]);
|
||||
const char *spans[8] = {"depth_restore", "queue_replay", "vram_copy", "interp_capture", "interp_interval", "centre_copy", "depth_gpu_sample", "colour_gpu_sample"};
|
||||
double us = stats.frequency ? 1e6 / stats.frequency : 0;
|
||||
for (int i=0; i<8; ++i) std::fprintf(f, "%s,%llu,%.3f,%.3f\n", spans[i],
|
||||
|
||||
@@ -157,7 +157,7 @@ def main():
|
||||
ok = False
|
||||
runs[threaded] = p
|
||||
if args.wide_present:
|
||||
for margin, coverage, state, upload, bloom, cache, layers, copy in ((0,0,0,0,0,0,256,1), (0,0,1,1,1,1,256,1), (0,1,1,1,1,1,256,1), (1,0,1,1,1,1,256,1), (1,1,1,0,1,1,256,1), (1,1,1,1,0,1,256,1), (1,1,1,1,1,0,256,1), (1,1,1,1,1,1,4,1), (1,1,1,1,1,1,256,0)):
|
||||
for margin, coverage, state, upload, bloom, cache, layers, copy, identity in ((0,0,0,0,0,0,256,1,1), (0,0,1,1,1,1,256,1,1), (0,1,1,1,1,1,256,1,1), (1,0,1,1,1,1,256,1,1), (1,1,1,0,1,1,256,1,1), (1,1,1,1,0,1,256,1,1), (1,1,1,1,1,0,256,1,1), (1,1,1,1,1,1,4,1,1), (1,1,1,1,1,1,256,0,1), (1,1,1,1,1,1,256,1,0)):
|
||||
reference = run([probe, s, threaded, args.frames, *mode],
|
||||
{"PSX_GL_WIDE_MARGIN_SCISSOR": str(margin),
|
||||
"PSX_GL_COVERAGE_FAST": str(coverage),
|
||||
@@ -166,7 +166,8 @@ def main():
|
||||
"PSX_GL_BLOOM_FUSE_EXTEND": str(bloom),
|
||||
"PSX_GL_TEXEL_CACHE": str(cache),
|
||||
"PSX_GL_TEXEL_CACHE_LAYERS": str(layers),
|
||||
"PSX_GL_HIW_COPY_FAST": str(copy)})
|
||||
"PSX_GL_HIW_COPY_FAST": str(copy),
|
||||
"PSX_GL_IDENTITY_COPY_FAST": str(identity)})
|
||||
baseline = parse(reference.stdout)
|
||||
if reference.returncode or baseline["failures"] != 0 or any(baseline[k] != p[k] for k in KEYS):
|
||||
print(f"FAIL scale {s}: margin={margin} coverage={coverage} changed rendered output", baseline, p)
|
||||
|
||||
@@ -247,6 +247,10 @@ static void frame(int f, int buf_x) {
|
||||
gr_draw_flat_rect(576, 64, 32, 32, (uint16_t)(0x03e0 + f));
|
||||
gr_draw_textured_rect(buf_x + 100, 200, 32, 32, 0, 64, 512, 256, 0x0009);
|
||||
gr_copy_rect(buf_x + 10, 10, buf_x + 14, 13, 80, 50);
|
||||
/* Identity copies preserve colour/mask unless set-mask adds bit15. */
|
||||
mask_bits(f % 4 == 2, 0);
|
||||
gr_copy_rect(buf_x + 14, 13, buf_x + 14, 13, 80, 50);
|
||||
mask_bits(0, 0);
|
||||
if (quality_scene && f % 3 == 1) {
|
||||
/* Consume the copied bit15 mask before any later framebuffer clear. */
|
||||
mask_bits(0, 1);
|
||||
|
||||
Reference in New Issue
Block a user