Texture: Change to mArrayLayerCount to mSize.depth

This makes the tracking in TextureBase match the shape of
wgpu::TextureDescriptor.

GetSize() becomes a bit more surprising because the depth can sometimes
be the array size, so new getters GetWidth(), GetHeight() and GetDepth()
are added.

Some simplifications to the backend texture creation code are included
that will make it less error prone to add support for 1D / 3D textures.

Bug: dawn:22

Change-Id: I33b6ca99af9d58fc88f5f626cfd5e2e62a8b45cb
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/23103
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index d58fb32..f029981 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -372,17 +372,10 @@
           mDimension(descriptor->dimension),
           mFormat(device->GetValidInternalFormat(descriptor->format)),
           mSize(descriptor->size),
-          mArrayLayerCount(descriptor->size.depth),
           mMipLevelCount(descriptor->mipLevelCount),
           mSampleCount(descriptor->sampleCount),
           mUsage(descriptor->usage),
           mState(state) {
-        // TODO(cwallez@chromium.org): Store the array layers in size.depth instead if extracting it
-        // in mArrayLayerCount.
-        ASSERT(mDimension == wgpu::TextureDimension::e2D);
-        mArrayLayerCount = mSize.depth;
-        mSize.depth = 1;
-
         uint32_t subresourceCount = GetSubresourceCount();
         mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
 
@@ -418,9 +411,26 @@
         ASSERT(!IsError());
         return mSize;
     }
+    uint32_t TextureBase::GetWidth() const {
+        ASSERT(!IsError());
+        return mSize.width;
+    }
+    uint32_t TextureBase::GetHeight() const {
+        ASSERT(!IsError());
+        ASSERT(mDimension == wgpu::TextureDimension::e2D ||
+               mDimension == wgpu::TextureDimension::e3D);
+        return mSize.height;
+    }
+    uint32_t TextureBase::GetDepth() const {
+        ASSERT(!IsError());
+        ASSERT(mDimension == wgpu::TextureDimension::e3D);
+        return mSize.depth;
+    }
     uint32_t TextureBase::GetArrayLayers() const {
         ASSERT(!IsError());
-        return mArrayLayerCount;
+        // TODO(cwallez@chromium.org): Update for 1D / 3D textures when they are supported.
+        ASSERT(mDimension == wgpu::TextureDimension::e2D);
+        return mSize.depth;
     }
     uint32_t TextureBase::GetNumMipLevels() const {
         ASSERT(!IsError());
@@ -428,7 +438,7 @@
     }
     SubresourceRange TextureBase::GetAllSubresources() const {
         ASSERT(!IsError());
-        return {0, mMipLevelCount, 0, mArrayLayerCount};
+        return {0, mMipLevelCount, 0, GetArrayLayers()};
     }
     uint32_t TextureBase::GetSampleCount() const {
         ASSERT(!IsError());
@@ -436,7 +446,7 @@
     }
     uint32_t TextureBase::GetSubresourceCount() const {
         ASSERT(!IsError());
-        return mMipLevelCount * mArrayLayerCount;
+        return mMipLevelCount * mSize.depth;
     }
     wgpu::TextureUsage TextureBase::GetUsage() const {
         ASSERT(!IsError());
@@ -501,9 +511,16 @@
     }
 
     Extent3D TextureBase::GetMipLevelVirtualSize(uint32_t level) const {
-        Extent3D extent;
-        extent.width = std::max(mSize.width >> level, 1u);
+        Extent3D extent = {std::max(mSize.width >> level, 1u), 1u, 1u};
+        if (mDimension == wgpu::TextureDimension::e1D) {
+            return extent;
+        }
+
         extent.height = std::max(mSize.height >> level, 1u);
+        if (mDimension == wgpu::TextureDimension::e2D) {
+            return extent;
+        }
+
         extent.depth = std::max(mSize.depth >> level, 1u);
         return extent;
     }
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index 3beafb6..2900794 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -66,6 +66,9 @@
         wgpu::TextureDimension GetDimension() const;
         const Format& GetFormat() const;
         const Extent3D& GetSize() const;
