This change introduces the basic Vulkan filter machinery, while preserving the
original vf_framerate timing logic. At this stage, the filter simply picks the
temporally closest input frame for the output.
Note that while input frames are not modified in anyway, they must be
deep-copied for output. This ensures that they match the output context, which
may differ from the input context in important way, and avoids extending the
lifetime of hardware decoded frames that are part of the decoder's DPB.
This requires exposing vkCmdCopyImage in the Vulkan function loader, and a
compute queue family and execution pool to record the copy on.
The filter depends on vulkan_1_4 for its Vulkan-Headers requirement; while this
is not required by any of the code in this commit, the final optical-flow
pipeline will need VK_KHR_maintenance9, which first appeared with Vulkan 1.4.
To avoid confusion, the requirement is asserted from the beginning.
Drivers may expose the host image transfer format feature, yet reject
the final image parameter combination, or provide no memory type from
which such an image can be allocated. Notably video decode/encode
images are often not possible to allocate from host visible memory
type. Validate the final image parameters, including DRM format
modifiers, and keep the usage flag only when it is actually usable.
Fixes: #21704
Co-authored-by: llyyr <llyyr.public@gmail.com>
Signed-off-by: Kacper Michajłow <kasper93@gmail.com>
Enables VK_KHR_unified_image_layouts when available, and queries its
feature bits into FFVulkanContext. The extension guarantees that using
the GENERAL image layout comes with no performance penalty, with the
unifiedImageLayoutsVideo feature extending this to video usage.
An execution abandoned on error between start and submission left the
ownership mutex locked forever, deadlocking the context's next reuse.
Replace the submission fence with a timeline semaphore:
ff_vk_exec_start() claims the context by incrementing the awaited
value, the submission signals it, and the mutex only briefly guards
the dependency lists. Abandonment becomes ff_vk_exec_discard(), called
exactly once on a started, unsubmitted context: it frees the
dependencies, drops the recording, and un-claims by signalling from
the host - which a fence cannot do. ff_vk_exec_submit() cleans up
after its own failures; error paths which leaked the claim now
discard, and ff_vk_exec_start() failures are checked everywhere.
Enables VK_KHR_maintenance9 when available. The feature of interest
is that queue family ownership transfers become optional for resources
created with exclusive sharing mode, with their contents preserved
when accessed by another queue family.
For optimal-tiling images, this is only guaranteed between queue
families flagged in VkQueueFamilyOwnershipTransferPropertiesKHR, so
query it for each queue family alongside the other properties.
vkGetDeviceQueue2 with flags = 0 is equivalent to vkGetDeviceQueue and
is available since Vulkan 1.1. Needed to support queues created with
non-zero VkDeviceQueueCreateFlags.
Fixes VUID-vkGetDeviceQueue-flags-01841 VVL error.
Descriptor buffers were a neat attempt at organizing descriptors.
Simple, robust, reliable.
Unfortunately, driver support never caught on, and neither did validation
layer support.
Now they're being replaced by descriptor heaps, which promises to be
the future. We'll see how it goes.
This commit adds support for compiler hints.
While on AMD these are not used/needed, Nvidia benefits from them, and gives
a sizeable 10% speedup on 4k.
This reduces the intermediate VRAM used for RGB decoding by a
factor of 100x for 6k video.
This also speeds the decoder up by 16% for 4k RGB24 and 31% for 6k video.
This is equivalent to what the software decoder does, but with less pointers.
lavapipe recently added support for external_semaphore_fd, but only for syncfiles,
not for opaque file descriptors.
The code is written to allow using syncfiles later on.
Ref: https://gitlab.freedesktop.org/mesa/mesa/-/issues/12422
This allows the encoder to fully saturate all queues the GPU
has, giving a good 10% in certain cases and resolutions.
This also improves error resilience if an allocation fails,
and properly cleans up after itself if it does.
Push descriptors are in theory slightly faster, but come with
limitations for which we have to check.
Either way, they're not difficult to implement, so even though
no one should be using peasant-tier descriptors, do it anyway.
This permits:
- The use of Vulkan filtering on many more devices
- Better debugging due to lack of descriptor buffer support in layers
Much of the changes here are due to a requirement that updates to
descriptors must happen between the command buffer being waited on,
and the pipeline not being bound.
We routinely did it the other way around, by updating only after
we bind the pipeline.
More recent kernel versions allow for users to extract a sync_file
handle from a DMA-BUF, which can then be imported into Vulkan as a
binary semaphore.
This finally allows for synchronization between Vulkan and DMA-BUF
images, such as those from screen capture software, or VAAPI,
avoiding any corruption artifacts.
This is done fully asynchronously, where we use the kernel's
given binary semaphores as a dependency to increment the image's
usual VkSemaphores we allocate. The old imported binary semaphores
are cleaned up after execution as usual.
In the future, hwcontext_drm should receive support for explicitly
synchronized images as well, which would make the synchronization
more robust and portable.
This commit rewrites the majority of vulkan.c to enable its use
as a general-purpose high-level utility code, usable for decoding,
encoding, and filtering of video frames.
The dependency system was rewritten to simplify management of
execution.
The image handling system was rewritten to accomodate multiplane
images.
Due to how related all the new features were, this is a single
commit.