GPU: Swap Buffers Design #111389
No reviewers
Labels
No Label
Interest
Alembic
Interest
Animation & Rigging
Interest
Asset System
Interest
Audio
Interest
Automated Testing
Interest
Blender Asset Bundle
Interest
BlendFile
Interest
Code Documentation
Interest
Collada
Interest
Compatibility
Interest
Compositing
Interest
Core
Interest
Cycles
Interest
Dependency Graph
Interest
Development Management
Interest
EEVEE
Interest
Freestyle
Interest
Geometry Nodes
Interest
Grease Pencil
Interest
ID Management
Interest
Images & Movies
Interest
Import Export
Interest
Line Art
Interest
Masking
Interest
Metal
Interest
Modeling
Interest
Modifiers
Interest
Motion Tracking
Interest
Nodes & Physics
Interest
OpenGL
Interest
Overlay
Interest
Overrides
Interest
Performance
Interest
Physics
Interest
Pipeline, Assets & IO
Interest
Platforms, Builds & Tests
Interest
Python API
Interest
Render & Cycles
Interest
Render Pipeline
Interest
Sculpt, Paint & Texture
Interest
Text Editor
Interest
Translations
Interest
Triaging
Interest
Undo
Interest
USD
Interest
User Interface
Interest
UV Editing
Interest
VFX & Video
Interest
Video Sequencer
Interest
Viewport & EEVEE
Interest
Virtual Reality
Interest
Vulkan
Interest
Wayland
Interest
Workbench
Interest: X11
Legacy
Asset Browser Project
Legacy
Blender 2.8 Project
Legacy
Milestone 1: Basic, Local Asset Browser
Legacy
OpenGL Error
Meta
Good First Issue
Meta
Papercut
Meta
Retrospective
Meta
Security
Module
Animation & Rigging
Module
Core
Module
Development Management
Module
Grease Pencil
Module
Modeling
Module
Nodes & Physics
Module
Pipeline, Assets & IO
Module
Platforms, Builds & Tests
Module
Python API
Module
Render & Cycles
Module
Sculpt, Paint & Texture
Module
Triaging
Module
User Interface
Module
VFX & Video
Module
Viewport & EEVEE
Platform
FreeBSD
Platform
Linux
Platform
macOS
Platform
Windows
Severity
High
Severity
Low
Severity
Normal
Severity
Unbreak Now!
Status
Archived
Status
Confirmed
Status
Duplicate
Status
Needs Info from Developers
Status
Needs Information from User
Status
Needs Triage
Status
Resolved
Type
Bug
Type
Design
Type
Known Issue
Type
Patch
Type
Report
Type
To Do
No Milestone
No project
No Assignees
3 Participants
Notifications
Due Date
No due date set.
Dependencies
No dependencies set.
Reference: blender/blender#111389
Loading…
Reference in New Issue
Block a user
No description provided.
Delete Branch "Jeroen-Bakker:gpu/gpu-swap-buffers"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
In the current implementation window manager directly calls GHOST
swap buffers. The GPU backend state could become invalid as it is
not aware of the buffer swap.
NOTE: This should move to documentation, as the implementation
has done in a different PR.
Solution 1
Introduce
GPU_context_swap_buffers
so the backend cando pre/post stuff to ensure the state is always valid.
Reasoning
In Vulkan the texture layout is not query-able, but the application is
responsible to always communicate the correct layout to the Vulkan API.
This isn't working for images from the swap chain.
In Vulkan the command buffer needs to be in a certain state as GHOST and
the GPU module share the same instance. Separating the command buffers
could be done, but would have synchronization issues as there can still
be command in flight or not, which isn't known by GHOST.
During start of blender contexts are initialized twice that leads to
incorrect behaviors as the state is not clear.
During start of blender buffers are swapped without submitting the
command buffer, leading to missing texture clears.
Vulkan
VKContext::swap_buffers_begin
can then make sure that the textureof the default framebuffer is set to what GHOST expects (GENERAL)
it can also flush all commands that are still in recording state.
this includes the barrier to change the framebuffer texture layout.
VKContext::swap_buffers_end
can than retrieve the new framebuffer,command buffer, texture from GHOST and reset what is needed to reset.
Solution 2
Use backend specific callbacks as to keep the issue located in the
vulkan backend. Similar to MTL, except we might still need to have
pre/post callbacks.
Reasoning
Control flow of the swap chain currently isn't clear in Vulkan,
Solution 1 might close the gab a bit, but is a solution that
would only add value to vulkan. So what is the value of adding
it to the public API.
GHOST Context and GPU are highly connected, but would still use
callbacks to keep them a bit separated.
Using a single callback would require giving control away from
GHOST_swapBuffers to the GPU module, which leads to potential
invalid state in GHOST. Currently not an issue, but best to avoid.
Main difference with Metal is that the Metal backend only draws
into the swapchain texture, during the present callback. Until
then it uses an intermediate. The Vulkan backend does draw
directly onto a swapchain texture, and swap buffers performs
a swap.
Solution 3
Similar to Metal where it is only allowed to draw/blit to the swap
chain texture in the scope of the present callback.
Reasoning
Is less complex as both the GPU module and GHOST have their own
responsibility. Requires additional texture and blitting overhead.
In Metal swapchain are part of commands, in vulkan swap chain are
done on queue level.
NOTE: this solution will have allocated 3 times the required
texture memory to present a screen to the user. 1 are the per
area offscreen buffers/viewports, 1 the framebuffer and 1 the
swapchain texture.
It would improve the performance as the display texture can
be acquired later.
Conclusion
We will align the vulkan implementation with the metal one.
Having a single callback would reduce the complexity and
needed resources owned by the GHOST context.
GPU: Swap Buffersto WIP: GPU: Swap BuffersThis looks like it would certainly be useful!
One feature that exists within the Metal backend/GHOST_ContextCGL currently is the present callback, which allows the GPU backend to specify a function to call in order to perform a present.
i.e:
metalRegisterPresentCallback
For Metal, this is required to achieve the same thing. Rather than the GHOST_* module being responsible for presenting, instead the GPU backend is.
in Metal:
GHOST_ContextCGL::metalSwapBuffers()
calls directly intovoid present(MTLRenderPassDescriptor *blit_descriptor, id<MTLRenderPipelineState> blit_pso, id<MTLTexture> swapchain_texture, id<CAMetalDrawable> drawable)
which exists within the GPU module, in order to achieve the same end result as a swap_buffers_begin/end implementation.In this case however, there is only a single function allowing the backend full control to coordinate everything, with the drawable being handed back from the GHOST module.
I'm not sure if it would then be easier to generalise the implementation to just a single callback where the GPU backend is responsible for the full presentation?
I guess this perhaps makes sense for Metal as there is only one possible GHOST context per API, whereas I imagine this is not true for Vulkan, where there are several different window manager implementations.
Anyway, I think the design looks good, but just throwing some thoughts out there.
For Metal, the existing mechanism could instead just be moved into either of the begin/end functions, and the actual present could be a no-op. This is also often a requirement in Metal, as the actual present can be called from within a dependent command buffer e.g.
[command_buffer present]
, hence for synchronisation (to resolve old flickering issues), this had to be done this way before.Thanks for the feedback. I think that a callback might become to platform specific. vulkan would require different arguments, datatypes etc. But will look in more depth to the Mtl implementation before deciding what is best
First of all, the swap-chain acquirer function is not constrained by any image-layout, nor does it perform transitions.
The layout simply needs to be VK_IMAGE_LAYOUT_PRESENT_SRC_KHR when presenting.
Regarding synchronization.
When I first implemented it in my branch, I synced using semaphores.
source
Here's how it works:
By doing this, we can be assured that we have acquired the image of that time. This is because the Semaphore and swap-chain-image are linked.
As for the commands, we don't need to synchronize them at all. So, I think the commands for present should be dedicated.
But then the official branch was significantly rewritten, so I made it a different implementation. At this stage, synchronization can be done without using semaphore. Also, I was able to implement resize.
However, in this case, we wait image-available-semaphores at present, so it is difficult to say that it is being used very effectively.
source
Either way, I can't find a clear reason why we have to share commands. Conversely, using the same command as the offscreen render for present submission increases the probability of leading to a serious error.
To clarify synchronization, the system provided by Vulkan is semaphore.
Regarding tracking Image-Layout
Ideally, swap-buffer should be systematic with GHOST*. I think the problem now is the instability of that Image-Layout. However, I think that the actual blender drawing system is wonderful, so even if the layout is hidden in the dark during the development stage, I think that a robust layout transition structure will be visible.
So, I think that it is an effective means to track the layout for the time being.
PS. I think that Layout's GENERAL means Layout when using Storage-Image rather than general purpose.
In the case of Swap-Chain-Image, it is often the target of Attachment and Blit, but I don't think it will be Storage-Image.
WIP: GPU: Swap Buffersto GPU: Swap Buffers DesignPull request closed