From 56fe96fe179e8d91a5981fb143ec8d439017f7d6 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 16 Apr 2026 16:50:59 +0300 Subject: [PATCH 1/5] Implement wgpuDeviceCreateShaderModuleTrusted (fixes #396) --- CHANGELOG.md | 1 + ffi/wgpu.h | 32 ++++++++++++++++++++++++++++++++ src/conv.rs | 12 +++++++++++- src/lib.rs | 25 +++++++++++++++++++++---- 4 files changed, 65 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6d42faa5..b2b94f39 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -67,6 +67,7 @@ The format is loosely based on [Keep a Changelog](https://keepachangelog.com/en/ - `WGPUNativeLimits::maxMultiviewViewCount` @lisyarus - `WGPUNativeFeature_StorageTextureArrayNonUniformIndexing`, `WGPUNativeFeature_Multiview`, `WGPUNativeFeature_ShaderFloat32Atomic`, `WGPUNativeFeature_TextureAtomic`, `WGPUNativeFeature_TextureFormatP010`, `WGPUNativeFeature_PipelineCache`, `WGPUNativeFeature_ShaderInt64AtomicMinMax`, `WGPUNativeFeature_ShaderInt64AtomicAllOps`, `WGPUNativeFeature_TextureInt64Atomic`, `WGPUNativeFeature_ShaderBarycentrics`, `WGPUNativeFeature_SelectiveMultiview`, `WGPUNativeFeature_MultisampleArray`, `WGPUNativeFeature_CooperativeMatrix`, `WGPUNativeFeature_ShaderPerVertex`, `WGPUNativeFeature_ShaderDrawIndex`, `WGPUNativeFeature_AccelerationStructureBindingArray`, `WGPUNativeFeature_MemoryDecorationCoherent`, `WGPUNativeFeature_MemoryDecorationVolatile` @lisyarus - `wgpuCommandEncoderClearTexture` @lisyarus +- `wgpuDeviceCreateShaderModuleTrusted` @lisyarus ### Removed diff --git a/ffi/wgpu.h b/ffi/wgpu.h index aea7b896..166f9dc1 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -1471,6 +1471,36 @@ typedef struct WGPUImageSubresourceRange { uint32_t arrayLayerCount; } WGPUImageSubresourceRange WGPU_STRUCTURE_ATTRIBUTE; +/** + * Describes how shader bound checks should be performed. + */ +typedef WGPUFlags WGPUNativeShaderRuntimeChecks; + +static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_None = 0x0000000000000000; +/** + * Enforce bounds checks in shaders, even if the underlying driver doesn’t support doing so natively. + */ +static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_BoundsChecks = 0x0000000000000001; +/** + * If not set, the caller MUST ensure that all passed shaders do not contain any infinite loops. + */ +static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_ForceLoopBounding = 0x0000000000000002; +/** + * If not set, the caller MUST ensure that in all passed shaders every function operating on a ray + * query must obey these rules (functions using wgsl naming). + */ +static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_RayQueryInitializationTracking = 0x0000000000000004; +/** + * If not set, task shaders will not validate that the mesh shader grid they dispatch is within legal limits. + */ +static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_TaskShaderDispatchTracking = 0x0000000000000008; +/** + * If not set, mesh shaders won’t clamp the output primitives’ vertex indices, which can lead to + * undefined behavior and arbitrary memory access. + */ +static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp = 0x0000000000000010; +>>>>>>> b26b8f3 (Implement wgpuDeviceCreateShaderModuleTrusted (fixes #396)) + #ifdef __cplusplus extern "C" { @@ -1543,6 +1573,8 @@ extern "C" void wgpuCommandEncoderClearTexture(WGPUCommandEncoder commandEncoder, WGPUTexture texture, WGPUImageSubresourceRange const * range); + WGPUShaderModule wgpuDeviceCreateShaderModuleTrusted(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor, WGPUNativeShaderRuntimeChecks runtimeChecks); + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/conv.rs b/src/conv.rs index 3411c537..b78df105 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -2017,10 +2017,20 @@ pub fn map_primitive_state( } } +pub fn map_shader_runtime_checks(value: native::WGPUNativeShaderRuntimeChecks) -> wgt::ShaderRuntimeChecks { + wgt::ShaderRuntimeChecks { + bounds_checks: (value & native::WGPUNativeShaderRuntimeChecks_BoundsChecks) != 0, + force_loop_bounding: (value & native::WGPUNativeShaderRuntimeChecks_ForceLoopBounding) != 0, + ray_query_initialization_tracking: (value & native::WGPUNativeShaderRuntimeChecks_RayQueryInitializationTracking) != 0, + task_shader_dispatch_tracking: (value & native::WGPUNativeShaderRuntimeChecks_TaskShaderDispatchTracking) != 0, + mesh_shader_primitive_indices_clamp: (value & native::WGPUNativeShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp) != 0, + } +} + pub fn from_u64_bits>(value: u64) -> Option { if value > u32::MAX.into() { return None; } T::from_bits(value as u32) -} +} \ No newline at end of file diff --git a/src/lib.rs b/src/lib.rs index 7a349c62..d697e1b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -5,7 +5,7 @@ use conv::{ 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, + map_shader_runtime_checks, CreateSurfaceParams, }; use parking_lot::Mutex; use smallvec::SmallVec; @@ -2453,10 +2453,10 @@ pub unsafe extern "C" fn wgpuDeviceCreateSampler( })) } -#[no_mangle] -pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( +unsafe fn create_shader_module_impl( device: native::WGPUDevice, descriptor: Option<&native::WGPUShaderModuleDescriptor>, + runtime_checks: wgt::ShaderRuntimeChecks ) -> native::WGPUShaderModule { let (device_id, context, error_sink) = { let device = device.as_ref().expect("invalid device"); @@ -2490,7 +2490,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( let desc = wgc::pipeline::ShaderModuleDescriptor { label: desc_label, - runtime_checks: wgt::ShaderRuntimeChecks::default(), + runtime_checks, }; let (shader_module_id, error) = @@ -2510,6 +2510,23 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( })) } +#[no_mangle] +pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( + device: native::WGPUDevice, + descriptor: Option<&native::WGPUShaderModuleDescriptor>, +) -> native::WGPUShaderModule { + create_shader_module_impl(device, descriptor, wgt::ShaderRuntimeChecks::default()) +} + +#[no_mangle] +pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleTrusted( + device: native::WGPUDevice, + descriptor: Option<&native::WGPUShaderModuleDescriptor>, + runtime_checks: native::WGPUNativeShaderRuntimeChecks, +) -> native::WGPUShaderModule { + create_shader_module_impl(device, descriptor, map_shader_runtime_checks(runtime_checks)) +} + #[no_mangle] pub unsafe extern "C" fn wgpuDeviceCreateTexture( device: native::WGPUDevice, From a9eb72c329843aec1903f2710ac602e1d778133d Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 16 Apr 2026 17:09:11 +0300 Subject: [PATCH 2/5] Fix formatting --- src/conv.rs | 18 +++++++++++++----- src/lib.rs | 12 ++++++++---- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/conv.rs b/src/conv.rs index b78df105..da254428 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -2017,13 +2017,21 @@ pub fn map_primitive_state( } } -pub fn map_shader_runtime_checks(value: native::WGPUNativeShaderRuntimeChecks) -> wgt::ShaderRuntimeChecks { +pub fn map_shader_runtime_checks( + value: native::WGPUNativeShaderRuntimeChecks +) -> wgt::ShaderRuntimeChecks { wgt::ShaderRuntimeChecks { bounds_checks: (value & native::WGPUNativeShaderRuntimeChecks_BoundsChecks) != 0, force_loop_bounding: (value & native::WGPUNativeShaderRuntimeChecks_ForceLoopBounding) != 0, - ray_query_initialization_tracking: (value & native::WGPUNativeShaderRuntimeChecks_RayQueryInitializationTracking) != 0, - task_shader_dispatch_tracking: (value & native::WGPUNativeShaderRuntimeChecks_TaskShaderDispatchTracking) != 0, - mesh_shader_primitive_indices_clamp: (value & native::WGPUNativeShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp) != 0, + ray_query_initialization_tracking: (value + & native::WGPUNativeShaderRuntimeChecks_RayQueryInitializationTracking) + != 0, + task_shader_dispatch_tracking: (value + & native::WGPUNativeShaderRuntimeChecks_TaskShaderDispatchTracking) + != 0, + mesh_shader_primitive_indices_clamp: (value + & native::WGPUNativeShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp) + != 0, } } @@ -2033,4 +2041,4 @@ pub fn from_u64_bits>(value: u64) -> Option { } T::from_bits(value as u32) -} \ No newline at end of file +} diff --git a/src/lib.rs b/src/lib.rs index d697e1b1..fd4589e7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -4,8 +4,8 @@ use conv::{ 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, - map_shader_runtime_checks, CreateSurfaceParams, + map_query_set_index, map_shader_module, map_shader_runtime_checks, map_surface, + map_surface_configuration, CreateSurfaceParams, }; use parking_lot::Mutex; use smallvec::SmallVec; @@ -2456,7 +2456,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateSampler( unsafe fn create_shader_module_impl( device: native::WGPUDevice, descriptor: Option<&native::WGPUShaderModuleDescriptor>, - runtime_checks: wgt::ShaderRuntimeChecks + runtime_checks: wgt::ShaderRuntimeChecks, ) -> native::WGPUShaderModule { let (device_id, context, error_sink) = { let device = device.as_ref().expect("invalid device"); @@ -2524,7 +2524,11 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleTrusted( descriptor: Option<&native::WGPUShaderModuleDescriptor>, runtime_checks: native::WGPUNativeShaderRuntimeChecks, ) -> native::WGPUShaderModule { - create_shader_module_impl(device, descriptor, map_shader_runtime_checks(runtime_checks)) + create_shader_module_impl( + device, + descriptor, + map_shader_runtime_checks(runtime_checks), + ) } #[no_mangle] From 70d22ded5907a3dc2d4531d1dcb4ccb14540c917 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 16 Apr 2026 17:13:02 +0300 Subject: [PATCH 3/5] Fix function name in error messages --- src/lib.rs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index fd4589e7..f536dc04 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2457,6 +2457,8 @@ unsafe fn create_shader_module_impl( device: native::WGPUDevice, descriptor: Option<&native::WGPUShaderModuleDescriptor>, runtime_checks: wgt::ShaderRuntimeChecks, + fn_ident: &'static str, + ) -> native::WGPUShaderModule { let (device_id, context, error_sink) = { let device = device.as_ref().expect("invalid device"); @@ -2478,7 +2480,7 @@ unsafe fn create_shader_module_impl( error_sink, cause, desc_label, - "wgpuDeviceCreateShaderModule", + fn_ident, ); return Arc::into_raw(Arc::new(WGPUShaderModuleImpl { @@ -2500,7 +2502,7 @@ unsafe fn create_shader_module_impl( error_sink, cause, desc.label, - "wgpuDeviceCreateShaderModule", + fn_ident, ); } @@ -2515,7 +2517,12 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( device: native::WGPUDevice, descriptor: Option<&native::WGPUShaderModuleDescriptor>, ) -> native::WGPUShaderModule { - create_shader_module_impl(device, descriptor, wgt::ShaderRuntimeChecks::default()) + create_shader_module_impl( + device, + descriptor, + wgt::ShaderRuntimeChecks::default(), + "wgpuDeviceCreateShaderModule", + ) } #[no_mangle] @@ -2528,6 +2535,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleTrusted( device, descriptor, map_shader_runtime_checks(runtime_checks), + "wgpuDeviceCreateShaderModuleTrusted", ) } From 999711e8aad106a948496fdf2216ca91c96b3560 Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 16 Apr 2026 17:30:37 +0300 Subject: [PATCH 4/5] Fix formatting (again?) --- src/conv.rs | 2 +- src/lib.rs | 15 ++------------- 2 files changed, 3 insertions(+), 14 deletions(-) diff --git a/src/conv.rs b/src/conv.rs index da254428..60e26387 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -2018,7 +2018,7 @@ pub fn map_primitive_state( } pub fn map_shader_runtime_checks( - value: native::WGPUNativeShaderRuntimeChecks + value: native::WGPUNativeShaderRuntimeChecks, ) -> wgt::ShaderRuntimeChecks { wgt::ShaderRuntimeChecks { bounds_checks: (value & native::WGPUNativeShaderRuntimeChecks_BoundsChecks) != 0, diff --git a/src/lib.rs b/src/lib.rs index f536dc04..136a623c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2458,7 +2458,6 @@ unsafe fn create_shader_module_impl( descriptor: Option<&native::WGPUShaderModuleDescriptor>, runtime_checks: wgt::ShaderRuntimeChecks, fn_ident: &'static str, - ) -> native::WGPUShaderModule { let (device_id, context, error_sink) = { let device = device.as_ref().expect("invalid device"); @@ -2476,12 +2475,7 @@ unsafe fn create_shader_module_impl( ) { Ok(source) => source, Err(cause) => { - handle_error( - error_sink, - cause, - desc_label, - fn_ident, - ); + handle_error(error_sink, cause, desc_label, fn_ident); return Arc::into_raw(Arc::new(WGPUShaderModuleImpl { context: context.clone(), @@ -2498,12 +2492,7 @@ unsafe fn create_shader_module_impl( let (shader_module_id, error) = context.device_create_shader_module(device_id, &desc, source, None); if let Some(cause) = error { - handle_error( - error_sink, - cause, - desc.label, - fn_ident, - ); + handle_error(error_sink, cause, desc.label, fn_ident); } Arc::into_raw(Arc::new(WGPUShaderModuleImpl { From 376ee27374ddcef49facd817b6feee784e3f334b Mon Sep 17 00:00:00 2001 From: lisyarus Date: Thu, 16 Apr 2026 17:59:26 +0300 Subject: [PATCH 5/5] Rename WGPUNativeShaderRuntimeChecks -> WGPUShaderRuntimeChecks --- ffi/wgpu.h | 17 ++++++++--------- src/conv.rs | 12 ++++++------ src/lib.rs | 2 +- 3 files changed, 15 insertions(+), 16 deletions(-) diff --git a/ffi/wgpu.h b/ffi/wgpu.h index 166f9dc1..3d3e8fde 100644 --- a/ffi/wgpu.h +++ b/ffi/wgpu.h @@ -1474,32 +1474,31 @@ typedef struct WGPUImageSubresourceRange { /** * Describes how shader bound checks should be performed. */ -typedef WGPUFlags WGPUNativeShaderRuntimeChecks; +typedef WGPUFlags WGPUShaderRuntimeChecks; -static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_None = 0x0000000000000000; +static const WGPUShaderRuntimeChecks WGPUShaderRuntimeChecks_None = 0x0000000000000000; /** * Enforce bounds checks in shaders, even if the underlying driver doesn’t support doing so natively. */ -static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_BoundsChecks = 0x0000000000000001; +static const WGPUShaderRuntimeChecks WGPUShaderRuntimeChecks_BoundsChecks = 0x0000000000000001; /** * If not set, the caller MUST ensure that all passed shaders do not contain any infinite loops. */ -static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_ForceLoopBounding = 0x0000000000000002; +static const WGPUShaderRuntimeChecks WGPUShaderRuntimeChecks_ForceLoopBounding = 0x0000000000000002; /** * If not set, the caller MUST ensure that in all passed shaders every function operating on a ray * query must obey these rules (functions using wgsl naming). */ -static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_RayQueryInitializationTracking = 0x0000000000000004; +static const WGPUShaderRuntimeChecks WGPUShaderRuntimeChecks_RayQueryInitializationTracking = 0x0000000000000004; /** * If not set, task shaders will not validate that the mesh shader grid they dispatch is within legal limits. */ -static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_TaskShaderDispatchTracking = 0x0000000000000008; +static const WGPUShaderRuntimeChecks WGPUShaderRuntimeChecks_TaskShaderDispatchTracking = 0x0000000000000008; /** * If not set, mesh shaders won’t clamp the output primitives’ vertex indices, which can lead to * undefined behavior and arbitrary memory access. */ -static const WGPUBufferUsage WGPUNativeShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp = 0x0000000000000010; ->>>>>>> b26b8f3 (Implement wgpuDeviceCreateShaderModuleTrusted (fixes #396)) +static const WGPUShaderRuntimeChecks WGPUShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp = 0x0000000000000010; #ifdef __cplusplus extern "C" @@ -1573,7 +1572,7 @@ extern "C" void wgpuCommandEncoderClearTexture(WGPUCommandEncoder commandEncoder, WGPUTexture texture, WGPUImageSubresourceRange const * range); - WGPUShaderModule wgpuDeviceCreateShaderModuleTrusted(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor, WGPUNativeShaderRuntimeChecks runtimeChecks); + WGPUShaderModule wgpuDeviceCreateShaderModuleTrusted(WGPUDevice device, WGPUShaderModuleDescriptor const * descriptor, WGPUShaderRuntimeChecks runtimeChecks); #ifdef __cplusplus } // extern "C" diff --git a/src/conv.rs b/src/conv.rs index 60e26387..5dd7312c 100644 --- a/src/conv.rs +++ b/src/conv.rs @@ -2018,19 +2018,19 @@ pub fn map_primitive_state( } pub fn map_shader_runtime_checks( - value: native::WGPUNativeShaderRuntimeChecks, + value: native::WGPUShaderRuntimeChecks, ) -> wgt::ShaderRuntimeChecks { wgt::ShaderRuntimeChecks { - bounds_checks: (value & native::WGPUNativeShaderRuntimeChecks_BoundsChecks) != 0, - force_loop_bounding: (value & native::WGPUNativeShaderRuntimeChecks_ForceLoopBounding) != 0, + bounds_checks: (value & native::WGPUShaderRuntimeChecks_BoundsChecks) != 0, + force_loop_bounding: (value & native::WGPUShaderRuntimeChecks_ForceLoopBounding) != 0, ray_query_initialization_tracking: (value - & native::WGPUNativeShaderRuntimeChecks_RayQueryInitializationTracking) + & native::WGPUShaderRuntimeChecks_RayQueryInitializationTracking) != 0, task_shader_dispatch_tracking: (value - & native::WGPUNativeShaderRuntimeChecks_TaskShaderDispatchTracking) + & native::WGPUShaderRuntimeChecks_TaskShaderDispatchTracking) != 0, mesh_shader_primitive_indices_clamp: (value - & native::WGPUNativeShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp) + & native::WGPUShaderRuntimeChecks_MeshShaderPrimitiveIndicesClamp) != 0, } } diff --git a/src/lib.rs b/src/lib.rs index 136a623c..8814ab94 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2518,7 +2518,7 @@ pub unsafe extern "C" fn wgpuDeviceCreateShaderModule( pub unsafe extern "C" fn wgpuDeviceCreateShaderModuleTrusted( device: native::WGPUDevice, descriptor: Option<&native::WGPUShaderModuleDescriptor>, - runtime_checks: native::WGPUNativeShaderRuntimeChecks, + runtime_checks: native::WGPUShaderRuntimeChecks, ) -> native::WGPUShaderModule { create_shader_module_impl( device,