Closed terrybrash closed 4 weeks ago
Does Metal only allow using the swapchain once per frame?
It's expected behaviour. It's probably not documented anywhere and also not caught by the sokol-gfx validation layer, but there should only be one render pass per swapchain (or in general: render target) and frame.
For offscreen render targets, doing multiple passes to the same render target is at most less efficient, but for rendering to the window system swapchains there are additional restrictions (as you noticed with that Metal error).
Basically, you shouldn't think of render passes as a way to group draw calls with similar render state (which was often the case in 'traditional' DX9 style engines - those often had separate passes to split opaque and alpha rendering into the same render target), but instead as nodes in a dependency tree of render targets, with a final swapchain pass at the root which depends on the entire node tree.
TL;DR: rule of thumb: one render pass per render target (or swapchain) and frame :)
PS: before the 'render pass cleanup' this probably worked by accident because the 'present' call was in the final sg_commit()
but with the render-pass cleanup this had to move into sg_end_pass()
to allow rendering into multiple independent swapchains per frame. In any case, there shouldn't be a reason to do multiple render passes into the same render target.
Ok that makes sense. Thanks for the knowledge!
On Mac, doing a swapchain pass twice prints an error/warning:
Each CAMetalLayerDrawable can only be presented once!
This doesn't happen on Windows using the D3D11 backend. It's not clear if this is a bug or just misuse of sokol.
I've modified the "clear" example in sokol-rust to reproduce the issue: https://github.com/terrybrash/sokol-rust/commit/f153ae8448fb852caedb0eb38e3f788779d16d58