devkitPro / SDL

Simple Directmedia Layer
https://libsdl.org
zlib License
11 stars 12 forks source link

Wii U Render: disabling vSync causes vertex corruption #77

Open ds-sloth opened 1 month ago

ds-sloth commented 1 month ago

Bug Report

What's the issue you encountered?

This is another issue we found while testing recent TheXTech engine (https://github.com/TheXTech/TheXTech) builds on Wii U.

When we tested a branch with in-game configuration support that calls SDL_RenderSetVSync(renderer, g_config.render_vsync); on our Wii U target, we found substantial vertex corruption that appears only when that call in included. (Note that the default value for vSync is disabled.)

Later I found that the devkitPro SDL2 renderer for Wii U forces vSync to be enabled on render initialization (likely due to this issue). However, it still exposes the SDL_RenderSetVSync method (added in SDL 2.0.18).

We worked around the issue by forcing vSync to always be on on Wii U. This is not ideal because our game engine runs at 65 FPS for historical reasons.

How can the issue be reproduced?

This issue can be trivially reproduced by calling SDL_RenderSetVSync(renderer, 0); after initializing an SDL2 renderer on Wii U.

Environment?

Duplicated from my other report regarding Wii U:

I'm using Fedora, but this also affects our CI builds which pull from your Docker image. I really don't think that the environment is related.

Additional context?

I tried to create a fix that waited for a buffer flip instead of for a vSync by removing the condition if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) from WIIU_SDL_RenderPresent and instead making the Vsync call depend on the flag as shown below, but this reduced performance, so we used the workaround explained above.

        wait_count++;

        if (renderer->info.flags & SDL_RENDERER_PRESENTVSYNC) {
            GX2WaitForVsync();
        }
        else {
            GX2WaitForFlip();
        }
    }

Thanks for your time and hard work on the library!

GaryOderNichts commented 1 month ago

The vertex corruption is caused by the CPU writing to the attribute buffers, while the GPU is still drawing them to the current frame. The current V-Sync code waits for the previous frame to be drawn before moving on, which is why enabling V-Sync is necessary. I'm currently working on some renderer changes which should hopefully address this.

ds-sloth commented 1 month ago

It's great to hear you've got some render improvements in the pipeline. In that case I might suggest that you temporarily paper over this bug by defining a stubbed implementation of SDL_RenderSetVSync.