vulkan: Add support for timeline semaphores
Unlike binary semaphores, timeline semaphores represent a (64bit unsigned) value and the binary decision about whether they have signaled or not is decided by comparing their value to a predefined value. So this code adds the ability to pass that value. In fact, it now requires this value, but that is not a problem because Vulkan ignores the value for binary semaphores, so we can just pass 0 everywhere a binary sempahore is used. There is no use of the code in those commit, but timeline semaphores are used for explicit sync with dmabufs and D3D12 uses them exclusively.
This commit is contained in:
@@ -49,10 +49,11 @@ typedef enum {
|
||||
GDK_VULKAN_FEATURE_DMABUF = 1 << 0,
|
||||
GDK_VULKAN_FEATURE_WIN32 = 1 << 1,
|
||||
GDK_VULKAN_FEATURE_YCBCR = 1 << 2,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 4,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 5,
|
||||
GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE = 1 << 6,
|
||||
GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE = 1 << 3,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT = 1 << 4,
|
||||
GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT = 1 << 5,
|
||||
GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT = 1 << 6,
|
||||
GDK_VULKAN_FEATURE_SWAPCHAIN_MAINTENANCE = 1 << 7,
|
||||
} GdkVulkanFeatures;
|
||||
|
||||
#define GDK_VULKAN_N_FEATURES 6
|
||||
|
||||
@@ -39,6 +39,7 @@ const GdkDebugKey gdk_vulkan_feature_keys[] = {
|
||||
{ "dmabuf", GDK_VULKAN_FEATURE_DMABUF, "Never import Dmabufs" },
|
||||
{ "win32", GDK_VULKAN_FEATURE_WIN32, "Never import Windows resources" },
|
||||
{ "ycbcr", GDK_VULKAN_FEATURE_YCBCR, "Do not support Ycbcr textures (also disables dmabufs)" },
|
||||
{ "timeline-semaphore", GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE, "Disable timeline semaphore support (disables Windows sync)"},
|
||||
{ "semaphore-export", GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT, "Disable sync of exported dmabufs" },
|
||||
{ "semaphore-import", GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT, "Disable sync of imported dmabufs" },
|
||||
{ "incremental-present", GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT, "Do not send damage regions" },
|
||||
@@ -632,6 +633,9 @@ physical_device_check_features (VkPhysicalDevice device)
|
||||
physical_device_supports_extension (device, VK_EXT_EXTERNAL_MEMORY_DMA_BUF_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_DMABUF;
|
||||
|
||||
if (physical_device_supports_extension (device, VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE;
|
||||
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (physical_device_supports_extension (device, VK_KHR_EXTERNAL_MEMORY_WIN32_EXTENSION_NAME))
|
||||
features |= GDK_VULKAN_FEATURE_WIN32;
|
||||
@@ -1579,6 +1583,11 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_EXT_IMAGE_DRM_FORMAT_MODIFIER_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
|
||||
}
|
||||
if (features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE)
|
||||
{
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_TIMELINE_SEMAPHORE_EXTENSION_NAME);
|
||||
}
|
||||
#ifdef GDK_WINDOWING_WIN32
|
||||
if (features & GDK_VULKAN_FEATURE_WIN32)
|
||||
{
|
||||
@@ -1589,6 +1598,8 @@ gdk_display_create_vulkan_device (GdkDisplay *display,
|
||||
#endif
|
||||
if (features & (GDK_VULKAN_FEATURE_SEMAPHORE_IMPORT | GDK_VULKAN_FEATURE_SEMAPHORE_EXPORT))
|
||||
{
|
||||
if (!(features & GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE))
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_EXTENSION_NAME);
|
||||
g_ptr_array_add (device_extensions, (gpointer) VK_KHR_EXTERNAL_SEMAPHORE_FD_EXTENSION_NAME);
|
||||
}
|
||||
if (features & GDK_VULKAN_FEATURE_INCREMENTAL_PRESENT)
|
||||
|
||||
@@ -18,6 +18,13 @@
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_semaphore_values
|
||||
#define GDK_ARRAY_TYPE_NAME GskSemaphoreValues
|
||||
#define GDK_ARRAY_ELEMENT_TYPE uint64_t
|
||||
#define GDK_ARRAY_PREALLOC 16
|
||||
#define GDK_ARRAY_NO_MEMSET 1
|
||||
#include "gdk/gdkarrayimpl.c"
|
||||
|
||||
#define GDK_ARRAY_NAME gsk_pipeline_stages
|
||||
#define GDK_ARRAY_TYPE_NAME GskPipelineStages
|
||||
#define GDK_ARRAY_ELEMENT_TYPE VkPipelineStageFlags
|
||||
@@ -28,6 +35,7 @@
|
||||
struct _GskVulkanSemaphores
|
||||
{
|
||||
GskSemaphores wait_semaphores;
|
||||
GskSemaphoreValues wait_semaphore_values;
|
||||
GskPipelineStages wait_stages;
|
||||
GskSemaphores signal_semaphores;
|
||||
};
|
||||
@@ -260,9 +268,12 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
GskGpuOp *op)
|
||||
{
|
||||
GskVulkanFrame *self = GSK_VULKAN_FRAME (frame);
|
||||
GskVulkanDevice *device;
|
||||
GskVulkanSemaphores semaphores;
|
||||
GskVulkanCommandState state = { 0, };
|
||||
|
||||
device = GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame));
|
||||
|
||||
GSK_VK_CHECK (vkBeginCommandBuffer, self->vk_command_buffer,
|
||||
&(VkCommandBufferBeginInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
|
||||
@@ -279,6 +290,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
(VkDeviceSize[1]) { 0 });
|
||||
|
||||
gsk_semaphores_init (&semaphores.wait_semaphores);
|
||||
gsk_semaphore_values_init (&semaphores.wait_semaphore_values);
|
||||
gsk_pipeline_stages_init (&semaphores.wait_stages);
|
||||
gsk_semaphores_init (&semaphores.signal_semaphores);
|
||||
|
||||
@@ -286,6 +298,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
{
|
||||
gsk_vulkan_semaphores_add_wait (&semaphores,
|
||||
self->vk_acquire_semaphore,
|
||||
0,
|
||||
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
|
||||
}
|
||||
|
||||
@@ -302,7 +315,7 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
|
||||
GSK_VK_CHECK (vkEndCommandBuffer, self->vk_command_buffer);
|
||||
|
||||
GSK_VK_CHECK (vkQueueSubmit, gsk_vulkan_device_get_vk_queue (GSK_VULKAN_DEVICE (gsk_gpu_frame_get_device (frame))),
|
||||
GSK_VK_CHECK (vkQueueSubmit, gsk_vulkan_device_get_vk_queue (device),
|
||||
1,
|
||||
&(VkSubmitInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
@@ -313,10 +326,16 @@ gsk_vulkan_frame_submit (GskGpuFrame *frame,
|
||||
.waitSemaphoreCount = gsk_semaphores_get_size (&semaphores.wait_semaphores),
|
||||
.pSignalSemaphores = gsk_semaphores_get_data (&semaphores.signal_semaphores),
|
||||
.signalSemaphoreCount = gsk_semaphores_get_size (&semaphores.signal_semaphores),
|
||||
.pNext = gsk_vulkan_device_has_feature (device, GDK_VULKAN_FEATURE_TIMELINE_SEMAPHORE) ? &(VkTimelineSemaphoreSubmitInfo) {
|
||||
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
|
||||
.waitSemaphoreValueCount = gsk_semaphore_values_get_size (&semaphores.wait_semaphore_values),
|
||||
.pWaitSemaphoreValues = gsk_semaphore_values_get_data (&semaphores.wait_semaphore_values),
|
||||
} : NULL,
|
||||
},
|
||||
self->vk_fence);
|
||||
|
||||
gsk_semaphores_clear (&semaphores.wait_semaphores);
|
||||
gsk_semaphore_values_clear (&semaphores.wait_semaphore_values);
|
||||
gsk_pipeline_stages_clear (&semaphores.wait_stages);
|
||||
gsk_semaphores_clear (&semaphores.signal_semaphores);
|
||||
}
|
||||
@@ -384,9 +403,11 @@ gsk_vulkan_frame_get_vk_fence (GskVulkanFrame *self)
|
||||
void
|
||||
gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self,
|
||||
VkSemaphore semaphore,
|
||||
guint64 semaphore_wait,
|
||||
VkPipelineStageFlags stage)
|
||||
{
|
||||
gsk_semaphores_append (&self->wait_semaphores, semaphore);
|
||||
gsk_semaphore_values_append (&self->wait_semaphore_values, semaphore_wait);
|
||||
gsk_pipeline_stages_append (&self->wait_stages, stage);
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ VkFence gsk_vulkan_frame_get_vk_fence (GskVulk
|
||||
|
||||
void gsk_vulkan_semaphores_add_wait (GskVulkanSemaphores *self,
|
||||
VkSemaphore semaphore,
|
||||
uint64_t semaphore_wait,
|
||||
VkPipelineStageFlags stage);
|
||||
void gsk_vulkan_semaphores_add_signal (GskVulkanSemaphores *self,
|
||||
VkSemaphore semaphore);
|
||||
|
||||
@@ -34,6 +34,7 @@ struct _GskVulkanImage
|
||||
VkImageView vk_framebuffer_image_view;
|
||||
GskVulkanYcbcr *ycbcr;
|
||||
VkSemaphore vk_semaphore;
|
||||
uint64_t vk_semaphore_wait;
|
||||
struct {
|
||||
VkDescriptorSet vk_descriptor_set;
|
||||
gsize pool_id;
|
||||
@@ -1501,7 +1502,10 @@ gsk_vulkan_image_transition (GskVulkanImage *self,
|
||||
if (self->vk_pipeline_stage == VK_IMAGE_LAYOUT_GENERAL &&
|
||||
self->vk_semaphore)
|
||||
{
|
||||
gsk_vulkan_semaphores_add_wait (semaphores, self->vk_semaphore, stage);
|
||||
gsk_vulkan_semaphores_add_wait (semaphores,
|
||||
self->vk_semaphore,
|
||||
self->vk_semaphore_wait,
|
||||
stage);
|
||||
}
|
||||
|
||||
vkCmdPipelineBarrier (command_buffer,
|
||||
|
||||
Reference in New Issue
Block a user