diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c92ad9..8b058a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ ### Fixed - Fixed `no_std_error` feature not compiling +- Instance-level functions that are part of device extensions are loaded with `vkGetInstanceProcAddr` ([#281](https://github.com/KyleMayes/vulkanalia/issues/281)) ### Bindings Updates - [July 26, 2024 Vulkan 1.3.292 spec update](https://github.com/KhronosGroup/Vulkan-Docs/commit/e090b1020fb9636b752e73adfc82a3c595fb6615) diff --git a/generator/src/main/kotlin/com/kylemayes/generator/generate/file/Commands.kt b/generator/src/main/kotlin/com/kylemayes/generator/generate/file/Commands.kt index d2f89b7..f9a1ef0 100644 --- a/generator/src/main/kotlin/com/kylemayes/generator/generate/file/Commands.kt +++ b/generator/src/main/kotlin/com/kylemayes/generator/generate/file/Commands.kt @@ -7,6 +7,7 @@ import com.kylemayes.generator.generate.support.generateManualUrl import com.kylemayes.generator.generate.support.getCommandType import com.kylemayes.generator.registry.Command import com.kylemayes.generator.registry.Registry +import com.kylemayes.generator.registry.getIdentifier /** Generates Rust type aliases for Vulkan commands. */ fun Registry.generateCommands() = @@ -51,6 +52,8 @@ $structs """ } +private val loader = "impl FnMut(*const c_char) -> Option" + /** Generates a Rust struct for a group of Vulkan commands of the same type. */ private fun Registry.generateCommandStruct( type: CommandType, @@ -64,17 +67,33 @@ pub struct ${type.display}Commands { impl ${type.display}Commands { #[inline] - pub unsafe fn load(mut loader: impl FnMut(*const c_char) -> Option) -> Self { - Self { ${commands.joinToString { generateLoad(it) }} } + pub unsafe fn load( + ${if (type == CommandType.DEVICE) "mut instance_loader: $loader," else ""} + mut loader: $loader, + ) -> Self { + Self { ${commands.joinToString { generateLoad(it, type) }} } } } """ /** Generates a Rust struct field-value pair to load a command. */ -private fun Registry.generateLoad(command: Command) = - """ +private fun Registry.generateLoad( + command: Command, + type: CommandType, +): String { + // It seems that device extension commands are instance-level commands if + // they take a `VkPhysicalDevice` as their first parameter. + val first = command.params.getOrNull(0)?.type?.getIdentifier()?.value + val loader = + if (type == CommandType.DEVICE && first == "PhysicalDevice") { + "instance_loader" + } else { + "loader" + } + + return """ ${command.name}: { - let value = loader(b"${command.name.original}\0".as_ptr().cast()); + let value = $loader(b"${command.name.original}\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -85,6 +104,7 @@ ${command.name}: { } } """ +} /** Generates a Rust function signature for a Vulkan command. */ private fun generateSignature( diff --git a/vulkanalia/src/lib.rs b/vulkanalia/src/lib.rs index ee50c1c..2969814 100644 --- a/vulkanalia/src/lib.rs +++ b/vulkanalia/src/lib.rs @@ -274,12 +274,13 @@ impl Entry { allocator: Option<&vk::AllocationCallbacks>, ) -> VkResult { let handle = EntryV1_0::create_instance(self, info, allocator)?; - let load = |n| (self.get_instance)(handle, n); - let commands = InstanceCommands::load(load); + let instance_load = |n| (self.get_instance)(handle, n); + let commands = InstanceCommands::load(instance_load); let version = self.version()?; let extensions = get_names(info.enabled_extension_count, info.enabled_extension_names); let layers = get_names(info.enabled_layer_count, info.enabled_layer_names); Ok(Instance { + get_instance: self.get_instance, get_device: self.get_device, handle, commands, @@ -302,6 +303,7 @@ unsafe impl Sync for Entry {} /// A Vulkan instance. #[derive(Clone)] pub struct Instance { + get_instance: vk::PFN_vkGetInstanceProcAddr, get_device: vk::PFN_vkGetDeviceProcAddr, handle: vk::Instance, commands: InstanceCommands, @@ -344,8 +346,9 @@ impl Instance { allocator: Option<&vk::AllocationCallbacks>, ) -> VkResult { let handle = InstanceV1_0::create_device(self, physical_device, info, allocator)?; - let load = |n| (self.get_device)(handle, n); - let commands = DeviceCommands::load(load); + let instance_load = |n| (self.get_instance)(self.handle, n); + let device_load = |n| (self.get_device)(handle, n); + let commands = DeviceCommands::load(instance_load, device_load); let extensions = get_names(info.enabled_extension_count, info.enabled_extension_names); let layers = get_names(info.enabled_layer_count, info.enabled_layer_names); Ok(Device { diff --git a/vulkanalia/src/vk/commands.rs b/vulkanalia/src/vk/commands.rs index d218294..84e9b98 100644 --- a/vulkanalia/src/vk/commands.rs +++ b/vulkanalia/src/vk/commands.rs @@ -670,6 +670,7 @@ pub struct DeviceCommands { impl DeviceCommands { #[inline] pub unsafe fn load( + mut instance_loader: impl FnMut(*const c_char) -> Option, mut loader: impl FnMut(*const c_char) -> Option, ) -> Self { Self { @@ -750,7 +751,7 @@ impl DeviceCommands { } }, acquire_winrt_display_nv: { - let value = loader(b"vkAcquireWinrtDisplayNV\0".as_ptr().cast()); + let value = instance_loader(b"vkAcquireWinrtDisplayNV\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -6564,7 +6565,7 @@ impl DeviceCommands { } }, enumerate_physical_device_queue_family_performance_query_counters_khr: { - let value = loader( + let value = instance_loader( b"vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR\0" .as_ptr() .cast(), @@ -8101,7 +8102,7 @@ impl DeviceCommands { } }, get_physical_device_calibrateable_time_domains_ext: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceCalibrateableTimeDomainsEXT\0" .as_ptr() .cast(), @@ -8120,7 +8121,7 @@ impl DeviceCommands { } }, get_physical_device_calibrateable_time_domains_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceCalibrateableTimeDomainsKHR\0" .as_ptr() .cast(), @@ -8139,7 +8140,7 @@ impl DeviceCommands { } }, get_physical_device_cooperative_matrix_properties_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR\0" .as_ptr() .cast(), @@ -8158,7 +8159,7 @@ impl DeviceCommands { } }, get_physical_device_cooperative_matrix_properties_nv: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceCooperativeMatrixPropertiesNV\0" .as_ptr() .cast(), @@ -8177,7 +8178,7 @@ impl DeviceCommands { } }, get_physical_device_external_memory_sci_buf_properties_nv: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceExternalMemorySciBufPropertiesNV\0" .as_ptr() .cast(), @@ -8197,7 +8198,7 @@ impl DeviceCommands { } }, get_physical_device_fragment_shading_rates_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceFragmentShadingRatesKHR\0" .as_ptr() .cast(), @@ -8216,7 +8217,7 @@ impl DeviceCommands { } }, get_physical_device_multisample_properties_ext: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceMultisamplePropertiesEXT\0" .as_ptr() .cast(), @@ -8235,7 +8236,7 @@ impl DeviceCommands { } }, get_physical_device_optical_flow_image_formats_nv: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceOpticalFlowImageFormatsNV\0" .as_ptr() .cast(), @@ -8255,7 +8256,8 @@ impl DeviceCommands { } }, get_physical_device_present_rectangles_khr: { - let value = loader(b"vkGetPhysicalDevicePresentRectanglesKHR\0".as_ptr().cast()); + let value = + instance_loader(b"vkGetPhysicalDevicePresentRectanglesKHR\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -8271,7 +8273,7 @@ impl DeviceCommands { } }, get_physical_device_queue_family_performance_query_passes_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR\0" .as_ptr() .cast(), @@ -8290,7 +8292,7 @@ impl DeviceCommands { } }, get_physical_device_refreshable_object_types_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceRefreshableObjectTypesKHR\0" .as_ptr() .cast(), @@ -8309,7 +8311,8 @@ impl DeviceCommands { } }, get_physical_device_sci_buf_attributes_nv: { - let value = loader(b"vkGetPhysicalDeviceSciBufAttributesNV\0".as_ptr().cast()); + let value = + instance_loader(b"vkGetPhysicalDeviceSciBufAttributesNV\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -8323,7 +8326,8 @@ impl DeviceCommands { } }, get_physical_device_sci_sync_attributes_nv: { - let value = loader(b"vkGetPhysicalDeviceSciSyncAttributesNV\0".as_ptr().cast()); + let value = + instance_loader(b"vkGetPhysicalDeviceSciSyncAttributesNV\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -8338,7 +8342,7 @@ impl DeviceCommands { } }, get_physical_device_supported_framebuffer_mixed_samples_combinations_nv: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV\0" .as_ptr() .cast(), @@ -8357,7 +8361,7 @@ impl DeviceCommands { } }, get_physical_device_surface_present_modes2_ext: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceSurfacePresentModes2EXT\0" .as_ptr() .cast(), @@ -8377,7 +8381,8 @@ impl DeviceCommands { } }, get_physical_device_tool_properties_ext: { - let value = loader(b"vkGetPhysicalDeviceToolPropertiesEXT\0".as_ptr().cast()); + let value = + instance_loader(b"vkGetPhysicalDeviceToolPropertiesEXT\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -8392,7 +8397,8 @@ impl DeviceCommands { } }, get_physical_device_video_capabilities_khr: { - let value = loader(b"vkGetPhysicalDeviceVideoCapabilitiesKHR\0".as_ptr().cast()); + let value = + instance_loader(b"vkGetPhysicalDeviceVideoCapabilitiesKHR\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else { @@ -8407,7 +8413,7 @@ impl DeviceCommands { } }, get_physical_device_video_encode_quality_level_properties_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR\0" .as_ptr() .cast(), @@ -8426,7 +8432,7 @@ impl DeviceCommands { } }, get_physical_device_video_format_properties_khr: { - let value = loader( + let value = instance_loader( b"vkGetPhysicalDeviceVideoFormatPropertiesKHR\0" .as_ptr() .cast(), @@ -9035,7 +9041,7 @@ impl DeviceCommands { } }, get_winrt_display_nv: { - let value = loader(b"vkGetWinrtDisplayNV\0".as_ptr().cast()); + let value = instance_loader(b"vkGetWinrtDisplayNV\0".as_ptr().cast()); if let Some(value) = value { mem::transmute(value) } else {