+        uint32_t GetWidth() const;
+        uint32_t GetHeight() const;
+        uint32_t GetDepth() const;
         uint32_t GetArrayLayers() const;
         uint32_t GetNumMipLevels() const;
         SubresourceRange GetAllSubresources() const;
@@ -105,7 +108,6 @@
         // TODO(cwallez@chromium.org): This should be deduplicated in the Device
         const Format& mFormat;
         Extent3D mSize;
-        uint32_t mArrayLayerCount;
         uint32_t mMipLevelCount;
         uint32_t mSampleCount;
         wgpu::TextureUsage mUsage = wgpu::TextureUsage::None;
diff --git a/src/dawn_native/d3d12/CommandBufferD3D12.cpp b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
index 239415e..c2a3282 100644
--- a/src/dawn_native/d3d12/CommandBufferD3D12.cpp
+++ b/src/dawn_native/d3d12/CommandBufferD3D12.cpp
@@ -63,17 +63,6 @@
             const Extent3D& srcSize = src->GetSize();
             const Extent3D& dstSize = dst->GetSize();
 
-            auto GetCopyDepth = [](const Texture* texture) {
-                switch (texture->GetDimension()) {
-                    case wgpu::TextureDimension::e1D:
-                        return 1u;
-                    case wgpu::TextureDimension::e2D:
-                        return texture->GetArrayLayers();
-                    case wgpu::TextureDimension::e3D:
-                        return texture->GetSize().depth;
-                }
-            };
-
             // https://docs.microsoft.com/en-us/windows/win32/api/d3d12/nf-d3d12-id3d12graphicscommandlist-copyresource
             // In order to use D3D12's copy resource, the textures must be the same dimensions, and
             // the copy must be of the entire resource.
@@ -85,10 +74,10 @@
                                                        // cannot use CopyResource.
                    copySize.width == dstSize.width &&  //
                    copySize.width == srcSize.width &&  //
-                   copySize.height == dstSize.height &&    //
-                   copySize.height == srcSize.height &&    //
-                   copySize.depth == GetCopyDepth(src) &&  //
-                   copySize.depth == GetCopyDepth(dst);
+                   copySize.height == dstSize.height &&  //
+                   copySize.height == srcSize.height &&  //
+                   copySize.depth == dstSize.depth &&    //
+                   copySize.depth == srcSize.depth;
         }
 
     }  // anonymous namespace
diff --git a/src/dawn_native/d3d12/TextureD3D12.cpp b/src/dawn_native/d3d12/TextureD3D12.cpp
index d44014b..b2021f8 100644
--- a/src/dawn_native/d3d12/TextureD3D12.cpp
+++ b/src/dawn_native/d3d12/TextureD3D12.cpp
@@ -452,6 +452,7 @@
         const Extent3D& size = GetSize();
         resourceDescriptor.Width = size.width;
         resourceDescriptor.Height = size.height;
+        resourceDescriptor.DepthOrArraySize = size.depth;
 
         // This will need to be much more nuanced when WebGPU has
         // texture view compatibility rules.
@@ -462,7 +463,6 @@
                                      ? D3D12TypelessTextureFormat(GetFormat().format)
                                      : D3D12TextureFormat(GetFormat().format);
 
-        resourceDescriptor.DepthOrArraySize = GetDepthOrArraySize();
         resourceDescriptor.MipLevels = static_cast<UINT16>(GetNumMipLevels());
         resourceDescriptor.Format = dxgiFormat;
         resourceDescriptor.SampleDesc.Count = GetSampleCount();
@@ -547,15 +547,6 @@
         return mResourceAllocation.GetD3D12Resource().Get();
     }
 
