Currently, GTK does not check the result of vkAcquireNextImageKHR() and
assumes that it always succeeds. As a result, the vkQueuePresentKHR() is
unconditionally set to wait for the semaphore passed to
vkAcquireNextImageKHR() earlier.
However, if vkAcquireNextImageKHR() fails for some reason, the semaphore
passed to it does not get signalled. This causes the presentation
command to wait for the semaphore to be signalled indefinitely, which
causes GTK to hang.
This change adds error handling around vkAcquireNextImageKHR() to make
GTK recreate the Vulkan swapchain when it is necessary or beneficial and
helps avoiding situations that could cause indefinite waits.
In order for the size change check to make sense, vk_pipeline_cache_size
needs to correspond to the size of the cache we last wrote to disk.
We were forgetting to update it after saving the cache, so the
check was ineffective.
GdkVulkanContext is deprecated and only exposed in the api because
we need it as return type of the (deprecated)
gdk_surface_create_vulkan_context() API.
This is using the Vulkan renderer.
It also allows claiming support for all the formats that only Vulkan
supports, but that neither GL nor native mmap can handle.
I did it because it unifies the code.
But it also gains the benefit of being debuggable because it can
now be turned off via GDK_VULKAN_SKIP=incremental-present
This ensures both that we signal a semaphore for a dmabuf when we export
an image and that we import semaphores for dmabufs and wait on them.
Fixes Vulkan node-editor displaying the Vulkan renderer in the sidebar.
This code does not add a downloader, so we do not claim support for all
the new formats.
It just queries the formats. But this can be used to import dmabufs
directly into the Vulkaan renderer.
use it to collect the optional features we are interested in and turn
them on only if available.
For now we add the dmabuf features, but we don't use them yet.
Some dmabuf formats were added in Vulkan 1.3.
Note that this does not require the Vulkan drivers to be version 1.3 -
it just means compilation against libvulkan 1.3
It started out as busywork, but it does many separate things. If I could
start over, I'd take them apart into multiple commits:
1. Remove G_ENABLE_DEBUG around GDK_DEBUG_*() calls
This is not needed at all, the calls themselves take care of it.
2. Remove G_ENABLE_DEBUG around profiling code
This now enables profiling support in release builds.
3. Stop poking _gdk_debug_flags and use GDK_DEBUG_CHECK()
This was old code that was never updated.
4. Make !G_ENABLE_DEBUG turn off GDK_DEBUG_CHECK()
The code used to
#define GDK_DEBUG_CHECK(...) false
#define GDK_DEBUG(...)
which would compile away all the code inside those macros. This
means a lot of variable definitions and debug utility functions
would suddenly no longer be used and cause compiler errors.
We need to inist on the nonuniform access beuing available and that
requires Vulkan 1.2.
Also simplifies the descriptor indexing stuff, because that's all part
of Vulkan 1.2, too.
Have a resource path => vkShaderModule hash table instead of doing fancy
custom objects.
A benefit is that shader modules are now shared between all renderers
and pipelines.
Wait for device to be idle because this function is also called in
window resizes.
And if we destroy old swapchain it also destroy the old VkImages,
those images could be in use by a vulkan render.
This fixes a issue reported in Mesa repository when running
GTK with Xe KMD.
Fixes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/9044
Signed-off-by: José Roberto de Souza <jose.souza@intel.com>
Make the display handle the cache, because we only need one.
We store the cache in
$CACHE_DIR/gtk-4.0/vulkan-pipeline-cache/$UUID.$VERSION
so we regenerate caches for each different device (different UUID) and
each different driver version.
We also keep track of the etag of the cache file, so if 2 different
applications update the cache, we can detect that.
Vulkan allows merging caches, so the 2nd app reloads the new cache file
and merges it into its cache before saving.
It's necessary now that we use storage buffers for gradients:
[ VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingStorageBufferUpdateAfterBind-03008 ] Object 0: handle = 0x1e72d70, type = VK_OBJECT_TYPE_DEVICE; | MessageID = 0x943cc552 | vkCreateDescriptorSetLayout(): pBindings[0] can't have VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT for VK_DESCRIPTOR_TYPE_STORAGE_BUFFER since descriptorBindingStorageBufferUpdateAfterBind is not enabled. The Vulkan spec states: If VkPhysicalDeviceDescriptorIndexingFeatures::descriptorBindingStorageBufferUpdateAfterBind is not enabled, all bindings with descriptor type VK_DESCRIPTOR_TYPE_STORAGE_BUFFER must not use VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT (https://www.khronos.org/registry/vulkan/specs/1.3-extensions/html/vkspec.html#VUID-VkDescriptorSetLayoutBindingFlagsCreateInfo-descriptorBindingStorageBufferUpdateAfterBind-03008)
Pretty much copy what GL does and just use the default display to create
GPU-related resources without the need for a display.
This also adds gdk_display_create_vulkan_context() but I've
kept it private because the Vulkan API is generally considered in flux,
in particular with our pending attempts to redo how renderers work.
Instead of having a descriptor set per operation, we just have one
descriptor set and bind all our images into it.
Then the shaders get to use an index into the large texture array
instead.
Getting this to work - because it's a Vulkan extension that needs to be
manually enabled, even though it's officially part of Vulkan 1.2 - is
insane.
Check if the driver supports MAILBOX and prefer using it; in its
absense, checkif the driver supports IMMEDIATE and prefer using
it; finally, if neither of them are supported, use the guaranteed
to be supported FIFO mode.
Basically what GL does, but without any debug or feature flag
to gatekeep it, since the Vulkan backend itself is experimental
already.
Ceil surface sizes, and floor coordinates, to the fractional scale
value.
The Lunarg validation layers seem to have been deprecated in favour
of the Khronos ones. There's no reason not to have both, to accept
loading both - simultaneously, even.
Instead of passing a single, potentially massive rectangle that is
just the extents of the damage rect, collect and pass all damage
rects individually.