diff --git a/src/dawn/native/metal/TextureMTL.mm b/src/dawn/native/metal/TextureMTL.mm index bee2a1e7d2..05473ab825 100644 --- a/src/dawn/native/metal/TextureMTL.mm +++ b/src/dawn/native/metal/TextureMTL.mm @@ -90,7 +90,13 @@ namespace dawn::native::metal { return true; } - if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount) { + if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount || + (texture->GetArrayLayers() == 1 && + texture->GetDimension() == wgpu::TextureDimension::e2D && + textureViewDescriptor->dimension == wgpu::TextureViewDimension::e2DArray)) { + // If the view has a different number of array layers, we need a new view. + // And, if the original texture is a 2D texture with one array layer, we need a new + // view to view it as a 2D array texture. return true; } diff --git a/src/dawn/native/opengl/TextureGL.cpp b/src/dawn/native/opengl/TextureGL.cpp index 6f65f9e7e2..4a9cda6a75 100644 --- a/src/dawn/native/opengl/TextureGL.cpp +++ b/src/dawn/native/opengl/TextureGL.cpp @@ -56,8 +56,9 @@ namespace dawn::native::opengl { case wgpu::TextureViewDimension::e2D: return (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; case wgpu::TextureViewDimension::e2DArray: - if (arrayLayerCount == 1) { - return (sampleCount > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D; + if (sampleCount > 1) { + ASSERT(arrayLayerCount == 1); + return GL_TEXTURE_2D_MULTISAMPLE; } ASSERT(sampleCount == 1); return GL_TEXTURE_2D_ARRAY; @@ -93,7 +94,13 @@ namespace dawn::native::opengl { return true; } - if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount) { + if (texture->GetArrayLayers() != textureViewDescriptor->arrayLayerCount || + (texture->GetArrayLayers() == 1 && + texture->GetDimension() == wgpu::TextureDimension::e2D && + textureViewDescriptor->dimension == wgpu::TextureViewDimension::e2DArray)) { + // If the view has a different number of array layers, we need a new view. + // And, if the original texture is a 2D texture with one array layer, we need a new + // view to view it as a 2D array texture. return true; } diff --git a/src/dawn/tests/end2end/TextureViewTests.cpp b/src/dawn/tests/end2end/TextureViewTests.cpp index e29d4ccfd1..2dac51d8ca 100644 --- a/src/dawn/tests/end2end/TextureViewTests.cpp +++ b/src/dawn/tests/end2end/TextureViewTests.cpp @@ -119,7 +119,7 @@ class TextureViewSamplingTest : public DawnTest { mVSModule = CreateDefaultVertexShaderModule(device); } - void initTexture(uint32_t arrayLayerCount, uint32_t mipLevelCount) { + void InitTexture(uint32_t arrayLayerCount, uint32_t mipLevelCount) { ASSERT(arrayLayerCount > 0 && mipLevelCount > 0); const uint32_t textureWidthLevel0 = 1 << mipLevelCount; @@ -208,7 +208,7 @@ class TextureViewSamplingTest : public DawnTest { ASSERT(textureViewBaseLayer < textureArrayLayers); ASSERT(textureViewBaseMipLevel < textureMipLevels); - initTexture(textureArrayLayers, textureMipLevels); + InitTexture(textureArrayLayers, textureMipLevels); wgpu::TextureViewDescriptor descriptor = mDefaultTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e2D; @@ -246,7 +246,7 @@ class TextureViewSamplingTest : public DawnTest { constexpr uint32_t kTextureViewLayerCount = 3; ASSERT(textureArrayLayers >= textureViewBaseLayer + kTextureViewLayerCount); - initTexture(textureArrayLayers, textureMipLevels); + InitTexture(textureArrayLayers, textureMipLevels); wgpu::TextureViewDescriptor descriptor = mDefaultTextureViewDescriptor; descriptor.dimension = wgpu::TextureViewDimension::e2DArray; @@ -320,7 +320,7 @@ class TextureViewSamplingTest : public DawnTest { // of 2D textures. Find a workaround. DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES()); constexpr uint32_t kMipLevels = 1u; - initTexture(textureArrayLayers, kMipLevels); + InitTexture(textureArrayLayers, kMipLevels); ASSERT_TRUE((textureViewLayerCount == 6) || (isCubeMapArray && textureViewLayerCount % 6 == 0)); @@ -359,7 +359,7 @@ TEST_P(TextureViewSamplingTest, Default2DArrayTexture) { constexpr uint32_t kLayers = 3; constexpr uint32_t kMipLevels = 1; - initTexture(kLayers, kMipLevels); + InitTexture(kLayers, kMipLevels); wgpu::TextureViewDescriptor descriptor; descriptor.dimension = wgpu::TextureViewDimension::e2DArray; @@ -393,6 +393,35 @@ TEST_P(TextureViewSamplingTest, Texture2DArrayViewOn2DArrayTexture) { Texture2DArrayViewTest(6, 1, 2, 0); } +// Test sampling from a 2D array texture view created on a 2D texture with one layer. +// Regression test for crbug.com/dawn/1309. +TEST_P(TextureViewSamplingTest, Texture2DArrayViewOnSingleLayer2DTexture) { + // TODO(crbug.com/dawn/593): This test requires glTextureView, which is unsupported on GLES. + DAWN_TEST_UNSUPPORTED_IF(IsOpenGLES()); + InitTexture(1 /* array layer count */, 1 /* mip level count */); + + wgpu::TextureViewDescriptor descriptor = mDefaultTextureViewDescriptor; + descriptor.dimension = wgpu::TextureViewDimension::e2DArray; + descriptor.baseArrayLayer = 0; + descriptor.arrayLayerCount = 1; + descriptor.baseMipLevel = 0; + descriptor.mipLevelCount = 1; + wgpu::TextureView textureView = mTexture.CreateView(&descriptor); + + const char* fragmentShader = R"( + @group(0) @binding(0) var sampler0 : sampler; + @group(0) @binding(1) var texture0 : texture_2d_array; + + @stage(fragment) + fn main(@location(0) texCoord : vec2) -> @location(0) vec4 { + return textureSample(texture0, sampler0, texCoord, 0); + } + )"; + + int expected = GenerateTestPixelValue(0, 0); + Verify(textureView, fragmentShader, expected); +} + // Test sampling from a 2D texture view created on a mipmap level of a 2D texture. TEST_P(TextureViewSamplingTest, Texture2DViewOnOneLevelOf2DTexture) { Texture2DViewTest(1, 6, 0, 4);