]> git.nega.tv - josh/narcissus/commitdiff
narcissus-gpu: Enable swapchain_maintenance1
authorJosh Simmons <josh@nega.tv>
Sat, 5 Apr 2025 14:16:16 +0000 (16:16 +0200)
committerJosh Simmons <josh@nega.tv>
Sat, 5 Apr 2025 14:16:16 +0000 (16:16 +0200)
Avoids a validator when using the feature without enabling it.

engine/narcissus-gpu/src/backend/vulkan/allocator.rs
engine/narcissus-gpu/src/backend/vulkan/mod.rs
engine/narcissus-gpu/src/backend/vulkan/physical_device_features.rs [new file with mode: 0644]
engine/narcissus-gpu/src/backend/vulkan/physical_device_properties.rs [new file with mode: 0644]
engine/narcissus-gpu/src/backend/vulkan/wsi.rs

index 098e5b364a3c1c42c784b1d0a331810a0b3eb8b0..29a3a4cae6e1c560cf350218e7edcbf4ee1f2fcd 100644 (file)
@@ -230,8 +230,7 @@ impl VulkanDevice {
         if self.allocator.stats.num_allocations()
             >= self
                 .physical_device_properties
-                .properties
-                .limits
+                .limits()
                 .max_memory_allocation_count
         {
             return None;
index 1a1a01484284aeca27328e1a6dbcc9203431fd4e..9ef452283430b37ad5b196ef18e47fd5aec2aaa5 100644 (file)
@@ -15,6 +15,8 @@ use narcissus_core::{
     Arc, Arena, HybridArena, Mutex, PhantomUnsend, Pool, Widen,
 };
 
+use physical_device_features::VulkanPhysicalDeviceFeatures;
+use physical_device_properties::VulkanPhysicalDeviceProperties;
 use vulkan_sys::{self as vk};
 
 use crate::{
@@ -33,6 +35,8 @@ mod allocator;
 mod barrier;
 mod convert;
 mod libc;
+mod physical_device_features;
+mod physical_device_properties;
 mod wsi;
 
 use self::{
@@ -382,16 +386,9 @@ pub(crate) struct VulkanDevice {
 
     allocator: VulkanAllocator,
 
-    physical_device_properties: Box<vk::PhysicalDeviceProperties2>,
-    _physical_device_properties_11: Box<vk::PhysicalDeviceVulkan11Properties>,
-    _physical_device_properties_12: Box<vk::PhysicalDeviceVulkan12Properties>,
-    physical_device_properties_13: Box<vk::PhysicalDeviceVulkan13Properties>,
+    physical_device_properties: Box<VulkanPhysicalDeviceProperties>,
     physical_device_memory_properties: Box<vk::PhysicalDeviceMemoryProperties>,
-
-    _physical_device_features: Box<vk::PhysicalDeviceFeatures2>,
-    _physical_device_features_11: Box<vk::PhysicalDeviceVulkan11Features>,
-    _physical_device_features_12: Box<vk::PhysicalDeviceVulkan12Features>,
-    _physical_device_features_13: Box<vk::PhysicalDeviceVulkan13Features>,
+    _physical_device_features: Box<VulkanPhysicalDeviceFeatures>,
 
     _global_fn: vk::GlobalFunctions,
     instance_fn: vk::InstanceFunctions,
@@ -510,31 +507,8 @@ impl VulkanDevice {
             instance_fn.enumerate_physical_devices(instance, count, ptr)
         });
 
-        let mut physical_device_properties: Box<vk::PhysicalDeviceProperties2> = default();
-        let mut physical_device_properties_11: Box<vk::PhysicalDeviceVulkan11Properties> =
-            default();
-        let mut physical_device_properties_12: Box<vk::PhysicalDeviceVulkan12Properties> =
-            default();
-        let mut physical_device_properties_13: Box<vk::PhysicalDeviceVulkan13Properties> =
-            default();
-
-        physical_device_properties_12._next =
-            physical_device_properties_13.as_mut() as *mut _ as *mut _;
-        physical_device_properties_11._next =
-            physical_device_properties_12.as_mut() as *mut _ as *mut _;
-        physical_device_properties._next =
-            physical_device_properties_11.as_mut() as *mut _ as *mut _;
-
-        let mut physical_device_features: Box<vk::PhysicalDeviceFeatures2> = default();
-        let mut physical_device_features_11: Box<vk::PhysicalDeviceVulkan11Features> = default();
-        let mut physical_device_features_12: Box<vk::PhysicalDeviceVulkan12Features> = default();
-        let mut physical_device_features_13: Box<vk::PhysicalDeviceVulkan13Features> = default();
-
-        physical_device_features_12._next =
-            physical_device_features_13.as_mut() as *mut _ as *mut _;
-        physical_device_features_11._next =
-            physical_device_features_12.as_mut() as *mut _ as *mut _;
-        physical_device_features._next = physical_device_features_11.as_mut() as *mut _ as *mut _;
+        let mut physical_device_properties: Box<VulkanPhysicalDeviceProperties> = default();
+        let mut physical_device_features: Box<VulkanPhysicalDeviceFeatures> = default();
 
         let physical_device = physical_devices
             .iter()
@@ -543,26 +517,24 @@ impl VulkanDevice {
                 unsafe {
                     instance_fn.get_physical_device_properties2(
                         physical_device,
-                        physical_device_properties.as_mut(),
+                        physical_device_properties.link(),
                     );
                     instance_fn.get_physical_device_features2(
                         physical_device,
-                        physical_device_features.as_mut(),
+                        physical_device_features.link(),
                     );
                 }
 
-                physical_device_properties.properties.api_version >= vk::VERSION_1_3
-                    && physical_device_features_13.dynamic_rendering == vk::Bool32::True
-                    && physical_device_features_13.subgroup_size_control == vk::Bool32::True
-                    && physical_device_features_13.maintenance4 == vk::Bool32::True
-                    && physical_device_features_13.compute_full_subgroups == vk::Bool32::True
-                    && physical_device_features_12.timeline_semaphore == vk::Bool32::True
-                    && physical_device_features_12.descriptor_indexing == vk::Bool32::True
-                    && physical_device_features_12.descriptor_binding_partially_bound
-                        == vk::Bool32::True
-                    && physical_device_features_12.draw_indirect_count == vk::Bool32::True
-                    && physical_device_features_12.uniform_buffer_standard_layout
-                        == vk::Bool32::True
+                physical_device_properties.api_version() >= vk::VERSION_1_3
+                    && physical_device_features.dynamic_rendering()
+                    && physical_device_features.subgroup_size_control()
+                    && physical_device_features.maintenance4()
+                    && physical_device_features.compute_full_subgroups()
+                    && physical_device_features.timeline_semaphore()
+                    && physical_device_features.descriptor_indexing()
+                    && physical_device_features.descriptor_binding_partially_bound()
+                    && physical_device_features.draw_indirect_count()
+                    && physical_device_features.uniform_buffer_standard_layout()
             })
             .expect("no supported physical devices reported");
 
@@ -616,38 +588,32 @@ impl VulkanDevice {
                 .iter()
                 .map(|x| x.as_ptr())
                 .collect::<Vec<*const c_char>>();
-            let enabled_features_13 = vk::PhysicalDeviceVulkan13Features {
-                dynamic_rendering: vk::Bool32::True,
-                synchronization2: vk::Bool32::True,
-                subgroup_size_control: vk::Bool32::True,
-                compute_full_subgroups: vk::Bool32::True,
-                maintenance4: vk::Bool32::True,
-                ..default()
-            };
-            let enabled_features_12 = vk::PhysicalDeviceVulkan12Features {
-                _next: &enabled_features_13 as *const vk::PhysicalDeviceVulkan13Features as *mut _,
-                buffer_device_address: vk::Bool32::True,
-                timeline_semaphore: vk::Bool32::True,
-                descriptor_indexing: vk::Bool32::True,
-                descriptor_binding_partially_bound: vk::Bool32::True,
-                draw_indirect_count: vk::Bool32::True,
-                uniform_buffer_standard_layout: vk::Bool32::True,
-                ..default()
-            };
-            let enabled_features_11 = vk::PhysicalDeviceVulkan11Features {
-                _next: &enabled_features_12 as *const vk::PhysicalDeviceVulkan12Features as *mut _,
-                ..default()
-            };
-            let enabled_features = vk::PhysicalDeviceFeatures2 {
-                _next: &enabled_features_11 as *const vk::PhysicalDeviceVulkan11Features as *mut _,
-                ..default()
-            };
+
+            let mut enabled_features: Box<VulkanPhysicalDeviceFeatures> = default();
+
+            enabled_features.set_dynamic_rendering(true);
+            enabled_features.set_synchronization2(true);
+            enabled_features.set_subgroup_size_control(true);
+            enabled_features.set_compute_full_subgroups(true);
+            enabled_features.set_maintenance4(true);
+            enabled_features.set_buffer_device_address(true);
+            enabled_features.set_timeline_semaphore(true);
+            enabled_features.set_descriptor_indexing(true);
+            enabled_features.set_descriptor_binding_partially_bound(true);
+            enabled_features.set_draw_indirect_count(true);
+            enabled_features.set_uniform_buffer_standard_layout(true);
+
+            if wsi_support.swapchain_maintenance1() {
+                enabled_features.set_swapchain_maintenance1(true);
+            }
+
             let create_info = vk::DeviceCreateInfo {
-                _next: &enabled_features as *const vk::PhysicalDeviceFeatures2 as *const _,
+                _next: enabled_features.link() as *mut _ as *const _,
                 enabled_extension_names: enabled_extensions.as_slice().into(),
                 queue_create_infos: device_queue_create_infos.into(),
                 ..default()
             };
+
             let mut device = vk::Device::null();
             vk_check!(unsafe {
                 instance_fn.create_device(physical_device, &create_info, None, &mut device)
@@ -742,10 +708,7 @@ impl VulkanDevice {
         }));
 
         let allocator = VulkanAllocator::new(
-            physical_device_properties
-                .properties
-                .limits
-                .buffer_image_granularity,
+            physical_device_properties.limits().buffer_image_granularity,
             physical_device_memory_properties.as_ref(),
         );
 
@@ -780,15 +743,8 @@ impl VulkanDevice {
             allocator,
 
             physical_device_properties,
-            _physical_device_properties_11: physical_device_properties_11,
-            _physical_device_properties_12: physical_device_properties_12,
-            physical_device_properties_13,
             physical_device_memory_properties,
-
             _physical_device_features: physical_device_features,
-            _physical_device_features_11: physical_device_features_11,
-            _physical_device_features_12: physical_device_features_12,
-            _physical_device_features_13: physical_device_features_13,
 
             _global_fn: global_fn,
             instance_fn,
@@ -1616,13 +1572,13 @@ impl Device for VulkanDevice {
 
         if let Some(required_subgroup_size) = pipeline_desc.shader.required_subgroup_size {
             assert!(self
-                .physical_device_properties_13
-                .required_subgroup_size_stages
+                .physical_device_properties
+                .required_subgroup_size_stages()
                 .contains(vk::ShaderStageFlags::COMPUTE));
             assert!(
-                required_subgroup_size >= self.physical_device_properties_13.min_subgroup_size
+                required_subgroup_size >= self.physical_device_properties.min_subgroup_size()
                     && required_subgroup_size
-                        <= self.physical_device_properties_13.max_subgroup_size
+                        <= self.physical_device_properties.max_subgroup_size()
             );
 
             let shader_stage_required_subgroup_size_create_info =
@@ -2999,8 +2955,7 @@ impl VulkanDevice {
         let align = if usage.contains(BufferUsageFlags::UNIFORM) {
             align.max(
                 self.physical_device_properties
-                    .properties
-                    .limits
+                    .limits()
                     .min_uniform_buffer_offset_alignment,
             )
         } else {
@@ -3010,8 +2965,7 @@ impl VulkanDevice {
         let align = if usage.contains(BufferUsageFlags::STORAGE) {
             align.max(
                 self.physical_device_properties
-                    .properties
-                    .limits
+                    .limits()
                     .min_storage_buffer_offset_alignment,
             )
         } else {
@@ -3023,8 +2977,7 @@ impl VulkanDevice {
         let align = if usage.contains(BufferUsageFlags::TRANSFER) {
             align.max(
                 self.physical_device_properties
-                    .properties
-                    .limits
+                    .limits()
                     .optimal_buffer_copy_offset_alignment,
             )
         } else {
diff --git a/engine/narcissus-gpu/src/backend/vulkan/physical_device_features.rs b/engine/narcissus-gpu/src/backend/vulkan/physical_device_features.rs
new file mode 100644 (file)
index 0000000..66f3299
--- /dev/null
@@ -0,0 +1,104 @@
+use vulkan_sys::{self as vk};
+
+#[derive(Default)]
+pub struct VulkanPhysicalDeviceFeatures {
+    features: vk::PhysicalDeviceFeatures2,
+    features_11: vk::PhysicalDeviceVulkan11Features,
+    features_12: vk::PhysicalDeviceVulkan12Features,
+    features_13: vk::PhysicalDeviceVulkan13Features,
+    features_swapchain_maintenance1: vk::PhysicalDeviceSwapchainMaintenance1FeaturesEXT,
+}
+
+impl VulkanPhysicalDeviceFeatures {
+    pub fn dynamic_rendering(&self) -> bool {
+        self.features_13.dynamic_rendering == vk::Bool32::True
+    }
+
+    pub fn subgroup_size_control(&self) -> bool {
+        self.features_13.subgroup_size_control == vk::Bool32::True
+    }
+
+    pub fn maintenance4(&self) -> bool {
+        self.features_13.maintenance4 == vk::Bool32::True
+    }
+
+    pub fn compute_full_subgroups(&self) -> bool {
+        self.features_13.compute_full_subgroups == vk::Bool32::True
+    }
+
+    pub fn timeline_semaphore(&self) -> bool {
+        self.features_12.timeline_semaphore == vk::Bool32::True
+    }
+
+    pub fn descriptor_indexing(&self) -> bool {
+        self.features_12.descriptor_indexing == vk::Bool32::True
+    }
+
+    pub fn descriptor_binding_partially_bound(&self) -> bool {
+        self.features_12.descriptor_binding_partially_bound == vk::Bool32::True
+    }
+
+    pub fn draw_indirect_count(&self) -> bool {
+        self.features_12.draw_indirect_count == vk::Bool32::True
+    }
+
+    pub fn uniform_buffer_standard_layout(&self) -> bool {
+        self.features_12.uniform_buffer_standard_layout == vk::Bool32::True
+    }
+
+    pub fn set_dynamic_rendering(&mut self, arg: bool) {
+        self.features_13.dynamic_rendering = vk::Bool32::from(arg)
+    }
+
+    pub fn set_synchronization2(&mut self, arg: bool) {
+        self.features_13.synchronization2 = vk::Bool32::from(arg)
+    }
+
+    pub fn set_subgroup_size_control(&mut self, arg: bool) {
+        self.features_13.subgroup_size_control = vk::Bool32::from(arg)
+    }
+
+    pub fn set_compute_full_subgroups(&mut self, arg: bool) {
+        self.features_13.compute_full_subgroups = vk::Bool32::from(arg)
+    }
+
+    pub fn set_maintenance4(&mut self, arg: bool) {
+        self.features_13.maintenance4 = vk::Bool32::from(arg)
+    }
+
+    pub fn set_buffer_device_address(&mut self, arg: bool) {
+        self.features_12.buffer_device_address = vk::Bool32::from(arg)
+    }
+
+    pub fn set_timeline_semaphore(&mut self, arg: bool) {
+        self.features_12.timeline_semaphore = vk::Bool32::from(arg)
+    }
+
+    pub fn set_descriptor_indexing(&mut self, arg: bool) {
+        self.features_12.descriptor_indexing = vk::Bool32::from(arg)
+    }
+
+    pub fn set_descriptor_binding_partially_bound(&mut self, arg: bool) {
+        self.features_12.descriptor_binding_partially_bound = vk::Bool32::from(arg)
+    }
+
+    pub fn set_draw_indirect_count(&mut self, arg: bool) {
+        self.features_12.draw_indirect_count = vk::Bool32::from(arg)
+    }
+
+    pub fn set_uniform_buffer_standard_layout(&mut self, arg: bool) {
+        self.features_12.uniform_buffer_standard_layout = vk::Bool32::from(arg)
+    }
+
+    pub fn set_swapchain_maintenance1(&mut self, arg: bool) {
+        self.features_swapchain_maintenance1.swapchain_maintenance1 = vk::Bool32::from(arg)
+    }
+
+    pub fn link(&mut self) -> &mut vk::PhysicalDeviceFeatures2 {
+        self.features_13._next = &mut self.features_swapchain_maintenance1 as *mut _ as *mut _;
+        self.features_12._next = &mut self.features_13 as *mut _ as *mut _;
+        self.features_11._next = &mut self.features_12 as *mut _ as *mut _;
+        self.features._next = &mut self.features_11 as *mut _ as *mut _;
+        &mut self.features
+    }
+}
diff --git a/engine/narcissus-gpu/src/backend/vulkan/physical_device_properties.rs b/engine/narcissus-gpu/src/backend/vulkan/physical_device_properties.rs
new file mode 100644 (file)
index 0000000..19ed640
--- /dev/null
@@ -0,0 +1,38 @@
+use vulkan_sys::{self as vk};
+
+#[derive(Default)]
+pub struct VulkanPhysicalDeviceProperties {
+    properties: vk::PhysicalDeviceProperties2,
+    properties_11: vk::PhysicalDeviceVulkan11Properties,
+    properties_12: vk::PhysicalDeviceVulkan12Properties,
+    properties_13: vk::PhysicalDeviceVulkan13Properties,
+}
+
+impl VulkanPhysicalDeviceProperties {
+    pub fn api_version(&self) -> u32 {
+        self.properties.properties.api_version
+    }
+
+    pub fn required_subgroup_size_stages(&self) -> vk::ShaderStageFlags {
+        self.properties_13.required_subgroup_size_stages
+    }
+
+    pub fn min_subgroup_size(&self) -> u32 {
+        self.properties_13.min_subgroup_size
+    }
+
+    pub fn max_subgroup_size(&self) -> u32 {
+        self.properties_13.max_subgroup_size
+    }
+
+    pub fn limits(&self) -> &vk::PhysicalDeviceLimits {
+        &self.properties.properties.limits
+    }
+
+    pub fn link(&mut self) -> &mut vk::PhysicalDeviceProperties2 {
+        self.properties_12._next = &mut self.properties_13 as *mut _ as *mut _;
+        self.properties_11._next = &mut self.properties_12 as *mut _ as *mut _;
+        self.properties._next = &mut self.properties_11 as *mut _ as *mut _;
+        &mut self.properties
+    }
+}
index 30c18f61ce1da6483029eb1faabd0b4e8006ffe3..6c7e35908aba2d41dbbe2690ee0c82db1218b46a 100644 (file)
@@ -57,6 +57,12 @@ pub struct VulkanWsiSupport {
     swapchain_mutable_format: bool,
 }
 
+impl VulkanWsiSupport {
+    pub fn swapchain_maintenance1(&self) -> bool {
+        self.swapchain_maintenance1
+    }
+}
+
 struct RecycleSwapchainSemaphore {
     fence: vk::Fence,
     semaphore: vk::Semaphore,