diff --git a/wgpu-core/src/device/mod.rs b/wgpu-core/src/device/mod.rs index 59c4f6e92c..2657d6649e 100644 --- a/wgpu-core/src/device/mod.rs +++ b/wgpu-core/src/device/mod.rs @@ -27,7 +27,9 @@ use hal::{ }; use parking_lot::{Mutex, MutexGuard}; use thiserror::Error; -use wgt::{BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat}; +use wgt::{ + BufferAddress, BufferSize, InputStepMode, TextureDimension, TextureFormat, TextureViewDimension, +}; use std::{ borrow::Cow, @@ -1477,16 +1479,50 @@ impl Global { .ok_or(resource::CreateTextureViewError::InvalidTexture)?; let device = &device_guard[texture.device_id.value]; - let view_kind = match desc.dimension { - Some(dim) => conv::map_texture_view_dimension(dim), - None => match texture.kind { - hal::image::Kind::D1(_, 1) => hal::image::ViewKind::D1, - hal::image::Kind::D1(..) => hal::image::ViewKind::D1Array, - hal::image::Kind::D2(_, _, 1, _) => hal::image::ViewKind::D2, - hal::image::Kind::D2(..) => hal::image::ViewKind::D2Array, - hal::image::Kind::D3(..) => hal::image::ViewKind::D3, - }, - }; + let view_kind = + match desc.dimension { + Some(dim) => { + use hal::image::Kind; + + let required_tex_dim = dim.compatible_texture_dimension(); + + if required_tex_dim != texture.dimension { + return Err( + resource::CreateTextureViewError::InvalidTextureViewDimension { + view: dim, + image: texture.dimension, + }, + ); + } + + if let Kind::D2(_, _, depth, _) = texture.kind { + match dim { + TextureViewDimension::Cube if depth != 6 => { + return Err( + resource::CreateTextureViewError::InvalidCubemapTextureDepth { + depth, + }, + ) + } + TextureViewDimension::CubeArray if depth % 6 != 0 => return Err( + resource::CreateTextureViewError::InvalidCubemapArrayTextureDepth { + depth, + }, + ), + _ => {} + } + } + + conv::map_texture_view_dimension(dim) + } + None => match texture.kind { + hal::image::Kind::D1(_, 1) => hal::image::ViewKind::D1, + hal::image::Kind::D1(..) => hal::image::ViewKind::D1Array, + hal::image::Kind::D2(_, _, 1, _) => hal::image::ViewKind::D2, + hal::image::Kind::D2(..) => hal::image::ViewKind::D2Array, + hal::image::Kind::D3(..) => hal::image::ViewKind::D3, + }, + }; let required_level_count = desc.base_mip_level + desc.level_count.map_or(1, |count| count.get()); let required_layer_count = diff --git a/wgpu-core/src/resource.rs b/wgpu-core/src/resource.rs index 5f4e2427e9..6ed92b3810 100644 --- a/wgpu-core/src/resource.rs +++ b/wgpu-core/src/resource.rs @@ -317,6 +317,15 @@ pub enum CreateTextureViewError { InvalidTexture, #[error("not enough memory left")] OutOfMemory, + #[error("Invalid texture view dimension `{view:?}` with texture of dimension `{image:?}`")] + InvalidTextureViewDimension { + view: wgt::TextureViewDimension, + image: wgt::TextureDimension, + }, + #[error("Invalid texture depth `{depth}` for texture view of dimension `Cubemap`. Cubemap views must use images of size 6.")] + InvalidCubemapTextureDepth { depth: u16 }, + #[error("Invalid texture depth `{depth}` for texture view of dimension `CubemapArray`. Cubemap views must use images with sizes which are a multiple of 6.")] + InvalidCubemapArrayTextureDepth { depth: u16 }, #[error( "TextureView mip level count + base mip level {requested} must be <= Texture mip level count {total}" )] diff --git a/wgpu-types/src/lib.rs b/wgpu-types/src/lib.rs index 117be55aca..6ed9622a16 100644 --- a/wgpu-types/src/lib.rs +++ b/wgpu-types/src/lib.rs @@ -434,6 +434,17 @@ pub enum TextureViewDimension { D3, } +impl TextureViewDimension { + /// Get the texture dimension required fo this texture view dimension. + pub fn compatible_texture_dimension(self) -> TextureDimension { + match self { + Self::D1 => TextureDimension::D1, + Self::D2 | Self::D2Array | Self::Cube | Self::CubeArray => TextureDimension::D2, + Self::D3 => TextureDimension::D3, + } + } +} + /// Alpha blend factor. /// /// Alpha blending is very complicated: see the OpenGL or Vulkan spec for more information.