diff --git a/wgpu-core/src/command/allocator.rs b/wgpu-core/src/command/allocator.rs index 13334736fb..5d0778fc64 100644 --- a/wgpu-core/src/command/allocator.rs +++ b/wgpu-core/src/command/allocator.rs @@ -84,11 +84,13 @@ pub struct CommandAllocator { } impl CommandAllocator { + #[allow(clippy::too_many_arguments)] pub(crate) fn allocate( &self, device_id: Stored, device: &B::Device, limits: wgt::Limits, + downlevel: wgt::DownlevelProperties, private_features: PrivateFeatures, label: &crate::Label, #[cfg(feature = "trace")] enable_tracing: bool, @@ -131,6 +133,7 @@ impl CommandAllocator { used_swap_chains: Default::default(), buffer_memory_init_actions: Default::default(), limits, + downlevel, private_features, has_labels: label.is_some(), #[cfg(feature = "trace")] diff --git a/wgpu-core/src/command/compute.rs b/wgpu-core/src/command/compute.rs index b2134c2fbf..57c86a97be 100644 --- a/wgpu-core/src/command/compute.rs +++ b/wgpu-core/src/command/compute.rs @@ -14,7 +14,7 @@ use crate::{ resource::{Buffer, BufferUse, Texture}, track::{TrackerSet, UsageConflict}, validation::{check_buffer_usage, MissingBufferUsageError}, - Label, + Label, DOWNLEVEL_ERROR_WARNING_MESSAGE, }; use hal::command::CommandBuffer as _; @@ -153,6 +153,11 @@ pub enum ComputePassErrorInner { MissingBufferUsage(#[from] MissingBufferUsageError), #[error("cannot pop debug group, because number of pushed debug groups is zero")] InvalidPopDebugGroup, + #[error( + "Compute shaders are not supported by the underlying platform. {}", + DOWNLEVEL_ERROR_WARNING_MESSAGE + )] + ComputeShadersUnsupported, #[error(transparent)] Dispatch(#[from] DispatchError), #[error(transparent)] @@ -270,6 +275,13 @@ impl Global { }); } + if !cmd_buf.downlevel.compute_shaders { + return Err(ComputePassError { + scope: PassErrorScope::Pass(encoder_id), + inner: ComputePassErrorInner::ComputeShadersUnsupported, + }) + } + if let Some(ref label) = base.label { unsafe { raw.begin_debug_marker(label, 0); diff --git a/wgpu-core/src/command/mod.rs b/wgpu-core/src/command/mod.rs index 92025cef34..5402970f36 100644 --- a/wgpu-core/src/command/mod.rs +++ b/wgpu-core/src/command/mod.rs @@ -48,6 +48,7 @@ pub struct CommandBuffer { pub(crate) used_swap_chains: SmallVec<[Stored; 1]>, pub(crate) buffer_memory_init_actions: Vec>, limits: wgt::Limits, + downlevel: wgt::DownlevelProperties, private_features: PrivateFeatures, has_labels: bool, #[cfg(feature = "trace")] diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index e3d71b0fce..22a8ee1c4b 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -1861,6 +1861,10 @@ impl Device { ), pipeline::CreateComputePipelineError, > { + if !self.downlevel.compute_shaders { + return Err(pipeline::CreateComputePipelineError::ComputeShadersUnsupported); + } + //TODO: only lock mutable if the layout is derived let (mut pipeline_layout_guard, mut token) = hub.pipeline_layouts.write(token); let (mut bgl_guard, mut token) = hub.bind_group_layouts.write(&mut token); @@ -3723,6 +3727,7 @@ impl Global { dev_stored, &device.raw, device.limits.clone(), + device.downlevel, device.private_features, &desc.label, #[cfg(feature = "trace")] diff --git a/wgpu-core/src/instance.rs b/wgpu-core/src/instance.rs index 2f2f59a5c6..e058adbc76 100644 --- a/wgpu-core/src/instance.rs +++ b/wgpu-core/src/instance.rs @@ -7,7 +7,7 @@ use crate::{ device::{Device, DeviceDescriptor}, hub::{GfxBackend, Global, GlobalIdentityHandlerFactory, Input, Token}, id::{AdapterId, DeviceId, SurfaceId, Valid}, - LabelHelpers, LifeGuard, PrivateFeatures, Stored, MAX_BIND_GROUPS, + LabelHelpers, LifeGuard, PrivateFeatures, Stored, DOWNLEVEL_WARNING_MESSAGE, MAX_BIND_GROUPS, }; use wgt::{Backend, BackendBit, PowerPreference, BIND_BUFFER_ALIGNMENT}; @@ -397,6 +397,10 @@ impl Adapter { )); } + if !self.downlevel.is_webgpu_compliant() { + log::warn!("{}", DOWNLEVEL_WARNING_MESSAGE); + } + // Verify feature preconditions if desc .features diff --git a/wgpu-core/src/lib.rs b/wgpu-core/src/lib.rs index a2f04d6443..f268997b23 100644 --- a/wgpu-core/src/lib.rs +++ b/wgpu-core/src/lib.rs @@ -237,6 +237,17 @@ struct PrivateFeatures { texture_d24_s8: bool, } +const DOWNLEVEL_WARNING_MESSAGE: &str = "The underlying API or device in use does not \ +support enough features to be a fully compliant implementation of WebGPU. A subset of the features can still be used. \ +If you are running this program on native and not in a browser and wish to limit the features you use to the supported subset, \ +call Adapter::downlevel_properties or Device::downlevel_properties to get a listing of the features the current \ +platform is supports."; +const DOWNLEVEL_ERROR_WARNING_MESSAGE: &str = "This is not an invalid use of WebGPU: the underlying API or device does not \ +support enough features to be a fully compliant implementation. A subset of the features can still be used. \ +If you are running this program on native and not in a browser and wish to work around this issue, call \ +Adapter::downlevel_properties or Device::downlevel_properties to get a listing of the features the current \ +platform is supports."; + #[macro_export] macro_rules! gfx_select { ($id:expr => $global:ident.$method:ident( $($param:expr),* )) => { diff --git a/wgpu-core/src/pipeline.rs b/wgpu-core/src/pipeline.rs index 4218b4655a..e96e1510cf 100644 --- a/wgpu-core/src/pipeline.rs +++ b/wgpu-core/src/pipeline.rs @@ -7,7 +7,7 @@ use crate::{ device::{DeviceError, RenderPassContext}, hub::Resource, id::{DeviceId, PipelineLayoutId, ShaderModuleId}, - validation, Label, LifeGuard, Stored, + validation, Label, LifeGuard, Stored, DOWNLEVEL_ERROR_WARNING_MESSAGE, }; use std::borrow::Cow; use thiserror::Error; @@ -115,6 +115,11 @@ pub enum CreateComputePipelineError { Stage(validation::StageError), #[error("Internal error: {0}")] Internal(String), + #[error( + "Compute shaders are not supported by the underlying platform. {}", + DOWNLEVEL_ERROR_WARNING_MESSAGE + )] + ComputeShadersUnsupported, } #[derive(Debug)]