We are currently migrating Bugzilla to GitHub issues.
Any changes made to the bug tracker now will be lost, so please do not post new bugs or make changes to them.
When we're done, all bug URLs will redirect to their equivalent location on the new bug tracker.

Bug 5011

Summary: Metal renderer produces black screen when calling SDL_RenderPresent after changing render target
Product: SDL Reporter: Pennie Quinn <pennie.ada.quinn>
Component: renderAssignee: Ryan C. Gordon <icculus>
Status: RESOLVED FIXED QA Contact: Sam Lantinga <slouken>
Severity: blocker    
Priority: P2 CC: pennie.ada.quinn, ssrobins
Version: 2.0.10Keywords: target-2.0.14
Hardware: x86_64   
OS: macOS 10.15   

Description Pennie Quinn 2020-03-02 02:59:55 UTC
OS is specifically macOS 10.15.3 on a 2019 MacBook Pro.
SDL_RendererInfo indicates Metal is the chosen driver.

Summary:
Changing a renderer's target to a texture, then back to the default target, produces a black screen when calling SDL_RenderPresent.

If you SDL_RenderCopy something between steps (4) and (5) below, things work as expected.

No results from SDL_GetError at any point along the way.

Workaround:
I am currently avoiding this issue via SDL_HINT_RENDER_DRIVER (OpenGL works as expected).

Steps to repro:
1) Make an SDL_TEXTUREACCESS_TARGET texture.
2) (draw things to the main render target)
3) SDL_SetRenderTarget( renderer, texture );
4) SDL_SetRenderTarget( renderer, NULL );
5) SDL_RenderPresent( renderer );

Thanks.
Comment 1 Sam Lantinga 2020-03-02 22:57:14 UTC
Ryan, this sounds like a regression, can you look at this for 2.0.12 release?
Comment 2 Steve Robinson 2020-04-05 20:08:15 UTC
Sounds similar to what I hit on Android:
https://bugzilla.libsdl.org/show_bug.cgi?id=5077
Comment 3 Ryan C. Gordon 2020-07-16 17:51:59 UTC
METAL_SetRenderTarget commits data.mtlcmdbuffer to the GPU and then sets it to nil.

METAL_RenderPresent tries to add a presentDrawable command to the now-nil command buffer, and commit it, which are safe no-ops in Objective-C, so the framebuffer never gets presented in this scenario.

This code is probably also wrong if you try to present without setting the render target back to NULL first, but I'm not sure what SDL is meant to do in that case.

I _think_ if you just stick this line:

    METAL_ActivateRenderCommandEncoder(renderer, MTLLoadActionLoad, NULL, nil);

Before this in METAL_RenderPresent:

    if (data.mtlcmdencoder != nil) {

It'll fix the first issue (but not the second I mentioned).

I'll try this on a mac later, but if you get there before me, let me know if it works, please!

--ryan.
Comment 4 Ryan C. Gordon 2020-07-17 15:18:11 UTC
I tried this, it definitely fixes the issue, so this fix is now https://hg.libsdl.org/SDL/rev/f3aaa73bf221 !