From 2baea098e974fe2a7af8c02b0ec4bc4ec3dc4bac Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 19 Sep 2024 16:58:54 +0200 Subject: [PATCH 01/18] Update library to latest webgpu-native headers This goes up to https://github.com/webgpu-native/webgpu-headers/commit/2b5974750be7b2545d842ecec02e585022081952 Things I *didn't* do: * I didn't update the library to make sure "instance dropped" callback error codes are guaranteed to happen, like they seem to be in Dawn. List of changes (roughly in order of header commits): Various enum and struct renames Updated callbacks to use the new *CallbackInfo structs and 2-userdata system. Also updated functions to return WGPUFuture, though the WGPUFuture thing is just stubbed out at the moment as I don't think wgpu-core has the necessary functionality for it. wgpuInstanceWaitAny is unimplemented!() DepthClipControl merged into PrimitiveState, related code simplified. Updated depthWriteEnabled to use an optional bool, mostly matters due to added validation. Add TODOs for missing features (sliced 3D compressed textures) *Reference() became *AddRef() Added unorm10-10-10-2 vertex format Usage field in TextureViewDescriptor, just used for validation as wgpu-core doesn't allow specifying it anyways. Removed maxInterStageShaderComponents Added clang_macro_fallback to bindgen config, since the headers switched to using UINT32_MAX etc. UINT64_MAX still doesn't work so I had to manually define those. Renamed flags enums. Added a conversion helper function to convert them from u64 -> u32 for mapping. (means added direct dependency on bitflags crate) Removed device argument from (unimplemented) wgpuGetProcAddress Suboptimal surface texture acquisition moved to enum return value, was easy since wgpu-core already returns it like that. "Undefined" present mode added, it just selects FIFO. --- Cargo.lock | 1 + Cargo.toml | 1 + build.rs | 3 +- ffi/webgpu-headers | 2 +- ffi/wgpu.h | 4 +- src/conv.rs | 73 ++++---- src/lib.rs | 392 +++++++++++++++++++++++++------------------ src/unimplemented.rs | 26 +-- src/utils.rs | 34 +++- 9 files changed, 320 insertions(+), 216 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bcaa1d64..9cd70b15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1025,6 +1025,7 @@ name = "wgpu-native" version = "0.0.0" dependencies = [ "bindgen", + "bitflags 2.6.0", "log", "naga", "parking_lot", diff --git a/Cargo.toml b/Cargo.toml index bf7ebdd2..406947bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,6 +157,7 @@ log = "0.4" thiserror = "1" parking_lot = "0.12" smallvec = "1" +bitflags = "2.6.0" [build-dependencies] bindgen = "0.70" diff --git a/build.rs b/build.rs index b26a4f19..3a3abaf6 100644 --- a/build.rs +++ b/build.rs @@ -41,7 +41,8 @@ fn main() { .prepend_enum_name(false) .size_t_is_usize(true) .ignore_functions() - .layout_tests(true); + .layout_tests(true) + .clang_macro_fallback(); for (old_name, new_name) in types_to_rename { let line = format!("pub type {old_name} = *const crate::{new_name};"); diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index 043af6c7..2b597475 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit 043af6c77e566f707db36759d9c9f161ebb616fd +Subproject commit 2b5974750be7b2545d842ecec02e585022081952 diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 28a51f62..a3918a01 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -151,7 +151,7 @@ typedef struct WGPUSupportedLimitsExtras { } WGPUSupportedLimitsExtras; typedef struct WGPUPushConstantRange { - WGPUShaderStageFlags stages; + WGPUShaderStage stages; uint32_t start; uint32_t end; } WGPUPushConstantRange; @@ -281,7 +281,7 @@ void wgpuSetLogLevel(WGPULogLevel level); uint32_t wgpuGetVersion(void); -void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStageFlags stages, uint32_t offset, uint32_t sizeBytes, void const * data); +void wgpuRenderPassEncoderSetPushConstants(WGPURenderPassEncoder encoder, WGPUShaderStage stages, uint32_t offset, uint32_t sizeBytes, void const * data); void wgpuRenderPassEncoderMultiDrawIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count); void wgpuRenderPassEncoderMultiDrawIndexedIndirect(WGPURenderPassEncoder encoder, WGPUBuffer buffer, uint64_t offset, uint32_t count); diff --git a/src/conv.rs b/src/conv.rs index 9ac434ba..c8267191 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -1,5 +1,5 @@ use crate::utils::{make_slice, ptr_into_label, ptr_into_pathbuf}; -use crate::{follow_chain, map_enum}; +use crate::{follow_chain, map_enum, new_userdata}; use crate::{native, UncapturedErrorCallback}; use std::num::{NonZeroIsize, NonZeroU32, NonZeroU64}; use std::ptr::NonNull; @@ -164,7 +164,8 @@ map_enum!( Sint32, Sint32x2, Sint32x3, - Sint32x4 + Sint32x4, + Unorm10_10_10_2 ); #[cfg(feature = "glsl")] @@ -208,9 +209,10 @@ map_enum!( ReadWrite ); -pub const WGPU_WHOLE_SIZE: ::std::os::raw::c_ulonglong = native::WGPU_WHOLE_SIZE as _; -pub const WGPU_LIMIT_U64_UNDEFINED: ::std::os::raw::c_ulonglong = - native::WGPU_LIMIT_U64_UNDEFINED as _; +// These are defined as UINT64_MAX in the header, but bindgen currently can't process that define. +// See https://github.com/rust-lang/rust-bindgen/issues/2822 +pub const WGPU_WHOLE_SIZE: u64 = u64::MAX; +pub const WGPU_LIMIT_U64_UNDEFINED: u64 = u64::MAX; // it's SIZE_MAX in headers but it's not available in some compilers pub const WGPU_WHOLE_MAP_SIZE: usize = usize::MAX; @@ -338,7 +340,7 @@ pub(crate) fn map_device_descriptor<'a>( None => None, callback => Some(UncapturedErrorCallback { callback, - userdata: des.uncapturedErrorCallbackInfo.userdata, + userdata: new_userdata!(des.uncapturedErrorCallbackInfo), }), }, ) @@ -363,7 +365,7 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( make_slice(extras.pushConstantRanges, extras.pushConstantRangeCount) .iter() .map(|range| wgt::PushConstantRange { - stages: wgt::ShaderStages::from_bits(range.stages) + stages: from_u64_bits(range.stages) .expect("invalid shader stage for push constant range"), range: range.start..range.end, }) @@ -408,7 +410,6 @@ pub fn write_limits_struct( limits.maxVertexBufferArrayStride = wgt_limits.max_vertex_buffer_array_stride; limits.minUniformBufferOffsetAlignment = wgt_limits.min_uniform_buffer_offset_alignment; limits.minStorageBufferOffsetAlignment = wgt_limits.min_storage_buffer_offset_alignment; - 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 @@ -494,10 +495,10 @@ pub fn map_required_limits( if limits.maxUniformBuffersPerShaderStage != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_uniform_buffers_per_shader_stage = limits.maxUniformBuffersPerShaderStage; } - if limits.maxUniformBufferBindingSize != native::WGPU_LIMIT_U64_UNDEFINED as u64 { + if limits.maxUniformBufferBindingSize != WGPU_LIMIT_U64_UNDEFINED { wgt_limits.max_uniform_buffer_binding_size = limits.maxUniformBufferBindingSize as u32; } - if limits.maxStorageBufferBindingSize != native::WGPU_LIMIT_U64_UNDEFINED as u64 { + if limits.maxStorageBufferBindingSize != WGPU_LIMIT_U64_UNDEFINED { wgt_limits.max_storage_buffer_binding_size = limits.maxStorageBufferBindingSize as u32; } if limits.minUniformBufferOffsetAlignment != native::WGPU_LIMIT_U32_UNDEFINED { @@ -509,7 +510,7 @@ pub fn map_required_limits( if limits.maxVertexBuffers != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_vertex_buffers = limits.maxVertexBuffers; } - if limits.maxBufferSize != native::WGPU_LIMIT_U64_UNDEFINED as u64 { + if limits.maxBufferSize != WGPU_LIMIT_U64_UNDEFINED { wgt_limits.max_buffer_size = limits.maxBufferSize; } if limits.maxVertexAttributes != native::WGPU_LIMIT_U32_UNDEFINED { @@ -518,9 +519,6 @@ pub fn map_required_limits( if limits.maxVertexBufferArrayStride != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_vertex_buffer_array_stride = limits.maxVertexBufferArrayStride; } - if limits.maxInterStageShaderComponents != native::WGPU_LIMIT_U32_UNDEFINED { - wgt_limits.max_inter_stage_shader_components = limits.maxInterStageShaderComponents; - } // TODO: not yet in wgt // if limits.maxInterStageShaderVariables != native::WGPU_LIMIT_U32_UNDEFINED { // wgt_limits.max_inter_stage_shader_variables = limits.maxInterStageShaderVariables; @@ -576,8 +574,8 @@ pub enum ShaderParseError { #[inline] pub fn map_shader_module<'a>( _: &native::WGPUShaderModuleDescriptor, - spirv: Option<&native::WGPUShaderModuleSPIRVDescriptor>, - wgsl: Option<&native::WGPUShaderModuleWGSLDescriptor>, + spirv: Option<&native::WGPUShaderSourceSPIRV>, + wgsl: Option<&native::WGPUShaderSourceWGSL>, glsl: Option<&native::WGPUShaderModuleGLSLDescriptor>, ) -> Result, ShaderParseError> { #[cfg(feature = "wgsl")] @@ -975,18 +973,6 @@ pub fn map_stencil_face_state( } } -#[inline] -pub fn map_primitive_state( - _: &native::WGPUPrimitiveState, - depth_clip_control: Option<&native::WGPUPrimitiveDepthClipControl>, -) -> bool { - if let Some(depth_clip_control) = depth_clip_control { - return depth_clip_control.unclippedDepth != 0; - } - - false -} - #[inline] pub fn map_storage_report(report: &wgc::registry::RegistryReport) -> native::WGPURegistryReport { native::WGPURegistryReport { @@ -1230,8 +1216,10 @@ pub fn map_feature(feature: native::WGPUFeatureName) -> Option { native::WGPUFeatureName_DepthClipControl => Some(Features::DEPTH_CLIP_CONTROL), native::WGPUFeatureName_Depth32FloatStencil8 => Some(Features::DEPTH32FLOAT_STENCIL8), native::WGPUFeatureName_TextureCompressionBC => Some(Features::TEXTURE_COMPRESSION_BC), + // TODO: WGPUFeatureName_TextureCompressionBCSliced3D native::WGPUFeatureName_TextureCompressionETC2 => Some(Features::TEXTURE_COMPRESSION_ETC2), native::WGPUFeatureName_TextureCompressionASTC => Some(Features::TEXTURE_COMPRESSION_ASTC), + // TODO: WGPUFeatureName_TextureCompressionASTCSliced3D native::WGPUFeatureName_TimestampQuery => Some(Features::TIMESTAMP_QUERY), native::WGPUFeatureName_IndirectFirstInstance => Some(Features::INDIRECT_FIRST_INSTANCE), native::WGPUFeatureName_ShaderF16 => Some(Features::SHADER_F16), @@ -1476,7 +1464,7 @@ pub fn map_bind_group_layout_entry( wgt::BindGroupLayoutEntry { ty, binding: entry.binding, - visibility: wgt::ShaderStages::from_bits(entry.visibility) + visibility: from_u64_bits(entry.visibility) .expect("invalid visibility for bind group layout entry"), count: extras.and_then(|v| NonZeroU32::new(v.count)), } @@ -1582,12 +1570,12 @@ pub enum CreateSurfaceParams { pub unsafe fn map_surface( _: &native::WGPUSurfaceDescriptor, - win: Option<&native::WGPUSurfaceDescriptorFromWindowsHWND>, - xcb: Option<&native::WGPUSurfaceDescriptorFromXcbWindow>, - xlib: Option<&native::WGPUSurfaceDescriptorFromXlibWindow>, - wl: Option<&native::WGPUSurfaceDescriptorFromWaylandSurface>, - _metal: Option<&native::WGPUSurfaceDescriptorFromMetalLayer>, - android: Option<&native::WGPUSurfaceDescriptorFromAndroidNativeWindow>, + win: Option<&native::WGPUSurfaceSourceWindowsHWND>, + xcb: Option<&native::WGPUSurfaceSourceXCBWindow>, + xlib: Option<&native::WGPUSurfaceSourceXlibWindow>, + wl: Option<&native::WGPUSurfaceSourceWaylandSurface>, + _metal: Option<&native::WGPUSurfaceSourceMetalLayer>, + android: Option<&native::WGPUSurfaceSourceAndroidNativeWindow>, ) -> CreateSurfaceParams { if let Some(win) = win { let display_handle = raw_window_handle::WindowsDisplayHandle::new(); @@ -1660,13 +1648,18 @@ pub fn map_surface_configuration( config: &native::WGPUSurfaceConfiguration, extras: Option<&native::WGPUSurfaceConfigurationExtras>, ) -> wgt::SurfaceConfiguration> { + let present_mode = match config.presentMode { + native::WGPUPresentMode_Undefined => wgt::PresentMode::Fifo, + _ => map_present_mode(config.presentMode), + }; + wgt::SurfaceConfiguration { usage: map_texture_usage_flags(config.usage as native::WGPUTextureUsage), format: map_texture_format(config.format) .expect("invalid format for surface configuration"), width: config.width, height: config.height, - present_mode: map_present_mode(config.presentMode), + present_mode, alpha_mode: map_composite_alpha_mode(config.alphaMode) .expect("invalid alpha mode for surface configuration"), view_formats: make_slice(config.viewFormats, config.viewFormatCount) @@ -1701,3 +1694,11 @@ pub fn map_adapter_type(device_type: wgt::DeviceType) -> native::WGPUAdapterType wgt::DeviceType::Cpu => native::WGPUAdapterType_CPU, } } + +pub fn from_u64_bits>(value: u64) -> Option { + if value > u32::MAX.into() { + return None; + } + + T::from_bits(value as u32) +} diff --git a/src/lib.rs b/src/lib.rs index 21911150..095545dd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,7 @@ use conv::{ - map_adapter_type, map_backend_type, map_bind_group_entry, map_bind_group_layout_entry, - map_device_descriptor, map_instance_backend_flags, map_instance_descriptor, - map_pipeline_layout_descriptor, map_primitive_state, map_query_set_descriptor, + from_u64_bits, map_adapter_type, map_backend_type, map_bind_group_entry, + map_bind_group_layout_entry, map_device_descriptor, map_instance_backend_flags, + map_instance_descriptor, map_pipeline_layout_descriptor, map_query_set_descriptor, map_query_set_index, map_shader_module, map_surface, map_surface_configuration, CreateSurfaceParams, }; @@ -19,6 +19,7 @@ use std::{ }; use utils::{ get_base_device_limits_from_adapter_limits, make_slice, ptr_into_label, ptr_into_path, + texture_format_has_depth, }; use wgc::{ command::{bundle_ffi, DynComputePass, DynRenderPass}, @@ -80,7 +81,7 @@ impl Drop for WGPUBindGroupLayoutImpl { } struct BufferData { - usage: native::WGPUBufferUsageFlags, + usage: native::WGPUBufferUsage, size: u64, } pub struct WGPUBufferImpl { @@ -343,7 +344,7 @@ impl Drop for WGPUSurfaceImpl { #[derive(Copy, Clone)] struct TextureData { - usage: native::WGPUTextureUsageFlags, + usage: native::WGPUTextureUsage, dimension: native::WGPUTextureDimension, size: native::WGPUExtent3D, format: native::WGPUTextureFormat, @@ -396,19 +397,23 @@ impl Drop for WGPUTextureViewImpl { } } +const NULL_FUTURE: native::WGPUFuture = native::WGPUFuture { id: 0 }; + struct DeviceCallback { callback: T, - userdata: *mut std::os::raw::c_void, + userdata: utils::Userdata, } unsafe impl Send for DeviceCallback {} -type UncapturedErrorCallback = DeviceCallback; +type UncapturedErrorCallback = DeviceCallback; type DeviceLostCallback = DeviceCallback; unsafe extern "C" fn default_uncaptured_error_handler( + _device: *const native::WGPUDevice, _typ: native::WGPUErrorType, message: *const ::std::os::raw::c_char, - _userdata: *mut ::std::os::raw::c_void, + _userdata1: *mut ::std::os::raw::c_void, + _userdata2: *mut ::std::os::raw::c_void, ) { let message = unsafe { CStr::from_ptr(message) }.to_str().unwrap(); log::warn!("Handling wgpu uncaptured errors as fatal by default"); @@ -416,13 +421,15 @@ unsafe extern "C" fn default_uncaptured_error_handler( } const DEFAULT_UNCAPTURED_ERROR_HANDLER: UncapturedErrorCallback = UncapturedErrorCallback { callback: Some(default_uncaptured_error_handler), - userdata: std::ptr::null_mut(), + userdata: utils::Userdata::NULL, }; unsafe extern "C" fn default_device_lost_handler( + _device: *const native::WGPUDevice, _reason: native::WGPUDeviceLostReason, message: *const ::std::os::raw::c_char, - _userdata: *mut ::std::os::raw::c_void, + _userdata1: *mut ::std::os::raw::c_void, + _userdata2: *mut ::std::os::raw::c_void, ) { let message = unsafe { CStr::from_ptr(message) }.to_str().unwrap(); log::warn!("Handling wgpu device lost errors as fatal by default"); @@ -430,7 +437,7 @@ unsafe extern "C" fn default_device_lost_handler( } const DEFAULT_DEVICE_LOST_HANDLER: DeviceLostCallback = DeviceLostCallback { callback: Some(default_device_lost_handler), - userdata: std::ptr::null_mut(), + userdata: utils::Userdata::NULL, }; #[derive(Debug)] @@ -486,6 +493,7 @@ struct ErrorSinkRaw { scopes: Vec, uncaptured_handler: UncapturedErrorCallback, device_lost_handler: DeviceLostCallback, + device: Option, } impl ErrorSinkRaw { @@ -494,6 +502,7 @@ impl ErrorSinkRaw { scopes: Vec::new(), uncaptured_handler: DEFAULT_UNCAPTURED_ERROR_HANDLER, device_lost_handler, + device: None, } } @@ -502,13 +511,15 @@ impl ErrorSinkRaw { crate::Error::DeviceLost { .. } => { // handle device lost error early if let Some(callback) = self.device_lost_handler.callback { - let userdata = self.device_lost_handler.userdata; + let userdata = &self.device_lost_handler.userdata; let msg = CString::new(err.to_string()).unwrap(); unsafe { callback( + &self.device.unwrap(), native::WGPUDeviceLostReason_Destroyed, msg.as_ptr(), - userdata, + userdata.get_1(), + userdata.get_2(), ); }; } @@ -537,9 +548,17 @@ impl ErrorSinkRaw { } None => { if let Some(callback) = self.uncaptured_handler.callback { - let userdata = self.uncaptured_handler.userdata; + let userdata = &self.uncaptured_handler.userdata; let msg = CString::new(err.to_string()).unwrap(); - unsafe { callback(typ, msg.as_ptr(), userdata) }; + unsafe { + callback( + &self.device.unwrap(), + typ, + msg.as_ptr(), + userdata.get_1(), + userdata.get_2(), + ) + }; } } } @@ -751,14 +770,13 @@ pub unsafe extern "C" fn wgpuAdapterInfoFreeMembers(adapter_info: native::WGPUAd pub unsafe extern "C" fn wgpuAdapterRequestDevice( adapter: native::WGPUAdapter, descriptor: Option<&native::WGPUDeviceDescriptor>, - callback: native::WGPUAdapterRequestDeviceCallback, - userdata: *mut std::os::raw::c_void, -) { + callback_info: native::WGPURequestDeviceCallbackInfo, +) -> native::WGPUFuture { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); (adapter.id, &adapter.context) }; - let callback = callback.expect("invalid callback"); + let callback = callback_info.callback.expect("invalid callback"); let adapter_limits = match gfx_select!(adapter_id => context.adapter_limits(adapter_id)) { Ok(adapter_limits) => adapter_limits, @@ -768,9 +786,10 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( native::WGPURequestDeviceStatus_Error, std::ptr::null(), msg.as_ptr(), - userdata, + callback_info.userdata1, + callback_info.userdata2, ); - return; + return NULL_FUTURE; } }; let base_limits = get_base_device_limits_from_adapter_limits(&adapter_limits); @@ -782,8 +801,8 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( WGPUSType_DeviceExtras => native::WGPUDeviceExtras) ); let device_lost_handler = DeviceLostCallback { - callback: descriptor.deviceLostCallback, - userdata: descriptor.deviceLostUserdata, + callback: descriptor.deviceLostCallbackInfo.callback, + userdata: new_userdata!(descriptor.deviceLostCallbackInfo), }; (desc, trace_str, device_lost_handler, error_callback) } @@ -815,19 +834,24 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( error_sink.uncaptured_handler = error_callback; } + let error_sink = Arc::new(Mutex::new(error_sink)); + let device = Arc::into_raw(Arc::new(WGPUDeviceImpl { + context: context.clone(), + id: device_id, + queue: Arc::new(QueueId { + context: context.clone(), + id: queue_id, + }), + error_sink: error_sink.clone(), + })); + error_sink.lock().device = Some(device); + callback( native::WGPURequestDeviceStatus_Success, - Arc::into_raw(Arc::new(WGPUDeviceImpl { - context: context.clone(), - id: device_id, - queue: Arc::new(QueueId { - context: context.clone(), - id: queue_id, - }), - error_sink: Arc::new(Mutex::new(error_sink)), - })), + device, message.as_ptr(), - userdata, + callback_info.userdata1, + callback_info.userdata2, ); } Some(err) => { @@ -836,14 +860,17 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( native::WGPURequestDeviceStatus_Error, std::ptr::null_mut(), message.as_ptr(), - userdata, + callback_info.userdata1, + callback_info.userdata2, ); } - } + }; + + return NULL_FUTURE; } #[no_mangle] -pub unsafe extern "C" fn wgpuAdapterReference(adapter: native::WGPUAdapter) { +pub unsafe extern "C" fn wgpuAdapterAddRef(adapter: native::WGPUAdapter) { assert!(!adapter.is_null(), "invalid adapter"); Arc::increment_strong_count(adapter); } @@ -856,7 +883,7 @@ pub unsafe extern "C" fn wgpuAdapterRelease(adapter: native::WGPUAdapter) { // BindGroup methods #[no_mangle] -pub unsafe extern "C" fn wgpuBindGroupReference(bind_group: native::WGPUBindGroup) { +pub unsafe extern "C" fn wgpuBindGroupAddRef(bind_group: native::WGPUBindGroup) { assert!(!bind_group.is_null(), "invalid bind group"); Arc::increment_strong_count(bind_group); } @@ -869,9 +896,7 @@ pub unsafe extern "C" fn wgpuBindGroupRelease(bind_group: native::WGPUBindGroup) // BindGroupLayout methods #[no_mangle] -pub unsafe extern "C" fn wgpuBindGroupLayoutReference( - bind_group_layout: native::WGPUBindGroupLayout, -) { +pub unsafe extern "C" fn wgpuBindGroupLayoutAddRef(bind_group_layout: native::WGPUBindGroupLayout) { assert!(!bind_group_layout.is_null(), "invalid bind group layout"); Arc::increment_strong_count(bind_group_layout); } @@ -954,9 +979,7 @@ pub unsafe extern "C" fn wgpuBufferGetSize(buffer: native::WGPUBuffer) -> u64 { } #[no_mangle] -pub unsafe extern "C" fn wgpuBufferGetUsage( - buffer: native::WGPUBuffer, -) -> native::WGPUBufferUsageFlags { +pub unsafe extern "C" fn wgpuBufferGetUsage(buffer: native::WGPUBuffer) -> native::WGPUBufferUsage { let buffer = buffer.as_ref().expect("invalid buffer"); buffer.data.usage } @@ -964,18 +987,17 @@ pub unsafe extern "C" fn wgpuBufferGetUsage( #[no_mangle] pub unsafe extern "C" fn wgpuBufferMapAsync( buffer: native::WGPUBuffer, - mode: native::WGPUMapModeFlags, + mode: native::WGPUMapMode, offset: usize, size: usize, - callback: native::WGPUBufferMapAsyncCallback, - userdata: *mut std::ffi::c_void, -) { + callback_info: native::WGPUBufferMapCallbackInfo, +) -> native::WGPUFuture { let (buffer_id, context, error_sink) = { let buffer = buffer.as_ref().expect("invalid buffer"); (buffer.id, &buffer.context, &buffer.error_sink) }; - let callback = callback.expect("invalid callback"); - let userdata = utils::Userdata::new(userdata); + let callback = callback_info.callback.expect("invalid callback"); + let userdata = new_userdata!(callback_info); let operation = wgc::resource::BufferMapOperation { host: match mode as native::WGPUMapMode { @@ -985,24 +1007,29 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( }, callback: Some(wgc::resource::BufferMapCallback::from_rust(Box::new( move |result: resource::BufferAccessResult| { - let status = match result { - Ok(()) => native::WGPUBufferMapAsyncStatus_Success, - Err(resource::BufferAccessError::Device(_)) => { - native::WGPUBufferMapAsyncStatus_DeviceLost - } - Err(resource::BufferAccessError::MapAlreadyPending) => { - native::WGPUBufferMapAsyncStatus_MappingAlreadyPending + let (status, message) = match result { + Ok(()) => (native::WGPUBufferMapAsyncStatus_Success, CString::default()), + Err(cause) => { + let code = match cause { + resource::BufferAccessError::Device(_) => { + native::WGPUBufferMapAsyncStatus_DeviceLost + } + resource::BufferAccessError::MapAlreadyPending => { + native::WGPUBufferMapAsyncStatus_MappingAlreadyPending + } + resource::BufferAccessError::InvalidBufferId(_) + | resource::BufferAccessError::DestroyedResource(_) => { + native::WGPUBufferMapAsyncStatus_DestroyedBeforeCallback + } + _ => native::WGPUBufferMapAsyncStatus_ValidationError, // TODO: WGPUBufferMapAsyncStatus_OffsetOutOfRange + // TODO: WGPUBufferMapAsyncStatus_SizeOutOfRange + }; + + (code, CString::new(format_error(&cause)).unwrap()) } - Err(resource::BufferAccessError::InvalidBufferId(_)) - | Err(resource::BufferAccessError::DestroyedResource(_)) => { - native::WGPUBufferMapAsyncStatus_DestroyedBeforeCallback - } - Err(_) => native::WGPUBufferMapAsyncStatus_ValidationError, - // TODO: WGPUBufferMapAsyncStatus_OffsetOutOfRange - // TODO: WGPUBufferMapAsyncStatus_SizeOutOfRange }; - callback(status, userdata.as_ptr()); + callback(status, message.as_ptr(), userdata.get_1(), userdata.get_2()); }, ))), }; @@ -1015,6 +1042,9 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( )) { handle_error(error_sink, cause, None, "wgpuBufferMapAsync"); }; + + // TODO: Properly handle futures. + return NULL_FUTURE; } #[no_mangle] @@ -1030,7 +1060,7 @@ pub unsafe extern "C" fn wgpuBufferUnmap(buffer: native::WGPUBuffer) { } #[no_mangle] -pub unsafe extern "C" fn wgpuBufferReference(buffer: native::WGPUBuffer) { +pub unsafe extern "C" fn wgpuBufferAddRef(buffer: native::WGPUBuffer) { assert!(!buffer.is_null(), "invalid buffer"); Arc::increment_strong_count(buffer); } @@ -1043,7 +1073,7 @@ pub unsafe extern "C" fn wgpuBufferRelease(buffer: native::WGPUBuffer) { // CommandBuffer methods #[no_mangle] -pub unsafe extern "C" fn wgpuCommandBufferReference(command_buffer: native::WGPUCommandBuffer) { +pub unsafe extern "C" fn wgpuCommandBufferAddRef(command_buffer: native::WGPUCommandBuffer) { assert!(!command_buffer.is_null(), "invalid command buffer"); Arc::increment_strong_count(command_buffer); } @@ -1526,7 +1556,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderWriteTimestamp( } #[no_mangle] -pub unsafe extern "C" fn wgpuCommandEncoderReference(command_encoder: native::WGPUCommandEncoder) { +pub unsafe extern "C" fn wgpuCommandEncoderAddRef(command_encoder: native::WGPUCommandEncoder) { assert!(!command_encoder.is_null(), "invalid command encoder"); Arc::increment_strong_count(command_encoder); } @@ -1715,7 +1745,7 @@ pub unsafe extern "C" fn wgpuComputePassEncoderSetPipeline( } #[no_mangle] -pub unsafe extern "C" fn wgpuComputePassEncoderReference( +pub unsafe extern "C" fn wgpuComputePassEncoderAddRef( compute_pass_encoder: native::WGPUComputePassEncoder, ) { assert!( @@ -1764,9 +1794,7 @@ pub unsafe extern "C" fn wgpuComputePipelineGetBindGroupLayout( } #[no_mangle] -pub unsafe extern "C" fn wgpuComputePipelineReference( - compute_pipeline: native::WGPUComputePipeline, -) { +pub unsafe extern "C" fn wgpuComputePipelineAddRef(compute_pipeline: native::WGPUComputePipeline) { assert!(!compute_pipeline.is_null(), "invalid command pipeline"); Arc::increment_strong_count(compute_pipeline); } @@ -1875,7 +1903,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBuffer( let desc = wgt::BufferDescriptor { label: ptr_into_label(descriptor.label), size: descriptor.size, - usage: wgt::BufferUsages::from_bits(descriptor.usage).expect("invalid buffer usage"), + usage: from_u64_bits(descriptor.usage).expect("invalid buffer usage"), mapped_at_creation: descriptor.mappedAtCreation != 0, }; @@ -2190,22 +2218,28 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( native::WGPUCullMode_Back => Some(wgt::Face::Back), _ => panic!("invalid cull mode for primitive state"), }, - unclipped_depth: follow_chain!( - map_primitive_state( - (&descriptor.primitive), - WGPUSType_PrimitiveDepthClipControl => native::WGPUPrimitiveDepthClipControl - ) - ), + unclipped_depth: descriptor.primitive.unclippedDepth != 0, polygon_mode: wgt::PolygonMode::Fill, conservative: false, }, - depth_stencil: descriptor - .depthStencil - .as_ref() - .map(|desc| wgt::DepthStencilState { - format: conv::map_texture_format(desc.format) - .expect("invalid texture format for depth stencil state"), - depth_write_enabled: desc.depthWriteEnabled != 0, + depth_stencil: descriptor.depthStencil.as_ref().map(|desc| { + let format = conv::map_texture_format(desc.format) + .expect("invalid texture format for depth stencil state"); + + // Validation per spec. + if texture_format_has_depth(format) { + if desc.depthWriteEnabled == native::WGPUOptionalBool_Undefined { + panic!("Depth write not specified for depth format") + } + } else { + if desc.depthWriteEnabled == native::WGPUOptionalBool_True { + panic!("Depth write enabled for non-depth format") + } + } + + wgt::DepthStencilState { + format, + depth_write_enabled: desc.depthWriteEnabled == native::WGPUOptionalBool_True, depth_compare: conv::map_compare_function(desc.depthCompare) .expect("invalid depth compare function for depth stencil state"), stencil: wgt::StencilState { @@ -2219,7 +2253,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( slope_scale: desc.depthBiasSlopeScale, clamp: desc.depthBiasClamp, }, - }), + } + }), multisample: wgt::MultisampleState { count: descriptor.multisample.count, mask: descriptor.multisample.mask as u64, @@ -2266,8 +2301,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( alpha: conv::map_blend_component(blend.alpha), } }), - write_mask: wgt::ColorWrites::from_bits(color_target.writeMask) - .unwrap(), + write_mask: from_u64_bits(color_target.writeMask).unwrap(), } }) }) @@ -2380,8 +2414,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( let source = match follow_chain!( map_shader_module((descriptor), - WGPUSType_ShaderModuleSPIRVDescriptor => native::WGPUShaderModuleSPIRVDescriptor, - WGPUSType_ShaderModuleWGSLDescriptor => native::WGPUShaderModuleWGSLDescriptor, + WGPUSType_ShaderSourceSPIRV => native::WGPUShaderSourceSPIRV, + WGPUSType_ShaderSourceWGSL => native::WGPUShaderSourceWGSL, WGPUSType_ShaderModuleGLSLDescriptor => native::WGPUShaderModuleGLSLDescriptor) ) { Ok(source) => source, @@ -2435,7 +2469,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateTexture( dimension: conv::map_texture_dimension(descriptor.dimension), format: conv::map_texture_format(descriptor.format) .expect("invalid texture format for texture descriptor"), - usage: wgt::TextureUsages::from_bits(descriptor.usage) + usage: from_u64_bits(descriptor.usage) .expect("invalid texture usage for texture descriptor"), view_formats: make_slice(descriptor.viewFormats, descriptor.viewFormatCount) .iter() @@ -2554,11 +2588,10 @@ pub unsafe extern "C" fn wgpuDeviceHasFeature( #[no_mangle] pub unsafe extern "C" fn wgpuDevicePopErrorScope( device: native::WGPUDevice, - callback: native::WGPUErrorCallback, - userdata: *mut ::std::os::raw::c_void, -) { + callback_info: native::WGPUPopErrorScopeCallbackInfo, +) -> native::WGPUFuture { let device = device.as_ref().expect("invalid device"); - let callback = callback.expect("invalid callback"); + let callback = callback_info.callback.expect("invalid callback"); let mut error_sink = device.error_sink.lock(); let scope = error_sink.scopes.pop().unwrap(); @@ -2574,16 +2607,30 @@ pub unsafe extern "C" fn wgpuDevicePopErrorScope( let msg = CString::new(error.to_string()).unwrap(); unsafe { - callback(typ, msg.as_ptr(), userdata); + callback( + native::WGPUPopErrorScopeStatus_Success, + typ, + msg.as_ptr(), + callback_info.userdata1, + callback_info.userdata2, + ); }; } None => { let msg = CString::default(); unsafe { - callback(native::WGPUErrorType_NoError, msg.as_ptr(), userdata); + callback( + native::WGPUPopErrorScopeStatus_Success, + native::WGPUErrorType_NoError, + msg.as_ptr(), + callback_info.userdata1, + callback_info.userdata2, + ); }; } }; + + return NULL_FUTURE; } #[no_mangle] @@ -2604,7 +2651,7 @@ pub unsafe extern "C" fn wgpuDevicePushErrorScope( } #[no_mangle] -pub unsafe extern "C" fn wgpuDeviceReference(device: native::WGPUDevice) { +pub unsafe extern "C" fn wgpuDeviceAddRef(device: native::WGPUDevice) { assert!(!device.is_null(), "invalid device"); Arc::increment_strong_count(device); } @@ -2626,12 +2673,12 @@ pub unsafe extern "C" fn wgpuInstanceCreateSurface( let create_surface_params = follow_chain!( map_surface((descriptor), - WGPUSType_SurfaceDescriptorFromWindowsHWND => native::WGPUSurfaceDescriptorFromWindowsHWND, - WGPUSType_SurfaceDescriptorFromXcbWindow => native::WGPUSurfaceDescriptorFromXcbWindow, - WGPUSType_SurfaceDescriptorFromXlibWindow => native::WGPUSurfaceDescriptorFromXlibWindow, - WGPUSType_SurfaceDescriptorFromWaylandSurface => native::WGPUSurfaceDescriptorFromWaylandSurface, - WGPUSType_SurfaceDescriptorFromMetalLayer => native::WGPUSurfaceDescriptorFromMetalLayer, - WGPUSType_SurfaceDescriptorFromAndroidNativeWindow => native::WGPUSurfaceDescriptorFromAndroidNativeWindow) + WGPUSType_SurfaceSourceWindowsHWND => native::WGPUSurfaceSourceWindowsHWND, + WGPUSType_SurfaceSourceXCBWindow => native::WGPUSurfaceSourceXCBWindow, + WGPUSType_SurfaceSourceXlibWindow => native::WGPUSurfaceSourceXlibWindow, + WGPUSType_SurfaceSourceWaylandSurface => native::WGPUSurfaceSourceWaylandSurface, + WGPUSType_SurfaceSourceMetalLayer => native::WGPUSurfaceSourceMetalLayer, + WGPUSType_SurfaceSourceAndroidNativeWindow => native::WGPUSurfaceSourceAndroidNativeWindow) ); let surface_id = match create_surface_params { @@ -2662,12 +2709,11 @@ pub unsafe extern "C" fn wgpuInstanceCreateSurface( pub unsafe extern "C" fn wgpuInstanceRequestAdapter( instance: native::WGPUInstance, options: Option<&native::WGPURequestAdapterOptions>, - callback: native::WGPUInstanceRequestAdapterCallback, - userdata: *mut std::os::raw::c_void, -) { + callback_info: native::WGPURequestAdapterCallbackInfo, +) -> native::WGPUFuture { let instance = instance.as_ref().expect("invalid instance"); let context = &instance.context; - let callback = callback.expect("invalid callback"); + let callback = callback_info.callback.expect("invalid callback"); let (desc, inputs) = match options { Some(options) => ( @@ -2697,9 +2743,11 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( native::WGPURequestAdapterStatus_Error, std::ptr::null_mut(), "unsupported backend type: d3d11".as_ptr() as _, - userdata, + callback_info.userdata1, + callback_info.userdata2, ); - return; + + return NULL_FUTURE; } backend_type => panic!("invalid backend type: 0x{backend_type:08X}"), }, @@ -2722,7 +2770,8 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( id: adapter_id, })), message.as_ptr(), - userdata, + callback_info.userdata1, + callback_info.userdata2, ); } Err(err) => { @@ -2739,10 +2788,13 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( }, std::ptr::null_mut(), message.as_ptr(), - userdata, + callback_info.userdata1, + callback_info.userdata2, ); } }; + + return NULL_FUTURE; } #[no_mangle] @@ -2789,7 +2841,7 @@ pub unsafe extern "C" fn wgpuInstanceEnumerateAdapters( } #[no_mangle] -pub unsafe extern "C" fn wgpuInstanceReference(instance: native::WGPUInstance) { +pub unsafe extern "C" fn wgpuInstanceAddRef(instance: native::WGPUInstance) { assert!(!instance.is_null(), "invalid instance"); Arc::increment_strong_count(instance); } @@ -2802,7 +2854,7 @@ pub unsafe extern "C" fn wgpuInstanceRelease(instance: native::WGPUInstance) { // PipelineLayout methods #[no_mangle] -pub unsafe extern "C" fn wgpuPipelineLayoutReference(pipeline_layout: native::WGPUPipelineLayout) { +pub unsafe extern "C" fn wgpuPipelineLayoutAddRef(pipeline_layout: native::WGPUPipelineLayout) { assert!(!pipeline_layout.is_null(), "invalid pipeline layout"); Arc::increment_strong_count(pipeline_layout); } @@ -2834,7 +2886,7 @@ pub unsafe extern "C" fn wgpuQuerySetGetType( } #[no_mangle] -pub unsafe extern "C" fn wgpuQuerySetReference(query_set: native::WGPUQuerySet) { +pub unsafe extern "C" fn wgpuQuerySetAddRef(query_set: native::WGPUQuerySet) { assert!(!query_set.is_null(), "invalid query set"); Arc::increment_strong_count(query_set); } @@ -2849,18 +2901,21 @@ pub unsafe extern "C" fn wgpuQuerySetRelease(query_set: native::WGPUQuerySet) { #[no_mangle] pub unsafe extern "C" fn wgpuQueueOnSubmittedWorkDone( queue: native::WGPUQueue, - callback: native::WGPUQueueOnSubmittedWorkDoneCallback, - userdata: *mut ::std::os::raw::c_void, -) { + callback_info: native::WGPUQueueWorkDoneCallbackInfo, +) -> native::WGPUFuture { let (queue_id, context) = { let queue = queue.as_ref().expect("invalid queue"); (queue.queue.id, &queue.queue.context) }; - let callback = callback.expect("invalid callback"); - let userdata = utils::Userdata::new(userdata); + let callback = callback_info.callback.expect("invalid callback"); + let userdata = new_userdata!(callback_info); let closure = wgc::device::queue::SubmittedWorkDoneClosure::from_rust(Box::new(move || { - callback(native::WGPUQueueWorkDoneStatus_Success, userdata.as_ptr()); + callback( + native::WGPUQueueWorkDoneStatus_Success, + userdata.get_1(), + userdata.get_2(), + ); })); if let Err(cause) = @@ -2868,6 +2923,9 @@ pub unsafe extern "C" fn wgpuQueueOnSubmittedWorkDone( { handle_error_fatal(cause, "wgpuQueueOnSubmittedWorkDone"); }; + + // TODO: Properly handle futures. + return NULL_FUTURE; } #[no_mangle] @@ -2945,7 +3003,7 @@ pub unsafe extern "C" fn wgpuQueueWriteTexture( } #[no_mangle] -pub unsafe extern "C" fn wgpuQueueReference(queue: native::WGPUQueue) { +pub unsafe extern "C" fn wgpuQueueAddRef(queue: native::WGPUQueue) { assert!(!queue.is_null(), "invalid queue"); Arc::increment_strong_count(queue); } @@ -2958,7 +3016,7 @@ pub unsafe extern "C" fn wgpuQueueRelease(queue: native::WGPUQueue) { // RenderBundle methods #[no_mangle] -pub unsafe extern "C" fn wgpuRenderBundleReference(render_bundle: native::WGPURenderBundle) { +pub unsafe extern "C" fn wgpuRenderBundleAddRef(render_bundle: native::WGPURenderBundle) { assert!(!render_bundle.is_null(), "invalid render bundle"); Arc::increment_strong_count(render_bundle); } @@ -3217,7 +3275,7 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderSetVertexBuffer( } #[no_mangle] -pub unsafe extern "C" fn wgpuRenderBundleEncoderReference( +pub unsafe extern "C" fn wgpuRenderBundleEncoderAddRef( render_bundle_encoder: native::WGPURenderBundleEncoder, ) { assert!( @@ -3681,7 +3739,7 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderSetViewport( } #[no_mangle] -pub unsafe extern "C" fn wgpuRenderPassEncoderReference( +pub unsafe extern "C" fn wgpuRenderPassEncoderAddRef( render_pass_encoder: native::WGPURenderPassEncoder, ) { assert!( @@ -3733,7 +3791,7 @@ pub unsafe extern "C" fn wgpuRenderPipelineGetBindGroupLayout( } #[no_mangle] -pub unsafe extern "C" fn wgpuRenderPipelineReference(render_pipeline: native::WGPURenderPipeline) { +pub unsafe extern "C" fn wgpuRenderPipelineAddRef(render_pipeline: native::WGPURenderPipeline) { assert!(!render_pipeline.is_null(), "invalid render pipeline"); Arc::increment_strong_count(render_pipeline); } @@ -3746,7 +3804,7 @@ pub unsafe extern "C" fn wgpuRenderPipelineRelease(render_pipeline: native::WGPU // Sampler methods #[no_mangle] -pub unsafe extern "C" fn wgpuSamplerReference(sampler: native::WGPUSampler) { +pub unsafe extern "C" fn wgpuSamplerAddRef(sampler: native::WGPUSampler) { assert!(!sampler.is_null(), "invalid sampler"); Arc::increment_strong_count(sampler); } @@ -3759,7 +3817,7 @@ pub unsafe extern "C" fn wgpuSamplerRelease(sampler: native::WGPUSampler) { // ShaderModule methods #[no_mangle] -pub unsafe extern "C" fn wgpuShaderModuleReference(shader_module: native::WGPUShaderModule) { +pub unsafe extern "C" fn wgpuShaderModuleAddRef(shader_module: native::WGPUShaderModule) { assert!(!shader_module.is_null(), "invalid shader module"); Arc::increment_strong_count(shader_module); } @@ -3840,7 +3898,7 @@ pub unsafe extern "C" fn wgpuSurfaceGetCapabilities( }; capabilities.usages = - conv::to_native_texture_usage_flags(caps.usages) as native::WGPUTextureUsageFlags; + conv::to_native_texture_usage_flags(caps.usages) as native::WGPUTextureUsage; let formats = caps .formats @@ -3919,18 +3977,16 @@ pub unsafe extern "C" fn wgpuSurfaceGetCurrentTexture( .has_surface_presented .store(false, atomic::Ordering::SeqCst); surface_texture.status = match status { - wgt::SurfaceStatus::Good => native::WGPUSurfaceGetCurrentTextureStatus_Success, + wgt::SurfaceStatus::Good => { + native::WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal + } wgt::SurfaceStatus::Suboptimal => { - native::WGPUSurfaceGetCurrentTextureStatus_Success + native::WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal } wgt::SurfaceStatus::Timeout => native::WGPUSurfaceGetCurrentTextureStatus_Timeout, wgt::SurfaceStatus::Outdated => native::WGPUSurfaceGetCurrentTextureStatus_Outdated, wgt::SurfaceStatus::Lost => native::WGPUSurfaceGetCurrentTextureStatus_Lost, }; - surface_texture.suboptimal = match status { - wgt::SurfaceStatus::Suboptimal => true as native::WGPUBool, - _ => false as native::WGPUBool, - }; surface_texture.texture = match texture_id { Some(texture_id) => Arc::into_raw(Arc::new(WGPUTextureImpl { context: context.clone(), @@ -3979,7 +4035,7 @@ pub unsafe extern "C" fn wgpuSurfaceUnconfigure(surface: native::WGPUSurface) { } #[no_mangle] -pub unsafe extern "C" fn wgpuSurfaceReference(surface: native::WGPUSurface) { +pub unsafe extern "C" fn wgpuSurfaceAddRef(surface: native::WGPUSurface) { assert!(!surface.is_null(), "invalid surface"); Arc::increment_strong_count(surface); } @@ -4025,32 +4081,44 @@ pub unsafe extern "C" fn wgpuTextureCreateView( texture: native::WGPUTexture, descriptor: Option<&native::WGPUTextureViewDescriptor>, ) -> native::WGPUTextureView { - let (texture_id, context, error_sink) = { + let (texture_id, context, error_sink, texture_usage) = { let texture = texture.as_ref().expect("invalid texture"); - (texture.id, &texture.context, &texture.error_sink) + ( + texture.id, + &texture.context, + &texture.error_sink, + texture.data.usage, + ) }; let desc = match descriptor { - Some(descriptor) => wgc::resource::TextureViewDescriptor { - label: ptr_into_label(descriptor.label), - format: conv::map_texture_format(descriptor.format), - dimension: conv::map_texture_view_dimension(descriptor.dimension), - range: wgt::ImageSubresourceRange { - aspect: conv::map_texture_aspect(descriptor.aspect), - base_mip_level: descriptor.baseMipLevel, - mip_level_count: match descriptor.mipLevelCount { - 0 => panic!("invalid mipLevelCount"), - native::WGPU_MIP_LEVEL_COUNT_UNDEFINED => None, - _ => Some(descriptor.mipLevelCount), - }, - base_array_layer: descriptor.baseArrayLayer, - array_layer_count: match descriptor.arrayLayerCount { - 0 => panic!("invalid arrayLayerCount"), - native::WGPU_ARRAY_LAYER_COUNT_UNDEFINED => None, - _ => Some(descriptor.arrayLayerCount), + Some(descriptor) => { + // TODO: Pass usage to texture view creation when wgpu-core supports it. + if descriptor.usage != 0 && (descriptor.usage & texture_usage) != descriptor.usage { + panic!("Texture view usage must be subset of texture's usage") + } + + wgc::resource::TextureViewDescriptor { + label: ptr_into_label(descriptor.label), + format: conv::map_texture_format(descriptor.format), + dimension: conv::map_texture_view_dimension(descriptor.dimension), + range: wgt::ImageSubresourceRange { + aspect: conv::map_texture_aspect(descriptor.aspect), + base_mip_level: descriptor.baseMipLevel, + mip_level_count: match descriptor.mipLevelCount { + 0 => panic!("invalid mipLevelCount"), + native::WGPU_MIP_LEVEL_COUNT_UNDEFINED => None, + _ => Some(descriptor.mipLevelCount), + }, + base_array_layer: descriptor.baseArrayLayer, + array_layer_count: match descriptor.arrayLayerCount { + 0 => panic!("invalid arrayLayerCount"), + native::WGPU_ARRAY_LAYER_COUNT_UNDEFINED => None, + _ => Some(descriptor.arrayLayerCount), + }, }, - }, - }, + } + } None => wgc::resource::TextureViewDescriptor::default(), }; @@ -4120,7 +4188,7 @@ pub unsafe extern "C" fn wgpuTextureGetSampleCount(texture: native::WGPUTexture) #[no_mangle] pub unsafe extern "C" fn wgpuTextureGetUsage( texture: native::WGPUTexture, -) -> native::WGPUTextureUsageFlags { +) -> native::WGPUTextureUsage { let texture = texture.as_ref().expect("invalid texture"); texture.data.usage } @@ -4132,7 +4200,7 @@ pub unsafe extern "C" fn wgpuTextureGetWidth(texture: native::WGPUTexture) -> u3 } #[no_mangle] -pub unsafe extern "C" fn wgpuTextureReference(texture: native::WGPUTexture) { +pub unsafe extern "C" fn wgpuTextureAddRef(texture: native::WGPUTexture) { assert!(!texture.is_null(), "invalid texture"); Arc::increment_strong_count(texture); } @@ -4145,7 +4213,7 @@ pub unsafe extern "C" fn wgpuTextureRelease(texture: native::WGPUTexture) { // TextureView methods #[no_mangle] -pub unsafe extern "C" fn wgpuTextureViewReference(texture_view: native::WGPUTextureView) { +pub unsafe extern "C" fn wgpuTextureViewAddRef(texture_view: native::WGPUTextureView) { assert!(!texture_view.is_null(), "invalid texture"); Arc::increment_strong_count(texture_view); } @@ -4233,7 +4301,7 @@ pub unsafe extern "C" fn wgpuDevicePoll( #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderSetPushConstants( pass: native::WGPURenderPassEncoder, - stages: native::WGPUShaderStageFlags, + stages: native::WGPUShaderStage, offset: u32, size_bytes: u32, data: *const u8, @@ -4243,7 +4311,7 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderSetPushConstants( match encoder.set_push_constants( &pass.context, - wgt::ShaderStages::from_bits(stages).expect("invalid shader stage"), + from_u64_bits(stages).expect("invalid shader stage"), offset, make_slice(data, size_bytes as usize), ) { diff --git a/src/unimplemented.rs b/src/unimplemented.rs index f58045f8..eebaf763 100644 --- a/src/unimplemented.rs +++ b/src/unimplemented.rs @@ -2,7 +2,6 @@ use crate::native; #[no_mangle] pub extern "C" fn wgpuGetProcAddress( - _device: native::WGPUDevice, _proc_name: *const ::std::os::raw::c_char, ) -> native::WGPUProc { unimplemented!(); @@ -73,9 +72,8 @@ pub extern "C" fn wgpuComputePipelineSetLabel( pub extern "C" fn wgpuDeviceCreateComputePipelineAsync( _device: native::WGPUDevice, _descriptor: *const native::WGPUComputePipelineDescriptor, - _callback: native::WGPUDeviceCreateComputePipelineAsyncCallback, - _userdata: *mut ::std::os::raw::c_void, -) { + _callback: native::WGPUCreateComputePipelineAsyncCallbackInfo, +) -> native::WGPUFuture { unimplemented!(); } @@ -83,9 +81,8 @@ pub extern "C" fn wgpuDeviceCreateComputePipelineAsync( pub extern "C" fn wgpuDeviceCreateRenderPipelineAsync( _device: native::WGPUDevice, _descriptor: *const native::WGPURenderPipelineDescriptor, - _callback: native::WGPUDeviceCreateRenderPipelineAsyncCallback, - _userdata: *mut ::std::os::raw::c_void, -) { + _callback: native::WGPUCreateRenderPipelineAsyncCallbackInfo, +) -> native::WGPUFuture { unimplemented!(); } @@ -177,9 +174,8 @@ pub extern "C" fn wgpuSamplerSetLabel( #[no_mangle] pub extern "C" fn wgpuShaderModuleGetCompilationInfo( _shader_module: native::WGPUShaderModule, - _callback: native::WGPUShaderModuleGetCompilationInfoCallback, - _userdata: *mut ::std::os::raw::c_void, -) { + _callback: native::WGPUCompilationInfoCallbackInfo, +) -> native::WGPUFuture { unimplemented!(); } @@ -214,3 +210,13 @@ pub extern "C" fn wgpuTextureViewSetLabel( ) { unimplemented!(); } + +#[no_mangle] +pub extern "C" fn wgpuInstanceWaitAny( + _instance: native::WGPUInstance, + _future_count: usize, + _futures: *mut native::WGPUFutureWaitInfo, + _timeout_ns: u64, +) -> native::WGPUWaitStatus { + unimplemented!(); +} diff --git a/src/utils.rs b/src/utils.rs index 8b65f115..f3b88c79 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -6,18 +6,36 @@ use std::{ // 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); +pub(crate) struct Userdata(*mut std::ffi::c_void, *mut std::ffi::c_void); impl Userdata { + pub(crate) const NULL: Userdata = Userdata::new(std::ptr::null_mut(), std::ptr::null_mut()); + #[inline] - pub(crate) const fn new(userdata: *mut std::ffi::c_void) -> Userdata { - Userdata(userdata) + pub(crate) const fn new( + userdata1: *mut std::ffi::c_void, + userdata2: *mut std::ffi::c_void, + ) -> Userdata { + Userdata(userdata1, userdata2) } #[inline] - pub(crate) fn as_ptr(&self) -> *mut std::ffi::c_void { + pub(crate) fn get_1(&self) -> *mut std::ffi::c_void { self.0 } + + #[inline] + pub(crate) fn get_2(&self) -> *mut std::ffi::c_void { + self.1 + } } + +#[macro_export] +macro_rules! new_userdata { + ($var:expr) => { + crate::utils::Userdata::new($var.userdata1, $var.userdata2) + }; +} + unsafe impl Send for Userdata {} unsafe impl Sync for Userdata {} @@ -98,6 +116,14 @@ pub fn get_base_device_limits_from_adapter_limits(adapter_limits: &wgt::Limits) } } +pub fn texture_format_has_depth(format: wgt::TextureFormat) -> bool { + return format == wgt::TextureFormat::Depth16Unorm + || format == wgt::TextureFormat::Depth24Plus + || format == wgt::TextureFormat::Depth24PlusStencil8 + || format == wgt::TextureFormat::Depth32Float + || format == wgt::TextureFormat::Depth32FloatStencil8; +} + /// Follow a chain of next pointers and automatically resolve them to the underlying structs. /// /// # Syntax: From 0c60733b8edf4ce16d6f4a98f33d0f9b8ec4c303 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 19 Sep 2024 17:45:36 +0200 Subject: [PATCH 02/18] Update C examples to new headers --- examples/capture/main.c | 37 +++++++++++++++++------- examples/compute/main.c | 35 ++++++++++++++++------- examples/framework/framework.c | 4 +-- examples/framework/framework.h | 2 +- examples/texture_arrays/main.c | 52 ++++++++++++++++++++-------------- examples/triangle/main.c | 42 ++++++++++++++++----------- 6 files changed, 109 insertions(+), 63 deletions(-) diff --git a/examples/capture/main.c b/examples/capture/main.c index e7133836..6d0ad184 100644 --- a/examples/capture/main.c +++ b/examples/capture/main.c @@ -15,20 +15,26 @@ const size_t COPY_BYTES_PER_ROW_ALIGNMENT = 256; static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUAdapter *)userdata = adapter; + UNUSED(userdata2) + *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUDevice *)userdata = device; + UNUSED(userdata2) + *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, void *userdata) { - UNUSED(userdata) +static void handle_buffer_map(WGPUBufferMapAsyncStatus status, + char const *message, + void *userdata1, void *userdata2) { + UNUSED(message) + UNUSED(userdata1) + UNUSED(userdata2) printf(LOG_PREFIX " buffer_map status=%#.8x\n", status); } @@ -67,14 +73,21 @@ int main(int argc, char *argv[]) { assert(instance); WGPUAdapter adapter = NULL; - wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, - (void *)&adapter); + wgpuInstanceRequestAdapter(instance, NULL, + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &adapter + }); assert(adapter); WGPUDevice device = NULL; - wgpuAdapterRequestDevice(adapter, NULL, handle_request_device, - (void *)&device); + wgpuAdapterRequestDevice(adapter, NULL, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &device + }); assert(device); + WGPUQueue queue = wgpuDeviceGetQueue(device); assert(queue); @@ -174,7 +187,9 @@ int main(int argc, char *argv[]) { wgpuQueueSubmit(queue, 1, (const WGPUCommandBuffer[]){command_buffer}); wgpuBufferMapAsync(output_buffer, WGPUMapMode_Read, 0, buffer_size, - handle_buffer_map, NULL); + (const WGPUBufferMapCallbackInfo){ + .callback = handle_buffer_map + }); wgpuDevicePoll(device, true, NULL); uint8_t *buf = diff --git a/examples/compute/main.c b/examples/compute/main.c index 03dcaeba..83ed6c6b 100644 --- a/examples/compute/main.c +++ b/examples/compute/main.c @@ -8,20 +8,25 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUAdapter *)userdata = adapter; + UNUSED(userdata2) + *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUDevice *)userdata = device; + UNUSED(userdata2) + *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, void *userdata) { - UNUSED(userdata) +static void handle_buffer_map(WGPUBufferMapAsyncStatus status, + char const * message, + void *userdata1, void *userdata2) { + UNUSED(userdata1) + UNUSED(userdata2) printf(LOG_PREFIX " buffer_map status=%#.8x\n", status); } @@ -38,13 +43,19 @@ int main(int argc, char *argv[]) { assert(instance); WGPUAdapter adapter = NULL; - wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, - (void *)&adapter); + wgpuInstanceRequestAdapter(instance, NULL, + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &adapter + }); assert(adapter); WGPUDevice device = NULL; - wgpuAdapterRequestDevice(adapter, NULL, handle_request_device, - (void *)&device); + wgpuAdapterRequestDevice(adapter, NULL, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &device + }); assert(device); WGPUQueue queue = wgpuDeviceGetQueue(device); @@ -139,7 +150,9 @@ int main(int argc, char *argv[]) { wgpuQueueSubmit(queue, 1, &command_buffer); wgpuBufferMapAsync(staging_buffer, WGPUMapMode_Read, 0, numbers_size, - handle_buffer_map, NULL); + (const WGPUBufferMapCallbackInfo){ + .callback = handle_buffer_map + }); wgpuDevicePoll(device, true, NULL); uint32_t *buf = diff --git a/examples/framework/framework.c b/examples/framework/framework.c index f0729e51..3a02e540 100644 --- a/examples/framework/framework.c +++ b/examples/framework/framework.c @@ -67,10 +67,10 @@ WGPUShaderModule frmwrk_load_shader_module(WGPUDevice device, .label = name, .nextInChain = (const WGPUChainedStruct *)&( - const WGPUShaderModuleWGSLDescriptor){ + const WGPUShaderSourceWGSL){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_ShaderModuleWGSLDescriptor, + .sType = WGPUSType_ShaderSourceWGSL, }, .code = buf, }, diff --git a/examples/framework/framework.h b/examples/framework/framework.h index c10084d7..cbde32bf 100644 --- a/examples/framework/framework.h +++ b/examples/framework/framework.h @@ -12,7 +12,7 @@ typedef struct frmwrk_buffer_init_descriptor { WGPU_NULLABLE char const *label; - WGPUBufferUsageFlags usage; + WGPUBufferUsage usage; void *content; size_t content_size; } frmwrk_buffer_init_descriptor; diff --git a/examples/texture_arrays/main.c b/examples/texture_arrays/main.c index 907355f7..c33fd993 100644 --- a/examples/texture_arrays/main.c +++ b/examples/texture_arrays/main.c @@ -27,9 +27,10 @@ struct demo { static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestAdapterStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->adapter = adapter; } else { printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status, @@ -38,9 +39,10 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, } static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestDeviceStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->device = device; } else { printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status, @@ -147,10 +149,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromMetalLayer){ + const WGPUSurfaceSourceromMetalLayer){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, + .sType = WGPUSType_SurfaceSourceMetalLayer, }, .layer = metal_layer, }, @@ -165,10 +167,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromXlibWindow){ + const WGPUSurfaceSourceXlibWindow){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, + .sType = WGPUSType_SurfaceSourceXlibWindow, }, .display = x11_display, .window = x11_window, @@ -183,11 +185,11 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWaylandSurface){ + const WGPUSurfaceSourceWaylandSurface){ .chain = (const WGPUChainedStruct){ .sType = - WGPUSType_SurfaceDescriptorFromWaylandSurface, + WGPUSType_SurfaceSourceWaylandSurface, }, .display = wayland_display, .surface = wayland_surface, @@ -203,10 +205,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWindowsHWND){ + const WGPUSurfaceSourceWindowsHWND){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + .sType = WGPUSType_SurfaceSourceWindowsHWND, }, .hinstance = hinstance, .hwnd = hwnd, @@ -222,7 +224,10 @@ int main(int argc, char *argv[]) { &(const WGPURequestAdapterOptions){ .compatibleSurface = demo.surface, }, - handle_request_adapter, &demo); + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &demo + }); assert(demo.adapter); WGPUSurfaceCapabilities surface_capabilities = {0}; @@ -260,13 +265,15 @@ int main(int argc, char *argv[]) { required_device_feature_count++; } - wgpuAdapterRequestDevice( - demo.adapter, - &(const WGPUDeviceDescriptor){ - .requiredFeatureCount = required_device_feature_count, - .requiredFeatures = required_device_features, - }, - handle_request_device, &demo); + wgpuAdapterRequestDevice(demo.adapter, + &(const WGPUDeviceDescriptor){ + .requiredFeatureCount = required_device_feature_count, + .requiredFeatures = required_device_features, + }, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &demo + }); assert(demo.device); WGPUQueue queue = wgpuDeviceGetQueue(demo.device); @@ -648,8 +655,9 @@ int main(int argc, char *argv[]) { WGPUSurfaceTexture surface_texture; wgpuSurfaceGetCurrentTexture(demo.surface, &surface_texture); switch (surface_texture.status) { - case WGPUSurfaceGetCurrentTextureStatus_Success: - // All good, could check for `surface_texture.suboptimal` here. + case WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal: + case WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal: + // All good, could handle suboptimal here break; case WGPUSurfaceGetCurrentTextureStatus_Timeout: case WGPUSurfaceGetCurrentTextureStatus_Outdated: diff --git a/examples/triangle/main.c b/examples/triangle/main.c index fb6eacdd..81ee2d88 100644 --- a/examples/triangle/main.c +++ b/examples/triangle/main.c @@ -27,9 +27,10 @@ struct demo { static void handle_request_adapter(WGPURequestAdapterStatus status, WGPUAdapter adapter, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestAdapterStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->adapter = adapter; } else { printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status, @@ -38,9 +39,10 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, } static void handle_request_device(WGPURequestDeviceStatus status, WGPUDevice device, char const *message, - void *userdata) { + void *userdata1, void *userdata2) { + UNUSED(userdata2) if (status == WGPURequestDeviceStatus_Success) { - struct demo *demo = userdata; + struct demo *demo = userdata1; demo->device = device; } else { printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status, @@ -110,10 +112,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromMetalLayer){ + const WGPUSurfaceSourceromMetalLayer){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromMetalLayer, + .sType = WGPUSType_SurfaceSourceMetalLayer, }, .layer = metal_layer, }, @@ -128,10 +130,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromXlibWindow){ + const WGPUSurfaceSourceXlibWindow){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromXlibWindow, + .sType = WGPUSType_SurfaceSourceXlibWindow, }, .display = x11_display, .window = x11_window, @@ -146,11 +148,11 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWaylandSurface){ + const WGPUSurfaceSourceWaylandSurface){ .chain = (const WGPUChainedStruct){ .sType = - WGPUSType_SurfaceDescriptorFromWaylandSurface, + WGPUSType_SurfaceSourceWaylandSurface, }, .display = wayland_display, .surface = wayland_surface, @@ -166,10 +168,10 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceDescriptorFromWindowsHWND){ + const WGPUSurfaceSourceWindowsHWND){ .chain = (const WGPUChainedStruct){ - .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND, + .sType = WGPUSType_SurfaceSourceWindowsHWND, }, .hinstance = hinstance, .hwnd = hwnd, @@ -185,12 +187,19 @@ int main(int argc, char *argv[]) { &(const WGPURequestAdapterOptions){ .compatibleSurface = demo.surface, }, - handle_request_adapter, &demo); + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &demo + }); assert(demo.adapter); frmwrk_print_adapter_info(demo.adapter); - wgpuAdapterRequestDevice(demo.adapter, NULL, handle_request_device, &demo); + wgpuAdapterRequestDevice(demo.adapter, NULL, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &demo + }); assert(demo.device); WGPUQueue queue = wgpuDeviceGetQueue(demo.device); @@ -267,8 +276,9 @@ int main(int argc, char *argv[]) { WGPUSurfaceTexture surface_texture; wgpuSurfaceGetCurrentTexture(demo.surface, &surface_texture); switch (surface_texture.status) { - case WGPUSurfaceGetCurrentTextureStatus_Success: - // All good, could check for `surface_texture.suboptimal` here. + case WGPUSurfaceGetCurrentTextureStatus_SuccessOptimal: + case WGPUSurfaceGetCurrentTextureStatus_SuccessSuboptimal: + // All good, could handle suboptimal here break; case WGPUSurfaceGetCurrentTextureStatus_Timeout: case WGPUSurfaceGetCurrentTextureStatus_Outdated: From 980c2ff095b5708afebb9ed2c0f53f59f2fb45d9 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 19 Sep 2024 18:14:58 +0200 Subject: [PATCH 03/18] Fix WGPUBufferMapAsyncStatus tomfoolery This enum was replaced with WGPUMapAsyncStatus, but I didn't quite notice. The error codes map different. --- examples/capture/main.c | 2 +- examples/compute/main.c | 2 +- src/lib.rs | 16 ++++------------ 3 files changed, 6 insertions(+), 14 deletions(-) diff --git a/examples/capture/main.c b/examples/capture/main.c index 6d0ad184..aa59557f 100644 --- a/examples/capture/main.c +++ b/examples/capture/main.c @@ -29,7 +29,7 @@ static void handle_request_device(WGPURequestDeviceStatus status, UNUSED(userdata2) *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, +static void handle_buffer_map(WGPUMapAsyncStatus status, char const *message, void *userdata1, void *userdata2) { UNUSED(message) diff --git a/examples/compute/main.c b/examples/compute/main.c index 83ed6c6b..452bc130 100644 --- a/examples/compute/main.c +++ b/examples/compute/main.c @@ -22,7 +22,7 @@ static void handle_request_device(WGPURequestDeviceStatus status, UNUSED(userdata2) *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, +static void handle_buffer_map(WGPUMapAsyncStatus status, char const * message, void *userdata1, void *userdata2) { UNUSED(userdata1) diff --git a/src/lib.rs b/src/lib.rs index 095545dd..bde9a98e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1008,21 +1008,13 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( callback: Some(wgc::resource::BufferMapCallback::from_rust(Box::new( move |result: resource::BufferAccessResult| { let (status, message) = match result { - Ok(()) => (native::WGPUBufferMapAsyncStatus_Success, CString::default()), + Ok(()) => (native::WGPUMapAsyncStatus_Success, CString::default()), Err(cause) => { let code = match cause { - resource::BufferAccessError::Device(_) => { - native::WGPUBufferMapAsyncStatus_DeviceLost + resource::BufferAccessError::MapAborted => { + native::WGPUMapAsyncStatus_Aborted } - resource::BufferAccessError::MapAlreadyPending => { - native::WGPUBufferMapAsyncStatus_MappingAlreadyPending - } - resource::BufferAccessError::InvalidBufferId(_) - | resource::BufferAccessError::DestroyedResource(_) => { - native::WGPUBufferMapAsyncStatus_DestroyedBeforeCallback - } - _ => native::WGPUBufferMapAsyncStatus_ValidationError, // TODO: WGPUBufferMapAsyncStatus_OffsetOutOfRange - // TODO: WGPUBufferMapAsyncStatus_SizeOutOfRange + _ => native::WGPUMapAsyncStatus_Error, }; (code, CString::new(format_error(&cause)).unwrap()) From 8f34e48f40b214e593e5ddaf8c8a698d46d42990 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 19 Sep 2024 18:21:31 +0200 Subject: [PATCH 04/18] Fix macOS typos in examples --- examples/texture_arrays/main.c | 2 +- examples/triangle/main.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/texture_arrays/main.c b/examples/texture_arrays/main.c index c33fd993..46d40503 100644 --- a/examples/texture_arrays/main.c +++ b/examples/texture_arrays/main.c @@ -149,7 +149,7 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceSourceromMetalLayer){ + const WGPUSurfaceSourceMetalLayer){ .chain = (const WGPUChainedStruct){ .sType = WGPUSType_SurfaceSourceMetalLayer, diff --git a/examples/triangle/main.c b/examples/triangle/main.c index 81ee2d88..267be154 100644 --- a/examples/triangle/main.c +++ b/examples/triangle/main.c @@ -112,7 +112,7 @@ int main(int argc, char *argv[]) { &(const WGPUSurfaceDescriptor){ .nextInChain = (const WGPUChainedStruct *)&( - const WGPUSurfaceSourceromMetalLayer){ + const WGPUSurfaceSourceMetalLayer){ .chain = (const WGPUChainedStruct){ .sType = WGPUSType_SurfaceSourceMetalLayer, From b36e558a4ee365916cc5abca9ea80cd0cdcf2f6c Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 27 Sep 2024 11:29:50 +0200 Subject: [PATCH 05/18] Update headers again Replaces *EnumerateFeatures with *GetFeatures. Also fixes CI due to fix in headers. --- examples/texture_arrays/main.c | 13 ++++---- ffi/webgpu-headers | 2 +- src/lib.rs | 55 +++++++++++++++++++++++++--------- 3 files changed, 47 insertions(+), 23 deletions(-) diff --git a/examples/texture_arrays/main.c b/examples/texture_arrays/main.c index 46d40503..7d27f1b3 100644 --- a/examples/texture_arrays/main.c +++ b/examples/texture_arrays/main.c @@ -233,16 +233,13 @@ int main(int argc, char *argv[]) { WGPUSurfaceCapabilities surface_capabilities = {0}; wgpuSurfaceGetCapabilities(demo.surface, demo.adapter, &surface_capabilities); - size_t adapter_feature_count = - wgpuAdapterEnumerateFeatures(demo.adapter, NULL); - WGPUFeatureName *adapter_features = (WGPUFeatureName *)malloc( - sizeof(WGPUFeatureName) * adapter_feature_count); - wgpuAdapterEnumerateFeatures(demo.adapter, adapter_features); + WGPUSupportedFeatures adapter_features = {0}; + wgpuAdapterGetFeatures(demo.adapter, &adapter_features); bool adapter_has_required_features = false; bool adapter_has_optional_features = false; - for (size_t i = 0; i < adapter_feature_count; i++) { - switch ((uint32_t)adapter_features[i]) { + for (size_t i = 0; i < adapter_features.featureCount; i++) { + switch ((uint32_t)adapter_features.features[i]) { case WGPUNativeFeature_TextureBindingArray: adapter_has_required_features = true; break; @@ -253,7 +250,7 @@ int main(int argc, char *argv[]) { } assert( adapter_has_required_features /* Adapter must support WGPUNativeFeature_TextureBindingArray feature for this example */); - free(adapter_features); + wgpuSupportedFeaturesFreeMembers(adapter_features); WGPUFeatureName required_device_features[2] = { (WGPUFeatureName)WGPUNativeFeature_TextureBindingArray, diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index 2b597475..4f7f7ed9 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit 2b5974750be7b2545d842ecec02e585022081952 +Subproject commit 4f7f7ed94a0040b65283035831bdffc024668ff8 diff --git a/src/lib.rs b/src/lib.rs index bde9a98e..3513ffbc 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,6 +5,7 @@ use conv::{ map_query_set_index, map_shader_module, map_surface, map_surface_configuration, CreateSurfaceParams, }; +use core::slice; use parking_lot::Mutex; use smallvec::SmallVec; use std::{ @@ -660,26 +661,33 @@ pub unsafe extern "C" fn wgpuCreateInstance( // Adapter methods #[no_mangle] -pub unsafe extern "C" fn wgpuAdapterEnumerateFeatures( +pub unsafe extern "C" fn wgpuAdapterGetFeatures( adapter: native::WGPUAdapter, - features: *mut native::WGPUFeatureName, -) -> usize { + features: Option<&mut native::WGPUSupportedFeatures>, +) -> native::WGPUStatus { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); (adapter.id, &adapter.context) }; + let features = features.expect("invalid return pointer \"features\""); + let adapter_features = match gfx_select!(adapter_id => context.adapter_features(adapter_id)) { Ok(features) => features, Err(err) => handle_error_fatal(err, "wgpuAdapterEnumerateFeatures"), }; let temp = conv::features_to_native(adapter_features); + let mut temp = temp.into_boxed_slice(); - if !features.is_null() { - std::ptr::copy_nonoverlapping(temp.as_ptr(), features, temp.len()); - } + *features = native::WGPUSupportedFeatures { + nextInChain: std::ptr::null_mut(), + featureCount: temp.len(), + features: temp.as_mut_ptr(), + }; - temp.len() + mem::forget(temp); + + native::WGPUStatus_Success } #[no_mangle] @@ -2500,26 +2508,45 @@ pub extern "C" fn wgpuDeviceDestroy(_device: native::WGPUDevice) { } #[no_mangle] -pub unsafe extern "C" fn wgpuDeviceEnumerateFeatures( +pub unsafe extern "C" fn wgpuDeviceGetFeatures( device: native::WGPUDevice, - features: *mut native::WGPUFeatureName, -) -> usize { + features: Option<&mut native::WGPUSupportedFeatures>, +) -> native::WGPUStatus { let (device_id, context) = { let device = device.as_ref().expect("invalid device"); (device.id, &device.context) }; + let features = features.expect("invalid return pointer \"features\""); + let device_features = match gfx_select!(device_id => context.device_features(device_id)) { Ok(features) => features, Err(err) => handle_error_fatal(err, "wgpuDeviceEnumerateFeatures"), }; let temp = conv::features_to_native(device_features); + let mut temp = temp.into_boxed_slice(); - if !features.is_null() { - std::ptr::copy_nonoverlapping(temp.as_ptr(), features, temp.len()); - } + *features = native::WGPUSupportedFeatures { + nextInChain: std::ptr::null_mut(), + featureCount: temp.len(), + features: temp.as_mut_ptr(), + }; + + mem::forget(temp); + + native::WGPUStatus_Success +} - temp.len() +#[no_mangle] +pub unsafe extern "C" fn wgpuSupportedFeaturesFreeMembers( + supported_features: native::WGPUSupportedFeatures, +) { + if !supported_features.features.is_null() && supported_features.featureCount > 0 { + drop(Box::from_raw(slice::from_raw_parts_mut( + supported_features.features as *mut native::WGPUFeatureName, + supported_features.featureCount, + ))) + } } #[no_mangle] From a4626db10b06c18ac351d972b75eafa059d98a48 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Fri, 27 Sep 2024 12:02:08 +0200 Subject: [PATCH 06/18] Update wgpu.h to match new flag scheme Upstream removed the "Flags" suffix from flags types and moved them to no longer be C enums. This matches that change. WGPUInstanceFlag still has "Flag" in the name because, well, there'd be nothing left to distinguish it from WGPUInstance, and it makes sense for it. --- ffi/wgpu.h | 50 +++++++++++++++++++++++--------------------------- src/conv.rs | 2 +- 2 files changed, 24 insertions(+), 28 deletions(-) diff --git a/ffi/wgpu.h b/ffi/wgpu.h index a3918a01..bfaa408a 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -66,30 +66,26 @@ typedef enum WGPULogLevel { WGPULogLevel_Force32 = 0x7FFFFFFF } WGPULogLevel; -typedef enum WGPUInstanceBackend { - WGPUInstanceBackend_All = 0x00000000, - WGPUInstanceBackend_Vulkan = 1 << 0, - WGPUInstanceBackend_GL = 1 << 1, - WGPUInstanceBackend_Metal = 1 << 2, - WGPUInstanceBackend_DX12 = 1 << 3, - WGPUInstanceBackend_DX11 = 1 << 4, - WGPUInstanceBackend_BrowserWebGPU = 1 << 5, - WGPUInstanceBackend_Primary = WGPUInstanceBackend_Vulkan | WGPUInstanceBackend_Metal | - WGPUInstanceBackend_DX12 | - WGPUInstanceBackend_BrowserWebGPU, - WGPUInstanceBackend_Secondary = WGPUInstanceBackend_GL | WGPUInstanceBackend_DX11, - WGPUInstanceBackend_Force32 = 0x7FFFFFFF -} WGPUInstanceBackend; -typedef WGPUFlags WGPUInstanceBackendFlags; - -typedef enum WGPUInstanceFlag { - WGPUInstanceFlag_Default = 0x00000000, - WGPUInstanceFlag_Debug = 1 << 0, - WGPUInstanceFlag_Validation = 1 << 1, - WGPUInstanceFlag_DiscardHalLabels = 1 << 2, - WGPUInstanceFlag_Force32 = 0x7FFFFFFF -} WGPUInstanceFlag; -typedef WGPUFlags WGPUInstanceFlags; +typedef WGPUFlags WGPUInstanceBackend; +static const WGPUInstanceBackend WGPUInstanceBackend_All = 0x00000000; +static const WGPUInstanceBackend WGPUInstanceBackend_Vulkan = 1 << 0; +static const WGPUInstanceBackend WGPUInstanceBackend_GL = 1 << 1; +static const WGPUInstanceBackend WGPUInstanceBackend_Metal = 1 << 2; +static const WGPUInstanceBackend WGPUInstanceBackend_DX12 = 1 << 3; +static const WGPUInstanceBackend WGPUInstanceBackend_DX11 = 1 << 4; +static const WGPUInstanceBackend WGPUInstanceBackend_BrowserWebGPU = 1 << 5; +// Vulkan, Metal, DX12 and BrowserWebGPU +static const WGPUInstanceBackend WGPUInstanceBackend_Primary = (1 << 0) | (1 << 2) | (1 << 3) | (1 << 5); +// GL and DX11 +static const WGPUInstanceBackend WGPUInstanceBackend_Secondary = (1 << 1) | (1 << 4); +static const WGPUInstanceBackend WGPUInstanceBackend_Force32 = 0x7FFFFFFF; + +typedef WGPUFlags WGPUInstanceFlag; +static const WGPUInstanceFlag WGPUInstanceFlag_Default = 0x00000000; +static const WGPUInstanceFlag WGPUInstanceFlag_Debug = 1 << 0; +static const WGPUInstanceFlag WGPUInstanceFlag_Validation = 1 << 1; +static const WGPUInstanceFlag WGPUInstanceFlag_DiscardHalLabels = 1 << 2; +static const WGPUInstanceFlag WGPUInstanceFlag_Force32 = 0x7FFFFFFF; typedef enum WGPUDx12Compiler { WGPUDx12Compiler_Undefined = 0x00000000, @@ -122,8 +118,8 @@ typedef enum WGPUNativeQueryType { typedef struct WGPUInstanceExtras { WGPUChainedStruct chain; - WGPUInstanceBackendFlags backends; - WGPUInstanceFlags flags; + WGPUInstanceBackend backends; + WGPUInstanceFlag flags; WGPUDx12Compiler dx12ShaderCompiler; WGPUGles3MinorVersion gles3MinorVersion; const char * dxilPath; @@ -220,7 +216,7 @@ typedef struct WGPUGlobalReport { typedef struct WGPUInstanceEnumerateAdapterOptions { WGPUChainedStruct const * nextInChain; - WGPUInstanceBackendFlags backends; + WGPUInstanceBackend backends; } WGPUInstanceEnumerateAdapterOptions; typedef struct WGPUBindGroupEntryExtras { diff --git a/src/conv.rs b/src/conv.rs index c8267191..372d2c67 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -293,7 +293,7 @@ pub fn map_instance_descriptor( backends: map_instance_backend_flags(extras.backends as native::WGPUInstanceBackend), dx12_shader_compiler, gles_minor_version: map_gles3_minor_version(extras.gles3MinorVersion), - flags: match extras.flags as native::WGPUInstanceFlag { + flags: match extras.flags { native::WGPUInstanceFlag_Default => wgt::InstanceFlags::default(), flags => map_instance_flags(flags), }, From a256544fa1478b076a1dfb1bb03b32f2b1beb6e6 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 3 Oct 2024 01:44:52 +0200 Subject: [PATCH 07/18] Update headers again, WGPUStringView Also updates wgpu.h to use WGPUStringView everywhere. --- examples/capture/main.c | 16 +-- examples/compute/main.c | 22 +-- examples/enumerate_adapters/main.c | 11 +- examples/framework/framework.c | 20 +-- examples/texture_arrays/main.c | 36 ++--- examples/triangle/main.c | 26 ++-- ffi/webgpu-headers | 2 +- ffi/wgpu.h | 14 +- src/conv.rs | 44 +++--- src/lib.rs | 206 +++++++++++++++-------------- src/logging.rs | 6 +- src/unimplemented.rs | 53 +++----- src/utils.rs | 95 +++++++++---- 13 files changed, 290 insertions(+), 261 deletions(-) diff --git a/examples/capture/main.c b/examples/capture/main.c index aa59557f..5d2a4f08 100644 --- a/examples/capture/main.c +++ b/examples/capture/main.c @@ -14,7 +14,7 @@ const size_t IMAGE_HEIGHT = 200; const size_t COPY_BYTES_PER_ROW_ALIGNMENT = 256; static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, + WGPUAdapter adapter, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) @@ -22,7 +22,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, + WGPUDevice device, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) @@ -30,7 +30,7 @@ static void handle_request_device(WGPURequestDeviceStatus status, *(WGPUDevice *)userdata1 = device; } static void handle_buffer_map(WGPUMapAsyncStatus status, - char const *message, + WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(message) UNUSED(userdata1) @@ -99,7 +99,7 @@ int main(int argc, char *argv[]) { WGPUBuffer output_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "output_buffer", + .label = {"output_buffer", WGPU_STRLEN}, .size = buffer_size, .usage = WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, .mappedAtCreation = false, @@ -115,7 +115,7 @@ int main(int argc, char *argv[]) { WGPUTexture texture = wgpuDeviceCreateTexture( device, &(const WGPUTextureDescriptor){ - .label = "texture", + .label = {"texture", WGPU_STRLEN}, .size = texture_extent, .mipLevelCount = 1, .sampleCount = 1, @@ -129,13 +129,13 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); WGPURenderPassEncoder render_pass_encoder = wgpuCommandEncoderBeginRenderPass( command_encoder, &(const WGPURenderPassDescriptor){ - .label = "rende_pass_encoder", + .label = {"rende_pass_encoder", WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = (const WGPURenderPassColorAttachment[]){ @@ -180,7 +180,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); diff --git a/examples/compute/main.c b/examples/compute/main.c index 452bc130..19f6c3a3 100644 --- a/examples/compute/main.c +++ b/examples/compute/main.c @@ -7,7 +7,7 @@ #define LOG_PREFIX "[compute]" static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, + WGPUAdapter adapter, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) @@ -15,7 +15,7 @@ static void handle_request_adapter(WGPURequestAdapterStatus status, *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, + WGPUDevice device, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) @@ -23,7 +23,7 @@ static void handle_request_device(WGPURequestDeviceStatus status, *(WGPUDevice *)userdata1 = device; } static void handle_buffer_map(WGPUMapAsyncStatus status, - char const * message, + WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(userdata1) UNUSED(userdata2) @@ -67,7 +67,7 @@ int main(int argc, char *argv[]) { WGPUBuffer staging_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "staging_buffer", + .label = {"staging_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, .size = numbers_size, .mappedAtCreation = false, @@ -76,7 +76,7 @@ int main(int argc, char *argv[]) { WGPUBuffer storage_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "storage_buffer", + .label = {"storage_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc, .size = numbers_size, @@ -86,11 +86,11 @@ int main(int argc, char *argv[]) { WGPUComputePipeline compute_pipeline = wgpuDeviceCreateComputePipeline( device, &(const WGPUComputePipelineDescriptor){ - .label = "compute_pipeline", + .label = {"compute_pipeline", WGPU_STRLEN}, .compute = (const WGPUProgrammableStageDescriptor){ .module = shader_module, - .entryPoint = "main", + .entryPoint = {"main", WGPU_STRLEN}, }, }); assert(compute_pipeline); @@ -101,7 +101,7 @@ int main(int argc, char *argv[]) { WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup( device, &(const WGPUBindGroupDescriptor){ - .label = "bind_group", + .label = {"bind_group", WGPU_STRLEN}, .layout = bind_group_layout, .entryCount = 1, .entries = @@ -118,14 +118,14 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); WGPUComputePassEncoder compute_pass_encoder = wgpuCommandEncoderBeginComputePass(command_encoder, &(const WGPUComputePassDescriptor){ - .label = "compute_pass", + .label = {"compute_pass", WGPU_STRLEN}, }); assert(compute_pass_encoder); @@ -142,7 +142,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); diff --git a/examples/enumerate_adapters/main.c b/examples/enumerate_adapters/main.c index 25b533d8..7e3db303 100644 --- a/examples/enumerate_adapters/main.c +++ b/examples/enumerate_adapters/main.c @@ -26,16 +26,17 @@ int main(int argc, char *argv[]) { wgpuAdapterGetInfo(adapter, &info); printf("WGPUAdapter: %d\n", i); printf("WGPUAdapterInfo {\n" - "\tvendor: %s\n" - "\tarchitecture: %s\n" - "\tdevice: %s\n" - "\tdescription: %s\n" + "\tvendor: %.*s\n" + "\tarchitecture: %.*s\n" + "\tdevice: %.*s\n" + "\tdescription: %.*s\n" "\tbackendType: %#.8x\n" "\tadapterType: %#.8x\n" "\tvendorID: %" PRIu32 "\n" "\tdeviceID: %" PRIu32 "\n" "}\n", - info.vendor, info.architecture, info.device, info.description, + (int) info.vendor.length, info.vendor.data, (int) info.architecture.length, info.architecture.data, + (int) info.device.length, info.device.data, (int) info.description.length, info.description.data, info.backendType, info.adapterType, info.vendorID, info.deviceID); wgpuAdapterInfoFreeMembers(info); diff --git a/examples/framework/framework.c b/examples/framework/framework.c index 3a02e540..dadde215 100644 --- a/examples/framework/framework.c +++ b/examples/framework/framework.c @@ -1,6 +1,6 @@ #include "framework.h" -static void log_callback(WGPULogLevel level, char const *message, +static void log_callback(WGPULogLevel level, WGPUStringView message, void *userdata) { UNUSED(userdata) char *level_str; @@ -23,7 +23,7 @@ static void log_callback(WGPULogLevel level, char const *message, default: level_str = "unknown_level"; } - fprintf(stderr, "[wgpu] [%s] %s\n", level_str, message); + fprintf(stderr, "[wgpu] [%s] %.*s\n", level_str, (int) message.length, message.data); } void frmwrk_setup_logging(WGPULogLevel level) { @@ -64,7 +64,7 @@ WGPUShaderModule frmwrk_load_shader_module(WGPUDevice device, shader_module = wgpuDeviceCreateShaderModule( device, &(const WGPUShaderModuleDescriptor){ - .label = name, + .label = {name, WGPU_STRLEN}, .nextInChain = (const WGPUChainedStruct *)&( const WGPUShaderSourceWGSL){ @@ -72,7 +72,7 @@ WGPUShaderModule frmwrk_load_shader_module(WGPUDevice device, (const WGPUChainedStruct){ .sType = WGPUSType_ShaderSourceWGSL, }, - .code = buf, + .code = {buf, WGPU_STRLEN}, }, }); @@ -92,7 +92,7 @@ WGPUBuffer frmwrk_device_create_buffer_init( assert(descriptor); if (descriptor->content_size == 0) { return wgpuDeviceCreateBuffer(device, &(WGPUBufferDescriptor){ - .label = descriptor->label, + .label = {descriptor->label, WGPU_STRLEN}, .size = 0, .usage = descriptor->usage, .mappedAtCreation = false, @@ -105,7 +105,7 @@ WGPUBuffer frmwrk_device_create_buffer_init( MAX((unpadded_size + align_mask) & ~align_mask, COPY_BUFFER_ALIGNMENT); WGPUBuffer buffer = wgpuDeviceCreateBuffer(device, &(WGPUBufferDescriptor){ - .label = descriptor->label, + .label = {descriptor->label, WGPU_STRLEN}, .size = padded_size, .usage = descriptor->usage, .mappedAtCreation = true, @@ -168,10 +168,10 @@ void frmwrk_print_global_report(WGPUGlobalReport report) { void frmwrk_print_adapter_info(WGPUAdapter adapter) { struct WGPUAdapterInfo info = {0}; wgpuAdapterGetInfo(adapter, &info); - printf("description: %s\n", info.description); - printf("vendor: %s\n", info.vendor); - printf("architecture: %s\n", info.architecture); - printf("device: %s\n", info.device); + printf("description: %.*s\n", (int) info.description.length, info.description.data); + printf("vendor: %.*s\n", (int) info.vendor.length, info.vendor.data); + printf("architecture: %.*s\n", (int) info.architecture.length, info.architecture.data); + printf("device: %.*s\n", (int) info.device.length, info.device.data); printf("backend type: %u\n", info.backendType); printf("adapter type: %u\n", info.adapterType); printf("vendorID: %x\n", info.vendorID); diff --git a/examples/texture_arrays/main.c b/examples/texture_arrays/main.c index 7d27f1b3..4a5c1a88 100644 --- a/examples/texture_arrays/main.c +++ b/examples/texture_arrays/main.c @@ -26,27 +26,27 @@ struct demo { }; static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, + WGPUAdapter adapter, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(userdata2) if (status == WGPURequestAdapterStatus_Success) { struct demo *demo = userdata1; demo->adapter = adapter; } else { - printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_adapter status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, + WGPUDevice device, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(userdata2) if (status == WGPURequestDeviceStatus_Success) { struct demo *demo = userdata1; demo->device = device; } else { - printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_device status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_glfw_framebuffer_size(GLFWwindow *window, int width, @@ -368,25 +368,25 @@ int main(int argc, char *argv[]) { WGPUTexture red_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "red", + .label = {"red", WGPU_STRLEN}, }); assert(red_texture); WGPUTexture green_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "green", + .label = {"green", WGPU_STRLEN}, }); assert(green_texture); WGPUTexture blue_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "blue", + .label = {"blue", WGPU_STRLEN}, }); assert(blue_texture); WGPUTexture white_texture = wgpuDeviceCreateTexture( demo.device, &(const WGPUTextureDescriptor){ COLOR_TEXTURE_DESCRIPTOR_COMMON_FIELDS, - .label = "white", + .label = {"white", WGPU_STRLEN}, }); assert(white_texture); @@ -516,7 +516,7 @@ int main(int argc, char *argv[]) { }; WGPUBindGroupLayout bind_group_layout = wgpuDeviceCreateBindGroupLayout( demo.device, &(const WGPUBindGroupLayoutDescriptor){ - .label = "bind group layout", + .label = {"bind group layout", WGPU_STRLEN}, .entryCount = sizeof(bind_group_layout_entries) / sizeof(bind_group_layout_entries[0]), .entries = bind_group_layout_entries, @@ -582,7 +582,7 @@ int main(int argc, char *argv[]) { WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup( demo.device, &(const WGPUBindGroupDescriptor){ .layout = bind_group_layout, - .label = "bind group", + .label = {"bind group", WGPU_STRLEN}, .entryCount = sizeof(bind_group_entries) / sizeof(bind_group_entries[0]), .entries = bind_group_entries, @@ -591,7 +591,7 @@ int main(int argc, char *argv[]) { WGPUPipelineLayout pipeline_layout = wgpuDeviceCreatePipelineLayout( demo.device, &(const WGPUPipelineLayoutDescriptor){ - .label = "main", + .label = {"main", WGPU_STRLEN}, .bindGroupLayoutCount = 1, .bindGroupLayouts = (const WGPUBindGroupLayout[]){ @@ -607,7 +607,7 @@ int main(int argc, char *argv[]) { .vertex = (const WGPUVertexState){ .module = base_shader_module, - .entryPoint = "vert_main", + .entryPoint = {"vert_main", WGPU_STRLEN}, .bufferCount = 1, .buffers = (const WGPUVertexBufferLayout[]){ @@ -623,7 +623,7 @@ int main(int argc, char *argv[]) { .fragment = &(const WGPUFragmentState){ .module = fragment_shader_module, - .entryPoint = fragment_entry_point, + .entryPoint = {fragment_entry_point, WGPU_STRLEN}, .targetCount = 1, .targets = (const WGPUColorTargetState[]){ @@ -688,7 +688,7 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( demo.device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); @@ -696,7 +696,7 @@ int main(int argc, char *argv[]) { wgpuCommandEncoderBeginRenderPass( command_encoder, &(const WGPURenderPassDescriptor){ - .label = "render_pass_encoder", + .label = {"render_pass_encoder", WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = (const WGPURenderPassColorAttachment[]){ @@ -740,7 +740,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); diff --git a/examples/triangle/main.c b/examples/triangle/main.c index 267be154..50d468d8 100644 --- a/examples/triangle/main.c +++ b/examples/triangle/main.c @@ -26,27 +26,27 @@ struct demo { }; static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, + WGPUAdapter adapter, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(userdata2) if (status == WGPURequestAdapterStatus_Success) { struct demo *demo = userdata1; demo->adapter = adapter; } else { - printf(LOG_PREFIX " request_adapter status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_adapter status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, + WGPUDevice device, WGPUStringView message, void *userdata1, void *userdata2) { UNUSED(userdata2) if (status == WGPURequestDeviceStatus_Success) { struct demo *demo = userdata1; demo->device = device; } else { - printf(LOG_PREFIX " request_device status=%#.8x message=%s\n", status, - message); + printf(LOG_PREFIX " request_device status=%#.8x message=%.*s\n", status, + (int) message.length, message.data); } } static void handle_glfw_key(GLFWwindow *window, int key, int scancode, @@ -211,7 +211,7 @@ int main(int argc, char *argv[]) { WGPUPipelineLayout pipeline_layout = wgpuDeviceCreatePipelineLayout( demo.device, &(const WGPUPipelineLayoutDescriptor){ - .label = "pipeline_layout", + .label = {"pipeline_layout", WGPU_STRLEN}, }); assert(pipeline_layout); @@ -221,17 +221,17 @@ int main(int argc, char *argv[]) { WGPURenderPipeline render_pipeline = wgpuDeviceCreateRenderPipeline( demo.device, &(const WGPURenderPipelineDescriptor){ - .label = "render_pipeline", + .label = {"render_pipeline", WGPU_STRLEN}, .layout = pipeline_layout, .vertex = (const WGPUVertexState){ .module = shader_module, - .entryPoint = "vs_main", + .entryPoint = {"vs_main", WGPU_STRLEN}, }, .fragment = &(const WGPUFragmentState){ .module = shader_module, - .entryPoint = "fs_main", + .entryPoint = {"fs_main", WGPU_STRLEN}, .targetCount = 1, .targets = (const WGPUColorTargetState[]){ @@ -312,7 +312,7 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( demo.device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); @@ -320,7 +320,7 @@ int main(int argc, char *argv[]) { wgpuCommandEncoderBeginRenderPass( command_encoder, &(const WGPURenderPassDescriptor){ - .label = "render_pass_encoder", + .label = {"render_pass_encoder", WGPU_STRLEN}, .colorAttachmentCount = 1, .colorAttachments = (const WGPURenderPassColorAttachment[]){ @@ -348,7 +348,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index 4f7f7ed9..a41b613a 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit 4f7f7ed94a0040b65283035831bdffc024668ff8 +Subproject commit a41b613a48a1df22262326d4ed85a9fcdc510afb diff --git a/ffi/wgpu.h b/ffi/wgpu.h index bfaa408a..0d07c65b 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -122,13 +122,13 @@ typedef struct WGPUInstanceExtras { WGPUInstanceFlag flags; WGPUDx12Compiler dx12ShaderCompiler; WGPUGles3MinorVersion gles3MinorVersion; - const char * dxilPath; - const char * dxcPath; + WGPUStringView dxilPath; + WGPUStringView dxcPath; } WGPUInstanceExtras; typedef struct WGPUDeviceExtras { WGPUChainedStruct chain; - const char * tracePath; + WGPUStringView tracePath; } WGPUDeviceExtras; typedef struct WGPUNativeLimits { @@ -166,14 +166,14 @@ typedef struct WGPUWrappedSubmissionIndex { } WGPUWrappedSubmissionIndex; typedef struct WGPUShaderDefine { - char const * name; - char const * value; + WGPUStringView name; + WGPUStringView value; } WGPUShaderDefine; typedef struct WGPUShaderModuleGLSLDescriptor { WGPUChainedStruct chain; WGPUShaderStage stage; - char const * code; + WGPUStringView code; uint32_t defineCount; WGPUShaderDefine * defines; } WGPUShaderModuleGLSLDescriptor; @@ -245,7 +245,7 @@ typedef struct WGPUSurfaceConfigurationExtras { uint32_t desiredMaximumFrameLatency; } WGPUSurfaceConfigurationExtras WGPU_STRUCTURE_ATTRIBUTE; -typedef void (*WGPULogCallback)(WGPULogLevel level, char const * message, void * userdata); +typedef void (*WGPULogCallback)(WGPULogLevel level, WGPUStringView message, void * userdata); typedef enum WGPUNativeTextureFormat { // From Features::TEXTURE_FORMAT_16BIT_NORM diff --git a/src/conv.rs b/src/conv.rs index 372d2c67..e2c15d6c 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -1,9 +1,10 @@ -use crate::utils::{make_slice, ptr_into_label, ptr_into_pathbuf}; +use crate::utils::{make_slice, string_view_into_label, string_view_into_str}; use crate::{follow_chain, map_enum, new_userdata}; use crate::{native, UncapturedErrorCallback}; +use std::borrow::Cow; use std::num::{NonZeroIsize, NonZeroU32, NonZeroU64}; +use std::path::PathBuf; use std::ptr::NonNull; -use std::{borrow::Cow, ffi::CStr}; map_enum!(map_load_op, WGPULoadOp, wgc::command::LoadOp, Clear, Load); map_enum!( @@ -215,6 +216,7 @@ pub const WGPU_WHOLE_SIZE: u64 = u64::MAX; pub const WGPU_LIMIT_U64_UNDEFINED: u64 = u64::MAX; // it's SIZE_MAX in headers but it's not available in some compilers pub const WGPU_WHOLE_MAP_SIZE: usize = usize::MAX; +pub const WGPU_STRLEN: usize = usize::MAX; #[inline] pub fn map_extent3d(native: &native::WGPUExtent3D) -> wgt::Extent3d { @@ -275,7 +277,7 @@ pub fn map_instance_flags(flags: native::WGPUInstanceFlag) -> wgt::InstanceFlags } #[inline] -pub fn map_instance_descriptor( +pub unsafe fn map_instance_descriptor( _base: &native::WGPUInstanceDescriptor, extras: Option<&native::WGPUInstanceExtras>, ) -> wgt::InstanceDescriptor { @@ -283,8 +285,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: ptr_into_pathbuf(extras.dxilPath), - dxc_path: ptr_into_pathbuf(extras.dxcPath), + dxil_path: string_view_into_str(extras.dxilPath).map(PathBuf::from), + dxc_path: string_view_into_str(extras.dxcPath).map(PathBuf::from), }, _ => wgt::Dx12Compiler::default(), }; @@ -304,18 +306,18 @@ pub fn map_instance_descriptor( } #[inline] -pub(crate) fn map_device_descriptor<'a>( +pub(crate) unsafe fn map_device_descriptor<'a>( des: &native::WGPUDeviceDescriptor, base_limits: wgt::Limits, extras: Option<&native::WGPUDeviceExtras>, ) -> ( wgt::DeviceDescriptor>, - *const std::ffi::c_char, + Option<&'a str>, Option, ) { ( wgt::DeviceDescriptor { - label: ptr_into_label(des.label), + label: string_view_into_label(des.label), required_features: map_features(make_slice( des.requiredFeatures, des.requiredFeatureCount, @@ -332,10 +334,7 @@ pub(crate) fn map_device_descriptor<'a>( // TODO(wgpu.h) memory_hints: Default::default(), }, - match extras { - Some(extras) => extras.tracePath, - None => std::ptr::null(), - }, + extras.and_then(|extras| string_view_into_str(extras.tracePath)), match des.uncapturedErrorCallbackInfo.callback { None => None, callback => Some(UncapturedErrorCallback { @@ -373,7 +372,7 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( }); return wgc::binding_model::PipelineLayoutDescriptor { - label: ptr_into_label(des.label), + label: string_view_into_label(des.label), bind_group_layouts: Cow::from(bind_group_layouts), push_constant_ranges: Cow::from(push_constant_ranges), }; @@ -572,7 +571,7 @@ pub enum ShaderParseError { } #[inline] -pub fn map_shader_module<'a>( +pub unsafe fn map_shader_module<'a>( _: &native::WGPUShaderModuleDescriptor, spirv: Option<&native::WGPUShaderSourceSPIRV>, wgsl: Option<&native::WGPUShaderSourceWGSL>, @@ -580,8 +579,7 @@ pub fn map_shader_module<'a>( ) -> Result, ShaderParseError> { #[cfg(feature = "wgsl")] if let Some(wgsl) = wgsl { - let c_str: &CStr = unsafe { CStr::from_ptr(wgsl.code) }; - let str_slice: &str = c_str.to_str().expect("not a valid utf-8 string"); + let str_slice: &str = string_view_into_str(wgsl.code).unwrap_or(""); return Ok(wgc::pipeline::ShaderModuleSource::Wgsl(Cow::Borrowed( str_slice, ))); @@ -605,8 +603,7 @@ pub fn map_shader_module<'a>( #[cfg(feature = "glsl")] if let Some(glsl) = glsl { - let c_str: &CStr = unsafe { CStr::from_ptr(glsl.code) }; - let str_slice: &str = c_str.to_str().expect("not a valid utf-8 string"); + let str_slice: &str = string_view_into_str(glsl.code).unwrap_or(""); let mut options = naga::front::glsl::Options::from( map_shader_stage(glsl.stage) .expect("invalid shader stage for shader module glsl descriptor"), @@ -614,11 +611,8 @@ pub fn map_shader_module<'a>( 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"); - - let value_c_str: &CStr = unsafe { CStr::from_ptr(define.value) }; - let value_str_slice: &str = value_c_str.to_str().expect("not a valid utf-8 string"); + let name_str_slice: &str = string_view_into_str(define.name).unwrap_or(""); + let value_str_slice: &str = string_view_into_str(define.value).unwrap_or(""); options .defines @@ -1478,12 +1472,12 @@ pub fn map_query_set_index(index: u32) -> Option { } #[inline] -pub fn map_query_set_descriptor<'a>( +pub unsafe fn map_query_set_descriptor<'a>( desc: &native::WGPUQuerySetDescriptor, extras: Option<&native::WGPUQuerySetDescriptorExtras>, ) -> wgt::QuerySetDescriptor> { wgt::QuerySetDescriptor { - label: ptr_into_label(desc.label), + label: string_view_into_label(desc.label), count: desc.count, ty: match (desc.type_, extras) { (native::WGPUQueryType_Occlusion, _) => wgt::QueryType::Occlusion, diff --git a/src/lib.rs b/src/lib.rs index 3513ffbc..f52e3521 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -11,7 +11,6 @@ use smallvec::SmallVec; use std::{ borrow::Cow, error, - ffi::{CStr, CString}, fmt::Display, mem, num::NonZeroU64, @@ -19,8 +18,8 @@ use std::{ thread, }; use utils::{ - get_base_device_limits_from_adapter_limits, make_slice, ptr_into_label, ptr_into_path, - texture_format_has_depth, + get_base_device_limits_from_adapter_limits, make_slice, str_into_string_view, + string_view_into_label, string_view_into_str, texture_format_has_depth, }; use wgc::{ command::{bundle_ffi, DynComputePass, DynRenderPass}, @@ -399,6 +398,10 @@ impl Drop for WGPUTextureViewImpl { } const NULL_FUTURE: native::WGPUFuture = native::WGPUFuture { id: 0 }; +const EMPTY_STRING: native::WGPUStringView = native::WGPUStringView { + length: 0, + data: std::ptr::null(), +}; struct DeviceCallback { callback: T, @@ -412,11 +415,11 @@ type DeviceLostCallback = DeviceCallback; unsafe extern "C" fn default_uncaptured_error_handler( _device: *const native::WGPUDevice, _typ: native::WGPUErrorType, - message: *const ::std::os::raw::c_char, + message: native::WGPUStringView, _userdata1: *mut ::std::os::raw::c_void, _userdata2: *mut ::std::os::raw::c_void, ) { - let message = unsafe { CStr::from_ptr(message) }.to_str().unwrap(); + let message = string_view_into_str(message).unwrap_or(""); log::warn!("Handling wgpu uncaptured errors as fatal by default"); panic!("wgpu uncaptured error:\n{message}\n"); } @@ -428,11 +431,11 @@ const DEFAULT_UNCAPTURED_ERROR_HANDLER: UncapturedErrorCallback = UncapturedErro unsafe extern "C" fn default_device_lost_handler( _device: *const native::WGPUDevice, _reason: native::WGPUDeviceLostReason, - message: *const ::std::os::raw::c_char, + message: native::WGPUStringView, _userdata1: *mut ::std::os::raw::c_void, _userdata2: *mut ::std::os::raw::c_void, ) { - let message = unsafe { CStr::from_ptr(message) }.to_str().unwrap(); + let message = string_view_into_str(message).unwrap_or(""); log::warn!("Handling wgpu device lost errors as fatal by default"); panic!("wgpu device lost error:\n{message}\n"); } @@ -513,12 +516,12 @@ impl ErrorSinkRaw { // handle device lost error early if let Some(callback) = self.device_lost_handler.callback { let userdata = &self.device_lost_handler.userdata; - let msg = CString::new(err.to_string()).unwrap(); + let msg = err.to_string(); unsafe { callback( &self.device.unwrap(), native::WGPUDeviceLostReason_Destroyed, - msg.as_ptr(), + str_into_string_view(&msg), userdata.get_1(), userdata.get_2(), ); @@ -550,12 +553,12 @@ impl ErrorSinkRaw { None => { if let Some(callback) = self.uncaptured_handler.callback { let userdata = &self.uncaptured_handler.userdata; - let msg = CString::new(err.to_string()).unwrap(); + let msg = err.to_string(); unsafe { callback( &self.device.unwrap(), typ, - msg.as_ptr(), + str_into_string_view(&msg), userdata.get_1(), userdata.get_2(), ) @@ -726,10 +729,10 @@ pub unsafe extern "C" fn wgpuAdapterGetInfo( Err(err) => handle_error_fatal(err, "wgpuAdapterGetInfo"), }; - info.vendor = CString::new(result.driver).unwrap().into_raw(); - info.architecture = CString::default().into_raw(); // TODO(webgpu.h) - info.device = CString::new(result.name).unwrap().into_raw(); - info.description = CString::new(result.driver_info).unwrap().into_raw(); + info.vendor = utils::str_into_owned_string_view(&result.driver); + info.architecture = EMPTY_STRING; // TODO(webgpu.h) + info.device = utils::str_into_owned_string_view(&result.name); + info.description = utils::str_into_owned_string_view(&result.driver_info); info.backendType = map_backend_type(result.backend); info.adapterType = map_adapter_type(result.device_type); info.vendorID = result.vendor; @@ -760,18 +763,10 @@ pub unsafe extern "C" fn wgpuAdapterHasFeature( #[no_mangle] pub unsafe extern "C" fn wgpuAdapterInfoFreeMembers(adapter_info: native::WGPUAdapterInfo) { - drop(CString::from_raw( - adapter_info.vendor as *mut std::ffi::c_char, - )); - drop(CString::from_raw( - adapter_info.architecture as *mut std::ffi::c_char, - )); - drop(CString::from_raw( - adapter_info.device as *mut std::ffi::c_char, - )); - drop(CString::from_raw( - adapter_info.description as *mut std::ffi::c_char, - )); + utils::drop_string_view(adapter_info.vendor); + utils::drop_string_view(adapter_info.architecture); + utils::drop_string_view(adapter_info.device); + utils::drop_string_view(adapter_info.description); } #[no_mangle] @@ -789,11 +784,11 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( let adapter_limits = match gfx_select!(adapter_id => context.adapter_limits(adapter_id)) { Ok(adapter_limits) => adapter_limits, Err(cause) => { - let msg = CString::new(format_error(&cause)).unwrap(); + let msg = format_error(&cause); callback( native::WGPURequestDeviceStatus_Error, std::ptr::null(), - msg.as_ptr(), + str_into_string_view(&msg), callback_info.userdata1, callback_info.userdata2, ); @@ -819,7 +814,7 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( required_limits: base_limits, ..Default::default() }, - std::ptr::null(), + None, DEFAULT_DEVICE_LOST_HANDLER, None, ), @@ -829,14 +824,13 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( context.adapter_request_device( adapter_id, &desc, - ptr_into_path(trace_str), + trace_str.map(std::path::Path::new), None, None ) ); match err { None => { - let message = CString::default(); let mut error_sink = ErrorSinkRaw::new(device_lost_handler); if let Some(error_callback) = error_callback { error_sink.uncaptured_handler = error_callback; @@ -857,17 +851,17 @@ pub unsafe extern "C" fn wgpuAdapterRequestDevice( callback( native::WGPURequestDeviceStatus_Success, device, - message.as_ptr(), + EMPTY_STRING, callback_info.userdata1, callback_info.userdata2, ); } Some(err) => { - let message = CString::new(format_error(&err)).unwrap(); + let message = format_error(&err); callback( native::WGPURequestDeviceStatus_Error, std::ptr::null_mut(), - message.as_ptr(), + str_into_string_view(&message), callback_info.userdata1, callback_info.userdata2, ); @@ -1016,7 +1010,7 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( callback: Some(wgc::resource::BufferMapCallback::from_rust(Box::new( move |result: resource::BufferAccessResult| { let (status, message) = match result { - Ok(()) => (native::WGPUMapAsyncStatus_Success, CString::default()), + Ok(()) => (native::WGPUMapAsyncStatus_Success, String::default()), Err(cause) => { let code = match cause { resource::BufferAccessError::MapAborted => { @@ -1025,11 +1019,16 @@ pub unsafe extern "C" fn wgpuBufferMapAsync( _ => native::WGPUMapAsyncStatus_Error, }; - (code, CString::new(format_error(&cause)).unwrap()) + (code, format_error(&cause)) } }; - callback(status, message.as_ptr(), userdata.get_1(), userdata.get_2()); + callback( + status, + str_into_string_view(&message), + userdata.get_1(), + userdata.get_2(), + ); }, ))), }; @@ -1117,7 +1116,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginComputePass( let desc = match descriptor { Some(descriptor) => wgc::command::ComputePassDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), timestamp_writes: timestamp_writes.as_ref(), }, None => wgc::command::ComputePassDescriptor::default(), @@ -1194,7 +1193,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderBeginRenderPass( }); let desc = wgc::command::RenderPassDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), color_attachments: Cow::Owned( make_slice(descriptor.colorAttachments, descriptor.colorAttachmentCount) .iter() @@ -1417,7 +1416,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderFinish( let desc = match descriptor { Some(descriptor) => wgt::CommandBufferDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), }, None => wgt::CommandBufferDescriptor::default(), }; @@ -1437,7 +1436,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderFinish( #[no_mangle] pub unsafe extern "C" fn wgpuCommandEncoderInsertDebugMarker( command_encoder: native::WGPUCommandEncoder, - marker_label: *const std::ffi::c_char, + marker_label: native::WGPUStringView, ) { let (command_encoder_id, context, error_sink) = { let command_encoder = command_encoder.as_ref().expect("invalid command encoder"); @@ -1448,7 +1447,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderInsertDebugMarker( ) }; - if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_insert_debug_marker(command_encoder_id, CStr::from_ptr(marker_label).to_str().unwrap())) + if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_insert_debug_marker(command_encoder_id, string_view_into_str(marker_label).unwrap_or(""))) { handle_error( error_sink, @@ -1481,7 +1480,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderPopDebugGroup( #[no_mangle] pub unsafe extern "C" fn wgpuCommandEncoderPushDebugGroup( command_encoder: native::WGPUCommandEncoder, - group_label: *const std::ffi::c_char, + group_label: native::WGPUStringView, ) { let (command_encoder_id, context, error_sink) = { let command_encoder = command_encoder.as_ref().expect("invalid command encoder"); @@ -1492,7 +1491,7 @@ pub unsafe extern "C" fn wgpuCommandEncoderPushDebugGroup( ) }; - if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_push_debug_group(command_encoder_id, CStr::from_ptr(group_label).to_str().unwrap())) + if let Err(cause) = gfx_select!(command_encoder_id => context.command_encoder_push_debug_group(command_encoder_id, string_view_into_str(group_label).unwrap_or(""))) { handle_error(error_sink, cause, None, "wgpuCommandEncoderPushDebugGroup"); } @@ -1633,14 +1632,14 @@ pub unsafe extern "C" fn wgpuComputePassEncoderEnd(pass: native::WGPUComputePass #[no_mangle] pub unsafe extern "C" fn wgpuComputePassEncoderInsertDebugMarker( pass: native::WGPUComputePassEncoder, - marker_label: *const std::ffi::c_char, + marker_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid compute pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.insert_debug_marker( &pass.context, - CStr::from_ptr(marker_label).to_str().unwrap(), + string_view_into_str(marker_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -1672,14 +1671,14 @@ pub unsafe extern "C" fn wgpuComputePassEncoderPopDebugGroup(pass: native::WGPUC #[no_mangle] pub unsafe extern "C" fn wgpuComputePassEncoderPushDebugGroup( pass: native::WGPUComputePassEncoder, - group_label: *const std::ffi::c_char, + group_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid compute pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.push_debug_group( &pass.context, - CStr::from_ptr(group_label).to_str().unwrap(), + string_view_into_str(group_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -1832,7 +1831,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroup( .collect::>(); let desc = wgc::binding_model::BindGroupDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), layout: bind_group_layout_id, entries: Cow::Borrowed(&entries), }; @@ -1869,7 +1868,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBindGroupLayout( .collect::>(); let desc = wgc::binding_model::BindGroupLayoutDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), entries: Cow::Borrowed(&entries), }; let (bind_group_layout_id, error) = @@ -1901,7 +1900,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateBuffer( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgt::BufferDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), size: descriptor.size, usage: from_u64_bits(descriptor.usage).expect("invalid buffer usage"), mapped_at_creation: descriptor.mappedAtCreation != 0, @@ -1935,7 +1934,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateCommandEncoder( }; let desc = match descriptor { Some(descriptor) => wgt::CommandEncoderDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), }, None => wgt::CommandEncoderDescriptor::default(), }; @@ -1970,7 +1969,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::ComputePipelineDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), layout: descriptor.layout.as_ref().map(|v| v.id), stage: wgc::pipeline::ProgrammableStageDescriptor { module: descriptor @@ -1980,7 +1979,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( .expect("invalid fragment shader module for render pipeline descriptor") .id .expect("invalid fragment shader module for render pipeline descriptor"), - entry_point: ptr_into_label(descriptor.compute.entryPoint), + entry_point: string_view_into_label(descriptor.compute.entryPoint), constants: Cow::Owned( make_slice( descriptor.compute.constants, @@ -1989,7 +1988,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateComputePipeline( .iter() .map(|entry| { ( - CStr::from_ptr(entry.key).to_str().unwrap().to_string(), + string_view_into_str(entry.key).unwrap_or("").to_string(), entry.value, ) }) @@ -2112,7 +2111,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderBundleEncoder( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::command::RenderBundleEncoderDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), color_formats: make_slice(descriptor.colorFormats, descriptor.colorFormatCount) .iter() .map(|format| conv::map_texture_format(*format)) @@ -2151,7 +2150,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::RenderPipelineDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), layout: descriptor.layout.as_ref().map(|v| v.id), vertex: wgc::pipeline::VertexState { stage: wgc::pipeline::ProgrammableStageDescriptor { @@ -2162,13 +2161,13 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .expect("invalid vertex shader module for vertex state") .id .expect("invalid vertex shader module for vertex state"), - entry_point: ptr_into_label(descriptor.vertex.entryPoint), + entry_point: string_view_into_label(descriptor.vertex.entryPoint), constants: Cow::Owned( make_slice(descriptor.vertex.constants, descriptor.vertex.constantCount) .iter() .map(|entry| { ( - CStr::from_ptr(entry.key).to_str().unwrap().to_string(), + string_view_into_str(entry.key).unwrap_or("").to_string(), entry.value, ) }) @@ -2271,13 +2270,13 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( .expect("invalid fragment shader module for render pipeline descriptor") .id .expect("invalid fragment shader module for render pipeline descriptor"), - entry_point: ptr_into_label(fragment.entryPoint), + entry_point: string_view_into_label(fragment.entryPoint), constants: Cow::Owned( make_slice(fragment.constants, fragment.constantCount) .iter() .map(|entry| { ( - CStr::from_ptr(entry.key).to_str().unwrap().to_string(), + string_view_into_str(entry.key).unwrap_or("").to_string(), entry.value, ) }) @@ -2347,7 +2346,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateSampler( let desc = match descriptor { Some(descriptor) => wgc::resource::SamplerDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), address_modes: [ conv::map_address_mode(descriptor.addressModeU), conv::map_address_mode(descriptor.addressModeV), @@ -2408,7 +2407,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::ShaderModuleDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), shader_bound_checks: wgt::ShaderBoundChecks::default(), }; @@ -2462,7 +2461,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateTexture( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgt::TextureDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), size: conv::map_extent3d(&descriptor.size), mip_level_count: descriptor.mipLevelCount, sample_count: descriptor.sampleCount, @@ -2624,24 +2623,23 @@ pub unsafe extern "C" fn wgpuDevicePopErrorScope( crate::Error::DeviceLost { .. } => unreachable!(), }; - let msg = CString::new(error.to_string()).unwrap(); + let msg = error.to_string(); unsafe { callback( native::WGPUPopErrorScopeStatus_Success, typ, - msg.as_ptr(), + str_into_string_view(&msg), callback_info.userdata1, callback_info.userdata2, ); }; } None => { - let msg = CString::default(); unsafe { callback( native::WGPUPopErrorScopeStatus_Success, native::WGPUErrorType_NoError, - msg.as_ptr(), + EMPTY_STRING, callback_info.userdata1, callback_info.userdata2, ); @@ -2761,7 +2759,7 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( callback( native::WGPURequestAdapterStatus_Error, std::ptr::null_mut(), - "unsupported backend type: d3d11".as_ptr() as _, + str_into_string_view("unsupported backend type: d3d11"), callback_info.userdata1, callback_info.userdata2, ); @@ -2781,20 +2779,19 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( match context.request_adapter(&desc, inputs) { Ok(adapter_id) => { - let message = CString::default(); callback( native::WGPURequestAdapterStatus_Success, Arc::into_raw(Arc::new(WGPUAdapterImpl { context: context.clone(), id: adapter_id, })), - message.as_ptr(), + EMPTY_STRING, callback_info.userdata1, callback_info.userdata2, ); } Err(err) => { - let message = CString::new(format_error(&err)).unwrap(); + let message = format_error(&err); callback( match err { wgc::instance::RequestAdapterError::NotFound => { @@ -2806,7 +2803,7 @@ pub unsafe extern "C" fn wgpuInstanceRequestAdapter( _ => native::WGPURequestAdapterStatus_Unknown, }, std::ptr::null_mut(), - message.as_ptr(), + str_into_string_view(&message), callback_info.userdata1, callback_info.userdata2, ); @@ -3146,7 +3143,7 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderFinish( let desc = match descriptor { Some(descriptor) => wgt::RenderBundleDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), }, None => wgt::RenderBundleDescriptor::default(), }; @@ -3164,40 +3161,49 @@ pub unsafe extern "C" fn wgpuRenderBundleEncoderFinish( #[no_mangle] pub unsafe extern "C" fn wgpuRenderBundleEncoderInsertDebugMarker( - bundle: native::WGPURenderBundleEncoder, - marker_label: *const std::ffi::c_char, + _bundle: native::WGPURenderBundleEncoder, + _marker_label: native::WGPUStringView, ) { - let bundle = bundle.as_ref().expect("invalid render bundle"); - let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); - let encoder = encoder.expect("invalid render bundle"); - let encoder = encoder.as_mut().unwrap(); + // These functions are not implemented in wgpu-core, and the API is incompatible with the new WGPUStringView. + // Commenting out until it's actually implemented. - bundle_ffi::wgpu_render_bundle_insert_debug_marker(encoder, marker_label); + // let bundle = bundle.as_ref().expect("invalid render bundle"); + // let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); + // let encoder = encoder.expect("invalid render bundle"); + // let encoder = encoder.as_mut().unwrap(); + + // bundle_ffi::wgpu_render_bundle_insert_debug_marker(encoder, marker_label); } #[no_mangle] pub unsafe extern "C" fn wgpuRenderBundleEncoderPopDebugGroup( - bundle: native::WGPURenderBundleEncoder, + _bundle: native::WGPURenderBundleEncoder, ) { - let bundle = bundle.as_ref().expect("invalid render bundle"); - let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); - let encoder = encoder.expect("invalid render bundle"); - let encoder = encoder.as_mut().unwrap(); + // These functions are not implemented in wgpu-core, and the API is incompatible with the new WGPUStringView. + // Commenting out until it's actually implemented. + + // let bundle = bundle.as_ref().expect("invalid render bundle"); + // let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); + // let encoder = encoder.expect("invalid render bundle"); + // let encoder = encoder.as_mut().unwrap(); - bundle_ffi::wgpu_render_bundle_pop_debug_group(encoder); + // bundle_ffi::wgpu_render_bundle_pop_debug_group(encoder); } #[no_mangle] pub unsafe extern "C" fn wgpuRenderBundleEncoderPushDebugGroup( - bundle: native::WGPURenderBundleEncoder, - group_label: *const std::ffi::c_char, + _bundle: native::WGPURenderBundleEncoder, + _group_label: native::WGPUStringView, ) { - let bundle = bundle.as_ref().expect("invalid render bundle"); - let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); - let encoder = encoder.expect("invalid render bundle"); - let encoder = encoder.as_mut().unwrap(); + // These functions are not implemented in wgpu-core, and the API is incompatible with the new WGPUStringView. + // Commenting out until it's actually implemented. + + // let bundle = bundle.as_ref().expect("invalid render bundle"); + // let encoder = bundle.encoder.as_mut().expect("invalid render bundle"); + // let encoder = encoder.expect("invalid render bundle"); + // let encoder = encoder.as_mut().unwrap(); - bundle_ffi::wgpu_render_bundle_push_debug_group(encoder, group_label); + // bundle_ffi::wgpu_render_bundle_push_debug_group(encoder, group_label); } #[no_mangle] @@ -3492,14 +3498,14 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderExecuteBundles( #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderInsertDebugMarker( pass: native::WGPURenderPassEncoder, - marker_label: *const std::ffi::c_char, + marker_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid render pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.insert_debug_marker( &pass.context, - CStr::from_ptr(marker_label).to_str().unwrap(), + string_view_into_str(marker_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -3531,14 +3537,14 @@ pub unsafe extern "C" fn wgpuRenderPassEncoderPopDebugGroup(pass: native::WGPURe #[no_mangle] pub unsafe extern "C" fn wgpuRenderPassEncoderPushDebugGroup( pass: native::WGPURenderPassEncoder, - group_label: *const std::ffi::c_char, + group_label: native::WGPUStringView, ) { let pass = pass.as_ref().expect("invalid render pass"); let encoder = pass.encoder.as_mut().unwrap(); match encoder.push_debug_group( &pass.context, - CStr::from_ptr(group_label).to_str().unwrap(), + string_view_into_str(group_label).unwrap_or(""), 0, ) { Ok(()) => (), @@ -4118,7 +4124,7 @@ pub unsafe extern "C" fn wgpuTextureCreateView( } wgc::resource::TextureViewDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), format: conv::map_texture_format(descriptor.format), dimension: conv::map_texture_view_dimension(descriptor.dimension), range: wgt::ImageSubresourceRange { diff --git a/src/logging.rs b/src/logging.rs index f5c31e78..1b71147c 100644 --- a/src/logging.rs +++ b/src/logging.rs @@ -1,7 +1,6 @@ -use crate::{map_enum, native}; +use crate::{map_enum, native, utils}; use log::{Level, LevelFilter, Metadata, Record}; use parking_lot::RwLock; -use std::ffi::CString; #[no_mangle] pub extern "C" fn wgpuGetVersion() -> std::os::raw::c_uint { @@ -40,7 +39,6 @@ impl log::Log for Logger { if let Some(callback) = logger.callback { let msg = record.args().to_string(); - let msg_c = CString::new(msg).unwrap(); let level = match record.level() { Level::Error => native::WGPULogLevel_Error, Level::Warn => native::WGPULogLevel_Warn, @@ -50,7 +48,7 @@ impl log::Log for Logger { }; unsafe { - callback(level, msg_c.as_ptr(), logger.userdata); + callback(level, utils::str_into_string_view(&msg), logger.userdata); } // We do not use std::mem::forget(msg_c), so Rust will reclaim the memory diff --git a/src/unimplemented.rs b/src/unimplemented.rs index eebaf763..8f56ab25 100644 --- a/src/unimplemented.rs +++ b/src/unimplemented.rs @@ -1,16 +1,14 @@ use crate::native; #[no_mangle] -pub extern "C" fn wgpuGetProcAddress( - _proc_name: *const ::std::os::raw::c_char, -) -> native::WGPUProc { +pub extern "C" fn wgpuGetProcAddress(_proc_name: native::WGPUStringView) -> native::WGPUProc { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuBindGroupSetLabel( _bind_group: native::WGPUBindGroup, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -18,7 +16,7 @@ pub extern "C" fn wgpuBindGroupSetLabel( #[no_mangle] pub extern "C" fn wgpuBindGroupLayoutSetLabel( _bind_group_layout: native::WGPUBindGroupLayout, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -29,17 +27,14 @@ pub extern "C" fn wgpuBufferGetMapState(_buffer: native::WGPUBuffer) -> native:: } #[no_mangle] -pub extern "C" fn wgpuBufferSetLabel( - _buffer: native::WGPUBuffer, - _label: *const ::std::os::raw::c_char, -) { +pub extern "C" fn wgpuBufferSetLabel(_buffer: native::WGPUBuffer, _label: native::WGPUStringView) { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuCommandBufferSetLabel( _command_buffer: native::WGPUCommandBuffer, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -47,7 +42,7 @@ pub extern "C" fn wgpuCommandBufferSetLabel( #[no_mangle] pub extern "C" fn wgpuCommandEncoderSetLabel( _command_encoder: native::WGPUCommandEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -55,7 +50,7 @@ pub extern "C" fn wgpuCommandEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuComputePassEncoderSetLabel( _compute_pass_encoder: native::WGPUComputePassEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -63,7 +58,7 @@ pub extern "C" fn wgpuComputePassEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuComputePipelineSetLabel( _compute_pipeline: native::WGPUComputePipeline, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -87,10 +82,7 @@ pub extern "C" fn wgpuDeviceCreateRenderPipelineAsync( } #[no_mangle] -pub extern "C" fn wgpuDeviceSetLabel( - _device: native::WGPUDevice, - _label: *const ::std::os::raw::c_char, -) { +pub extern "C" fn wgpuDeviceSetLabel(_device: native::WGPUDevice, _label: native::WGPUStringView) { unimplemented!(); } @@ -110,7 +102,7 @@ pub extern "C" fn wgpuInstanceProcessEvents(_instance: native::WGPUInstance) { #[no_mangle] pub extern "C" fn wgpuPipelineLayoutSetLabel( _pipeline_layout: native::WGPUPipelineLayout, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -118,23 +110,20 @@ pub extern "C" fn wgpuPipelineLayoutSetLabel( #[no_mangle] pub extern "C" fn wgpuQuerySetSetLabel( _query_set: native::WGPUQuerySet, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } #[no_mangle] -pub extern "C" fn wgpuQueueSetLabel( - _queue: native::WGPUQueue, - _label: *const ::std::os::raw::c_char, -) { +pub extern "C" fn wgpuQueueSetLabel(_queue: native::WGPUQueue, _label: native::WGPUStringView) { unimplemented!(); } #[no_mangle] pub extern "C" fn wgpuRenderBundleSetLabel( _render_bundle: native::WGPURenderBundle, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -142,7 +131,7 @@ pub extern "C" fn wgpuRenderBundleSetLabel( #[no_mangle] pub extern "C" fn wgpuRenderBundleEncoderSetLabel( _render_bundle_encoder: native::WGPURenderBundleEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -150,7 +139,7 @@ pub extern "C" fn wgpuRenderBundleEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuRenderPassEncoderSetLabel( _render_pass_encoder: native::WGPURenderPassEncoder, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -158,7 +147,7 @@ pub extern "C" fn wgpuRenderPassEncoderSetLabel( #[no_mangle] pub extern "C" fn wgpuRenderPipelineSetLabel( _render_pipeline: native::WGPURenderPipeline, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -166,7 +155,7 @@ pub extern "C" fn wgpuRenderPipelineSetLabel( #[no_mangle] pub extern "C" fn wgpuSamplerSetLabel( _sampler: native::WGPUSampler, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -182,7 +171,7 @@ pub extern "C" fn wgpuShaderModuleGetCompilationInfo( #[no_mangle] pub extern "C" fn wgpuShaderModuleSetLabel( _shader_module: native::WGPUShaderModule, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -190,7 +179,7 @@ pub extern "C" fn wgpuShaderModuleSetLabel( #[no_mangle] pub extern "C" fn wgpuSurfaceSetLabel( _surface: native::WGPUSurface, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -198,7 +187,7 @@ pub extern "C" fn wgpuSurfaceSetLabel( #[no_mangle] pub extern "C" fn wgpuTextureSetLabel( _texture: native::WGPUTexture, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } @@ -206,7 +195,7 @@ pub extern "C" fn wgpuTextureSetLabel( #[no_mangle] pub extern "C" fn wgpuTextureViewSetLabel( _texture_view: native::WGPUTextureView, - _label: *const ::std::os::raw::c_char, + _label: native::WGPUStringView, ) { unimplemented!(); } diff --git a/src/utils.rs b/src/utils.rs index f3b88c79..e0fdf463 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,8 +1,6 @@ -use std::{ - borrow::Cow, - ffi::CStr, - path::{Path, PathBuf}, -}; +use std::{borrow::Cow, ffi::CStr}; + +use crate::native; // A dummy wrapper that is `Send` + `Sync` to store userdata pointer // to be usable across Rust callbacks. @@ -39,28 +37,6 @@ macro_rules! new_userdata { unsafe impl Send for Userdata {} unsafe impl Sync for Userdata {} -#[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) -} - // Safer wrapper around `slice::from_raw_parts` to handle // invalid `ptr` when `len` is zero. #[inline] @@ -294,6 +270,71 @@ macro_rules! map_enum { }; } +pub unsafe fn string_view_into_str<'a>(string_view: native::WGPUStringView) -> Option<&'a str> { + if string_view.data.is_null() { + match string_view.length { + crate::conv::WGPU_STRLEN => None, + 0 => Some(""), + _ => panic!("Null address to WGPUStringView!"), + } + } else { + unsafe { + let bytes = match string_view.length { + crate::conv::WGPU_STRLEN => CStr::from_ptr(string_view.data).to_bytes(), + _ => make_slice(string_view.data as *const u8, string_view.length), + }; + + Some(std::str::from_utf8_unchecked(bytes)) + } + } +} + +pub unsafe fn string_view_into_label<'a>(string_view: native::WGPUStringView) -> wgc::Label<'a> { + string_view_into_str(string_view).map(Cow::Borrowed) +} + +pub const fn str_into_string_view(str: &str) -> native::WGPUStringView { + native::WGPUStringView { + data: str.as_ptr() as *const std::os::raw::c_char, + length: str.len(), + } +} + +/// Create a string view that "owns" its memory, so it can be later dropped with [drop_string_view]. +pub fn str_into_owned_string_view(str: &str) -> native::WGPUStringView { + let boxed = String::from(str).into_boxed_str(); + + let result = native::WGPUStringView { + data: boxed.as_ptr() as *const std::os::raw::c_char, + length: boxed.len(), + }; + + std::mem::forget(boxed); + + result +} + +/// Drop a string view created by [str_into_owned_string_view]. +pub unsafe fn drop_string_view(view: native::WGPUStringView) { + if view.data.is_null() { + return; + } + + drop(Box::from_raw(std::slice::from_raw_parts_mut( + view.data as *mut u8, + view.length, + ))) +} + +#[test] +pub fn test_string_view_into_str() { + let str = "Hello, world!"; + let string_view = str_into_string_view(str); + let str_2 = unsafe { string_view_into_str(string_view) }.unwrap(); + + assert_eq!(str, str_2) +} + #[test] pub fn test_get_base_device_limits_from_adapter_limits() { fn expected_limits_with_default_resolution( From 8947cf2b2fe298f7885ccd39a0c74ca75cd59abc Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 3 Oct 2024 01:46:23 +0200 Subject: [PATCH 08/18] Only specify major version for bitflags dependency --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index 406947bf..8fa64f86 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -157,7 +157,7 @@ log = "0.4" thiserror = "1" parking_lot = "0.12" smallvec = "1" -bitflags = "2.6.0" +bitflags = "2" [build-dependencies] bindgen = "0.70" From fe965c8fac7de8af61819e03a3e56c6344a707fc Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Thu, 3 Oct 2024 01:51:22 +0200 Subject: [PATCH 09/18] Remove redundant unsafe block --- src/utils.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index e0fdf463..3b383511 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -278,14 +278,12 @@ pub unsafe fn string_view_into_str<'a>(string_view: native::WGPUStringView) -> O _ => panic!("Null address to WGPUStringView!"), } } else { - unsafe { - let bytes = match string_view.length { - crate::conv::WGPU_STRLEN => CStr::from_ptr(string_view.data).to_bytes(), - _ => make_slice(string_view.data as *const u8, string_view.length), - }; + let bytes = match string_view.length { + crate::conv::WGPU_STRLEN => CStr::from_ptr(string_view.data).to_bytes(), + _ => make_slice(string_view.data as *const u8, string_view.length), + }; - Some(std::str::from_utf8_unchecked(bytes)) - } + Some(std::str::from_utf8_unchecked(bytes)) } } From 482bc249632d28f8be46c3db181571f7f3440c08 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 19 Oct 2024 16:36:39 +0200 Subject: [PATCH 10/18] Add wgpuGetInstanceFeatures stuff All stubs, since we don't have WaitAny at the moment. --- src/lib.rs | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index f52e3521..7e3ec587 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -649,10 +649,16 @@ pub unsafe extern "C" fn wgpuCreateInstance( descriptor: Option<&native::WGPUInstanceDescriptor>, ) -> native::WGPUInstance { let instance_desc = match descriptor { - Some(descriptor) => follow_chain!(map_instance_descriptor( - (descriptor), - WGPUSType_InstanceExtras => native::WGPUInstanceExtras - )), + Some(descriptor) => { + if descriptor.features.timedWaitAnyEnable != 0 || descriptor.features.timedWaitAnyMaxCount > 0 { + panic!("Unsupported timed WaitAny features specified"); + } + + follow_chain!(map_instance_descriptor( + (descriptor), + WGPUSType_InstanceExtras => native::WGPUInstanceExtras + )) + }, None => wgt::InstanceDescriptor::default(), }; @@ -661,6 +667,19 @@ pub unsafe extern "C" fn wgpuCreateInstance( })) } +#[no_mangle] +pub unsafe extern "C" fn wgpuGetInstanceFeatures( + features: Option<&mut native::WGPUInstanceFeatures>, +) { + let features = features.expect("invalid return pointer \"features\""); + *features = native::WGPUInstanceFeatures { + nextInChain: std::ptr::null_mut(), + // WaitAny is currently completely unsupported, so... + timedWaitAnyEnable: false as native::WGPUBool, + timedWaitAnyMaxCount: 0 + } +} + // Adapter methods #[no_mangle] From 8f80a2cec7aaceb55a6e72dffba59630324535bc Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 19 Oct 2024 17:19:34 +0200 Subject: [PATCH 11/18] I forgot to cargo fmt again --- src/lib.rs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 7e3ec587..2af62407 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -650,15 +650,17 @@ pub unsafe extern "C" fn wgpuCreateInstance( ) -> native::WGPUInstance { let instance_desc = match descriptor { Some(descriptor) => { - if descriptor.features.timedWaitAnyEnable != 0 || descriptor.features.timedWaitAnyMaxCount > 0 { + if descriptor.features.timedWaitAnyEnable != 0 + || descriptor.features.timedWaitAnyMaxCount > 0 + { panic!("Unsupported timed WaitAny features specified"); } follow_chain!(map_instance_descriptor( - (descriptor), - WGPUSType_InstanceExtras => native::WGPUInstanceExtras - )) - }, + (descriptor), + WGPUSType_InstanceExtras => native::WGPUInstanceExtras + )) + } None => wgt::InstanceDescriptor::default(), }; @@ -676,7 +678,7 @@ pub unsafe extern "C" fn wgpuGetInstanceFeatures( nextInChain: std::ptr::null_mut(), // WaitAny is currently completely unsupported, so... timedWaitAnyEnable: false as native::WGPUBool, - timedWaitAnyMaxCount: 0 + timedWaitAnyMaxCount: 0, } } From 77dfe522533f5ca6f5f92d4e5b66661d635bb232 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sat, 19 Oct 2024 17:20:08 +0200 Subject: [PATCH 12/18] Implement "NotUsed" bind group entry types Updates to https://github.com/webgpu-native/webgpu-headers/commit/6a23100d61ee768f42a81880a0f5c982cffc4c30 --- ffi/webgpu-headers | 2 +- src/conv.rs | 18 ++++++++++-------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index a41b613a..6a23100d 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit a41b613a48a1df22262326d4ed85a9fcdc510afb +Subproject commit 6a23100d61ee768f42a81880a0f5c982cffc4c30 diff --git a/src/conv.rs b/src/conv.rs index e2c15d6c..0dee4ed1 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -1367,16 +1367,16 @@ pub fn map_bind_group_layout_entry( entry: &native::WGPUBindGroupLayoutEntry, extras: Option<&native::WGPUBindGroupLayoutEntryExtras>, ) -> wgt::BindGroupLayoutEntry { - let is_buffer = entry.buffer.type_ != native::WGPUBufferBindingType_Undefined; - let is_sampler = entry.sampler.type_ != native::WGPUSamplerBindingType_Undefined; - let is_texture = entry.texture.sampleType != native::WGPUTextureSampleType_Undefined; + let is_buffer = entry.buffer.type_ != native::WGPUBufferBindingType_BindingNotUsed; + let is_sampler = entry.sampler.type_ != native::WGPUSamplerBindingType_BindingNotUsed; + let is_texture = entry.texture.sampleType != native::WGPUTextureSampleType_BindingNotUsed; let is_storage_texture = - entry.storageTexture.access != native::WGPUStorageTextureAccess_Undefined; + entry.storageTexture.access != native::WGPUStorageTextureAccess_BindingNotUsed; let ty = if is_texture { wgt::BindingType::Texture { sample_type: match entry.texture.sampleType { - native::WGPUTextureSampleType_Float => { + native::WGPUTextureSampleType_Float | native::WGPUTextureSampleType_Undefined => { wgt::TextureSampleType::Float { filterable: true } } native::WGPUTextureSampleType_UnfilterableFloat => { @@ -1400,7 +1400,7 @@ pub fn map_bind_group_layout_entry( } } else if is_sampler { match entry.sampler.type_ { - native::WGPUSamplerBindingType_Filtering => { + native::WGPUSamplerBindingType_Filtering | native::WGPUSamplerBindingType_Undefined => { wgt::BindingType::Sampler(wgt::SamplerBindingType::Filtering) } native::WGPUSamplerBindingType_NonFiltering => { @@ -1414,7 +1414,7 @@ pub fn map_bind_group_layout_entry( } else if is_storage_texture { wgt::BindingType::StorageTexture { access: map_storage_texture_access(entry.storageTexture.access) - .expect("invalid storage texture access for storage texture binding layout"), + .unwrap_or(wgt::StorageTextureAccess::WriteOnly), format: map_texture_format(entry.storageTexture.format) .expect("invalid texture format for storage texture binding layout"), view_dimension: match entry.storageTexture.viewDimension { @@ -1432,7 +1432,9 @@ pub fn map_bind_group_layout_entry( } else if is_buffer { wgt::BindingType::Buffer { ty: match entry.buffer.type_ { - native::WGPUBufferBindingType_Uniform => wgt::BufferBindingType::Uniform, + native::WGPUBufferBindingType_Uniform | native::WGPUBufferBindingType_Undefined => { + wgt::BufferBindingType::Uniform + } native::WGPUBufferBindingType_Storage => { wgt::BufferBindingType::Storage { read_only: false } } From 3c3c2921a1bd94487bcac124b9406086eb9cf910 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Oct 2024 02:33:09 +0200 Subject: [PATCH 13/18] Update to new undefined enums Update to https://github.com/webgpu-native/webgpu-headers/commit/f1cdc3fd149cebe166991310b34259f9af5b9df5 Also went through a bunch of existing enum conversions and fixed up some seemingly spec-incorrect cases of undefined enums not being handled properly. As part of this, I made a new helper map_enum_with_undefined!() which distinguishes undefined and unknown enum values. Previously, much code relied on undefined being caught in the same net as an unknown value. This is no longer the case. --- ffi/webgpu-headers | 2 +- src/conv.rs | 71 ++++++++++++++++++++++++---------------------- src/lib.rs | 38 ++++++++++++++++--------- src/utils.rs | 41 ++++++++++++++++++++++++++ 4 files changed, 104 insertions(+), 48 deletions(-) diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index 6a23100d..f1cdc3fd 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit 6a23100d61ee768f42a81880a0f5c982cffc4c30 +Subproject commit f1cdc3fd149cebe166991310b34259f9af5b9df5 diff --git a/src/conv.rs b/src/conv.rs index 0dee4ed1..2366ff75 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -1,5 +1,5 @@ use crate::utils::{make_slice, string_view_into_label, string_view_into_str}; -use crate::{follow_chain, map_enum, new_userdata}; +use crate::{follow_chain, map_enum, map_enum_with_undefined, new_userdata}; use crate::{native, UncapturedErrorCallback}; use std::borrow::Cow; use std::num::{NonZeroIsize, NonZeroU32, NonZeroU64}; @@ -14,7 +14,7 @@ map_enum!( Discard, Store ); -map_enum!( +map_enum_with_undefined!( map_address_mode, WGPUAddressMode, wgt::AddressMode, @@ -23,7 +23,7 @@ map_enum!( Repeat, MirrorRepeat ); -map_enum!( +map_enum_with_undefined!( map_filter_mode, WGPUFilterMode, wgt::FilterMode, @@ -31,7 +31,7 @@ map_enum!( Nearest, Linear ); -map_enum!( +map_enum_with_undefined!( map_mipmap_filter_mode, WGPUMipmapFilterMode, wgt::FilterMode, @@ -39,7 +39,7 @@ map_enum!( Nearest, Linear ); -map_enum!( +map_enum_with_undefined!( map_compare_function, WGPUCompareFunction, wgt::CompareFunction, @@ -52,7 +52,7 @@ map_enum!( GreaterEqual, Always ); -map_enum!( +map_enum_with_undefined!( map_texture_aspect, WGPUTextureAspect, wgt::TextureAspect, @@ -61,7 +61,7 @@ map_enum!( StencilOnly, DepthOnly ); -map_enum!( +map_enum_with_undefined!( map_present_mode, WGPUPresentMode, wgt::PresentMode, @@ -71,7 +71,7 @@ map_enum!( Fifo, FifoRelaxed ); -map_enum!( +map_enum_with_undefined!( map_primitive_topology, WGPUPrimitiveTopology, wgt::PrimitiveTopology, @@ -89,7 +89,7 @@ map_enum!( Uint16, Uint32 ); -map_enum!( +map_enum_with_undefined!( map_blend_factor, WGPUBlendFactor, wgt::BlendFactor, @@ -108,7 +108,7 @@ map_enum!( Constant: Constant, OneMinusConstant: OneMinusConstant ); -map_enum!( +map_enum_with_undefined!( map_blend_operation, WGPUBlendOperation, wgt::BlendOperation, @@ -119,10 +119,11 @@ map_enum!( Min, Max ); -map_enum!( +map_enum_with_undefined!( map_stencil_operation, WGPUStencilOperation, wgt::StencilOperation, + "Unknown stencil operation", Keep, Zero, Replace, @@ -201,10 +202,11 @@ map_enum!( Version2 ); -map_enum!( +map_enum_with_undefined!( map_storage_texture_access, WGPUStorageTextureAccess, wgt::StorageTextureAccess, + "Unknown storage texture access", WriteOnly, ReadOnly, ReadWrite @@ -641,7 +643,7 @@ pub unsafe fn map_image_copy_texture( .id, mip_level: native.mipLevel, origin: map_origin3d(&native.origin), - aspect: map_texture_aspect(native.aspect), + aspect: map_texture_aspect(native.aspect).unwrap_or(wgt::TextureAspect::All), } } @@ -689,9 +691,9 @@ pub fn map_color(native: &native::WGPUColor) -> wgt::Color { #[inline] pub fn map_blend_component(native: native::WGPUBlendComponent) -> wgt::BlendComponent { wgt::BlendComponent { - src_factor: map_blend_factor(native.srcFactor), - dst_factor: map_blend_factor(native.dstFactor), - operation: map_blend_operation(native.operation), + src_factor: map_blend_factor(native.srcFactor).unwrap_or(wgt::BlendFactor::One), + dst_factor: map_blend_factor(native.dstFactor).unwrap_or(wgt::BlendFactor::Zero), + operation: map_blend_operation(native.operation).unwrap_or(wgt::BlendOperation::Add), } } @@ -699,6 +701,8 @@ pub fn map_blend_component(native: native::WGPUBlendComponent) -> wgt::BlendComp pub fn map_texture_view_dimension( value: native::WGPUTextureViewDimension, ) -> Option { + // This doesn't use map_enum_with_undefined! because the enum name after the _ + // isn't a valid ident on its own for the macro. match value { native::WGPUTextureViewDimension_1D => Some(wgt::TextureViewDimension::D1), native::WGPUTextureViewDimension_2D => Some(wgt::TextureViewDimension::D2), @@ -706,16 +710,20 @@ pub fn map_texture_view_dimension( native::WGPUTextureViewDimension_Cube => Some(wgt::TextureViewDimension::Cube), native::WGPUTextureViewDimension_CubeArray => Some(wgt::TextureViewDimension::CubeArray), native::WGPUTextureViewDimension_3D => Some(wgt::TextureViewDimension::D3), - _ => None, + native::WGPUTextureDimension_Undefined => None, + _ => panic!("Unknown texture view dimension"), } } #[inline] -pub fn map_texture_dimension(value: native::WGPUTextureDimension) -> wgt::TextureDimension { +pub fn map_texture_dimension(value: native::WGPUTextureDimension) -> Option { + // This doesn't use map_enum_with_undefined! because the enum name after the _ + // isn't a valid ident on its own for the macro. match value { - native::WGPUTextureDimension_1D => wgt::TextureDimension::D1, - native::WGPUTextureDimension_2D => wgt::TextureDimension::D2, - native::WGPUTextureDimension_3D => wgt::TextureDimension::D3, + native::WGPUTextureDimension_1D => Some(wgt::TextureDimension::D1), + native::WGPUTextureDimension_2D => Some(wgt::TextureDimension::D2), + native::WGPUTextureDimension_3D => Some(wgt::TextureDimension::D3), + native::WGPUTextureDimension_Undefined => None, x => panic!("Unknown texture dimension: {x}"), } } @@ -726,6 +734,7 @@ pub fn map_texture_format(value: native::WGPUTextureFormat) -> Option None, native::WGPUTextureFormat_R8Unorm => Some(wgt::TextureFormat::R8Unorm), native::WGPUTextureFormat_R8Snorm => Some(wgt::TextureFormat::R8Snorm), native::WGPUTextureFormat_R8Uint => Some(wgt::TextureFormat::R8Uint), @@ -830,7 +839,7 @@ pub fn map_texture_format(value: native::WGPUTextureFormat) -> Option Some(wgt::TextureFormat::Rgba16Unorm), native::WGPUNativeTextureFormat_Rgba16Snorm => Some(wgt::TextureFormat::Rgba16Snorm), native::WGPUNativeTextureFormat_NV12 => Some(wgt::TextureFormat::NV12), - _ => None, + _ => panic!("Unknown texture format"), } } @@ -957,13 +966,12 @@ pub fn map_stencil_face_state( ) -> wgt::StencilFaceState { wgt::StencilFaceState { compare: map_compare_function(value.compare) - .unwrap_or_else(|_| panic!("invalid compare function for {mode} stencil face state")), - fail_op: map_stencil_operation(value.failOp) - .unwrap_or_else(|_| panic!("invalid fail op for {mode} stencil face state")), + .unwrap_or_else(|_| panic!("invalid compare function for {mode} stencil face state")) + .unwrap_or(wgt::CompareFunction::Always), + fail_op: map_stencil_operation(value.failOp).unwrap_or(wgt::StencilOperation::Keep), depth_fail_op: map_stencil_operation(value.depthFailOp) - .unwrap_or_else(|_| panic!("invalid depth fail op for {mode} stencil face state")), - pass_op: map_stencil_operation(value.passOp) - .unwrap_or_else(|_| panic!("invalid pass op for {mode} stencil face state")), + .unwrap_or(wgt::StencilOperation::Keep), + pass_op: map_stencil_operation(value.passOp).unwrap_or(wgt::StencilOperation::Keep), } } @@ -1644,18 +1652,13 @@ pub fn map_surface_configuration( config: &native::WGPUSurfaceConfiguration, extras: Option<&native::WGPUSurfaceConfigurationExtras>, ) -> wgt::SurfaceConfiguration> { - let present_mode = match config.presentMode { - native::WGPUPresentMode_Undefined => wgt::PresentMode::Fifo, - _ => map_present_mode(config.presentMode), - }; - wgt::SurfaceConfiguration { usage: map_texture_usage_flags(config.usage as native::WGPUTextureUsage), format: map_texture_format(config.format) .expect("invalid format for surface configuration"), width: config.width, height: config.height, - present_mode, + present_mode: map_present_mode(config.presentMode).unwrap_or(wgt::PresentMode::Fifo), alpha_mode: map_composite_alpha_mode(config.alphaMode) .expect("invalid alpha mode for surface configuration"), view_formats: make_slice(config.viewFormats, config.viewFormatCount) diff --git a/src/lib.rs b/src/lib.rs index 2af62407..3d301c31 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2225,15 +2225,16 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( ), }, primitive: wgt::PrimitiveState { - topology: conv::map_primitive_topology(descriptor.primitive.topology), + topology: conv::map_primitive_topology(descriptor.primitive.topology) + .unwrap_or(wgt::PrimitiveTopology::TriangleList), strip_index_format: conv::map_index_format(descriptor.primitive.stripIndexFormat).ok(), front_face: match descriptor.primitive.frontFace { - native::WGPUFrontFace_CCW => wgt::FrontFace::Ccw, + native::WGPUFrontFace_CCW | native::WGPUFrontFace_Undefined => wgt::FrontFace::Ccw, native::WGPUFrontFace_CW => wgt::FrontFace::Cw, _ => panic!("invalid front face for primitive state"), }, cull_mode: match descriptor.primitive.cullMode { - native::WGPUCullMode_None => None, + native::WGPUCullMode_None | native::WGPUCullMode_Undefined => None, native::WGPUCullMode_Front => Some(wgt::Face::Front), native::WGPUCullMode_Back => Some(wgt::Face::Back), _ => panic!("invalid cull mode for primitive state"), @@ -2260,8 +2261,10 @@ pub unsafe extern "C" fn wgpuDeviceCreateRenderPipeline( wgt::DepthStencilState { format, depth_write_enabled: desc.depthWriteEnabled == native::WGPUOptionalBool_True, + // TODO: Is validation correct if we return always for undefined depth compare? depth_compare: conv::map_compare_function(desc.depthCompare) - .expect("invalid depth compare function for depth stencil state"), + .expect("invalid depth compare function for depth stencil state") + .unwrap_or(wgt::CompareFunction::Always), stencil: wgt::StencilState { front: conv::map_stencil_face_state(desc.stencilFront, "front"), back: conv::map_stencil_face_state(desc.stencilBack, "back"), @@ -2369,16 +2372,23 @@ pub unsafe extern "C" fn wgpuDeviceCreateSampler( Some(descriptor) => wgc::resource::SamplerDescriptor { label: string_view_into_label(descriptor.label), address_modes: [ - conv::map_address_mode(descriptor.addressModeU), - conv::map_address_mode(descriptor.addressModeV), - conv::map_address_mode(descriptor.addressModeW), + conv::map_address_mode(descriptor.addressModeU) + .unwrap_or(wgt::AddressMode::ClampToEdge), + conv::map_address_mode(descriptor.addressModeV) + .unwrap_or(wgt::AddressMode::ClampToEdge), + conv::map_address_mode(descriptor.addressModeW) + .unwrap_or(wgt::AddressMode::ClampToEdge), ], - mag_filter: conv::map_filter_mode(descriptor.magFilter), - min_filter: conv::map_filter_mode(descriptor.minFilter), - mipmap_filter: conv::map_mipmap_filter_mode(descriptor.mipmapFilter), + mag_filter: conv::map_filter_mode(descriptor.magFilter) + .unwrap_or(wgt::FilterMode::Nearest), + min_filter: conv::map_filter_mode(descriptor.minFilter) + .unwrap_or(wgt::FilterMode::Nearest), + mipmap_filter: conv::map_mipmap_filter_mode(descriptor.mipmapFilter) + .unwrap_or(wgt::FilterMode::Nearest), lod_min_clamp: descriptor.lodMinClamp, lod_max_clamp: descriptor.lodMaxClamp, - compare: conv::map_compare_function(descriptor.compare).ok(), + compare: conv::map_compare_function(descriptor.compare) + .expect("Invalid compare function"), anisotropy_clamp: descriptor.maxAnisotropy, // TODO(wgpu.h) border_color: None, @@ -2486,7 +2496,8 @@ pub unsafe extern "C" fn wgpuDeviceCreateTexture( size: conv::map_extent3d(&descriptor.size), mip_level_count: descriptor.mipLevelCount, sample_count: descriptor.sampleCount, - dimension: conv::map_texture_dimension(descriptor.dimension), + dimension: conv::map_texture_dimension(descriptor.dimension) + .unwrap_or(wgt::TextureDimension::D2), format: conv::map_texture_format(descriptor.format) .expect("invalid texture format for texture descriptor"), usage: from_u64_bits(descriptor.usage) @@ -4149,7 +4160,8 @@ pub unsafe extern "C" fn wgpuTextureCreateView( format: conv::map_texture_format(descriptor.format), dimension: conv::map_texture_view_dimension(descriptor.dimension), range: wgt::ImageSubresourceRange { - aspect: conv::map_texture_aspect(descriptor.aspect), + aspect: conv::map_texture_aspect(descriptor.aspect) + .unwrap_or(wgt::TextureAspect::All), base_mip_level: descriptor.baseMipLevel, mip_level_count: match descriptor.mipLevelCount { 0 => panic!("invalid mipLevelCount"), diff --git a/src/utils.rs b/src/utils.rs index 3b383511..cc152f56 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -270,6 +270,47 @@ macro_rules! map_enum { }; } +/// Equivalent to [map_enum], but it returns [Option] and "undefined" values are converted to [None]. +#[macro_export] +macro_rules! map_enum_with_undefined { + ($name:ident, $c_name:ident, $rs_type:ty, $($variant:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Result, native::$c_name> { + match value { + paste::paste!(native::[<$c_name _ Undefined>]) => Ok(None), + $(paste::paste!(native::[<$c_name _ $variant>]) => Ok(Some(<$rs_type>::$variant))),+, + x => Err(x), + } + } + }; + ($name:ident, $c_name:ident, $rs_type:ty, $err_msg:literal, $($variant:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Option<$rs_type> { + map_enum_with_undefined!(map_fn, $c_name, $rs_type, $($variant),+); + + map_fn(value).expect($err_msg) + } + }; + ($name:ident, $c_name:ident, $rs_type:ty, $($native_variant:ident:$variant2:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Result, native::$c_name> { + match value { + paste::paste!(native::[<$c_name _ Undefined>]) => Ok(None), + $(paste::paste!(native::[<$c_name _ $native_variant>]) => Ok(Some(<$rs_type>::$variant2))),+, + x => Err(x), + } + } + }; + ($name:ident, $c_name:ident, $rs_type:ty, $err_msg:literal, $($native_variant:ident:$variant2:ident),+) => { + #[inline] + pub fn $name(value: native::$c_name) -> Option<$rs_type> { + map_enum_with_undefined!(map_fn, $c_name, $rs_type, $($native_variant:$variant2),+); + + map_fn(value).expect($err_msg) + } + }; +} + pub unsafe fn string_view_into_str<'a>(string_view: native::WGPUStringView) -> Option<&'a str> { if string_view.data.is_null() { match string_view.length { From aa6b617e7f8c16ce5c01a695a0666e5f7938cad1 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Oct 2024 02:36:49 +0200 Subject: [PATCH 14/18] Update for other enum changes This updates the headers to https://github.com/webgpu-native/webgpu-headers/commit/af63d3476bb9a97c3ac581c21a3273d47027e40b These changes are exclusively in the header enum values, so no Rust code needs changing. Making this a separate commit for easier review. --- ffi/webgpu-headers | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index f1cdc3fd..af63d347 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit f1cdc3fd149cebe166991310b34259f9af5b9df5 +Subproject commit af63d3476bb9a97c3ac581c21a3273d47027e40b From 2cb389bb5f37d50a2a373d694b32896635248858 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Oct 2024 16:14:57 +0200 Subject: [PATCH 15/18] Update for new header features Update headers to https://github.com/webgpu-native/webgpu-headers/commit/b7656d0ce59a6379b31a58abae956873364e9a17 Adds dual source blending. Other two features (float32 blendable and clip distances feature in wgsl) are not supported by wgpu. Also made map_blend_factor use the shorter macro form, as all the enum names match (they didn't 3 years ago when this code was originally written, according to Git history). --- ffi/webgpu-headers | 2 +- src/conv.rs | 37 +++++++++++++++++++++++-------------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index af63d347..b7656d0c 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit af63d3476bb9a97c3ac581c21a3273d47027e40b +Subproject commit b7656d0ce59a6379b31a58abae956873364e9a17 diff --git a/src/conv.rs b/src/conv.rs index 2366ff75..3f5986a1 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -94,19 +94,23 @@ map_enum_with_undefined!( WGPUBlendFactor, wgt::BlendFactor, "Unknown blend factor", - Zero: Zero, - One: One, - Src: Src, - OneMinusSrc: OneMinusSrc, - SrcAlpha: SrcAlpha, - OneMinusSrcAlpha: OneMinusSrcAlpha, - Dst: Dst, - OneMinusDst: OneMinusDst, - DstAlpha: DstAlpha, - OneMinusDstAlpha: OneMinusDstAlpha, - SrcAlphaSaturated: SrcAlphaSaturated, - Constant: Constant, - OneMinusConstant: OneMinusConstant + Zero, + One, + Src, + OneMinusSrc, + SrcAlpha, + OneMinusSrcAlpha, + Dst, + OneMinusDst, + DstAlpha, + OneMinusDstAlpha, + SrcAlphaSaturated, + Constant, + OneMinusConstant, + Src1, + OneMinusSrc1, + Src1Alpha, + OneMinusSrc1Alpha ); map_enum_with_undefined!( map_blend_operation, @@ -1101,7 +1105,9 @@ pub fn features_to_native(features: wgt::Features) -> Vec Option { native::WGPUFeatureName_ShaderF16 => Some(Features::SHADER_F16), native::WGPUFeatureName_RG11B10UfloatRenderable => Some(Features::RG11B10UFLOAT_RENDERABLE), native::WGPUFeatureName_BGRA8UnormStorage => Some(Features::BGRA8UNORM_STORAGE), + // TODO: WGPUFeatureName_ClipDistances + // TODO: WGPUFeatureName_Float32Blendable native::WGPUFeatureName_Float32Filterable => Some(Features::FLOAT32_FILTERABLE), + native::WGPUFeatureName_DualSourceBlending => Some(Features::DUAL_SOURCE_BLENDING), // wgpu-rs only features native::WGPUNativeFeature_PushConstants => Some(Features::PUSH_CONSTANTS), From b6b69036b2af9664310ab852379735cf790cd611 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Oct 2024 16:27:59 +0200 Subject: [PATCH 16/18] Fix getFeatures chained struct handling. Oops that's not how these chained structs work. --- src/lib.rs | 37 +++++++++++++------------------------ 1 file changed, 13 insertions(+), 24 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 3d301c31..d7e9629e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -674,12 +674,9 @@ pub unsafe extern "C" fn wgpuGetInstanceFeatures( features: Option<&mut native::WGPUInstanceFeatures>, ) { let features = features.expect("invalid return pointer \"features\""); - *features = native::WGPUInstanceFeatures { - nextInChain: std::ptr::null_mut(), - // WaitAny is currently completely unsupported, so... - timedWaitAnyEnable: false as native::WGPUBool, - timedWaitAnyMaxCount: 0, - } + // WaitAny is currently completely unsupported, so... + features.timedWaitAnyEnable = false as native::WGPUBool; + features.timedWaitAnyMaxCount = 0; } // Adapter methods @@ -700,18 +697,19 @@ pub unsafe extern "C" fn wgpuAdapterGetFeatures( Err(err) => handle_error_fatal(err, "wgpuAdapterEnumerateFeatures"), }; - let temp = conv::features_to_native(adapter_features); + return_features(features, adapter_features); + + native::WGPUStatus_Success +} + +fn return_features(native: &mut native::WGPUSupportedFeatures, features: wgt::Features) { + let temp = conv::features_to_native(features); let mut temp = temp.into_boxed_slice(); - *features = native::WGPUSupportedFeatures { - nextInChain: std::ptr::null_mut(), - featureCount: temp.len(), - features: temp.as_mut_ptr(), - }; + native.featureCount = temp.len(); + native.features = temp.as_mut_ptr(); mem::forget(temp); - - native::WGPUStatus_Success } #[no_mangle] @@ -2554,16 +2552,7 @@ pub unsafe extern "C" fn wgpuDeviceGetFeatures( Err(err) => handle_error_fatal(err, "wgpuDeviceEnumerateFeatures"), }; - let temp = conv::features_to_native(device_features); - let mut temp = temp.into_boxed_slice(); - - *features = native::WGPUSupportedFeatures { - nextInChain: std::ptr::null_mut(), - featureCount: temp.len(), - features: temp.as_mut_ptr(), - }; - - mem::forget(temp); + return_features(features, device_features); native::WGPUStatus_Success } From 4d49d7f492480050afaf24cf84ba94e6a45d49af Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Oct 2024 16:43:06 +0200 Subject: [PATCH 17/18] Flatten limits structures Updates headers to https://github.com/webgpu-native/webgpu-headers/commit/6f549cc3409663303b06f50483b9ebf9d1cf19dd Also made matching changes to wgpu.h --- ffi/webgpu-headers | 2 +- ffi/wgpu.h | 15 +++------------ src/conv.rs | 30 ++++++++++++------------------ src/lib.rs | 4 ++-- src/utils.rs | 2 +- 5 files changed, 19 insertions(+), 34 deletions(-) diff --git a/ffi/webgpu-headers b/ffi/webgpu-headers index b7656d0c..6f549cc3 160000 --- a/ffi/webgpu-headers +++ b/ffi/webgpu-headers @@ -1 +1 @@ -Subproject commit b7656d0ce59a6379b31a58abae956873364e9a17 +Subproject commit 6f549cc3409663303b06f50483b9ebf9d1cf19dd diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 0d07c65b..3626171f 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -6,10 +6,9 @@ typedef enum WGPUNativeSType { // Start at 0003 since that's allocated range for wgpu-native WGPUSType_DeviceExtras = 0x00030001, - WGPUSType_RequiredLimitsExtras = 0x00030002, + WGPUSType_NativeLimits = 0x00030002, WGPUSType_PipelineLayoutExtras = 0x00030003, WGPUSType_ShaderModuleGLSLDescriptor = 0x00030004, - WGPUSType_SupportedLimitsExtras = 0x00030005, WGPUSType_InstanceExtras = 0x00030006, WGPUSType_BindGroupEntryExtras = 0x00030007, WGPUSType_BindGroupLayoutEntryExtras = 0x00030008, @@ -132,20 +131,12 @@ typedef struct WGPUDeviceExtras { } WGPUDeviceExtras; typedef struct WGPUNativeLimits { + /** This struct chain is used as mutable in some places and immutable in others. */ + WGPUChainedStructOut * nextInChain; uint32_t maxPushConstantSize; uint32_t maxNonSamplerBindings; } WGPUNativeLimits; -typedef struct WGPURequiredLimitsExtras { - WGPUChainedStruct chain; - WGPUNativeLimits limits; -} WGPURequiredLimitsExtras; - -typedef struct WGPUSupportedLimitsExtras { - WGPUChainedStructOut chain; - WGPUNativeLimits limits; -} WGPUSupportedLimitsExtras; - typedef struct WGPUPushConstantRange { WGPUShaderStage stages; uint32_t start; diff --git a/src/conv.rs b/src/conv.rs index 3f5986a1..a44cb46e 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -332,7 +332,7 @@ pub(crate) unsafe fn map_device_descriptor<'a>( Some(required_limits) => unsafe { follow_chain!( map_required_limits((required_limits, base_limits), - WGPUSType_RequiredLimitsExtras => native::WGPURequiredLimitsExtras) + WGPUSType_NativeLimits => native::WGPUNativeLimits) ) }, None => base_limits, @@ -387,9 +387,8 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( #[inline] pub fn write_limits_struct( wgt_limits: wgt::Limits, - supported_limits: &mut native::WGPUSupportedLimits, + limits: &mut native::WGPULimits, ) { - 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; @@ -427,33 +426,29 @@ pub fn write_limits_struct( limits.maxComputeWorkgroupSizeY = wgt_limits.max_compute_workgroup_size_y; limits.maxComputeWorkgroupSizeZ = wgt_limits.max_compute_workgroup_size_z; limits.maxComputeWorkgroupsPerDimension = wgt_limits.max_compute_workgroups_per_dimension; - supported_limits.limits = limits; if let Some(native::WGPUChainedStructOut { - sType: native::WGPUSType_SupportedLimitsExtras, + sType: native::WGPUSType_NativeLimits, .. - }) = unsafe { supported_limits.nextInChain.as_ref() } + }) = unsafe { limits.nextInChain.as_ref() } { unsafe { - let extras = std::mem::transmute::< + let native_limits = std::mem::transmute::< *mut native::WGPUChainedStructOut, - *mut native::WGPUSupportedLimitsExtras, - >(supported_limits.nextInChain); - (*extras).limits = native::WGPUNativeLimits { - maxPushConstantSize: wgt_limits.max_push_constant_size, - maxNonSamplerBindings: wgt_limits.max_non_sampler_bindings, - }; + *mut native::WGPUNativeLimits, + >(limits.nextInChain); + (*native_limits).maxPushConstantSize = wgt_limits.max_push_constant_size; + (*native_limits).maxNonSamplerBindings = wgt_limits.max_non_sampler_bindings; } }; } #[inline] pub fn map_required_limits( - required_limits: &native::WGPURequiredLimits, + limits: &native::WGPULimits, base_limits: wgt::Limits, - extras: Option<&native::WGPURequiredLimitsExtras>, + extras: Option<&native::WGPUNativeLimits>, ) -> wgt::Limits { - let limits = required_limits.limits; let mut wgt_limits = base_limits; if limits.maxTextureDimension1D != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_texture_dimension_1d = limits.maxTextureDimension1D; @@ -554,8 +549,7 @@ pub fn map_required_limits( if limits.maxComputeWorkgroupsPerDimension != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_compute_workgroups_per_dimension = limits.maxComputeWorkgroupsPerDimension; } - if let Some(extras) = extras { - let limits = extras.limits; + if let Some(limits) = extras { if limits.maxPushConstantSize != native::WGPU_LIMIT_U32_UNDEFINED { wgt_limits.max_push_constant_size = limits.maxPushConstantSize; } diff --git a/src/lib.rs b/src/lib.rs index d7e9629e..c4c1fd75 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -715,7 +715,7 @@ fn return_features(native: &mut native::WGPUSupportedFeatures, features: wgt::Fe #[no_mangle] pub unsafe extern "C" fn wgpuAdapterGetLimits( adapter: native::WGPUAdapter, - limits: Option<&mut native::WGPUSupportedLimits>, + limits: Option<&mut native::WGPULimits>, ) -> native::WGPUBool { let (adapter_id, context) = { let adapter = adapter.as_ref().expect("invalid adapter"); @@ -2572,7 +2572,7 @@ pub unsafe extern "C" fn wgpuSupportedFeaturesFreeMembers( #[no_mangle] pub unsafe extern "C" fn wgpuDeviceGetLimits( device: native::WGPUDevice, - limits: Option<&mut native::WGPUSupportedLimits>, + limits: Option<&mut native::WGPULimits>, ) -> native::WGPUBool { let (device_id, context) = { let device = device.as_ref().expect("invalid device"); diff --git a/src/utils.rs b/src/utils.rs index cc152f56..0793b39e 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -166,7 +166,7 @@ macro_rules! follow_chain { $( let mut $stype: Option<&$ty> = None; )* - let mut chain_opt: Option<&$crate::native::WGPUChainedStruct> = $base1.nextInChain.as_ref(); + let mut chain_opt: Option<&$crate::native::WGPUChainedStruct> = ($base1.nextInChain as *const $crate::native::WGPUChainedStruct).as_ref(); while let Some(next_in_chain) = chain_opt { match next_in_chain.sType { $( From 620405f74b20ea72a718ceb68998d86ede5d1341 Mon Sep 17 00:00:00 2001 From: Pieter-Jan Briers Date: Sun, 20 Oct 2024 17:20:05 +0200 Subject: [PATCH 18/18] Some day I will learn to run cargo fmt and check compile before merges --- examples/push_constants/main.c | 86 +++++++++++++++++----------------- ffi/wgpu.h | 4 +- src/conv.rs | 5 +- src/lib.rs | 2 +- 4 files changed, 46 insertions(+), 51 deletions(-) diff --git a/examples/push_constants/main.c b/examples/push_constants/main.c index 6018eaa8..c1cbaec5 100644 --- a/examples/push_constants/main.c +++ b/examples/push_constants/main.c @@ -8,21 +8,26 @@ #define LOG_PREFIX "[push_constants]" static void handle_request_adapter(WGPURequestAdapterStatus status, - WGPUAdapter adapter, char const *message, - void *userdata) { + WGPUAdapter adapter, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUAdapter *)userdata = adapter; + UNUSED(userdata2) + *(WGPUAdapter *)userdata1 = adapter; } static void handle_request_device(WGPURequestDeviceStatus status, - WGPUDevice device, char const *message, - void *userdata) { + WGPUDevice device, WGPUStringView message, + void *userdata1, void *userdata2) { UNUSED(status) UNUSED(message) - *(WGPUDevice *)userdata = device; + UNUSED(userdata2) + *(WGPUDevice *)userdata1 = device; } -static void handle_buffer_map(WGPUBufferMapAsyncStatus status, void *userdata) { - UNUSED(userdata) +static void handle_buffer_map(WGPUMapAsyncStatus status, + WGPUStringView message, + void *userdata1, void *userdata2) { + UNUSED(userdata1) + UNUSED(userdata2) printf(LOG_PREFIX " buffer_map status=%#.8x\n", status); } @@ -39,50 +44,41 @@ int main(int argc, char *argv[]) { assert(instance); WGPUAdapter adapter = NULL; - wgpuInstanceRequestAdapter(instance, NULL, handle_request_adapter, - (void *)&adapter); + wgpuInstanceRequestAdapter(instance, NULL, + (const WGPURequestAdapterCallbackInfo){ + .callback = handle_request_adapter, + .userdata1 = &adapter + }); assert(adapter); - WGPUSupportedLimitsExtras supported_limits_extras = { + WGPUNativeLimits supported_limits_extras = { .chain = { - .sType = WGPUSType_SupportedLimitsExtras, - }, - .limits = - { - .maxPushConstantSize = 0, + .sType = WGPUSType_NativeLimits, }, + .maxPushConstantSize = 0, }; - WGPUSupportedLimits supported_limits = { + WGPULimits supported_limits = { .nextInChain = &supported_limits_extras.chain, }; wgpuAdapterGetLimits(adapter, &supported_limits); - WGPURequiredLimitsExtras required_limits_extras = { - .chain = - { - .sType = WGPUSType_RequiredLimitsExtras, - }, - .limits = supported_limits_extras.limits, - }; - WGPURequiredLimits required_limits = { - .nextInChain = &required_limits_extras.chain, - .limits = supported_limits.limits, - }; - WGPUFeatureName requiredFeatures[] = { WGPUNativeFeature_PushConstants, }; WGPUDeviceDescriptor device_desc = { - .label = "compute_device", + .label = {"compute_device", WGPU_STRLEN}, .requiredFeatures = requiredFeatures, .requiredFeatureCount = 1, - .requiredLimits = &required_limits, + .requiredLimits = &supported_limits, }; WGPUDevice device = NULL; - wgpuAdapterRequestDevice(adapter, &device_desc, handle_request_device, - (void *)&device); + wgpuAdapterRequestDevice(adapter, &device_desc, + (const WGPURequestDeviceCallbackInfo){ + .callback = handle_request_device, + .userdata1 = &device + }); assert(device); WGPUQueue queue = wgpuDeviceGetQueue(device); @@ -94,7 +90,7 @@ int main(int argc, char *argv[]) { WGPUBuffer storage_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "storage_buffer", + .label = {"storage_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_Storage | WGPUBufferUsage_CopyDst | WGPUBufferUsage_CopySrc, .size = numbers_size, @@ -104,7 +100,7 @@ int main(int argc, char *argv[]) { WGPUBuffer staging_buffer = wgpuDeviceCreateBuffer( device, &(const WGPUBufferDescriptor){ - .label = "staging_buffer", + .label = {"staging_buffer", WGPU_STRLEN}, .usage = WGPUBufferUsage_MapRead | WGPUBufferUsage_CopyDst, .size = numbers_size, .mappedAtCreation = false, @@ -137,7 +133,7 @@ int main(int argc, char *argv[]) { }, }; WGPUBindGroupLayoutDescriptor bind_group_layout_desc = { - .label = "bind_group_layout", + .label = {"bind_group_layout", WGPU_STRLEN}, .nextInChain = NULL, .entryCount = 1, .entries = bind_group_layout_entries, @@ -147,7 +143,7 @@ int main(int argc, char *argv[]) { assert(bind_group_layout); WGPUPipelineLayoutDescriptor pipeline_layout_desc = { - .label = "pipeline_layout", + .label = {"pipeline_layout", WGPU_STRLEN}, .nextInChain = &pipeline_layout_extras.chain, .bindGroupLayouts = &bind_group_layout, .bindGroupLayoutCount = 1, @@ -158,11 +154,11 @@ int main(int argc, char *argv[]) { WGPUComputePipeline compute_pipeline = wgpuDeviceCreateComputePipeline( device, &(const WGPUComputePipelineDescriptor){ - .label = "compute_pipeline", + .label = {"compute_pipeline", WGPU_STRLEN}, .compute = (const WGPUProgrammableStageDescriptor){ .module = shader_module, - .entryPoint = "main", + .entryPoint = {"main", WGPU_STRLEN}, }, .layout = pipeline_layout, }); @@ -170,7 +166,7 @@ int main(int argc, char *argv[]) { WGPUBindGroup bind_group = wgpuDeviceCreateBindGroup( device, &(const WGPUBindGroupDescriptor){ - .label = "bind_group", + .label = {"bind_group", WGPU_STRLEN}, .layout = bind_group_layout, .entryCount = 1, .entries = @@ -187,14 +183,14 @@ int main(int argc, char *argv[]) { WGPUCommandEncoder command_encoder = wgpuDeviceCreateCommandEncoder( device, &(const WGPUCommandEncoderDescriptor){ - .label = "command_encoder", + .label = {"command_encoder", WGPU_STRLEN}, }); assert(command_encoder); WGPUComputePassEncoder compute_pass_encoder = wgpuCommandEncoderBeginComputePass(command_encoder, &(const WGPUComputePassDescriptor){ - .label = "compute_pass", + .label = {"compute_pass", WGPU_STRLEN}, }); assert(compute_pass_encoder); @@ -219,7 +215,7 @@ int main(int argc, char *argv[]) { WGPUCommandBuffer command_buffer = wgpuCommandEncoderFinish( command_encoder, &(const WGPUCommandBufferDescriptor){ - .label = "command_buffer", + .label = {"command_buffer", WGPU_STRLEN}, }); assert(command_buffer); @@ -227,7 +223,9 @@ int main(int argc, char *argv[]) { wgpuQueueSubmit(queue, 1, &command_buffer); wgpuBufferMapAsync(staging_buffer, WGPUMapMode_Read, 0, numbers_size, - handle_buffer_map, NULL); + (const WGPUBufferMapCallbackInfo){ + .callback = handle_buffer_map + }); wgpuDevicePoll(device, true, NULL); uint32_t *buf = diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 4019f8c0..a490c556 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -135,7 +135,7 @@ typedef struct WGPUDeviceExtras { typedef struct WGPUNativeLimits { /** This struct chain is used as mutable in some places and immutable in others. */ - WGPUChainedStructOut * nextInChain; + WGPUChainedStructOut chain; uint32_t maxPushConstantSize; uint32_t maxNonSamplerBindings; } WGPUNativeLimits; @@ -173,7 +173,7 @@ typedef struct WGPUShaderModuleGLSLDescriptor { } WGPUShaderModuleGLSLDescriptor; typedef struct WGPUShaderModuleDescriptorSpirV { - char const * label; + WGPUStringView label; uint32_t sourceSize; uint32_t const * source; } WGPUShaderModuleDescriptorSpirV; diff --git a/src/conv.rs b/src/conv.rs index da836a09..e64bf25c 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -385,10 +385,7 @@ pub unsafe fn map_pipeline_layout_descriptor<'a>( } #[inline] -pub fn write_limits_struct( - wgt_limits: wgt::Limits, - limits: &mut native::WGPULimits, -) { +pub fn write_limits_struct(wgt_limits: wgt::Limits, limits: &mut native::WGPULimits) { limits.maxTextureDimension1D = wgt_limits.max_texture_dimension_1d; limits.maxTextureDimension2D = wgt_limits.max_texture_dimension_2d; limits.maxTextureDimension3D = wgt_limits.max_texture_dimension_3d; diff --git a/src/lib.rs b/src/lib.rs index 96348530..8c45627b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4357,7 +4357,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleSpirV( let descriptor = descriptor.expect("invalid descriptor"); let desc = wgc::pipeline::ShaderModuleDescriptor { - label: ptr_into_label(descriptor.label), + label: string_view_into_label(descriptor.label), shader_bound_checks: unsafe { wgt::ShaderBoundChecks::unchecked() }, };