diff --git a/Cargo.lock b/Cargo.lock index 8d999391..319c0c0a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -248,9 +248,9 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" [[package]] name = "glow" -version = "0.12.2" +version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "807edf58b70c0b5b2181dd39fe1839dbdb3ba02645630dc5f753e23da307f762" +checksum = "ca0fe580e4b60a8ab24a868bc08e2f03cbcb20d3d676601fa909386713333728" dependencies = [ "js-sys", "slotmap", @@ -523,9 +523,9 @@ dependencies = [ [[package]] name = "paste" -version = "1.0.13" +version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4b27ab7be369122c218afc2079489cdcb4b517c0a3fc386ff11e1fedfcc2b35" +checksum = "de3145af08024dea9fa9914f381a17b8fc6034dfb00f3a84013f7ff43f29ed4c" [[package]] name = "peeking_take_while" @@ -570,9 +570,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.64" +version = "1.0.66" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78803b62cbf1f46fde80d7c0e803111524b9877184cfe7c3033659490ac7a7da" +checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" dependencies = [ "unicode-ident", ] @@ -585,9 +585,9 @@ checksum = "332cd62e95873ea4f41f3dfd6bbbfc5b52aec892d7e8d534197c4720a0bbbab2" [[package]] name = "quote" -version = "1.0.29" +version = "1.0.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "573015e8ab27661678357f27dc26460738fd2b6c86e46f386fde94cb5d913105" +checksum = "5fe8a65d69dd0808184ebb5f836ab526bb259db23c657efa38711b1072ee47f0" dependencies = [ "proc-macro2", ] @@ -627,9 +627,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d3daa6976cffb758ec878f108ba0e062a45b2d6ca3a2cca965338855476caf" +checksum = "39354c10dd07468c2e73926b23bb9c2caca74c5501e38a35da70406f1d923310" dependencies = [ "aho-corasick", "memchr", @@ -638,9 +638,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.3" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2ab07dc67230e4a4718e70fd5c20055a4334b121f1f9db8fe63ef39ce9b8c846" +checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" [[package]] name = "ron" @@ -661,24 +661,24 @@ checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" [[package]] name = "scopeguard" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" [[package]] name = "serde" -version = "1.0.169" +version = "1.0.173" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd51c3db8f9500d531e6c12dd0fd4ad13d133e9117f5aebac3cdbb8b6d9824b0" +checksum = "e91f70896d6720bc714a4a57d22fc91f1db634680e65c8efe13323f1fa38d53f" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.169" +version = "1.0.173" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27738cfea0d944ab72c3ed01f3d5f23ec4322af8a1431e40ce630e4c01ea74fd" +checksum = "a6250dde8342e0232232be9ca3db7aa40aceb5a3e5dd9bddbc00d99a007cde49" dependencies = [ "proc-macro2", "quote", @@ -718,9 +718,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.24" +version = "2.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36ccaf716a23c35ff908f91c971a86a9a71af5998c1d8f10e828d9f55f68ac00" +checksum = "45c3457aacde3c65315de5031ec191ce46604304d2446e803d71ade03308d970" dependencies = [ "proc-macro2", "quote", @@ -758,9 +758,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.10" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22049a19f4a68748a168c0fc439f9516686aa045927ff767eca0a85101fb6e73" +checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" [[package]] name = "unicode-width" @@ -922,6 +922,7 @@ dependencies = [ "parking_lot", "paste", "raw-window-handle", + "smallvec", "thiserror", "wgpu-core", "wgpu-types", diff --git a/Cargo.toml b/Cargo.toml index 06c34b0b..6ce4b5fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -72,6 +72,7 @@ paste = "1.0" log = "0.4" thiserror = "1" parking_lot = "0.12" +smallvec = "1" [build-dependencies] bindgen = "0.66" diff --git a/src/conv.rs b/src/conv.rs index 7ec4cfde..bceb66c2 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -1,9 +1,8 @@ use wgc::Label; use crate::native; -use crate::utils::{make_slice, OwnedLabel}; +use crate::utils::{make_slice, ptr_into_label, ptr_into_pathbuf}; use crate::{follow_chain, map_enum}; -use std::path::Path; use std::{borrow::Cow, ffi::CStr}; map_enum!( @@ -253,12 +252,8 @@ pub fn map_instance_descriptor( let dx12_shader_compiler = match extras.dx12ShaderCompiler { native::WGPUDx12Compiler_Fxc => wgt::Dx12Compiler::Fxc, native::WGPUDx12Compiler_Dxc => wgt::Dx12Compiler::Dxc { - dxil_path: unsafe { extras.dxilPath.as_ref() } - .and_then(|v| unsafe { OwnedLabel::new(v) }.into_inner()) - .map(|v| Path::new(&v).to_path_buf()), - dxc_path: unsafe { extras.dxcPath.as_ref() } - .and_then(|v| unsafe { OwnedLabel::new(v) }.into_inner()) - .map(|v| Path::new(&v).to_path_buf()), + dxil_path: ptr_into_pathbuf(extras.dxilPath), + dxc_path: ptr_into_pathbuf(extras.dxcPath), }, _ => wgt::Dx12Compiler::default(), }; @@ -276,7 +271,7 @@ pub fn map_instance_descriptor( pub fn map_device_descriptor<'a>( des: &native::WGPUDeviceDescriptor, extras: Option<&native::WGPUDeviceExtras>, -) -> (wgt::DeviceDescriptor>, Option) { +) -> (wgt::DeviceDescriptor>, *const std::ffi::c_char) { let limits = unsafe { des.requiredLimits.as_ref() }.map_or( wgt::Limits::default(), |required_limits| unsafe { @@ -289,13 +284,14 @@ pub fn map_device_descriptor<'a>( ( wgt::DeviceDescriptor { - label: unsafe { OwnedLabel::new(des.label) }.into_cow(), - features: map_features(unsafe { - make_slice(des.requiredFeatures, des.requiredFeaturesCount) - }), + label: ptr_into_label(des.label), + features: map_features(make_slice(des.requiredFeatures, des.requiredFeaturesCount)), limits, }, - extras.and_then(|extras| unsafe { OwnedLabel::new(extras.tracePath) }.into_inner()), + match extras { + Some(extras) => extras.tracePath, + None => std::ptr::null(), + }, ) } @@ -304,7 +300,7 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( des: &native::WGPUPipelineLayoutDescriptor, extras: Option<&native::WGPUPipelineLayoutExtras>, ) -> wgc::binding_model::PipelineLayoutDescriptor<'a> { - let bind_group_layouts = unsafe { make_slice(des.bindGroupLayouts, des.bindGroupLayoutCount) } + let bind_group_layouts = make_slice(des.bindGroupLayouts, des.bindGroupLayoutCount) .iter() .map(|layout| { layout @@ -315,12 +311,10 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( .collect::>(); let push_constant_ranges = extras.map_or(Vec::new(), |extras| { - unsafe { - make_slice( - extras.pushConstantRanges, - extras.pushConstantRangeCount as usize, - ) - } + make_slice( + extras.pushConstantRanges, + extras.pushConstantRangeCount as usize, + ) .iter() .map(|range| wgt::PushConstantRange { stages: wgt::ShaderStages::from_bits(range.stages) @@ -331,7 +325,7 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( }); return wgc::binding_model::PipelineLayoutDescriptor { - label: OwnedLabel::new(des.label).into_cow(), + label: ptr_into_label(des.label), bind_group_layouts: Cow::from(bind_group_layouts), push_constant_ranges: Cow::from(push_constant_ranges), }; @@ -342,12 +336,13 @@ pub fn write_limits_struct( wgt_limits: wgt::Limits, supported_limits: &mut native::WGPUSupportedLimits, ) { - let mut limits = supported_limits.limits; // This makes a copy - we copy back at the end + let mut limits = supported_limits.limits; limits.maxTextureDimension1D = wgt_limits.max_texture_dimension_1d; limits.maxTextureDimension2D = wgt_limits.max_texture_dimension_2d; limits.maxTextureDimension3D = wgt_limits.max_texture_dimension_3d; limits.maxTextureArrayLayers = wgt_limits.max_texture_array_layers; limits.maxBindGroups = wgt_limits.max_bind_groups; + limits.maxBindingsPerBindGroup = wgt_limits.max_bindings_per_bind_group; limits.maxDynamicUniformBuffersPerPipelineLayout = wgt_limits.max_dynamic_uniform_buffers_per_pipeline_layout; limits.maxDynamicStorageBuffersPerPipelineLayout = @@ -357,8 +352,8 @@ pub fn write_limits_struct( limits.maxStorageBuffersPerShaderStage = wgt_limits.max_storage_buffers_per_shader_stage; limits.maxStorageTexturesPerShaderStage = wgt_limits.max_storage_textures_per_shader_stage; limits.maxUniformBuffersPerShaderStage = wgt_limits.max_uniform_buffers_per_shader_stage; - limits.maxUniformBufferBindingSize = wgt_limits.max_uniform_buffer_binding_size as u64; - limits.maxStorageBufferBindingSize = wgt_limits.max_storage_buffer_binding_size as u64; + limits.maxUniformBufferBindingSize = wgt_limits.max_uniform_buffer_binding_size as _; + limits.maxStorageBufferBindingSize = wgt_limits.max_storage_buffer_binding_size as _; limits.minUniformBufferOffsetAlignment = wgt_limits.min_uniform_buffer_offset_alignment; limits.minStorageBufferOffsetAlignment = wgt_limits.min_storage_buffer_offset_alignment; limits.maxVertexBuffers = wgt_limits.max_vertex_buffers; @@ -366,6 +361,12 @@ pub fn write_limits_struct( limits.maxVertexAttributes = wgt_limits.max_vertex_attributes; limits.maxVertexBufferArrayStride = wgt_limits.max_vertex_buffer_array_stride; limits.maxInterStageShaderComponents = wgt_limits.max_inter_stage_shader_components; + // TODO: not yet in wgt + // limits.maxInterStageShaderVariables = wgt_limits.max_inter_stage_shader_variables; + // TODO: not yet in wgt + // limits.maxColorAttachments = wgt_limits.max_color_attachments; + // TODO: not yet in wgt + // limits.maxColorAttachmentBytesPerSample = wgt_limits.max_color_attachment_bytes_per_sample; limits.maxComputeWorkgroupStorageSize = wgt_limits.max_compute_workgroup_storage_size; limits.maxComputeInvocationsPerWorkgroup = wgt_limits.max_compute_invocations_per_workgroup; limits.maxComputeWorkgroupSizeX = wgt_limits.max_compute_workgroup_size_x; @@ -376,7 +377,7 @@ pub fn write_limits_struct( if !supported_limits.nextInChain.is_null() { unsafe { - let mut extras = std::mem::transmute::< + let extras = std::mem::transmute::< *mut native::WGPUChainedStructOut, *mut native::WGPUSupportedLimitsExtras, >(supported_limits.nextInChain); @@ -411,9 +412,9 @@ pub fn map_required_limits( if limits.maxBindGroups != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_bind_groups = limits.maxBindGroups; } - //if limits.maxBindingsPerBindGroup != native::WGPU_LIMIT_U32_UNDEFINED { - // wgt_limits.max_bindings_per_bind_group = limits.maxBindingsPerBindGroup; - //} not yet supportted in wgt + if limits.maxBindingsPerBindGroup != native::WGPU_LIMIT_U32_UNDEFINED { + wgt_limits.max_bindings_per_bind_group = limits.maxBindingsPerBindGroup; + } if limits.maxDynamicUniformBuffersPerPipelineLayout != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_dynamic_uniform_buffers_per_pipeline_layout = limits.maxDynamicUniformBuffersPerPipelineLayout; @@ -464,12 +465,19 @@ pub fn map_required_limits( if limits.maxInterStageShaderComponents != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_inter_stage_shader_components = limits.maxInterStageShaderComponents; } - //if limits.maxInterStageShaderVariables != native::WGPU_LIMIT_U32_UNDEFINED { - // wgt_limits.max_inter_stage_shader_variables = limits.maxIntmaxInterStageShaderVariableserStageShaderComponents; - //} not yet in wgt - //if limits.maxColorAttachments != native::WGPU_LIMIT_U32_UNDEFINED { - // wgt_limits.max_color_attachments = limits.maxColorAttachments; - //} not yet in wgt + // TODO: not yet in wgt + // if limits.maxInterStageShaderVariables != native::WGPU_LIMIT_U32_UNDEFINED { + // wgt_limits.max_inter_stage_shader_variables = + // limits.maxInterStageShaderVariables; + // } + // TODO: not yet in wgt + // if limits.maxColorAttachments != native::WGPU_LIMIT_U32_UNDEFINED { + // wgt_limits.max_color_attachments = limits.maxColorAttachments; + // } + // TODO: not yet in wgt + // if limits.maxColorAttachmentBytesPerSample != native::WGPU_LIMIT_U32_UNDEFINED { + // wgt_limits.max_color_attachment_bytes_per_sample = limits.maxColorAttachmentBytesPerSample; + // } if limits.maxComputeWorkgroupStorageSize != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_compute_workgroup_storage_size = limits.maxComputeWorkgroupStorageSize; } @@ -512,7 +520,7 @@ pub fn map_shader_module<'a>( #[cfg(feature = "spirv")] if let Some(spirv) = spirv { - let slice = unsafe { make_slice(spirv.code, spirv.codeSize as usize) }; + let slice = make_slice(spirv.code, spirv.codeSize as usize); // Parse the given shader code and store its representation. let options = naga::front::spv::Options { adjust_coordinate_space: false, // we require NDC_Y_UP feature @@ -532,7 +540,7 @@ pub fn map_shader_module<'a>( map_shader_stage(glsl.stage).expect("Unknown shader stage"), ); - let raw_defines = unsafe { make_slice(glsl.defines, glsl.defineCount as usize) }; + let raw_defines = make_slice(glsl.defines, glsl.defineCount as usize); for define in raw_defines { let name_c_str: &CStr = unsafe { CStr::from_ptr(define.name) }; let name_str_slice: &str = name_c_str.to_str().expect("not a valid utf-8 string"); @@ -1112,7 +1120,7 @@ pub fn map_swapchain_descriptor( native::WGPUCompositeAlphaMode_Inherit => wgt::CompositeAlphaMode::Inherit, _ => panic!("invalid alpha mode for swapchain descriptor"), }, - unsafe { make_slice(extras.viewFormats, extras.viewFormatCount) } + make_slice(extras.viewFormats, extras.viewFormatCount) .iter() .map(|f| { map_texture_format(*f).expect("invalid view format for swapchain descriptor") @@ -1138,7 +1146,7 @@ pub fn map_query_set_descriptor<'a>( desc: &native::WGPUQuerySetDescriptor, ) -> wgt::QuerySetDescriptor> { wgt::QuerySetDescriptor { - label: unsafe { OwnedLabel::new(desc.label) }.into_cow(), + label: ptr_into_label(desc.label), count: desc.count, ty: match desc.type_ { native::WGPUQueryType_Occlusion => wgt::QueryType::Occlusion, @@ -1146,7 +1154,7 @@ pub fn map_query_set_descriptor<'a>( native::WGPUQueryType_PipelineStatistics => { let mut types = wgt::PipelineStatisticsTypes::empty(); - unsafe { make_slice(desc.pipelineStatistics, desc.pipelineStatisticsCount) } + make_slice(desc.pipelineStatistics, desc.pipelineStatisticsCount) .iter() .for_each(|f| { types.insert(match *f { diff --git a/src/lib.rs b/src/lib.rs index 293e8ce0..6cc93509 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,6 +4,7 @@ use conv::{ map_swapchain_descriptor, CreateSurfaceParams, }; use parking_lot::{Mutex, RwLock}; +use smallvec::SmallVec; use std::{ borrow::Cow, cell::OnceCell, @@ -11,12 +12,11 @@ use std::{ ffi::{CStr, CString}, fmt::Display, num::NonZeroU64, - path::Path, sync::{atomic, Arc}, thread, }; use thiserror::Error; -use utils::{make_slice, OwnedLabel}; +use utils::{make_slice, ptr_into_label, ptr_into_path}; use wgc::{ command::{self, bundle_ffi, compute_ffi, render_ffi}, gfx_select, id, resource, Label, @@ -703,14 +703,19 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( } None => ( wgt::DeviceDescriptor::default(), - None, + std::ptr::null(), DEFAULT_DEVICE_LOST_HANDLER, ), }; - let trace_path = trace_str.as_ref().map(Path::new); - - let (device_id, err) = gfx_select!(adapter_id => context.adapter_request_device(adapter_id, &desc, trace_path, ())); + let (device_id, err) = gfx_select!(adapter_id => + context.adapter_request_device( + adapter_id, + &desc, + ptr_into_path(trace_str), + () + ) + ); match err { None => { callback( @@ -962,7 +967,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginComputePass( let desc = match descriptor { Some(descriptor) => wgc::command::ComputePassDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), }, None => wgc::command::ComputePassDescriptor::default(), }; @@ -1010,8 +1015,9 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginRenderPass( }, } }); + let desc = wgc::command::RenderPassDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), color_attachments: Cow::Owned( make_slice(descriptor.colorAttachments, descriptor.colorAttachmentCount) .iter() @@ -1232,7 +1238,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderFinish( let desc = match descriptor { Some(descriptor) => wgt::CommandBufferDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), }, None => wgt::CommandBufferDescriptor::default(), }; @@ -1684,9 +1690,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroup( }) .collect::>(); - let label = OwnedLabel::new(descriptor.label); let desc = wgc::binding_model::BindGroupDescriptor { - label: label.as_cow(), + label: ptr_into_label(descriptor.label), layout: bind_group_layout_id, entries: Cow::Borrowed(&entries), }; @@ -1840,9 +1845,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroupLayout( }) .collect::>(); - let label = OwnedLabel::new(descriptor.label); let desc = wgc::binding_model::BindGroupLayoutDescriptor { - label: label.as_cow(), + label: ptr_into_label(descriptor.label), entries: Cow::Borrowed(&entries), }; let (bind_group_layout_id, error) = @@ -1875,9 +1879,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateBuffer( }; let descriptor = descriptor.expect("invalid descriptor"); - let label = OwnedLabel::new(descriptor.label); let desc = wgt::BufferDescriptor { - label: label.as_cow(), + label: ptr_into_label(descriptor.label), size: descriptor.size, usage: wgt::BufferUsages::from_bits(descriptor.usage).expect("invalid buffer usage"), mapped_at_creation: descriptor.mappedAtCreation, @@ -1915,7 +1918,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateCommandEncoder( }; let desc = match descriptor { Some(descriptor) => wgt::CommandEncoderDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), }, None => wgt::CommandEncoderDescriptor::default(), }; @@ -1958,12 +1961,11 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( .as_ref() .expect("invalid shader module for compute pipeline descriptor") .id, - entry_point: OwnedLabel::new(descriptor.compute.entryPoint) - .into_cow() + entry_point: ptr_into_label(descriptor.compute.entryPoint) .expect("invalid entry point for compute pipeline descriptor"), }; let desc = wgc::pipeline::ComputePipelineDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), layout: descriptor.layout.as_ref().map(|v| v.id), stage, }; @@ -2085,8 +2087,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderBundleEncoder( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::command::RenderBundleEncoderDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), - color_formats: unsafe { make_slice(descriptor.colorFormats, descriptor.colorFormatsCount) } + label: ptr_into_label(descriptor.label), + color_formats: make_slice(descriptor.colorFormats, descriptor.colorFormatsCount) .iter() .map(|format| conv::map_texture_format(*format)) .collect(), @@ -2124,7 +2126,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::RenderPipelineDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), layout: descriptor.layout.as_ref().map(|v| v.id), vertex: wgc::pipeline::VertexState { stage: wgc::pipeline::ProgrammableStageDescriptor { @@ -2134,8 +2136,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .as_ref() .expect("invalid vertex shader module for vertex state") .id, - entry_point: OwnedLabel::new(descriptor.vertex.entryPoint) - .into_cow() + entry_point: ptr_into_label(descriptor.vertex.entryPoint) .expect("invalid entry point for vertex state"), }, buffers: Cow::Owned( @@ -2222,8 +2223,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .as_ref() .expect("invalid fragment shader module for render pipeline descriptor") .id, - entry_point: OwnedLabel::new(fragment.entryPoint) - .into_cow() + entry_point: ptr_into_label(fragment.entryPoint) .expect("invalid entry point for fragment state"), }, targets: Cow::Owned( @@ -2292,7 +2292,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateSampler( let desc = match descriptor { Some(descriptor) => wgc::resource::SamplerDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), address_modes: [ conv::map_address_mode(descriptor.addressModeU), conv::map_address_mode(descriptor.addressModeV), @@ -2358,7 +2358,6 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( }; let descriptor = descriptor.expect("invalid descriptor"); - let label = OwnedLabel::new(descriptor.label); let source = follow_chain!( map_shader_module(descriptor, WGPUSType_ShaderModuleSPIRVDescriptor => native::WGPUShaderModuleSPIRVDescriptor, @@ -2367,7 +2366,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( ); let desc = wgc::pipeline::ShaderModuleDescriptor { - label: label.as_cow(), + label: ptr_into_label(descriptor.label), shader_bound_checks: wgt::ShaderBoundChecks::default(), }; let (shader_module_id, error) = @@ -2432,7 +2431,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateTexture( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgt::TextureDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), size: conv::map_extent3d(&descriptor.size), mip_level_count: descriptor.mipLevelCount, sample_count: descriptor.sampleCount, @@ -2871,7 +2870,7 @@ pub unsafe extern "C" fn wgpuQueueSubmit( command_buffer.open.store(false, atomic::Ordering::SeqCst); command_buffer.id }) - .collect::>(); + .collect::>(); if let Err(cause) = gfx_select!(queue_id => context.queue_submit(queue_id, &command_buffers)) { handle_error_fatal(context, cause, "wgpuQueueSubmit"); @@ -3051,7 +3050,7 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderFinish( let desc = match descriptor { Some(descriptor) => wgt::RenderBundleDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), }, None => wgt::RenderBundleDescriptor::default(), }; @@ -3335,7 +3334,7 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderExecuteBundles( let bundle_ids = make_slice(bundles, bundle_count) .iter() .map(|v| v.as_ref().expect("invalid render bundle").id) - .collect::>(); + .collect::>(); let mut encoder = pass.encoder.write(); render_ffi::wgpu_render_pass_execute_bundles( @@ -3766,7 +3765,7 @@ pub unsafe extern "C" fn wgpuTextureCreateView( let desc = match descriptor { Some(descriptor) => wgc::resource::TextureViewDescriptor { - label: OwnedLabel::new(descriptor.label).into_cow(), + label: ptr_into_label(descriptor.label), format: conv::map_texture_format(descriptor.format), dimension: conv::map_texture_view_dimension(descriptor.dimension), range: wgt::ImageSubresourceRange { @@ -3926,7 +3925,7 @@ pub unsafe extern "C" fn wgpuQueueSubmitForIndex( command_buffer.open.store(false, atomic::Ordering::SeqCst); command_buffer.id }) - .collect::>(); + .collect::>(); match gfx_select!(queue_id => context.queue_submit(queue_id, &command_buffers)) { Ok(submission_index) => submission_index.index, diff --git a/src/utils.rs b/src/utils.rs index 69205c2e..44b9f5a2 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,48 +1,56 @@ -use std::borrow::Cow; +use std::{ + borrow::Cow, + ffi::CStr, + path::{Path, PathBuf}, +}; -pub struct Userdata(*mut std::ffi::c_void); +// A dummy wrapper that is `Send` + `Sync` to store userdata pointer +// to be usable across Rust callbacks. +pub(crate) struct Userdata(*mut std::ffi::c_void); impl Userdata { - pub const fn new(userdata: *mut std::ffi::c_void) -> Userdata { + #[inline] + pub(crate) const fn new(userdata: *mut std::ffi::c_void) -> Userdata { Userdata(userdata) } - pub fn as_ptr(&self) -> *mut std::ffi::c_void { + #[inline] + pub(crate) fn as_ptr(&self) -> *mut std::ffi::c_void { self.0 } } - unsafe impl Send for Userdata {} unsafe impl Sync for Userdata {} -pub struct OwnedLabel(Option); -impl OwnedLabel { - pub unsafe fn new(ptr: *const std::os::raw::c_char) -> Self { - Self(if ptr.is_null() { - None - } else { - Some( - unsafe { std::ffi::CStr::from_ptr(ptr) } - .to_string_lossy() - .to_string(), - ) - }) - } - pub fn into_inner(self) -> Option { - self.0 - } - pub fn as_cow(&self) -> Option> { - self.0.as_ref().map(|s| Cow::Borrowed(s.as_str())) - } - pub fn into_cow<'a>(self) -> Option> { - self.0.map(Cow::Owned) - } +#[inline] +pub(crate) fn ptr_into_label<'a>(ptr: *const std::ffi::c_char) -> wgc::Label<'a> { + unsafe { ptr.as_ref() }.and_then(|ptr| { + unsafe { CStr::from_ptr(ptr) } + .to_str() + .ok() + .map(Cow::Borrowed) + }) +} +#[inline] +pub(crate) fn ptr_into_path<'a>(ptr: *const std::ffi::c_char) -> Option<&'a std::path::Path> { + unsafe { ptr.as_ref() } + .and_then(|v| unsafe { CStr::from_ptr(v) }.to_str().ok()) + .map(Path::new) +} +#[inline] +pub(crate) fn ptr_into_pathbuf(ptr: *const std::ffi::c_char) -> Option { + unsafe { ptr.as_ref() } + .and_then(|v| unsafe { CStr::from_ptr(v) }.to_str().ok()) + .map(PathBuf::from) } -pub unsafe fn make_slice<'a, T: 'a>(pointer: *const T, count: usize) -> &'a [T] { - if count == 0 { +// Safer wrapper around `slice::from_raw_parts` to handle +// invalid `ptr` when `len` is zero. +#[inline] +pub(crate) fn make_slice<'a, T: 'a>(ptr: *const T, len: usize) -> &'a [T] { + if len == 0 { &[] } else { - std::slice::from_raw_parts(pointer, count) + unsafe { std::slice::from_raw_parts(ptr, len) } } }