mirror of
https://github.com/gfx-rs/wgpu.git
synced 2026-04-22 03:02:01 -04:00
Add downlevel infrastructure
This commit is contained in:
@@ -284,6 +284,7 @@ pub struct Device<B: hal::Backend> {
|
||||
pub(crate) private_features: PrivateFeatures,
|
||||
pub(crate) limits: wgt::Limits,
|
||||
pub(crate) features: wgt::Features,
|
||||
pub(crate) downlevel: wgt::DownlevelProperties,
|
||||
spv_options: naga::back::spv::Options,
|
||||
//TODO: move this behind another mutex. This would allow several methods to switch
|
||||
// to borrow Device immutably, such as `write_buffer`, `write_texture`, and `buffer_unmap`.
|
||||
@@ -307,6 +308,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
mem_props: hal::adapter::MemoryProperties,
|
||||
hal_limits: hal::Limits,
|
||||
private_features: PrivateFeatures,
|
||||
downlevel: wgt::DownlevelProperties,
|
||||
desc: &DeviceDescriptor,
|
||||
trace_path: Option<&std::path::Path>,
|
||||
) -> Result<Self, CreateDeviceError> {
|
||||
@@ -376,6 +378,7 @@ impl<B: GfxBackend> Device<B> {
|
||||
private_features,
|
||||
limits: desc.limits.clone(),
|
||||
features: desc.features,
|
||||
downlevel,
|
||||
spv_options,
|
||||
pending_writes: queue::PendingWrites::new(),
|
||||
})
|
||||
@@ -1017,7 +1020,8 @@ impl<B: GfxBackend> Device<B> {
|
||||
let (naga_result, interface) = match module {
|
||||
// If succeeded, then validate it and attempt to give it to gfx-hal directly.
|
||||
Some(module) if desc.flags.contains(wgt::ShaderFlags::VALIDATION) || spv.is_none() => {
|
||||
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all()).validate(&module)?;
|
||||
let info = naga::valid::Validator::new(naga::valid::ValidationFlags::all())
|
||||
.validate(&module)?;
|
||||
if !self.features.contains(wgt::Features::PUSH_CONSTANTS)
|
||||
&& module
|
||||
.global_variables
|
||||
@@ -1060,12 +1064,8 @@ impl<B: GfxBackend> Device<B> {
|
||||
None => {
|
||||
// Produce a SPIR-V from the Naga module
|
||||
let shader = maybe_shader.unwrap();
|
||||
naga::back::spv::write_vec(
|
||||
&shader.module,
|
||||
&shader.info,
|
||||
&self.spv_options,
|
||||
)
|
||||
.map(Cow::Owned)
|
||||
naga::back::spv::write_vec(&shader.module, &shader.info, &self.spv_options)
|
||||
.map(Cow::Owned)
|
||||
}
|
||||
};
|
||||
match spv {
|
||||
@@ -2656,6 +2656,20 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
Ok(device.limits.clone())
|
||||
}
|
||||
|
||||
pub fn device_downlevel_properties<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
) -> Result<wgt::DownlevelProperties, InvalidDevice> {
|
||||
profiling::scope!("Device::downlevel_properties");
|
||||
|
||||
let hub = B::hub(self);
|
||||
let mut token = Token::root();
|
||||
let (device_guard, _) = hub.devices.read(&mut token);
|
||||
let device = device_guard.get(device_id).map_err(|_| InvalidDevice)?;
|
||||
|
||||
Ok(device.downlevel)
|
||||
}
|
||||
|
||||
pub fn device_create_buffer<B: GfxBackend>(
|
||||
&self,
|
||||
device_id: id::DeviceId,
|
||||
|
||||
@@ -122,6 +122,7 @@ pub struct Adapter<B: hal::Backend> {
|
||||
features: wgt::Features,
|
||||
pub(crate) private_features: PrivateFeatures,
|
||||
limits: wgt::Limits,
|
||||
downlevel: wgt::DownlevelProperties,
|
||||
life_guard: LifeGuard,
|
||||
}
|
||||
|
||||
@@ -274,11 +275,28 @@ impl<B: GfxBackend> Adapter<B> {
|
||||
.max(MIN_PUSH_CONSTANT_SIZE), // As an extension, the default is always 0, so define a separate minimum.
|
||||
};
|
||||
|
||||
let downlevel = wgt::DownlevelProperties {
|
||||
compute_shaders: properties.downlevel.compute_shaders,
|
||||
shader_model: match properties.downlevel.shader_model {
|
||||
hal::DownlevelShaderModel::ShaderModel2 => wgt::ShaderModel::Sm2,
|
||||
hal::DownlevelShaderModel::ShaderModel4 => wgt::ShaderModel::Sm4,
|
||||
hal::DownlevelShaderModel::ShaderModel5 => wgt::ShaderModel::Sm5,
|
||||
},
|
||||
storage_images: properties.downlevel.storage_images,
|
||||
read_only_depth_stencil: properties.downlevel.read_only_depth_stencil,
|
||||
device_local_image_copies: properties.downlevel.device_local_image_copies,
|
||||
non_power_of_two_mipmapped_textures: properties
|
||||
.downlevel
|
||||
.non_power_of_two_mipmapped_textures,
|
||||
anisotropic_filtering: private_features.anisotropic_filtering,
|
||||
};
|
||||
|
||||
Self {
|
||||
raw,
|
||||
features,
|
||||
private_features,
|
||||
limits,
|
||||
downlevel,
|
||||
life_guard: LifeGuard::new("<Adapter>"),
|
||||
}
|
||||
}
|
||||
@@ -523,6 +541,7 @@ impl<B: GfxBackend> Adapter<B> {
|
||||
mem_props,
|
||||
limits,
|
||||
self.private_features,
|
||||
self.downlevel,
|
||||
desc,
|
||||
trace_path,
|
||||
)
|
||||
@@ -926,6 +945,21 @@ impl<G: GlobalIdentityHandlerFactory> Global<G> {
|
||||
.map_err(|_| InvalidAdapter)
|
||||
}
|
||||
|
||||
pub fn adapter_downlevel_properties<B: GfxBackend>(
|
||||
&self,
|
||||
adapter_id: AdapterId,
|
||||
) -> Result<wgt::DownlevelProperties, InvalidAdapter> {
|
||||
profiling::scope!("Adapter::downlevel_properties");
|
||||
|
||||
let hub = B::hub(self);
|
||||
let mut token = Token::root();
|
||||
let (adapter_guard, _) = hub.adapters.read(&mut token);
|
||||
adapter_guard
|
||||
.get(adapter_id)
|
||||
.map(|adapter| adapter.downlevel)
|
||||
.map_err(|_| InvalidAdapter)
|
||||
}
|
||||
|
||||
pub fn adapter_drop<B: GfxBackend>(&self, adapter_id: AdapterId) {
|
||||
profiling::scope!("Adapter::drop");
|
||||
|
||||
|
||||
@@ -538,6 +538,65 @@ impl Default for Limits {
|
||||
}
|
||||
}
|
||||
|
||||
/// Lists various ways the underlying platform does not conform to the WebGPU standard.
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct DownlevelProperties {
|
||||
/// The device supports compiling and using compute shaders.
|
||||
pub compute_shaders: bool,
|
||||
/// Which collections of features shaders support. Defined in terms of D3D's shader models.
|
||||
pub shader_model: ShaderModel,
|
||||
/// Supports creating storage images.
|
||||
pub storage_images: bool,
|
||||
/// Supports reading from a depth/stencil buffer while using as a read-only depth/stencil attachment.
|
||||
pub read_only_depth_stencil: bool,
|
||||
/// Supports:
|
||||
/// - copy_image_to_image
|
||||
/// - copy_buffer_to_image and copy_image_to_buffer with a buffer without a MAP_* usage
|
||||
pub device_local_image_copies: bool,
|
||||
/// Supports textures with mipmaps which have a non power of two size.
|
||||
pub non_power_of_two_mipmapped_textures: bool,
|
||||
/// Supports samplers with anisotropic filtering
|
||||
pub anisotropic_filtering: bool,
|
||||
}
|
||||
|
||||
impl Default for DownlevelProperties {
|
||||
// Note, this defaults to all on, as that is the default assumption in wgpu.
|
||||
// gfx-hal's equivalent structure defaults to all off.
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
compute_shaders: true,
|
||||
shader_model: ShaderModel::Sm5,
|
||||
storage_images: true,
|
||||
read_only_depth_stencil: true,
|
||||
device_local_image_copies: true,
|
||||
non_power_of_two_mipmapped_textures: true,
|
||||
anisotropic_filtering: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl DownlevelProperties {
|
||||
/// Returns true if the underlying platform offers complete support of the baseline WebGPU standard.
|
||||
///
|
||||
/// If this returns false, some parts of the API will result in validation errors where they would not normally.
|
||||
/// These parts can be determined by the values in this structure.
|
||||
pub fn is_webgpu_compliant(self) -> bool {
|
||||
self == Self::default()
|
||||
}
|
||||
}
|
||||
|
||||
/// Collections of shader features a device supports if they support less than WebGPU normally allows.
|
||||
// TODO: Fill out the differences between shader models more completely
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub enum ShaderModel {
|
||||
/// Extremely limited shaders, including a total instruction limit.
|
||||
Sm2,
|
||||
/// Missing minor features and storage images.
|
||||
Sm4,
|
||||
/// WebGPU supports shader module 5.
|
||||
Sm5,
|
||||
}
|
||||
|
||||
/// Supported physical device types.
|
||||
#[repr(u8)]
|
||||
#[derive(Clone, Debug, PartialEq)]
|
||||
|
||||
Reference in New Issue
Block a user