-    UINT16 Texture::GetDepthOrArraySize() {
-        switch (GetDimension()) {
-            case wgpu::TextureDimension::e2D:
-                return static_cast<UINT16>(GetArrayLayers());
-            default:
-                UNREACHABLE();
-        }
-    }
-
     void Texture::TrackUsageAndTransitionNow(CommandRecordingContext* commandContext,
                                              wgpu::TextureUsage usage,
                                              uint32_t mipLevel,
@@ -878,9 +869,9 @@
             // TODO(natlee@microsoft.com): test compressed textures are cleared
             // create temp buffer with clear color to copy to the texture image
             uint32_t bytesPerRow =
-                Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
+                Align((GetWidth() / GetFormat().blockWidth) * GetFormat().blockByteSize,
                       kTextureBytesPerRowAlignment);
-            uint64_t bufferSize64 = bytesPerRow * (GetSize().height / GetFormat().blockHeight);
+            uint64_t bufferSize64 = bytesPerRow * (GetHeight() / GetFormat().blockHeight);
             if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
                 return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
             }
@@ -900,7 +891,7 @@
                 // compute d3d12 texture copy locations for texture and buffer
                 Extent3D copySize = GetMipLevelVirtualSize(level);
 
-                uint32_t rowsPerImage = GetSize().height;
+                uint32_t rowsPerImage = GetHeight();
                 TextureCopySplit copySplit =
                     ComputeTextureCopySplit({0, 0, 0}, copySize, GetFormat(),
                                             uploadHandle.startOffset, bytesPerRow, rowsPerImage);
diff --git a/src/dawn_native/d3d12/TextureD3D12.h b/src/dawn_native/d3d12/TextureD3D12.h
index fa15412..7def9be 100644
--- a/src/dawn_native/d3d12/TextureD3D12.h
+++ b/src/dawn_native/d3d12/TextureD3D12.h
@@ -95,8 +95,6 @@
                                 const SubresourceRange& range,
                                 TextureBase::ClearValue clearValue);
 
-        UINT16 GetDepthOrArraySize();
-
         void TransitionUsageAndGetResourceBarrier(CommandRecordingContext* commandContext,
                                                   std::vector<D3D12_RESOURCE_BARRIER>* barrier,
                                                   D3D12_RESOURCE_STATES newState,
diff --git a/src/dawn_native/metal/TextureMTL.mm b/src/dawn_native/metal/TextureMTL.mm
index 88184ee..454a14b 100644
--- a/src/dawn_native/metal/TextureMTL.mm
+++ b/src/dawn_native/metal/TextureMTL.mm
@@ -54,22 +54,6 @@
             return result;
         }
 
