Synchronize depth24 clears before immediate CPU reads

This commit is contained in:
Alexandros Mandravillis
2026-09-06 13:54:52 +03:00
parent 4c35d0515b
commit 7dc34829fb
3 changed files with 25 additions and 7 deletions
+7 -3
View File
@@ -23,7 +23,10 @@ CPU-authority mode retains its existing no-readback behavior.
context. It checks the complete native CPU image against full hardware readback
after ordered synthetic workloads. It covers single pixels, odd-width row
stride, disjoint uploads, texture dependencies, wrapping fills, overlapping
copies, masks, blending, clipping, precision margins and state restore.
copies, masks, blending, clipping, precision margins and state restore. A depth24 exit followed by an immediate
CPU read verifies that cleared movie pixels are visible and newer overlapping
texture uploads survive. It tests this existing clear policy, not full movie
playback or depth24 raster accuracy.
The hardware rasterizer is shared by the comparison; this proves coherence,
not independent raster accuracy. No retail assets are required.
@@ -32,8 +35,9 @@ Run `python runtime/tests/run_gl_readback_region.py --compiler-bin <mingw-bin>
`sdl3-src/include` and `sdl3-build/libSDL3.a`. The Windows runner uses hidden
windows. It tests
native and4x scales. `--gl-source <old-gpu_gl_renderer.c> --expect-unbounded`
checks the previous implementation: pixel comparisons pass, and only the small
transfer assertion fails. Each command/result is saved in `receipt.json` under a fresh run directory inside the output root. Configure `runtime/` with `BUILD_TESTING=ON` and `PSX_GL_READBACK_SDL_ROOT=<deps>` on MinGW to register `gl_readback_region_test`; run it with `ctest --test-dir <build> -R gl_readback_region_test --output-on-failure`. Missing dependencies print a configure-time message and do not count as a hardware pass.
accepts an unbounded implementation only when pixel comparisons pass and
exactly the small-transfer assertion fails. An older implementation with a
coherence defect (including the depth24 clear) is correctly rejected too. Each command/result is saved in `receipt.json` under a fresh run directory inside the output root. Configure `runtime/` with `BUILD_TESTING=ON` and `PSX_GL_READBACK_SDL_ROOT=<deps>` on MinGW to register `gl_readback_region_test`; run it with `ctest --test-dir <build> -R gl_readback_region_test --output-on-failure`. Missing dependencies print a configure-time message and do not count as a hardware pass.
## Prior art and scope
+4 -1
View File
@@ -2544,7 +2544,10 @@ static void depth24_clear_skipped_fb(void) {
glDisable(GL_SCISSOR_TEST);
p_glBindFramebuffer(PSXGL_FRAMEBUFFER, 0);
rect_add(&s_pack_dirty, x0, y0, x1, y1);
if (!s_cpu_auth_dual) rect_add(&s_cpu_dirty, x0, y0, x1, y1);
if (!s_cpu_auth_dual) {
rect_add(&s_cpu_dirty, x0, y0, x1, y1);
s_gpu_dirty = 1; /* The clear must reach an immediate CPU read too. */
}
present_dirty_rect(x0, y0, x1, y1, 1);
rect_clear(&s_d24_skip_fb);
}
+14 -3
View File
@@ -7,8 +7,9 @@ void gpu_vram_dirty_mark_row_impl(uint32_t y){}
void gpu_vram_dirty_mark_rect(int x,int y,int w,int h){}
void gpu_vram_dirty_mark_all(void){}
int psx_netplay_active(void){return 0;}
int gpu_display_is_depth24(void){return 0;}
void gpu_get_display_info(GpuDisplayInfo *out){memset(out,0,sizeof(*out));}
static int test_depth24;
int gpu_display_is_depth24(void){return test_depth24;}
void gpu_get_display_info(GpuDisplayInfo *out){memset(out,0,sizeof(*out));out->display_x=32;out->display_y=32;out->width=320;out->height=16;}
int psx_ws_prim_in_backdrop(void){return 0;}
int g_ws_tex_edge_pct=0;
int psx_ws_prim_is_tagged(void){return 0;}
@@ -60,7 +61,17 @@ int main(int argc,char **argv){
glb_set_draw_area(0,0,1023,511);glb_draw_flat_rect(320,320,8,8,0x4444);
for(int i=0;i<1024*512;i++)image[i]=(uint16_t)((i*23)&0x7fff);
gl_renderer_restage_vram_after_savestate();verify("state restage with pending draw");
check(image[511*1024+1020]==oracle[511*1024+1020],"edge preserved");
/* Existing depth24 policy clears the skipped movie band on return to15-bit.
* That GPU write must become visible without waiting for another primitive. */
static uint16_t movie[480*16], texture[4]={0x3210,0x3210,0x3210,0x3210};
for(int i=0;i<480*16;i++)movie[i]=0x1234;
test_depth24=1;depth24_upload_policy();
glb_vram_transfer_in(32,32,480,16,movie);
glb_vram_transfer_in(33,33,2,2,texture);
test_depth24=0;depth24_upload_policy();
check(glb_vram_read(40,40)==0,"depth24 cleared band immediate CPU read");
check(glb_vram_read(33,33)==0x3210,"newer overlapping texture survives clear");
verify("depth24 leave coherence without subsequent primitive");
printf("checks=%d failures=%d\n",checks,failures);
gl_renderer_shutdown();SDL_DestroyWindow(win);SDL_Quit();return failures?1:0;
}