// Copyright 2018 The Dawn Authors // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. #include "tests/unittests/validation/ValidationTest.h" namespace { class TextureViewValidationTest : public ValidationTest {}; constexpr uint32_t kWidth = 32u; constexpr uint32_t kHeight = 32u; constexpr uint32_t kDepth = 6u; constexpr uint32_t kDefaultMipLevels = 6u; constexpr wgpu::TextureFormat kDefaultTextureFormat = wgpu::TextureFormat::RGBA8Unorm; wgpu::Texture Create2DArrayTexture(wgpu::Device& device, uint32_t arrayLayerCount, uint32_t width = kWidth, uint32_t height = kHeight, uint32_t mipLevelCount = kDefaultMipLevels, uint32_t sampleCount = 1) { wgpu::TextureDescriptor descriptor; descriptor.dimension = wgpu::TextureDimension::e2D; descriptor.size.width = width; descriptor.size.height = height; descriptor.size.depthOrArrayLayers = arrayLayerCount; descriptor.sampleCount = sampleCount; descriptor.format = kDefaultTextureFormat; descriptor.mipLevelCount = mipLevelCount; descriptor.usage = wgpu::TextureUsage::TextureBinding; return device.CreateTexture(&descriptor); } wgpu::Texture Create3DTexture(wgpu::Device& device) { wgpu::TextureDescriptor descriptor; descriptor.dimension = wgpu::TextureDimension::e3D; descriptor.size = {kWidth, kHeight, kDepth}; descriptor.sampleCount = 1; descriptor.format = kDefaultTextureFormat; descriptor.mipLevelCount = kDefaultMipLevels; descriptor.usage = wgpu::TextureUsage::TextureBinding; return device.CreateTexture(&descriptor); } wgpu::Texture CreateDepthStencilTexture(wgpu::Device& device, wgpu::TextureFormat format) { wgpu::TextureDescriptor descriptor = {}; descriptor.size = {kWidth, kHeight, kDepth}; descriptor.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment; descriptor.mipLevelCount = kDefaultMipLevels; descriptor.format = format; return device.CreateTexture(&descriptor); } wgpu::TextureViewDescriptor CreateDefaultViewDescriptor(wgpu::TextureViewDimension dimension) { wgpu::TextureViewDescriptor descriptor; descriptor.format = kDefaultTextureFormat; descriptor.dimension = dimension; descriptor.baseMipLevel = 0; descriptor.mipLevelCount = kDefaultMipLevels; descriptor.baseArrayLayer = 0; descriptor.arrayLayerCount = 1; return descriptor; } // Test creating texture view on a 2D non-array texture TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture2D) { wgpu::Texture texture = Create2DArrayTexture(device, 1); wgpu::TextureViewDescriptor base2DTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D); // It is an error to create a view with zero 'arrayLayerCount'. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.arrayLayerCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to create a view with zero 'mipLevelCount'. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.mipLevelCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is OK to create a 2D texture view on a 2D texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.arrayLayerCount = 1; texture.CreateView(&descriptor); } // It is an error to view a layer past the end of the texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.arrayLayerCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is OK to create a 1-layer 2D array texture view on a 2D texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e2DArray; descriptor.arrayLayerCount = 1; texture.CreateView(&descriptor); } // It is an error to create a 3D texture view on a 2D texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e3D; descriptor.arrayLayerCount = 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // baseMipLevel == k && mipLevelCount == WGPU_MIP_LEVEL_COUNT_UNDEFINED means to use levels // k..end. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED; descriptor.baseMipLevel = 0; texture.CreateView(&descriptor); descriptor.baseMipLevel = 1; texture.CreateView(&descriptor); descriptor.baseMipLevel = kDefaultMipLevels - 1; texture.CreateView(&descriptor); descriptor.baseMipLevel = kDefaultMipLevels; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to make the mip level out of range. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.baseMipLevel = 0; descriptor.mipLevelCount = kDefaultMipLevels + 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseMipLevel = 1; descriptor.mipLevelCount = kDefaultMipLevels; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseMipLevel = kDefaultMipLevels - 1; descriptor.mipLevelCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseMipLevel = kDefaultMipLevels; descriptor.mipLevelCount = 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } // Test creating texture view on a 2D array texture TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture2DArray) { constexpr uint32_t kDefaultArrayLayers = 6; wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers); wgpu::TextureViewDescriptor base2DArrayTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2DArray); // It is an error to create a view with zero 'arrayLayerCount'. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e2D; descriptor.arrayLayerCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to create a view with zero 'mipLevelCount'. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e2D; descriptor.mipLevelCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is OK to create a 2D texture view on a 2D array texture. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e2D; descriptor.arrayLayerCount = 1; texture.CreateView(&descriptor); } // It is OK to create a 2D array texture view on a 2D array texture. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.arrayLayerCount = kDefaultArrayLayers; texture.CreateView(&descriptor); } // It is an error to create a 3D texture view on a 2D array texture. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e3D; descriptor.arrayLayerCount = 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // baseArrayLayer == k && arrayLayerCount == wgpu::kArrayLayerCountUndefined means to use // layers k..end. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.arrayLayerCount = wgpu::kArrayLayerCountUndefined; descriptor.baseArrayLayer = 0; texture.CreateView(&descriptor); descriptor.baseArrayLayer = 1; texture.CreateView(&descriptor); descriptor.baseArrayLayer = kDefaultArrayLayers - 1; texture.CreateView(&descriptor); descriptor.baseArrayLayer = kDefaultArrayLayers; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error for the array layer range of the view to exceed that of the texture. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.baseArrayLayer = 0; descriptor.arrayLayerCount = kDefaultArrayLayers + 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseArrayLayer = 1; descriptor.arrayLayerCount = kDefaultArrayLayers; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseArrayLayer = kDefaultArrayLayers - 1; descriptor.arrayLayerCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseArrayLayer = kDefaultArrayLayers; descriptor.arrayLayerCount = 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } // Test creating texture view on a 3D texture TEST_F(TextureViewValidationTest, CreateTextureViewOnTexture3D) { wgpu::Texture texture = Create3DTexture(device); wgpu::TextureViewDescriptor base3DTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e3D); // It is an error to create a view with zero 'arrayLayerCount'. { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; descriptor.arrayLayerCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to create a view with zero 'mipLevelCount'. { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; descriptor.mipLevelCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is OK to create a 3D texture view on a 3D texture. { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; texture.CreateView(&descriptor); } // It is an error to create a 2D/2DArray/Cube/CubeArray texture view on a 3D texture. { wgpu::TextureViewDimension invalidDimensions[] = { wgpu::TextureViewDimension::e2D, wgpu::TextureViewDimension::e2DArray, wgpu::TextureViewDimension::Cube, wgpu::TextureViewDimension::CubeArray, }; for (wgpu::TextureViewDimension dimension : invalidDimensions) { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; descriptor.dimension = dimension; if (dimension == wgpu::TextureViewDimension::Cube || dimension == wgpu::TextureViewDimension::CubeArray) { descriptor.arrayLayerCount = 6; } ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } // baseMipLevel == k && mipLevelCount == WGPU_MIP_LEVEL_COUNT_UNDEFINED means to use levels // k..end. { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; descriptor.mipLevelCount = WGPU_MIP_LEVEL_COUNT_UNDEFINED; descriptor.baseMipLevel = 0; texture.CreateView(&descriptor); descriptor.baseMipLevel = 1; texture.CreateView(&descriptor); descriptor.baseMipLevel = kDefaultMipLevels - 1; texture.CreateView(&descriptor); descriptor.baseMipLevel = kDefaultMipLevels; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to make the mip level out of range. { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; descriptor.baseMipLevel = 0; descriptor.mipLevelCount = kDefaultMipLevels + 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseMipLevel = 1; descriptor.mipLevelCount = kDefaultMipLevels; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseMipLevel = kDefaultMipLevels - 1; descriptor.mipLevelCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseMipLevel = kDefaultMipLevels; descriptor.mipLevelCount = 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // baseArrayLayer == k && arrayLayerCount == wgpu::kArrayLayerCountUndefined means to use // layers k..end. But baseArrayLayer must be 0, and arrayLayerCount must be 1 at most for 3D // texture view. { wgpu::TextureViewDescriptor descriptor = base3DTextureViewDescriptor; descriptor.arrayLayerCount = wgpu::kArrayLayerCountUndefined; descriptor.baseArrayLayer = 0; texture.CreateView(&descriptor); descriptor.baseArrayLayer = 1; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseArrayLayer = 0; descriptor.arrayLayerCount = 1; texture.CreateView(&descriptor); descriptor.arrayLayerCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.arrayLayerCount = kDepth; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } // Using the "none" ("default") values validates the same as explicitly // specifying the values they're supposed to default to. // Variant for a 2D texture with more than 1 array layer. TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaults2DArray) { constexpr uint32_t kDefaultArrayLayers = 8; wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers); { texture.CreateView(); } { wgpu::TextureViewDescriptor descriptor; descriptor.format = wgpu::TextureFormat::Undefined; texture.CreateView(&descriptor); descriptor.format = wgpu::TextureFormat::RGBA8Unorm; texture.CreateView(&descriptor); descriptor.format = wgpu::TextureFormat::R8Unorm; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; descriptor.dimension = wgpu::TextureViewDimension::Undefined; texture.CreateView(&descriptor); descriptor.dimension = wgpu::TextureViewDimension::e2DArray; texture.CreateView(&descriptor); // Setting view dimension to 2D, its arrayLayer will default to 1. And view creation // will success. descriptor.dimension = wgpu::TextureViewDimension::e2D; texture.CreateView(&descriptor); // Setting view dimension to Cube, its arrayLayer will default to 6. descriptor.dimension = wgpu::TextureViewDimension::Cube; texture.CreateView(&descriptor); descriptor.baseArrayLayer = 2; texture.CreateView(&descriptor); descriptor.baseArrayLayer = 3; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); // Setting view dimension to CubeArray, its arrayLayer will default to // size.depthOrArrayLayers (kDefaultArrayLayers) - baseArrayLayer. descriptor.dimension = wgpu::TextureViewDimension::CubeArray; descriptor.baseArrayLayer = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.baseArrayLayer = 2; texture.CreateView(&descriptor); descriptor.baseArrayLayer = 3; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; // Setting array layers to non-0 means the dimensionality will // default to 2D so by itself it causes an error. descriptor.arrayLayerCount = kDefaultArrayLayers; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.dimension = wgpu::TextureViewDimension::e2DArray; texture.CreateView(&descriptor); descriptor.mipLevelCount = kDefaultMipLevels; texture.CreateView(&descriptor); } } // Using the "none" ("default") values validates the same as explicitly // specifying the values they're supposed to default to. // Variant for a 2D texture with only 1 array layer. TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaults2DNonArray) { constexpr uint32_t kDefaultArrayLayers = 1; wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers); { texture.CreateView(); } { wgpu::TextureViewDescriptor descriptor; descriptor.format = wgpu::TextureFormat::Undefined; texture.CreateView(&descriptor); descriptor.format = wgpu::TextureFormat::RGBA8Unorm; texture.CreateView(&descriptor); descriptor.format = wgpu::TextureFormat::R8Unorm; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; descriptor.dimension = wgpu::TextureViewDimension::Undefined; texture.CreateView(&descriptor); descriptor.dimension = wgpu::TextureViewDimension::e2D; texture.CreateView(&descriptor); descriptor.dimension = wgpu::TextureViewDimension::e2DArray; texture.CreateView(&descriptor); } { wgpu::TextureViewDescriptor descriptor; descriptor.arrayLayerCount = wgpu::kArrayLayerCountUndefined; texture.CreateView(&descriptor); descriptor.arrayLayerCount = 1; texture.CreateView(&descriptor); descriptor.arrayLayerCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; descriptor.mipLevelCount = kDefaultMipLevels; texture.CreateView(&descriptor); descriptor.arrayLayerCount = kDefaultArrayLayers; texture.CreateView(&descriptor); } } // Using the "none" ("default") values validates the same as explicitly // specifying the values they're supposed to default to. // Variant for a 3D texture. TEST_F(TextureViewValidationTest, TextureViewDescriptorDefaults3D) { wgpu::Texture texture = Create3DTexture(device); { texture.CreateView(); } { wgpu::TextureViewDescriptor descriptor; descriptor.format = wgpu::TextureFormat::Undefined; texture.CreateView(&descriptor); descriptor.format = wgpu::TextureFormat::RGBA8Unorm; texture.CreateView(&descriptor); descriptor.format = wgpu::TextureFormat::R8Unorm; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; descriptor.dimension = wgpu::TextureViewDimension::Undefined; texture.CreateView(&descriptor); descriptor.dimension = wgpu::TextureViewDimension::e3D; texture.CreateView(&descriptor); descriptor.dimension = wgpu::TextureViewDimension::e2DArray; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); descriptor.dimension = wgpu::TextureViewDimension::e2D; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; descriptor.arrayLayerCount = wgpu::kArrayLayerCountUndefined; texture.CreateView(&descriptor); descriptor.arrayLayerCount = 1; texture.CreateView(&descriptor); descriptor.arrayLayerCount = 2; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } { wgpu::TextureViewDescriptor descriptor; descriptor.mipLevelCount = kDefaultMipLevels; texture.CreateView(&descriptor); descriptor.arrayLayerCount = kDepth; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } // Test creating cube map texture view TEST_F(TextureViewValidationTest, CreateCubeMapTextureView) { constexpr uint32_t kDefaultArrayLayers = 16; wgpu::Texture texture = Create2DArrayTexture(device, kDefaultArrayLayers); wgpu::TextureViewDescriptor base2DArrayTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2DArray); // It is an error to create a view with zero 'arrayLayerCount'. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::Cube; descriptor.arrayLayerCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to create a view with zero 'mipLevelCount'. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::Cube; descriptor.mipLevelCount = 0; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is OK to create a cube map texture view with arrayLayerCount == 6. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::Cube; descriptor.arrayLayerCount = 6; texture.CreateView(&descriptor); } // It is an error to create a cube map texture view with arrayLayerCount != 6. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::Cube; descriptor.arrayLayerCount = 3; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is OK to create a cube map array texture view with arrayLayerCount % 6 == 0. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::CubeArray; descriptor.arrayLayerCount = 12; texture.CreateView(&descriptor); } // It is an error to create a cube map array texture view with arrayLayerCount % 6 != 0. { wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::CubeArray; descriptor.arrayLayerCount = 11; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } // It is an error to create a cube map texture view with width != height. { wgpu::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5); wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::Cube; descriptor.arrayLayerCount = 6; ASSERT_DEVICE_ERROR(nonSquareTexture.CreateView(&descriptor)); } // It is an error to create a cube map array texture view with width != height. { wgpu::Texture nonSquareTexture = Create2DArrayTexture(device, 18, 32, 16, 5); wgpu::TextureViewDescriptor descriptor = base2DArrayTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::CubeArray; descriptor.arrayLayerCount = 12; ASSERT_DEVICE_ERROR(nonSquareTexture.CreateView(&descriptor)); } } // Test the format compatibility rules when creating a texture view. // TODO(jiawei.shao@intel.com): add more tests when the rules are fully implemented. TEST_F(TextureViewValidationTest, TextureViewFormatCompatibility) { wgpu::Texture texture = Create2DArrayTexture(device, 1); wgpu::TextureViewDescriptor base2DTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D); // It is an error to create a texture view in depth-stencil format on a RGBA texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.format = wgpu::TextureFormat::Depth24PlusStencil8; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } // Test that it's valid to create a texture view from a destroyed texture TEST_F(TextureViewValidationTest, DestroyCreateTextureView) { wgpu::Texture texture = Create2DArrayTexture(device, 1); wgpu::TextureViewDescriptor descriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D); texture.Destroy(); texture.CreateView(&descriptor); } // Test that the selected TextureAspects must exist in the texture format TEST_F(TextureViewValidationTest, AspectMustExist) { wgpu::TextureDescriptor descriptor = {}; descriptor.size = {1, 1, 1}; descriptor.usage = wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::RenderAttachment; // Can select: All and DepthOnly from Depth32Float, but not StencilOnly { descriptor.format = wgpu::TextureFormat::Depth32Float; wgpu::Texture texture = device.CreateTexture(&descriptor); wgpu::TextureViewDescriptor viewDescriptor = {}; viewDescriptor.aspect = wgpu::TextureAspect::All; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::StencilOnly; ASSERT_DEVICE_ERROR(texture.CreateView(&viewDescriptor)); } // Can select: All, DepthOnly, and StencilOnly from Depth24PlusStencil8 { descriptor.format = wgpu::TextureFormat::Depth24PlusStencil8; wgpu::Texture texture = device.CreateTexture(&descriptor); wgpu::TextureViewDescriptor viewDescriptor = {}; viewDescriptor.aspect = wgpu::TextureAspect::All; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::StencilOnly; texture.CreateView(&viewDescriptor); } // Can select: All from RGBA8Unorm { descriptor.format = wgpu::TextureFormat::RGBA8Unorm; wgpu::Texture texture = device.CreateTexture(&descriptor); wgpu::TextureViewDescriptor viewDescriptor = {}; viewDescriptor.aspect = wgpu::TextureAspect::All; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly; ASSERT_DEVICE_ERROR(texture.CreateView(&viewDescriptor)); viewDescriptor.aspect = wgpu::TextureAspect::StencilOnly; ASSERT_DEVICE_ERROR(texture.CreateView(&viewDescriptor)); } } class D24S8TextureViewValidationTests : public ValidationTest { protected: WGPUDevice CreateTestDevice() override { dawn_native::DawnDeviceDescriptor descriptor; descriptor.requiredFeatures = {"depth24unorm-stencil8"}; return adapter.CreateDevice(&descriptor); } }; // Test that the selected TextureAspects must exist in the Depth24UnormStencil8 texture format TEST_F(D24S8TextureViewValidationTests, AspectMustExist) { wgpu::Texture texture = CreateDepthStencilTexture(device, wgpu::TextureFormat::Depth24UnormStencil8); // Can select: All, DepthOnly, and StencilOnly from Depth24UnormStencil8 { wgpu::TextureViewDescriptor viewDescriptor = {}; viewDescriptor.aspect = wgpu::TextureAspect::All; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::StencilOnly; texture.CreateView(&viewDescriptor); } } // Test the format compatibility rules when creating a texture view. TEST_F(D24S8TextureViewValidationTests, TextureViewFormatCompatibility) { wgpu::Texture texture = CreateDepthStencilTexture(device, wgpu::TextureFormat::Depth24UnormStencil8); wgpu::TextureViewDescriptor base2DTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D); // It is an error to create a texture view in color format on a depth-stencil texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.format = wgpu::TextureFormat::RGBA8Unorm; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } class D32S8TextureViewValidationTests : public ValidationTest { protected: WGPUDevice CreateTestDevice() override { dawn_native::DawnDeviceDescriptor descriptor; descriptor.requiredFeatures = {"depth32float-stencil8"}; return adapter.CreateDevice(&descriptor); } }; // Test that the selected TextureAspects must exist in the Depth32FloatStencil8 texture format TEST_F(D32S8TextureViewValidationTests, AspectMustExist) { wgpu::Texture texture = CreateDepthStencilTexture(device, wgpu::TextureFormat::Depth32FloatStencil8); // Can select: All, DepthOnly, and StencilOnly from Depth32FloatStencil8 { wgpu::TextureViewDescriptor viewDescriptor = {}; viewDescriptor.aspect = wgpu::TextureAspect::All; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::DepthOnly; texture.CreateView(&viewDescriptor); viewDescriptor.aspect = wgpu::TextureAspect::StencilOnly; texture.CreateView(&viewDescriptor); } } // Test the format compatibility rules when creating a texture view. TEST_F(D32S8TextureViewValidationTests, TextureViewFormatCompatibility) { wgpu::Texture texture = CreateDepthStencilTexture(device, wgpu::TextureFormat::Depth32FloatStencil8); wgpu::TextureViewDescriptor base2DTextureViewDescriptor = CreateDefaultViewDescriptor(wgpu::TextureViewDimension::e2D); // It is an error to create a texture view in color format on a depth-stencil texture. { wgpu::TextureViewDescriptor descriptor = base2DTextureViewDescriptor; descriptor.format = wgpu::TextureFormat::RGBA8Unorm; ASSERT_DEVICE_ERROR(texture.CreateView(&descriptor)); } } } // anonymous namespace