From 9bf47dd77229be4f6f43f5a9ad62ff75e7f73376 Mon Sep 17 00:00:00 2001 From: Dzmitry Malyshau Date: Mon, 15 Feb 2021 19:59:15 -0500 Subject: [PATCH] Validate texture bindings --- wgpu-core/src/binding_model.rs | 24 ++++++++++++++ wgpu-core/src/device/mod.rs | 59 ++++++++++++++++++++++++++++++++-- wgpu-core/src/resource.rs | 1 + wgpu-core/src/swap_chain.rs | 1 + 4 files changed, 83 insertions(+), 2 deletions(-) diff --git a/wgpu-core/src/binding_model.rs b/wgpu-core/src/binding_model.rs index 6f7c671aea..541a6148b7 100644 --- a/wgpu-core/src/binding_model.rs +++ b/wgpu-core/src/binding_model.rs @@ -100,6 +100,30 @@ pub enum CreateBindGroupError { // Human-readable description of expected types expected: &'static str, }, + #[error("texture binding {binding} expects multisampled = {layout_multisampled}, but given a view with samples = {view_samples}")] + InvalidTextureMultisample { + binding: u32, + layout_multisampled: bool, + view_samples: u32, + }, + #[error("texture binding {binding} expects sample type = {layout_sample_type:?}, but given a view with format = {view_format:?}")] + InvalidTextureSampleType { + binding: u32, + layout_sample_type: wgt::TextureSampleType, + view_format: wgt::TextureFormat, + }, + #[error("texture binding {binding} expects dimension = {layout_dimension:?}, but given a view with dimension = {view_dimension:?}")] + InvalidTextureDimension { + binding: u32, + layout_dimension: wgt::TextureViewDimension, + view_dimension: wgt::TextureViewDimension, + }, + #[error("storage texture binding {binding} expects format = {layout_format:?}, but given a view with format = {view_format:?}")] + InvalidStorageTextureFormat { + binding: u32, + layout_format: wgt::TextureFormat, + view_format: wgt::TextureFormat, + }, #[error("the given sampler is/is not a comparison sampler, while the layout type indicates otherwise")] WrongSamplerComparison, #[error("bound texture views can not have both depth and stencil aspects enabled")] diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 9f17b824cc..690d694405 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -857,6 +857,7 @@ impl Device { aspects, format: texture.format, format_features: texture.format_features, + dimension: view_dim, extent: wgt::Extent3d { width: hal_extent.width, height: hal_extent.height, @@ -1414,11 +1415,65 @@ impl Device { .views .use_extend(&*texture_view_guard, id, (), ()) .map_err(|_| Error::InvalidTextureView(id))?; + let format_info = view.format.describe(); let (pub_usage, internal_use) = match decl.ty { - wgt::BindingType::Texture { .. } => { + wgt::BindingType::Texture { + sample_type, + view_dimension, + multisampled, + } => { + use wgt::TextureSampleType as Tst; + if multisampled != (view.samples != 1) { + return Err(Error::InvalidTextureMultisample { + binding, + layout_multisampled: multisampled, + view_samples: view.samples as u32, + }); + } + match (sample_type, format_info.sample_type) { + (Tst::Uint, Tst::Uint) | + (Tst::Sint, Tst::Sint) | + (Tst::Depth, Tst::Depth) | + // if we expect non-fiterable, accept anything float + (Tst::Float { filterable: false }, Tst::Float { .. }) | + // if we expect fiterable, require it + (Tst::Float { filterable: true }, Tst::Float { filterable: true }) | + // if we expect float, also accept depth + (Tst::Float { .. }, Tst::Depth) => {} + _ => return Err(Error::InvalidTextureSampleType { + binding, + layout_sample_type: sample_type, + view_format: view.format, + }), + } + if view_dimension != view.dimension { + return Err(Error::InvalidTextureDimension { + binding, + layout_dimension: view_dimension, + view_dimension: view.dimension, + }); + } (wgt::TextureUsage::SAMPLED, view.sampled_internal_use) } - wgt::BindingType::StorageTexture { access, .. } => { + wgt::BindingType::StorageTexture { + access, + format, + view_dimension, + } => { + if format != view.format { + return Err(Error::InvalidStorageTextureFormat { + binding, + layout_format: format, + view_format: view.format, + }); + } + if view_dimension != view.dimension { + return Err(Error::InvalidTextureDimension { + binding, + layout_dimension: view_dimension, + view_dimension: view.dimension, + }); + } let internal_use = match access { wgt::StorageTextureAccess::ReadOnly => { resource::TextureUse::STORAGE_LOAD diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index c13093d005..045f2ec65f 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -309,6 +309,7 @@ pub struct TextureView { pub(crate) aspects: hal::format::Aspects, pub(crate) format: wgt::TextureFormat, pub(crate) format_features: wgt::TextureFormatFeatures, + pub(crate) dimension: wgt::TextureViewDimension, pub(crate) extent: wgt::Extent3d, pub(crate) samples: hal::image::NumSamples, pub(crate) framebuffer_attachment: hal::image::FramebufferAttachment, diff --git a/wgpu-core/src/swap_chain.rs b/wgpu-core/src/swap_chain.rs index 14bbcd3922..f5bb3d3173 100644 --- a/wgpu-core/src/swap_chain.rs +++ b/wgpu-core/src/swap_chain.rs @@ -188,6 +188,7 @@ impl Global { allowed_usages: wgt::TextureUsage::RENDER_ATTACHMENT, flags: wgt::TextureFormatFeatureFlags::empty(), }, + dimension: wgt::TextureViewDimension::D2, extent: wgt::Extent3d { width: sc.desc.width, height: sc.desc.height,