diff --git a/runtime/src/gpu_gl_renderer.c b/runtime/src/gpu_gl_renderer.c index 329f1c45..6604f8ca 100644 --- a/runtime/src/gpu_gl_renderer.c +++ b/runtime/src/gpu_gl_renderer.c @@ -4291,8 +4291,9 @@ static int cpu_raster_required(void) { * GPU surface. The CPU mirror stays the authoritative record of the real * frame, so the pass never rasterizes into it. depth24 scanout still * presents from the CPU mirror and keeps its write-through. */ + /* A generated (in-between) frame is presentation only, like a pass. */ return !s_raster_ok || s_depth24_skip_up || - ((s_cpu_auth_dual || s_hd_native_authority) && !s_pass_active); + ((s_cpu_auth_dual || s_hd_native_authority) && !s_pass_active && !s_fg_drawing); } /* Bracket each authoritative draw so a later netplay/session policy change * cannot accidentally disable the faithful floor for HD replacement mode. */ diff --git a/runtime/tests/test_gl_frame_gen.c b/runtime/tests/test_gl_frame_gen.c index 1f45cd7b..fcf249ca 100644 --- a/runtime/tests/test_gl_frame_gen.c +++ b/runtime/tests/test_gl_frame_gen.c @@ -354,6 +354,15 @@ int main(int argc, char **argv) { FILE *f = fopen("pm.rgba", "wb"); fwrite(img, 4, (size_t)ww * wh, f); fclose(f); } check(dm != r0 && dm != r1, "phase 0.5 is neither endpoint"); + /* With an HD texture pack the CPU raster is native VRAM's authority; + * an in-between frame is presentation only and must not draw there. */ + gl_renderer_set_hd_texture_mode(1); + static uint16_t before[1024 * 512]; + memcpy(before, s_vram, sizeof before); + check(fg_generate(0.5, 0) == 1, "compose at phase 0.5 under HD authority"); + check(memcmp(before, s_vram, sizeof before) == 0, + "generated frame leaves native VRAM unchanged under HD authority"); + gl_renderer_set_hd_texture_mode(0); free(img); check(n_gen > 0, "generated frames were presented"); }