generator: Untangle mismatched parameter/return fn signatures in types (#437)
* generator: Untangle mismatched parameter/return fn signatures in types With function typedefs for commands having some elements filtered out (by name) if they were previously defined already, combined with unfiltered arrays containing the parameter sets and return type for _all_ commands expanded together in `quote!` macros the wrong array elements get combined resulting in incorrect signatures. No-one seems to use function pointer types (but we should!) which is why this has gone unnoticed for some time. * generator: Derive clone for function pointers instead of generating it * generator: Regroup token generation per command instead of across arrays This complements the previous commit by avoiding mismatches in array content altogether, instead of expanding multiple arrays within a single `#()*` quote expression and assuming they all contain the same data in the same order, reducing cognitive overhead while reading this code.
This commit is contained in:
parent
0ae6e49195
commit
82ca24663f
File diff suppressed because it is too large
Load diff
|
@ -5,19 +5,13 @@ use std::os::raw::*;
|
|||
#[allow(non_camel_case_types)]
|
||||
pub type PFN_vkGetInstanceProcAddr =
|
||||
unsafe extern "system" fn(instance: Instance, p_name: *const c_char) -> PFN_vkVoidFunction;
|
||||
#[derive(Clone)]
|
||||
pub struct StaticFn {
|
||||
pub get_instance_proc_addr:
|
||||
unsafe extern "system" fn(instance: Instance, p_name: *const c_char) -> PFN_vkVoidFunction,
|
||||
}
|
||||
unsafe impl Send for StaticFn {}
|
||||
unsafe impl Sync for StaticFn {}
|
||||
impl ::std::clone::Clone for StaticFn {
|
||||
fn clone(&self) -> Self {
|
||||
StaticFn {
|
||||
get_instance_proc_addr: self.get_instance_proc_addr,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl StaticFn {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -71,6 +65,7 @@ pub type PFN_vkEnumerateInstanceLayerProperties = unsafe extern "system" fn(
|
|||
p_property_count: *mut u32,
|
||||
p_properties: *mut LayerProperties,
|
||||
) -> Result;
|
||||
#[derive(Clone)]
|
||||
pub struct EntryFnV1_0 {
|
||||
pub create_instance: unsafe extern "system" fn(
|
||||
p_create_info: *const InstanceCreateInfo,
|
||||
|
@ -89,15 +84,6 @@ pub struct EntryFnV1_0 {
|
|||
}
|
||||
unsafe impl Send for EntryFnV1_0 {}
|
||||
unsafe impl Sync for EntryFnV1_0 {}
|
||||
impl ::std::clone::Clone for EntryFnV1_0 {
|
||||
fn clone(&self) -> Self {
|
||||
EntryFnV1_0 {
|
||||
create_instance: self.create_instance,
|
||||
enumerate_instance_extension_properties: self.enumerate_instance_extension_properties,
|
||||
enumerate_instance_layer_properties: self.enumerate_instance_layer_properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl EntryFnV1_0 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -270,6 +256,7 @@ pub type PFN_vkGetPhysicalDeviceSparseImageFormatProperties = unsafe extern "sys
|
|||
p_property_count: *mut u32,
|
||||
p_properties: *mut SparseImageFormatProperties,
|
||||
);
|
||||
#[derive(Clone)]
|
||||
pub struct InstanceFnV1_0 {
|
||||
pub destroy_instance:
|
||||
unsafe extern "system" fn(instance: Instance, p_allocator: *const AllocationCallbacks),
|
||||
|
@ -341,28 +328,6 @@ pub struct InstanceFnV1_0 {
|
|||
}
|
||||
unsafe impl Send for InstanceFnV1_0 {}
|
||||
unsafe impl Sync for InstanceFnV1_0 {}
|
||||
impl ::std::clone::Clone for InstanceFnV1_0 {
|
||||
fn clone(&self) -> Self {
|
||||
InstanceFnV1_0 {
|
||||
destroy_instance: self.destroy_instance,
|
||||
enumerate_physical_devices: self.enumerate_physical_devices,
|
||||
get_physical_device_features: self.get_physical_device_features,
|
||||
get_physical_device_format_properties: self.get_physical_device_format_properties,
|
||||
get_physical_device_image_format_properties: self
|
||||
.get_physical_device_image_format_properties,
|
||||
get_physical_device_properties: self.get_physical_device_properties,
|
||||
get_physical_device_queue_family_properties: self
|
||||
.get_physical_device_queue_family_properties,
|
||||
get_physical_device_memory_properties: self.get_physical_device_memory_properties,
|
||||
get_device_proc_addr: self.get_device_proc_addr,
|
||||
create_device: self.create_device,
|
||||
enumerate_device_extension_properties: self.enumerate_device_extension_properties,
|
||||
enumerate_device_layer_properties: self.enumerate_device_layer_properties,
|
||||
get_physical_device_sparse_image_format_properties: self
|
||||
.get_physical_device_sparse_image_format_properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl InstanceFnV1_0 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -1575,6 +1540,7 @@ pub type PFN_vkCmdExecuteCommands = unsafe extern "system" fn(
|
|||
command_buffer_count: u32,
|
||||
p_command_buffers: *const CommandBuffer,
|
||||
);
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceFnV1_0 {
|
||||
pub destroy_device:
|
||||
unsafe extern "system" fn(device: Device, p_allocator: *const AllocationCallbacks),
|
||||
|
@ -2253,132 +2219,6 @@ pub struct DeviceFnV1_0 {
|
|||
}
|
||||
unsafe impl Send for DeviceFnV1_0 {}
|
||||
unsafe impl Sync for DeviceFnV1_0 {}
|
||||
impl ::std::clone::Clone for DeviceFnV1_0 {
|
||||
fn clone(&self) -> Self {
|
||||
DeviceFnV1_0 {
|
||||
destroy_device: self.destroy_device,
|
||||
get_device_queue: self.get_device_queue,
|
||||
queue_submit: self.queue_submit,
|
||||
queue_wait_idle: self.queue_wait_idle,
|
||||
device_wait_idle: self.device_wait_idle,
|
||||
allocate_memory: self.allocate_memory,
|
||||
free_memory: self.free_memory,
|
||||
map_memory: self.map_memory,
|
||||
unmap_memory: self.unmap_memory,
|
||||
flush_mapped_memory_ranges: self.flush_mapped_memory_ranges,
|
||||
invalidate_mapped_memory_ranges: self.invalidate_mapped_memory_ranges,
|
||||
get_device_memory_commitment: self.get_device_memory_commitment,
|
||||
bind_buffer_memory: self.bind_buffer_memory,
|
||||
bind_image_memory: self.bind_image_memory,
|
||||
get_buffer_memory_requirements: self.get_buffer_memory_requirements,
|
||||
get_image_memory_requirements: self.get_image_memory_requirements,
|
||||
get_image_sparse_memory_requirements: self.get_image_sparse_memory_requirements,
|
||||
queue_bind_sparse: self.queue_bind_sparse,
|
||||
create_fence: self.create_fence,
|
||||
destroy_fence: self.destroy_fence,
|
||||
reset_fences: self.reset_fences,
|
||||
get_fence_status: self.get_fence_status,
|
||||
wait_for_fences: self.wait_for_fences,
|
||||
create_semaphore: self.create_semaphore,
|
||||
destroy_semaphore: self.destroy_semaphore,
|
||||
create_event: self.create_event,
|
||||
destroy_event: self.destroy_event,
|
||||
get_event_status: self.get_event_status,
|
||||
set_event: self.set_event,
|
||||
reset_event: self.reset_event,
|
||||
create_query_pool: self.create_query_pool,
|
||||
destroy_query_pool: self.destroy_query_pool,
|
||||
get_query_pool_results: self.get_query_pool_results,
|
||||
create_buffer: self.create_buffer,
|
||||
destroy_buffer: self.destroy_buffer,
|
||||
create_buffer_view: self.create_buffer_view,
|
||||
destroy_buffer_view: self.destroy_buffer_view,
|
||||
create_image: self.create_image,
|
||||
destroy_image: self.destroy_image,
|
||||
get_image_subresource_layout: self.get_image_subresource_layout,
|
||||
create_image_view: self.create_image_view,
|
||||
destroy_image_view: self.destroy_image_view,
|
||||
create_shader_module: self.create_shader_module,
|
||||
destroy_shader_module: self.destroy_shader_module,
|
||||
create_pipeline_cache: self.create_pipeline_cache,
|
||||
destroy_pipeline_cache: self.destroy_pipeline_cache,
|
||||
get_pipeline_cache_data: self.get_pipeline_cache_data,
|
||||
merge_pipeline_caches: self.merge_pipeline_caches,
|
||||
create_graphics_pipelines: self.create_graphics_pipelines,
|
||||
create_compute_pipelines: self.create_compute_pipelines,
|
||||
destroy_pipeline: self.destroy_pipeline,
|
||||
create_pipeline_layout: self.create_pipeline_layout,
|
||||
destroy_pipeline_layout: self.destroy_pipeline_layout,
|
||||
create_sampler: self.create_sampler,
|
||||
destroy_sampler: self.destroy_sampler,
|
||||
create_descriptor_set_layout: self.create_descriptor_set_layout,
|
||||
destroy_descriptor_set_layout: self.destroy_descriptor_set_layout,
|
||||
create_descriptor_pool: self.create_descriptor_pool,
|
||||
destroy_descriptor_pool: self.destroy_descriptor_pool,
|
||||
reset_descriptor_pool: self.reset_descriptor_pool,
|
||||
allocate_descriptor_sets: self.allocate_descriptor_sets,
|
||||
free_descriptor_sets: self.free_descriptor_sets,
|
||||
update_descriptor_sets: self.update_descriptor_sets,
|
||||
create_framebuffer: self.create_framebuffer,
|
||||
destroy_framebuffer: self.destroy_framebuffer,
|
||||
create_render_pass: self.create_render_pass,
|
||||
destroy_render_pass: self.destroy_render_pass,
|
||||
get_render_area_granularity: self.get_render_area_granularity,
|
||||
create_command_pool: self.create_command_pool,
|
||||
destroy_command_pool: self.destroy_command_pool,
|
||||
reset_command_pool: self.reset_command_pool,
|
||||
allocate_command_buffers: self.allocate_command_buffers,
|
||||
free_command_buffers: self.free_command_buffers,
|
||||
begin_command_buffer: self.begin_command_buffer,
|
||||
end_command_buffer: self.end_command_buffer,
|
||||
reset_command_buffer: self.reset_command_buffer,
|
||||
cmd_bind_pipeline: self.cmd_bind_pipeline,
|
||||
cmd_set_viewport: self.cmd_set_viewport,
|
||||
cmd_set_scissor: self.cmd_set_scissor,
|
||||
cmd_set_line_width: self.cmd_set_line_width,
|
||||
cmd_set_depth_bias: self.cmd_set_depth_bias,
|
||||
cmd_set_blend_constants: self.cmd_set_blend_constants,
|
||||
cmd_set_depth_bounds: self.cmd_set_depth_bounds,
|
||||
cmd_set_stencil_compare_mask: self.cmd_set_stencil_compare_mask,
|
||||
cmd_set_stencil_write_mask: self.cmd_set_stencil_write_mask,
|
||||
cmd_set_stencil_reference: self.cmd_set_stencil_reference,
|
||||
cmd_bind_descriptor_sets: self.cmd_bind_descriptor_sets,
|
||||
cmd_bind_index_buffer: self.cmd_bind_index_buffer,
|
||||
cmd_bind_vertex_buffers: self.cmd_bind_vertex_buffers,
|
||||
cmd_draw: self.cmd_draw,
|
||||
cmd_draw_indexed: self.cmd_draw_indexed,
|
||||
cmd_draw_indirect: self.cmd_draw_indirect,
|
||||
cmd_draw_indexed_indirect: self.cmd_draw_indexed_indirect,
|
||||
cmd_dispatch: self.cmd_dispatch,
|
||||
cmd_dispatch_indirect: self.cmd_dispatch_indirect,
|
||||
cmd_copy_buffer: self.cmd_copy_buffer,
|
||||
cmd_copy_image: self.cmd_copy_image,
|
||||
cmd_blit_image: self.cmd_blit_image,
|
||||
cmd_copy_buffer_to_image: self.cmd_copy_buffer_to_image,
|
||||
cmd_copy_image_to_buffer: self.cmd_copy_image_to_buffer,
|
||||
cmd_update_buffer: self.cmd_update_buffer,
|
||||
cmd_fill_buffer: self.cmd_fill_buffer,
|
||||
cmd_clear_color_image: self.cmd_clear_color_image,
|
||||
cmd_clear_depth_stencil_image: self.cmd_clear_depth_stencil_image,
|
||||
cmd_clear_attachments: self.cmd_clear_attachments,
|
||||
cmd_resolve_image: self.cmd_resolve_image,
|
||||
cmd_set_event: self.cmd_set_event,
|
||||
cmd_reset_event: self.cmd_reset_event,
|
||||
cmd_wait_events: self.cmd_wait_events,
|
||||
cmd_pipeline_barrier: self.cmd_pipeline_barrier,
|
||||
cmd_begin_query: self.cmd_begin_query,
|
||||
cmd_end_query: self.cmd_end_query,
|
||||
cmd_reset_query_pool: self.cmd_reset_query_pool,
|
||||
cmd_write_timestamp: self.cmd_write_timestamp,
|
||||
cmd_copy_query_pool_results: self.cmd_copy_query_pool_results,
|
||||
cmd_push_constants: self.cmd_push_constants,
|
||||
cmd_begin_render_pass: self.cmd_begin_render_pass,
|
||||
cmd_next_subpass: self.cmd_next_subpass,
|
||||
cmd_end_render_pass: self.cmd_end_render_pass,
|
||||
cmd_execute_commands: self.cmd_execute_commands,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl DeviceFnV1_0 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -5931,18 +5771,12 @@ impl DeviceFnV1_0 {
|
|||
#[allow(non_camel_case_types)]
|
||||
pub type PFN_vkEnumerateInstanceVersion =
|
||||
unsafe extern "system" fn(p_api_version: *mut u32) -> Result;
|
||||
#[derive(Clone)]
|
||||
pub struct EntryFnV1_1 {
|
||||
pub enumerate_instance_version: unsafe extern "system" fn(p_api_version: *mut u32) -> Result,
|
||||
}
|
||||
unsafe impl Send for EntryFnV1_1 {}
|
||||
unsafe impl Sync for EntryFnV1_1 {}
|
||||
impl ::std::clone::Clone for EntryFnV1_1 {
|
||||
fn clone(&self) -> Self {
|
||||
EntryFnV1_1 {
|
||||
enumerate_instance_version: self.enumerate_instance_version,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl EntryFnV1_1 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -5975,6 +5809,7 @@ impl EntryFnV1_1 {
|
|||
(self.enumerate_instance_version)(p_api_version)
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct InstanceFnV1_1 {
|
||||
pub enumerate_physical_device_groups: unsafe extern "system" fn(
|
||||
instance: Instance,
|
||||
|
@ -6032,29 +5867,6 @@ pub struct InstanceFnV1_1 {
|
|||
}
|
||||
unsafe impl Send for InstanceFnV1_1 {}
|
||||
unsafe impl Sync for InstanceFnV1_1 {}
|
||||
impl ::std::clone::Clone for InstanceFnV1_1 {
|
||||
fn clone(&self) -> Self {
|
||||
InstanceFnV1_1 {
|
||||
enumerate_physical_device_groups: self.enumerate_physical_device_groups,
|
||||
get_physical_device_features2: self.get_physical_device_features2,
|
||||
get_physical_device_properties2: self.get_physical_device_properties2,
|
||||
get_physical_device_format_properties2: self.get_physical_device_format_properties2,
|
||||
get_physical_device_image_format_properties2: self
|
||||
.get_physical_device_image_format_properties2,
|
||||
get_physical_device_queue_family_properties2: self
|
||||
.get_physical_device_queue_family_properties2,
|
||||
get_physical_device_memory_properties2: self.get_physical_device_memory_properties2,
|
||||
get_physical_device_sparse_image_format_properties2: self
|
||||
.get_physical_device_sparse_image_format_properties2,
|
||||
get_physical_device_external_buffer_properties: self
|
||||
.get_physical_device_external_buffer_properties,
|
||||
get_physical_device_external_fence_properties: self
|
||||
.get_physical_device_external_fence_properties,
|
||||
get_physical_device_external_semaphore_properties: self
|
||||
.get_physical_device_external_semaphore_properties,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl InstanceFnV1_1 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -6422,9 +6234,10 @@ impl InstanceFnV1_1 {
|
|||
#[allow(non_camel_case_types)]
|
||||
pub type PFN_vkGetDeviceQueue2 = unsafe extern "system" fn(
|
||||
device: Device,
|
||||
bind_info_count: u32,
|
||||
p_bind_infos: *const BindBufferMemoryInfo,
|
||||
) -> Result;
|
||||
p_queue_info: *const DeviceQueueInfo2,
|
||||
p_queue: *mut Queue,
|
||||
);
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceFnV1_1 {
|
||||
pub bind_buffer_memory2: unsafe extern "system" fn(
|
||||
device: Device,
|
||||
|
@ -6516,28 +6329,6 @@ pub struct DeviceFnV1_1 {
|
|||
}
|
||||
unsafe impl Send for DeviceFnV1_1 {}
|
||||
unsafe impl Sync for DeviceFnV1_1 {}
|
||||
impl ::std::clone::Clone for DeviceFnV1_1 {
|
||||
fn clone(&self) -> Self {
|
||||
DeviceFnV1_1 {
|
||||
bind_buffer_memory2: self.bind_buffer_memory2,
|
||||
bind_image_memory2: self.bind_image_memory2,
|
||||
get_device_group_peer_memory_features: self.get_device_group_peer_memory_features,
|
||||
cmd_set_device_mask: self.cmd_set_device_mask,
|
||||
cmd_dispatch_base: self.cmd_dispatch_base,
|
||||
get_image_memory_requirements2: self.get_image_memory_requirements2,
|
||||
get_buffer_memory_requirements2: self.get_buffer_memory_requirements2,
|
||||
get_image_sparse_memory_requirements2: self.get_image_sparse_memory_requirements2,
|
||||
trim_command_pool: self.trim_command_pool,
|
||||
get_device_queue2: self.get_device_queue2,
|
||||
create_sampler_ycbcr_conversion: self.create_sampler_ycbcr_conversion,
|
||||
destroy_sampler_ycbcr_conversion: self.destroy_sampler_ycbcr_conversion,
|
||||
create_descriptor_update_template: self.create_descriptor_update_template,
|
||||
destroy_descriptor_update_template: self.destroy_descriptor_update_template,
|
||||
update_descriptor_set_with_template: self.update_descriptor_set_with_template,
|
||||
get_descriptor_set_layout_support: self.get_descriptor_set_layout_support,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl DeviceFnV1_1 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -7048,14 +6839,10 @@ impl DeviceFnV1_1 {
|
|||
(self.get_descriptor_set_layout_support)(device, p_create_info, p_support)
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct EntryFnV1_2 {}
|
||||
unsafe impl Send for EntryFnV1_2 {}
|
||||
unsafe impl Sync for EntryFnV1_2 {}
|
||||
impl ::std::clone::Clone for EntryFnV1_2 {
|
||||
fn clone(&self) -> Self {
|
||||
EntryFnV1_2 {}
|
||||
}
|
||||
}
|
||||
impl EntryFnV1_2 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -7064,14 +6851,10 @@ impl EntryFnV1_2 {
|
|||
EntryFnV1_2 {}
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct InstanceFnV1_2 {}
|
||||
unsafe impl Send for InstanceFnV1_2 {}
|
||||
unsafe impl Sync for InstanceFnV1_2 {}
|
||||
impl ::std::clone::Clone for InstanceFnV1_2 {
|
||||
fn clone(&self) -> Self {
|
||||
InstanceFnV1_2 {}
|
||||
}
|
||||
}
|
||||
impl InstanceFnV1_2 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
@ -7080,6 +6863,7 @@ impl InstanceFnV1_2 {
|
|||
InstanceFnV1_2 {}
|
||||
}
|
||||
}
|
||||
#[derive(Clone)]
|
||||
pub struct DeviceFnV1_2 {
|
||||
pub cmd_draw_indirect_count: unsafe extern "system" fn(
|
||||
command_buffer: CommandBuffer,
|
||||
|
@ -7152,25 +6936,6 @@ pub struct DeviceFnV1_2 {
|
|||
}
|
||||
unsafe impl Send for DeviceFnV1_2 {}
|
||||
unsafe impl Sync for DeviceFnV1_2 {}
|
||||
impl ::std::clone::Clone for DeviceFnV1_2 {
|
||||
fn clone(&self) -> Self {
|
||||
DeviceFnV1_2 {
|
||||
cmd_draw_indirect_count: self.cmd_draw_indirect_count,
|
||||
cmd_draw_indexed_indirect_count: self.cmd_draw_indexed_indirect_count,
|
||||
create_render_pass2: self.create_render_pass2,
|
||||
cmd_begin_render_pass2: self.cmd_begin_render_pass2,
|
||||
cmd_next_subpass2: self.cmd_next_subpass2,
|
||||
cmd_end_render_pass2: self.cmd_end_render_pass2,
|
||||
reset_query_pool: self.reset_query_pool,
|
||||
get_semaphore_counter_value: self.get_semaphore_counter_value,
|
||||
wait_semaphores: self.wait_semaphores,
|
||||
signal_semaphore: self.signal_semaphore,
|
||||
get_buffer_device_address: self.get_buffer_device_address,
|
||||
get_buffer_opaque_capture_address: self.get_buffer_opaque_capture_address,
|
||||
get_device_memory_opaque_capture_address: self.get_device_memory_opaque_capture_address,
|
||||
}
|
||||
}
|
||||
}
|
||||
impl DeviceFnV1_2 {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where
|
||||
|
|
|
@ -841,48 +841,37 @@ fn generate_function_pointers<'a>(
|
|||
.iter()
|
||||
.unique_by(|cmd| cmd.name.as_str())
|
||||
.collect::<Vec<_>>();
|
||||
// PFN function pointers are global and can not have duplicates. This can happen because there
|
||||
// are aliases to commands
|
||||
let commands_pfn: Vec<_> = commands
|
||||
.iter()
|
||||
.filter(|cmd| fn_cache.insert(cmd.name.as_str()))
|
||||
.collect();
|
||||
|
||||
let function_name_raw = |name: &str| -> String {
|
||||
if let Some(alias_name) = aliases.get(name) {
|
||||
alias_name.to_string()
|
||||
} else {
|
||||
name.to_string()
|
||||
}
|
||||
};
|
||||
let function_name = |name: &str| -> Ident {
|
||||
let fn_name = function_name_raw(name);
|
||||
format_ident!(
|
||||
"{}",
|
||||
fn_name.strip_prefix("vk").unwrap().to_snake_case().as_str()
|
||||
)
|
||||
};
|
||||
let names: Vec<_> = commands
|
||||
.iter()
|
||||
.map(|cmd| function_name(&cmd.name))
|
||||
.collect();
|
||||
let names_ref = &names;
|
||||
let raw_names: Vec<_> = commands
|
||||
struct Command {
|
||||
type_needs_defining: bool,
|
||||
type_name: Ident,
|
||||
function_name_c: String,
|
||||
function_name_rust: Ident,
|
||||
parameter_names: TokenStream,
|
||||
parameters: TokenStream,
|
||||
parameters_unused: TokenStream,
|
||||
returns: TokenStream,
|
||||
}
|
||||
|
||||
let commands = commands
|
||||
.iter()
|
||||
.map(|cmd| {
|
||||
let byt = std::ffi::CString::new(function_name_raw(cmd.name.as_str())).unwrap();
|
||||
Literal::byte_string(byt.to_bytes_with_nul())
|
||||
})
|
||||
.collect();
|
||||
let raw_names_ref = &raw_names;
|
||||
let khronos_links: Vec<_> = commands
|
||||
.iter()
|
||||
.map(|cmd| khronos_link(&function_name_raw(cmd.name.as_str())))
|
||||
.collect();
|
||||
let type_name = format_ident!("PFN_{}", cmd.name);
|
||||
|
||||
let function_name_c = if let Some(alias_name) = aliases.get(&cmd.name) {
|
||||
alias_name.to_string()
|
||||
} else {
|
||||
cmd.name.to_string()
|
||||
};
|
||||
let function_name_rust = format_ident!(
|
||||
"{}",
|
||||
function_name_c
|
||||
.strip_prefix("vk")
|
||||
.unwrap()
|
||||
.to_snake_case()
|
||||
.as_str()
|
||||
);
|
||||
|
||||
let params: Vec<Vec<(Ident, TokenStream)>> = commands
|
||||
.iter()
|
||||
.map(|cmd| {
|
||||
let params: Vec<_> = cmd
|
||||
.param
|
||||
.iter()
|
||||
|
@ -892,131 +881,142 @@ fn generate_function_pointers<'a>(
|
|||
(name, ty)
|
||||
})
|
||||
.collect();
|
||||
params
|
||||
})
|
||||
.collect();
|
||||
|
||||
let params_names: Vec<Vec<_>> = params
|
||||
.iter()
|
||||
.map(|inner_params| {
|
||||
inner_params
|
||||
let params_iter = params.iter().map(|(param_name, _)| param_name);
|
||||
let parameter_names = quote!(#(#params_iter,)*);
|
||||
|
||||
let params_iter = params
|
||||
.iter()
|
||||
.map(|(param_name, _)| param_name.clone())
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
let expanded_params: Vec<_> = params
|
||||
.iter()
|
||||
.map(|inner_params| {
|
||||
let inner_params_iter = inner_params.iter().map(|&(ref param_name, ref param_ty)| {
|
||||
quote! {#param_name: #param_ty}
|
||||
});
|
||||
quote! {
|
||||
#(#inner_params_iter,)*
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let expanded_params_unused: Vec<_> = params
|
||||
.iter()
|
||||
.map(|inner_params| {
|
||||
let inner_params_iter = inner_params.iter().map(|&(ref param_name, ref param_ty)| {
|
||||
.map(|(param_name, param_ty)| quote!(#param_name: #param_ty));
|
||||
let parameters = quote!(#(#params_iter,)*);
|
||||
|
||||
let params_iter = params.iter().map(|(param_name, param_ty)| {
|
||||
let unused_name = format_ident!("_{}", param_name);
|
||||
quote! {#unused_name: #param_ty}
|
||||
quote!(#unused_name: #param_ty)
|
||||
});
|
||||
quote! {
|
||||
#(#inner_params_iter,)*
|
||||
let parameters_unused = quote!(#(#params_iter,)*);
|
||||
|
||||
Command {
|
||||
// PFN function pointers are global and can not have duplicates.
|
||||
// This can happen because there are aliases to commands
|
||||
type_needs_defining: fn_cache.insert(cmd.name.as_str()),
|
||||
type_name,
|
||||
function_name_c,
|
||||
function_name_rust,
|
||||
parameter_names,
|
||||
parameters,
|
||||
parameters_unused,
|
||||
returns: if cmd.return_type.is_void() {
|
||||
quote!()
|
||||
} else {
|
||||
let ret_ty_tokens = cmd.return_type.type_tokens(true);
|
||||
quote!(-> #ret_ty_tokens)
|
||||
},
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let expanded_params_ref = &expanded_params;
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let pfn_names: Vec<_> = commands_pfn
|
||||
.iter()
|
||||
.map(|cmd| format_ident!("PFN_{}", cmd.name))
|
||||
.collect();
|
||||
let pfn_names_ref = &pfn_names;
|
||||
struct CommandToType<'a>(&'a Command);
|
||||
impl<'a> quote::ToTokens for CommandToType<'a> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let type_name = &self.0.type_name;
|
||||
let parameters = &self.0.parameters;
|
||||
let returns = &self.0.returns;
|
||||
quote!(
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type #type_name = unsafe extern "system" fn(#parameters) #returns;
|
||||
)
|
||||
.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
let signature_params: Vec<Vec<_>> = commands
|
||||
.iter()
|
||||
.map(|cmd| {
|
||||
let params: Vec<_> = cmd
|
||||
.param
|
||||
.iter()
|
||||
.map(|field| {
|
||||
let name = field.param_ident();
|
||||
let ty = field.type_tokens(true);
|
||||
quote! { #name: #ty }
|
||||
})
|
||||
.collect();
|
||||
params
|
||||
})
|
||||
.collect();
|
||||
let signature_params_ref = &signature_params;
|
||||
struct CommandToMember<'a>(&'a Command);
|
||||
impl<'a> quote::ToTokens for CommandToMember<'a> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let function_name_rust = &self.0.function_name_rust;
|
||||
let parameters = &self.0.parameters;
|
||||
let returns = &self.0.returns;
|
||||
quote!(
|
||||
pub #function_name_rust: unsafe extern "system" fn(#parameters) #returns
|
||||
)
|
||||
.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
let return_types: Vec<_> = commands
|
||||
struct CommandToLoader<'a>(&'a Command);
|
||||
impl<'a> quote::ToTokens for CommandToLoader<'a> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let function_name_rust = &self.0.function_name_rust;
|
||||
let parameters_unused = &self.0.parameters_unused;
|
||||
let returns = &self.0.returns;
|
||||
|
||||
let byte_function_name =
|
||||
Literal::byte_string(format!("{}\0", self.0.function_name_c).as_bytes());
|
||||
|
||||
quote!(
|
||||
#function_name_rust: unsafe {
|
||||
unsafe extern "system" fn #function_name_rust (#parameters_unused) #returns {
|
||||
panic!(concat!("Unable to load ", stringify!(#function_name_rust)))
|
||||
}
|
||||
let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked(#byte_function_name);
|
||||
let val = _f(cname);
|
||||
if val.is_null() {
|
||||
#function_name_rust
|
||||
} else {
|
||||
::std::mem::transmute(val)
|
||||
}
|
||||
}
|
||||
)
|
||||
.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
struct CommandToBody<'a>(&'a Command);
|
||||
impl<'a> quote::ToTokens for CommandToBody<'a> {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
let function_name_rust = &self.0.function_name_rust;
|
||||
let parameters = &self.0.parameters;
|
||||
let parameter_names = &self.0.parameter_names;
|
||||
let returns = &self.0.returns;
|
||||
let khronos_link = khronos_link(&self.0.function_name_c);
|
||||
quote!(
|
||||
#[doc = #khronos_link]
|
||||
pub unsafe fn #function_name_rust(&self, #parameters) #returns {
|
||||
(self.#function_name_rust)(#parameter_names)
|
||||
}
|
||||
)
|
||||
.to_tokens(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
let pfn_typedefs = commands
|
||||
.iter()
|
||||
.map(|cmd| {
|
||||
if cmd.return_type.is_void() {
|
||||
quote!()
|
||||
} else {
|
||||
let ret_ty_tokens = cmd.return_type.type_tokens(true);
|
||||
quote!(-> #ret_ty_tokens)
|
||||
}
|
||||
})
|
||||
.collect();
|
||||
let return_types_ref = &return_types;
|
||||
.filter(|pfn| pfn.type_needs_defining)
|
||||
.map(|pfn| CommandToType(pfn));
|
||||
let members = commands.iter().map(|pfn| CommandToMember(pfn));
|
||||
let loaders = commands.iter().map(|pfn| CommandToLoader(pfn));
|
||||
let bodies = commands.iter().map(|pfn| CommandToBody(pfn));
|
||||
|
||||
quote! {
|
||||
#(
|
||||
#[allow(non_camel_case_types)]
|
||||
pub type #pfn_names_ref = unsafe extern "system" fn(#(#signature_params_ref),*) #return_types_ref;
|
||||
)*
|
||||
#(#pfn_typedefs)*
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct #ident {
|
||||
#(
|
||||
pub #names_ref: unsafe extern "system" fn(#expanded_params_ref) #return_types_ref,
|
||||
)*
|
||||
#(#members,)*
|
||||
}
|
||||
|
||||
unsafe impl Send for #ident {}
|
||||
unsafe impl Sync for #ident {}
|
||||
|
||||
impl ::std::clone::Clone for #ident {
|
||||
fn clone(&self) -> Self {
|
||||
#ident{
|
||||
#(#names: self.#names,)*
|
||||
}
|
||||
}
|
||||
}
|
||||
impl #ident {
|
||||
pub fn load<F>(mut _f: F) -> Self
|
||||
where F: FnMut(&::std::ffi::CStr) -> *const c_void
|
||||
{
|
||||
#ident {
|
||||
#(
|
||||
#names_ref: unsafe {
|
||||
|
||||
unsafe extern "system" fn #names_ref (#expanded_params_unused) #return_types_ref {
|
||||
panic!(concat!("Unable to load ", stringify!(#names_ref)))
|
||||
}
|
||||
let cname = ::std::ffi::CStr::from_bytes_with_nul_unchecked(#raw_names_ref);
|
||||
let val = _f(cname);
|
||||
if val.is_null(){
|
||||
#names_ref
|
||||
}
|
||||
else{
|
||||
::std::mem::transmute(val)
|
||||
}
|
||||
},
|
||||
)*
|
||||
#(#loaders,)*
|
||||
}
|
||||
}
|
||||
#(
|
||||
#[doc = #khronos_links]
|
||||
pub unsafe fn #names_ref(&self, #expanded_params_ref) #return_types_ref {
|
||||
(self.#names)(#(#params_names,)*)
|
||||
}
|
||||
)*
|
||||
#(#bodies)*
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue