mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-26 10:19:47 -04:00
Preserve background composite lifetime and park visual validation
This commit is contained in:
+21
-6
@@ -18,12 +18,27 @@ the composite remains continuous. Tags expire after two frames and reject
|
||||
reused packets whose words changed. This method performs no guest writes or
|
||||
extra guest allocations.
|
||||
|
||||
OpenGL preserves the tag across flat and textured batching. While an explicitly
|
||||
tagged background is active, it renders the full wide composite instead of
|
||||
copying the canonical center over it, which would create a scale seam. Other
|
||||
scenes retain the center-copy optimization. Measure performance in the title
|
||||
and validate the visible sky at the requested aspect before release. Vulkan's
|
||||
native-wide compositor is not implemented; this API does not add one.
|
||||
OpenGL preserves the tag across flat and textured batching. Once a valid
|
||||
background has been tagged, it renders the full wide composite instead of
|
||||
copying the canonical center over it, which would create a scale seam. Packet
|
||||
freshness and displayed-pixel lifetime are separate: a slow game or held display
|
||||
can retain stretched pixels after the two-frame packet guard expires. The
|
||||
full-composite requirement therefore remains latched until GPU reset or snapshot
|
||||
restore; packet-address/content freshness is not relaxed. Sessions that have not
|
||||
tagged a background retain the center-copy optimization. Measure performance in
|
||||
the title and validate the visible sky at the requested aspect before release.
|
||||
Vulkan's native-wide compositor is not implemented; this API does not add one.
|
||||
|
||||
### Parked validation checkpoint (2026-09-12)
|
||||
|
||||
The focused GPU packet/tag regression passes, including expired packets,
|
||||
changed packet contents, disabled widescreen and retained composite lifetime.
|
||||
The V8 Windows runtime builds and both game CTests pass. In the oil-field
|
||||
21:9 playtest the owner reports that terrain looks fine and the background
|
||||
flickers less badly, but still flickers. This is partial improvement, not visual
|
||||
acceptance. State replay required the HLE scheduler; repeat the comparison with
|
||||
matched scheduler settings before attributing the improvement solely to this
|
||||
change. Work is parked in a draft; no release is approved.
|
||||
|
||||
## Earlier projection-and-stretch implementation
|
||||
|
||||
|
||||
@@ -366,9 +366,12 @@ void gpu_ws_tag_hud_prim(uint32_t prim, int anchor);
|
||||
* Tag the complete background composite before submitting its ordering table.
|
||||
* The caller proves background identity/coverage; no guest data is modified. */
|
||||
void gpu_ws_tag_background_prim(uint32_t prim);
|
||||
/* Renderer policy: tagged background scenes need their full wide composite;
|
||||
* copying the canonical center over it would introduce a scale discontinuity. */
|
||||
/* Fresh packet tags are eligible for background classification. */
|
||||
int gpu_ws_background_stretch_active(void);
|
||||
/* A tagged background can remain in a wide surface after its packet expires.
|
||||
* Once used, retain full compositing until GPU reset or snapshot restoration.
|
||||
* Packet freshness must never re-enable canonical-center overwrites. */
|
||||
int gpu_ws_background_requires_full_composite(void);
|
||||
/* Clear synthetic margins to black over an opaque 0x64/65 rectangle's Y band
|
||||
* immediately before it executes. Packet-guarded; canonical VRAM is untouched. */
|
||||
void gpu_ws_tag_black_reveal_rect(uint32_t prim);
|
||||
|
||||
@@ -1967,6 +1967,15 @@ int gpu_ws_background_stretch_active(void) {
|
||||
frame - ws_background_tag_frame <= WS_HUD_ANCHOR_FRESH_FRAMES;
|
||||
}
|
||||
|
||||
int gpu_ws_background_requires_full_composite(void) {
|
||||
/* Freshness governs reuse of a packet address, not the lifetime of the
|
||||
* pixels it produced. A slow game frame or a held display buffer can keep
|
||||
* those pixels on screen indefinitely. Conservatively keep full mirroring
|
||||
* once a composite has been tagged; GPU reset/snapshot restore clears the
|
||||
* latch together with the tags. Never modify the packet freshness guard. */
|
||||
return ws_background_tags_used && ws_native_wide_configured();
|
||||
}
|
||||
|
||||
static int ws_nw_explicit_background(void) {
|
||||
if (!gpu_ws_background_stretch_active() ||
|
||||
gp0_cmd_source_addr == 0xFFFFFFFFu ||
|
||||
|
||||
@@ -1705,7 +1705,7 @@ static int wide_fast_center_valid(void) {
|
||||
/* An explicitly stretched sky differs inside the canonical viewport too.
|
||||
* Keep the full composite for those scenes, including later foreground
|
||||
* draws. Tags are installed before DMA, so no earlier center draws skip. */
|
||||
return s_wide_fast && !gpu_ws_background_stretch_active();
|
||||
return s_wide_fast && !gpu_ws_background_requires_full_composite();
|
||||
}
|
||||
static void wide_blit_center(GLuint wide_fbo, int base_x, int disp_y, int disp_h); /* def below */
|
||||
/* True if [lo,hi] (canonical draw-x) lies strictly inside the 4:3 frame, so the
|
||||
|
||||
@@ -113,11 +113,13 @@ static void test_background_packet_tags(void) {
|
||||
memcpy(gp0_cmd_buf, packet, sizeof(packet));
|
||||
gpu_ws_tag_background_prim(addr - 4u);
|
||||
assert(!gpu_ws_background_stretch_active());
|
||||
assert(!gpu_ws_background_requires_full_composite());
|
||||
assert(!ws_nw_explicit_background());
|
||||
|
||||
configure_native_wide_16_9();
|
||||
gpu_ws_tag_background_prim(0x80000000u | (addr - 4u));
|
||||
assert(gpu_ws_background_stretch_active());
|
||||
assert(gpu_ws_background_requires_full_composite());
|
||||
assert(ws_nw_explicit_background());
|
||||
/* Explicit proof remains valid after a foreground phase has begun. */
|
||||
s_bg_phase_frame = (uint32_t)s_frame_count;
|
||||
@@ -141,11 +143,19 @@ static void test_background_packet_tags(void) {
|
||||
++s_frame_count;
|
||||
assert(!gpu_ws_background_stretch_active());
|
||||
assert(!ws_nw_explicit_background());
|
||||
/* A held display retains its stretched pixels after packet expiry. The
|
||||
* compositor must not paste canonical 4:3 scenery over their center. */
|
||||
assert(gpu_ws_background_requires_full_composite());
|
||||
s_frame_count += 120;
|
||||
assert(gpu_ws_background_requires_full_composite());
|
||||
assert(!ws_nw_explicit_background());
|
||||
s_frame_count = 99;
|
||||
assert(!gpu_ws_background_stretch_active());
|
||||
assert(gpu_ws_background_requires_full_composite());
|
||||
s_frame_count = 100;
|
||||
ws_mode = 0;
|
||||
assert(!gpu_ws_background_stretch_active());
|
||||
assert(!gpu_ws_background_requires_full_composite());
|
||||
|
||||
/* Reject semi-transparent polygons, rectangles, misalignment and RAM
|
||||
* overflow; a rejected tag must not even enable the full-composite path. */
|
||||
@@ -153,6 +163,7 @@ static void test_background_packet_tags(void) {
|
||||
0x1F800000u};
|
||||
reset_gpu_state_for_test();
|
||||
configure_native_wide_16_9();
|
||||
assert(!gpu_ws_background_requires_full_composite());
|
||||
for (unsigned i = 0; i < sizeof(bad_prim) / sizeof(bad_prim[0]); ++i)
|
||||
gpu_ws_tag_background_prim(bad_prim[i]);
|
||||
assert(!gpu_ws_background_stretch_active());
|
||||
|
||||
Reference in New Issue
Block a user