1
0
Fork 0
forked from wry/wry

vulkan: use sync objects if possible

This commit is contained in:
Julian Orth 2026-03-01 17:25:40 +01:00
parent 2ac3519f2d
commit 3d3132fe39
23 changed files with 535 additions and 86 deletions

View file

@ -1,4 +1,5 @@
use {
crate::{eventfd_cache::EventfdError, video::drm::DrmError},
ahash::{AHashMap, AHashSet},
ash::{
Entry, Instance, LoadingError,
@ -6,9 +7,13 @@ use {
vk::{
self, API_VERSION_1_3, ApplicationInfo, Bool32, DebugUtilsMessageSeverityFlagsEXT,
DebugUtilsMessageTypeFlagsEXT, DebugUtilsMessengerCallbackDataEXT,
DebugUtilsMessengerCreateInfoEXT, DebugUtilsMessengerEXT, ExtensionProperties, FALSE,
InstanceCreateInfo, LayerProperties, ValidationFeaturesEXT, api_version_major,
api_version_minor, api_version_patch, api_version_variant,
DebugUtilsMessengerCreateInfoEXT, DebugUtilsMessengerEXT, ExtensionProperties,
ExternalSemaphoreFeatureFlags, ExternalSemaphoreHandleTypeFlags,
ExternalSemaphoreProperties, FALSE, InstanceCreateInfo, LayerProperties,
PhysicalDevice, PhysicalDeviceExternalSemaphoreInfo, PhysicalDeviceFeatures,
PhysicalDeviceFeatures2, PhysicalDeviceTimelineSemaphoreFeatures, SemaphoreType,
SemaphoreTypeCreateInfo, ValidationFeaturesEXT, api_version_major, api_version_minor,
api_version_patch, api_version_variant,
},
},
isnt::std_1::collections::IsntHashMapExt,
@ -28,6 +33,7 @@ use {
pub mod device;
pub mod fence;
pub mod sync;
pub mod timeline_semaphore;
static VULKAN_ENTRY: Lazy<Result<Entry, Arc<LoadingError>>> =
Lazy::new(|| unsafe { Entry::load() }.map_err(Arc::new));
@ -53,6 +59,22 @@ pub enum VulkanCoreError {
CreateFence(#[source] vk::Result),
#[error("Could not export a sync file from a semaphore")]
ExportSyncFile(#[source] vk::Result),
#[error("Could not create a semaphore")]
CreateSemaphore(#[source] vk::Result),
#[error("Device does not support timeline semaphore export")]
TimelineExportNotSupported,
#[error("Could not export an opaque fd from a semaphore")]
ExportTimelineSemaphore(#[source] vk::Result),
#[error("Could not signal the timeline semaphore")]
SignalSemaphore(#[source] vk::Result),
#[error("Could not query last signaled sync obj point")]
QueryLastSignaled(#[source] DrmError),
#[error("Mapping between syncobj points and timeline semaphore points is unexpected")]
UnsupportedPointMapping,
#[error("Could not acquire an eventfd")]
AcquireEventfd(#[source] EventfdError),
#[error("Could not create a sync obj eventfd wait")]
CreateSyncobjWait(#[source] DrmError),
}
pub struct VulkanCoreInstance {
@ -61,6 +83,13 @@ pub struct VulkanCoreInstance {
debug_utils: debug_utils::Instance,
messenger: DebugUtilsMessengerEXT,
pub log_level: Level,
pub validation: bool,
}
pub struct VulkanDeviceFeatures {
#[expect(dead_code)]
pub features: PhysicalDeviceFeatures,
pub semaphore_features: PhysicalDeviceTimelineSemaphoreFeatures<'static>,
}
impl VulkanCoreInstance {
@ -86,7 +115,8 @@ impl VulkanCoreInstance {
let mut severity = DebugUtilsMessageSeverityFlagsEXT::empty()
| DebugUtilsMessageSeverityFlagsEXT::ERROR
| DebugUtilsMessageSeverityFlagsEXT::WARNING;
if *VULKAN_VALIDATION {
let validation = *VULKAN_VALIDATION;
if validation {
severity |= DebugUtilsMessageSeverityFlagsEXT::INFO
| DebugUtilsMessageSeverityFlagsEXT::VERBOSE;
}
@ -110,7 +140,7 @@ impl VulkanCoreInstance {
.application_info(&app_info)
.push_next(&mut debug_info);
let validation_layer_name = VALIDATION_LAYER.as_ptr();
if *VULKAN_VALIDATION {
if validation {
if get_available_layers(entry)?.contains(VALIDATION_LAYER) {
create_info =
create_info.enabled_layer_names(slice::from_ref(&validation_layer_name));
@ -146,8 +176,49 @@ impl VulkanCoreInstance {
debug_utils,
messenger,
log_level,
validation,
})
}
pub fn get_features(&self, phy_dev: PhysicalDevice) -> VulkanDeviceFeatures {
let mut semaphore_features = PhysicalDeviceTimelineSemaphoreFeatures::default();
let mut features = PhysicalDeviceFeatures2::default().push_next(&mut semaphore_features);
unsafe {
self.instance
.get_physical_device_features2(phy_dev, &mut features);
}
VulkanDeviceFeatures {
features: features.features,
semaphore_features,
}
}
pub fn supports_timeline_opaque_export(
&self,
phy_dev: PhysicalDevice,
features: &VulkanDeviceFeatures,
) -> bool {
if features.semaphore_features.timeline_semaphore == vk::TRUE {
return self.supports_semaphore_opaque_export(phy_dev);
}
false
}
fn supports_semaphore_opaque_export(&self, phy_dev: PhysicalDevice) -> bool {
let mut props = ExternalSemaphoreProperties::default();
let mut type_info =
SemaphoreTypeCreateInfo::default().semaphore_type(SemaphoreType::TIMELINE);
let info = PhysicalDeviceExternalSemaphoreInfo::default()
.handle_type(ExternalSemaphoreHandleTypeFlags::OPAQUE_FD)
.push_next(&mut type_info);
unsafe {
self.instance
.get_physical_device_external_semaphore_properties(phy_dev, &info, &mut props);
}
props
.external_semaphore_features
.contains(ExternalSemaphoreFeatureFlags::EXPORTABLE)
}
}
impl Drop for VulkanCoreInstance {