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 - Metal renderer produces black screen when calling SDL_RenderPresent after changing render target
Summary: Metal renderer produces black screen when calling SDL_RenderPresent after cha...
Status: RESOLVED FIXED
Alias: None
Product: SDL
Classification: Unclassified
Component: render (show other bugs)
Version: 2.0.10
Hardware: x86_64 macOS 10.15
: P2 blocker
Assignee: Ryan C. Gordon
QA Contact: Sam Lantinga
URL:
Keywords: target-2.0.14
Depends on:
Blocks:
 
Reported: 2020-03-02 02:59 UTC by Pennie Quinn
Modified: 2020-07-17 15:18 UTC (History)
2 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
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 !