Skip to content

Commit

Permalink
Fix instance-level functions in device extensions (#281)
Browse files Browse the repository at this point in the history
  • Loading branch information
KyleMayes committed Aug 23, 2024
1 parent c58271f commit d2ea6d4
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 31 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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() =
Expand Down Expand Up @@ -51,6 +52,8 @@ $structs
"""
}

private val loader = "impl FnMut(*const c_char) -> Option<unsafe extern \"system\" fn()>"

/** Generates a Rust struct for a group of Vulkan commands of the same type. */
private fun Registry.generateCommandStruct(
type: CommandType,
Expand All @@ -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<unsafe extern "system" fn()>) -> 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 {
Expand All @@ -85,6 +104,7 @@ ${command.name}: {
}
}
"""
}

/** Generates a Rust function signature for a Vulkan command. */
private fun generateSignature(
Expand Down
11 changes: 7 additions & 4 deletions vulkanalia/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -274,12 +274,13 @@ impl Entry {
allocator: Option<&vk::AllocationCallbacks>,
) -> VkResult<Instance> {
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,
Expand All @@ -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,
Expand Down Expand Up @@ -344,8 +346,9 @@ impl Instance {
allocator: Option<&vk::AllocationCallbacks>,
) -> VkResult<Device> {
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 {
Expand Down
50 changes: 28 additions & 22 deletions vulkanalia/src/vk/commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -670,6 +670,7 @@ pub struct DeviceCommands {
impl DeviceCommands {
#[inline]
pub unsafe fn load(
mut instance_loader: impl FnMut(*const c_char) -> Option<unsafe extern "system" fn()>,
mut loader: impl FnMut(*const c_char) -> Option<unsafe extern "system" fn()>,
) -> Self {
Self {
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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(),
Expand Down Expand Up @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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 {
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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(),
Expand All @@ -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(),
Expand All @@ -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 {
Expand All @@ -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 {
Expand All @@ -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(),
Expand All @@ -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(),
Expand Down Expand Up @@ -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 {
Expand Down

0 comments on commit d2ea6d4

Please sign in to comment.