xemu-project / xemu

Original Xbox Emulator for Windows, macOS, and Linux (Active Development)
https://xemu.app
Other
2.72k stars 273 forks source link

Disney's The Haunted Mansion FMV Flicker #1183

Open Triticum0 opened 2 years ago

Triticum0 commented 2 years ago

Title

https://xemu.app/titles/544d000d/#Disney-s-The-Haunted-Mansion

Bug Description

This game suffers from FMV flickering unrelated to 1049#

https://user-images.githubusercontent.com/71127352/181931835-4b5bd7aa-32e7-4827-8daa-8fbd9ac45615.mp4

Expected Behavior

Should not flicker https://youtu.be/fYFFAjqXffY?t=80

xemu Version

Version: 0.7.58 Branch: master Commit: https://github.com/mborgerson/xemu/commit/6f878ede01ad1992392dde22b506a3c00fab87c4 Date: Wed Jul 6 02:14:58 UTC 2022

System Information

Field | Value -- | -- OS | Windows 10 CPU | AMD Ryzen 5 2600 Six-Core Processor Graphics Device | NVIDIA GeForce RTX 3060 Ti/PCIe/SSE2 Graphics Driver | 4.0.0 NVIDIA 512.95

Additional Context

No response

abaire commented 2 years ago

The game is not using the PVIDEO overlay for the initial FMVs, which explains why it's unaffected by the fix that addressed #1049.

For a frame that fails, I see a render of a 640x960 texture with format NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8 but it is entirely black. Addr 0x3584000

For a frame that works, I see a render of a 640x960 texture with format NV097_SET_TEXTURE_FORMAT_COLOR_LU_IMAGE_X8R8G8B8 that contains the video frame. Addr 0x3584000

In both cases the mesh is identical as are the texture coordinates, it is just the content of the texture that appears incorrect. The mesh is a single triangle (not a quad) with vertices {0,0}, {2560,0}, {0,1920} for a 640x480 framebuffer. The texcoords are {0,0}, {2560,0}, {0,3840} for a 640x960 texture (so in both cases the mesh is 4x the texture). The vertex shader is a simple passthrough that does no manipulation to the inputs.

In the frame that does not work, I see

nv2a_pgraph_surface_target       Target: [COLOR @ 0x03458000] (ln) aa:0 clip:x=0,w=640,y=0,h=480
nv2a_pgraph_surface_match_color  Match: [COLOR @ 0x03458000 (640x480)] (ln) aa:0 clip:x=0,w=640,y=0,h=480,p=2560
nv2a_pgraph_surface_hit_color    Hit: [COLOR @ 0x03458000 (640x480)] (ln) aa:0, clip:x=0,w=640,y=0,h=480,p=2560
nv2a_pgraph_surface_render_to_texture Rendering surface 0x03584000 to texture (640x960)

In the frame that does work I see

nv2a_pgraph_surface_target       Target: [COLOR @ 0x03458000] (ln) aa:0 clip:x=0,w=640,y=0,h=480
nv2a_pgraph_surface_match_color  Match: [COLOR @ 0x03458000 (640x480)] (ln) aa:0 clip:x=0,w=640,y=0,h=480,p=2560
nv2a_pgraph_surface_hit_color    Hit: [COLOR @ 0x03458000 (640x480)] (ln) aa:0, clip:x=0,w=640,y=0,h=480,p=2560

In both the working and broken case, the draw is using 0x3584000 as the input and 0x03458000 as the output.

Prior to the draw that works, I see a cpu write nv2a_pgraph_surface_cpu_access 0x03584000+0x0, prior to the draw that fails I do not. The game is clearing the target surface each frame, I assume this clears the GL texture that is then used by the frames that are blanked. The CPU writes are only done every 5th buffer flip and the surface is toggled between 0x3584000 and 0x03458000 between.

The sequence is roughly:

Clear 358
CPU write 358
Flip

Draw 345
Flip

Draw 345
Clear 358
Flip

Draw 345
Clear 358
Flip

Draw 345
Clear 358
Flip

Draw 345
Clear 358
CPU write 358
Flip

The surface clip, window clip, and clear rect all match the 358 surface size during each clear

abaire commented 2 years ago

I did an nv2a-trace on the hardware and the results are consistent with how xemu is behaving, apart from what is actually displayed on the AV output. I see the 358 surface being cleared and occasionally populated correctly. I see the 345 surface being alternately correct and black (2 draws correct, 7 draws black, repeat).

My guess at the moment is that there's something unusual about the framebuffer selection/flipping during this playback; perhaps during the blacked out 345 frames another framebuffer is being displayed with previous content. I don't see any pgraph commands that would indicate that there's rendering being done to another surface, however.

UPDATE: After each flip, I see NV_PCRTC_START set to 345