-        MTLTextureType MetalTextureType(wgpu::TextureDimension dimension,
-                                        unsigned int arrayLayers,
-                                        unsigned int sampleCount) {
-            switch (dimension) {
-                case wgpu::TextureDimension::e2D:
-                    if (sampleCount > 1) {
-                        ASSERT(arrayLayers == 1);
-                        return MTLTextureType2DMultisample;
-                    } else {
-                        return (arrayLayers > 1) ? MTLTextureType2DArray : MTLTextureType2D;
-                    }
-                default:
-                    UNREACHABLE();
-            }
-        }
-
         MTLTextureType MetalTextureViewType(wgpu::TextureViewDimension dimension,
                                             unsigned int sampleCount) {
             switch (dimension) {
@@ -301,21 +285,38 @@
 
     MTLTextureDescriptor* CreateMetalTextureDescriptor(const TextureDescriptor* descriptor) {
         MTLTextureDescriptor* mtlDesc = [MTLTextureDescriptor new];
-        mtlDesc.textureType = MetalTextureType(descriptor->dimension, descriptor->size.depth,
-                                               descriptor->sampleCount);
-        mtlDesc.usage = MetalTextureUsage(descriptor->usage);
-        mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
 
         mtlDesc.width = descriptor->size.width;
         mtlDesc.height = descriptor->size.height;
-        ASSERT(descriptor->dimension == wgpu::TextureDimension::e2D);
-        mtlDesc.depth = 1;
-
+        mtlDesc.sampleCount = descriptor->sampleCount;
+        mtlDesc.usage = MetalTextureUsage(descriptor->usage);
+        mtlDesc.pixelFormat = MetalPixelFormat(descriptor->format);
         mtlDesc.mipmapLevelCount = descriptor->mipLevelCount;
-        mtlDesc.arrayLength = descriptor->size.depth;
         mtlDesc.storageMode = MTLStorageModePrivate;
 
-        mtlDesc.sampleCount = descriptor->sampleCount;
+        // Choose the correct MTLTextureType and paper over differences in how the array layer count
+        // is specified.
+        mtlDesc.depth = descriptor->size.depth;
+        mtlDesc.arrayLength = 1;
+        switch (descriptor->dimension) {
+            case wgpu::TextureDimension::e2D:
+                if (mtlDesc.depth > 1) {
+                    ASSERT(mtlDesc.sampleCount == 1);
+                    mtlDesc.textureType = MTLTextureType2DArray;
+                    mtlDesc.arrayLength = mtlDesc.depth;
+                    mtlDesc.depth = 1;
+                } else {
+                    if (mtlDesc.sampleCount > 1) {
+                        mtlDesc.textureType = MTLTextureType2DMultisample;
+                    } else {
+                        mtlDesc.textureType = MTLTextureType2D;
+                    }
+                }
+                break;
+
+            default:
+                UNREACHABLE();
+        }
 
         return mtlDesc;
     }
diff --git a/src/dawn_native/opengl/TextureGL.cpp b/src/dawn_native/opengl/TextureGL.cpp
index 1236d47..029ecca 100644
--- a/src/dawn_native/opengl/TextureGL.cpp
+++ b/src/dawn_native/opengl/TextureGL.cpp
@@ -108,8 +108,8 @@
         : Texture(device, descriptor, GenTexture(device->gl), TextureState::OwnedInternal) {
         const OpenGLFunctions& gl = ToBackend(GetDevice())->gl;
 
-        uint32_t width = GetSize().width;
-        uint32_t height = GetSize().height;
+        uint32_t width = GetWidth();
+        uint32_t height = GetHeight();
         uint32_t levels = GetNumMipLevels();
         uint32_t arrayLayers = GetArrayLayers();
         uint32_t sampleCount = GetSampleCount();
@@ -292,15 +292,15 @@
             // create temp buffer with clear color to copy to the texture image
             ASSERT(kTextureBytesPerRowAlignment % GetFormat().blockByteSize == 0);
             uint32_t bytesPerRow =
-                Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
+                Align((GetWidth() / GetFormat().blockWidth) * GetFormat().blockByteSize,
                       kTextureBytesPerRowAlignment);
 
             // Make sure that we are not rounding
             ASSERT(bytesPerRow % GetFormat().blockByteSize == 0);
-            ASSERT(GetSize().height % GetFormat().blockHeight == 0);
+            ASSERT(GetHeight() % GetFormat().blockHeight == 0);
 
             dawn_native::BufferDescriptor descriptor;
-            descriptor.size = bytesPerRow * (GetSize().height / GetFormat().blockHeight);
+            descriptor.size = bytesPerRow * (GetHeight() / GetFormat().blockHeight);
             if (descriptor.size > std::numeric_limits<uint32_t>::max()) {
                 return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
             }
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index 3894d5a..7b35f14 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -32,18 +32,6 @@
 namespace dawn_native { namespace vulkan {
 
     namespace {
-        // Converts an Dawn texture dimension to a Vulkan image type.
-        // Note that in Vulkan dimensionality is only 1D, 2D, 3D. Arrays and cube maps are expressed
-        // via the array size and a "cubemap compatible" flag.
-        VkImageType VulkanImageType(wgpu::TextureDimension dimension) {
-            switch (dimension) {
-                case wgpu::TextureDimension::e2D:
-                    return VK_IMAGE_TYPE_2D;
-                default:
-                    UNREACHABLE();
-            }
-        }
-
         // Converts an Dawn texture dimension to a Vulkan image view type.
         // Contrary to image types, image view types include arrayness and cubemapness
         VkImageViewType VulkanImageViewType(wgpu::TextureViewDimension dimension) {
@@ -221,10 +209,6 @@
             }
         }
 
-        VkExtent3D VulkanExtent3D(const Extent3D& extent) {
-            return {extent.width, extent.height, extent.depth};
-        }
-
         VkImageMemoryBarrier BuildMemoryBarrier(const Format& format,
                                                 const VkImage& image,
                                                 wgpu::TextureUsage lastUsage,
@@ -252,6 +236,27 @@
             return barrier;
         }
 
+        void FillVulkanCreateInfoSizesAndType(const Texture& texture, VkImageCreateInfo* info) {
+            const Extent3D& size = texture.GetSize();
+
+            info->mipLevels = texture.GetNumMipLevels();
+            info->samples = VulkanSampleCount(texture.GetSampleCount());
+
+            // Fill in the image type, and paper over differences in how the array layer count is
+            // specified between WebGPU and Vulkan.
+            switch (texture.GetDimension()) {
+                case wgpu::TextureDimension::e2D:
+                    info->imageType = VK_IMAGE_TYPE_2D;
+                    info->extent = {size.width, size.height, 1};
+                    info->arrayLayers = size.depth;
+                    break;
+
+                default:
+                    UNREACHABLE();
+                    break;
+            }
+        }
+
     }  // namespace
 
     // Converts Dawn texture format to Vulkan formats.
@@ -495,15 +500,12 @@
         // combination of sample, usage etc. because validation should have been done in the Dawn
         // frontend already based on the minimum supported formats in the Vulkan spec
         VkImageCreateInfo createInfo = {};
+        FillVulkanCreateInfoSizesAndType(*this, &createInfo);
+
         createInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
         createInfo.pNext = nullptr;
         createInfo.flags = 0;
-        createInfo.imageType = VulkanImageType(GetDimension());
         createInfo.format = VulkanImageFormat(device, GetFormat().format);
-        createInfo.extent = VulkanExtent3D(GetSize());
-        createInfo.mipLevels = GetNumMipLevels();
-        createInfo.arrayLayers = GetArrayLayers();
-        createInfo.samples = VulkanSampleCount(GetSampleCount());
         createInfo.tiling = VK_IMAGE_TILING_OPTIMAL;
         createInfo.usage = VulkanImageUsage(GetUsage(), GetFormat());
         createInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
@@ -513,7 +515,7 @@
 
         ASSERT(IsSampleCountSupported(device, createInfo));
 
-        if (GetArrayLayers() >= 6 && GetSize().width == GetSize().height) {
+        if (GetArrayLayers() >= 6 && GetWidth() == GetHeight()) {
             createInfo.flags |= VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
         }
 
@@ -556,15 +558,13 @@
         }
 
         mExternalState = ExternalState::PendingAcquire;
+
         VkImageCreateInfo baseCreateInfo = {};
+        FillVulkanCreateInfoSizesAndType(*this, &baseCreateInfo);
+
         baseCreateInfo.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO;
         baseCreateInfo.pNext = nullptr;
-        baseCreateInfo.imageType = VulkanImageType(GetDimension());
         baseCreateInfo.format = format;
-        baseCreateInfo.extent = VulkanExtent3D(GetSize());
-        baseCreateInfo.mipLevels = GetNumMipLevels();
-        baseCreateInfo.arrayLayers = GetArrayLayers();
-        baseCreateInfo.samples = VulkanSampleCount(GetSampleCount());
         baseCreateInfo.usage = usage;
         baseCreateInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
         baseCreateInfo.queueFamilyIndexCount = 0;
@@ -909,9 +909,9 @@
             // TODO(natlee@microsoft.com): test compressed textures are cleared
             // create temp buffer with clear color to copy to the texture image
             uint32_t bytesPerRow =
-                Align((GetSize().width / GetFormat().blockWidth) * GetFormat().blockByteSize,
+                Align((GetWidth() / GetFormat().blockWidth) * GetFormat().blockByteSize,
                       kTextureBytesPerRowAlignment);
-            uint64_t bufferSize64 = bytesPerRow * (GetSize().height / GetFormat().blockHeight);
+            uint64_t bufferSize64 = bytesPerRow * (GetHeight() / GetFormat().blockHeight);
             if (bufferSize64 > std::numeric_limits<uint32_t>::max()) {
                 return DAWN_OUT_OF_MEMORY_ERROR("Unable to allocate buffer.");
             }