I am facing a problem with FLTK that I currently do not **yet** know how to solve, so I am looking for advice and some understanding of FLTK's innards.
Vulkan is a multi thread safe API, but it requires manual synchronization to try to send all drawing commands at once, unlike OpenGL where synchronization is handled by the driver and commands can be sent in any order.
While this is not a problem with one window, I believe FLTK's single threaded design is stalling my application's drawing when I have two or more Vulkan windows open. In my player, I get 60FPS at 4K with one window, but about 48-50 FPS with two windows.
The current pattern I use for each window:
1. Start recording commands for Viewport (Vulkan Window)
2. Draw commands for Viewport
3. End recording commands for Viewport
4. Synchronize Viewport
5. Start recording commands for Timeline (2nd Vulkan Window)
6. Draw commands for Timeline
7. End recording commands for Timeline
8. Synchronize Timeline
Ideally, the access pattern for Vulkan should be:
1. Start recording commands for Viewport (Vulkan Window)
2. Draw commands for Viewport
3. End recording commands for Viewport
4. Start recording commands for Timeline (2nd Vulkan Window)
5. Draw commands for Timeline
6. End recording commands for Timeline
7. Synchronize Viewport **AND** Timeline together
Does anyone have a suggestion on how can this be handled sanely with FLTK's event loop?
Sounds reasonable: two windows need some more time to draw than one window. What do you expect with two windows?
I think we need more info to give a useful answer. You wrote that "Vulkan is a multi thread safe API" but you didn't tell us what parts you are (currently) doing in worker threads and how you want to synchronize.
In my simple model I would likely (try to) do it like this:
I assume that "recording commands" and "draw commands" can be done in threads and that you don't use the draw() method for these parts. Is this correct?
If yes, this could be done in parallel for both windows. When you need to synchronize your drawing you'd call redraw() on your windows, but this would likely have to be done in the FLTK (GUI) thread and would mark both windows to be drawn. I'd suggest to use Fl::awake(your_handler, your_window) for this. If this happens somehow simultaneously, then the next Fl::flush() in the FLTK event loop would call draw() for both windows.
In your draw() method you would have to do the last part: "synchronize" your Vulkan drawings. This would hopefully happen in the same pass of the event loop for both windows, and that's what you want to achieve, if I understood correctly.
That's where the problem lies. When you call Fl::flush(), Vulkan uses vkQueueSubmit which sends all recorded commands to the GPU and then the swap_buffer() command waits for the presentation (vkQueuePresentKHR). That's where the stall happens as these are done sequentially, IIUC.
In order to have the best performance, vkQueueSubmit (ie flush)
should be called only ONCE with all the drawing commands for
**BOTH** windows so that GPU does not stall.
In summary, I am looking for a way to count the number of
Fl_Vk_Windows' (FLTK's as_vk_window()) and skip the flush except
for the last Vulkan window found after the drawings for **both**
windows are done.
-- ggar...@gmail.com
--
You received this message because you are subscribed to the Google Groups "fltk.coredev" group.
To unsubscribe from this group and stop receiving emails from it, send an email to fltkcoredev...@googlegroups.com.
To view this discussion visit https://groups.google.com/d/msgid/fltkcoredev/0fe331ad-7094-4067-9622-590b86094eb1%40gmail.com.