Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Render to tex improvements #70

Merged
merged 6 commits into from
Apr 22, 2024

Conversation

mardy
Copy link
Collaborator

@mardy mardy commented Apr 19, 2024

Here's a few changes that fix various issues I've met with a game I'm writing, which makes extensive use of the "render to texture" feature.

Easier to review commit by commit (please don't squash them into merging, since the addressed issues are all slightly different).

I honestly haven't understood why the commit "ogc: invalidate current texture contents before copying the EFB onto it" is needed, but without it I do see (minor) random corruption on the generated texture.

Instead of copying at the end of every command queue flush, copy the EFB
to the texture only when the texture stops being a render target.

Unfortunately SDL invokes the SetRenderTarget() method after having
updated the render target pointer, forcing us to keep our own copy of
it.
If we are rendering to a texture, we must avoid writing to the XFB,
because the image we are rendering might not be intended to be shown
as-is on the XFB.
So, when clearing the display, pay attention to whether we are rendering
to a texture and, in that case, do not copy the EFB to the XFB. Instead,
copy it to the texture itself (not that we care a lot about this copy,
since the texture will anyway be overwitten once it stops being a render
target; but we do care about this operation causing a full clearing of
the EFB).
It can happens that the client program immediately calls
SDL_DestroyTexture() after draawing it. Luckily for us, SDL is smart
enough to realize that the texture has been used in a draw operation and
issues a SDL_RenderFlush() so that all the operations get executed. But
this means that on our side, we must also make sure that when we return
from OGC_RunCommandQueue() the texture data is no longer needed. The
call to GX_DrawDone() does exactly this.
Indeed, the situation where a rendering to texture operation begins
after the EFB has already been painted can happen. In order not to lose
the existing EFB contents, make a copy of them into a texture (using the
same size of the render-to-texture target) and then restore them by
redrawing the saved texture over the EFB, once the render-to-texture
operation has completed.

Note that it's important that any calls to GX_SetPixelFmt() happen in
the appropriate order:

1. Save the current EFB contents
2. Change the EFB format (by calling GX_SetPixelFmt())
3. Perform all the render-to-texture drawing operations
4. Save the EFB into the target texture
5. Restore the EFB format
6. Restore the EFB contents by drawing the texture saved in step 1

Swapping the 5th and 6th steps does not cause any visible issues in
Dolphin, but causes the EFB to be painted back with wrong colors on a
real Wii.
This is needed to avoid visual artifacts on the saved texture.
The documentation says that this is needed, though in practice I haven't
yet seen any issue with not using it.
@WinterMute
Copy link
Member

I honestly haven't understood why the commit "ogc: invalidate current texture contents before copying the EFB onto it" is needed, but without it I do see (minor) random corruption on the generated texture.

Because the GPU doesn't go through the cache and if the CPU has touched that memory before you do the copy then it will get corrupted when those cache lines get evicted.

@WinterMute WinterMute merged commit 9ca06e0 into devkitPro:ogc-sdl-2.28 Apr 22, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants