Move Subresource-related datatypes to their own file.

Aspect and SubresourceRange will be used by the SubresourceStorage
container that will itself be used by TextureBase. Avoid cyclic header
dependencies by moving SubresourceRange and Aspect to their own header.

Also refactors the handling of Aspect to aspect index in preparation for
using it in SubresourceStorage (each Aspect will have a fixed index).

Bug: dawn:441

Change-Id: I66c60f899d236a233ef30a287227610f8b469f88
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/34463
Reviewed-by: Austin Eng <enga@chromium.org>
Reviewed-by: Stephen White <senorblanco@chromium.org>
Commit-Queue: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index 5e1999f..4d0bd76 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -261,6 +261,8 @@
     "SpirvUtils.h",
     "StagingBuffer.cpp",
     "StagingBuffer.h",
+    "Subresource.cpp",
+    "Subresource.h",
     "Surface.cpp",
     "Surface.h",
     "SwapChain.cpp",
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
index 4321a44..e9b9580 100644
--- a/src/dawn_native/CMakeLists.txt
+++ b/src/dawn_native/CMakeLists.txt
@@ -148,6 +148,8 @@
     "SpirvUtils.h"
     "StagingBuffer.cpp"
     "StagingBuffer.h"
+    "Subresource.cpp"
+    "Subresource.h"
     "Surface.cpp"
     "Surface.h"
     "SwapChain.cpp"
diff --git a/src/dawn_native/Subresource.cpp b/src/dawn_native/Subresource.cpp
new file mode 100644
index 0000000..f3581e9
--- /dev/null
+++ b/src/dawn_native/Subresource.cpp
@@ -0,0 +1,78 @@
+// Copyright 2020 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 "dawn_native/Subresource.h"
+
+#include "common/Assert.h"
+#include "dawn_native/Format.h"
+
+namespace dawn_native {
+
+    Aspect ConvertSingleAspect(const Format& format, wgpu::TextureAspect aspect) {
+        Aspect aspectMask = ConvertAspect(format, aspect);
+        ASSERT(HasOneBit(aspectMask));
+        return aspectMask;
+    }
+
+    Aspect ConvertAspect(const Format& format, wgpu::TextureAspect aspect) {
+        Aspect aspectMask = TryConvertAspect(format, aspect);
+        ASSERT(aspectMask != Aspect::None);
+        return aspectMask;
+    }
+
+    Aspect TryConvertAspect(const Format& format, wgpu::TextureAspect aspect) {
+        switch (aspect) {
+            case wgpu::TextureAspect::All:
+                return format.aspects;
+            case wgpu::TextureAspect::DepthOnly:
+                return format.aspects & Aspect::Depth;
+            case wgpu::TextureAspect::StencilOnly:
+                return format.aspects & Aspect::Stencil;
+        }
+    }
+
+    uint8_t GetAspectIndex(Aspect aspect) {
+        ASSERT(HasOneBit(aspect));
+        switch (aspect) {
+            case Aspect::Color:
+                return 0;
+            case Aspect::Depth:
+                return 0;
+            case Aspect::Stencil:
+                return 1;
+            default:
+                UNREACHABLE();
+        }
+    }
+
+    uint8_t GetAspectCount(Aspect aspects) {
+        // TODO(cwallez@chromium.org): This should use popcount once Dawn has such a function.
+        // Note that we can't do a switch because compilers complain that Depth | Stencil is not
+        // a valid enum value.
+        if (aspects == Aspect::Color || aspects == Aspect::Depth) {
+            return 1;
+        } else {
+            ASSERT(aspects == (Aspect::Depth | Aspect::Stencil));
+            return 2;
+        }
+    }
+
+    // static
+    SubresourceRange SubresourceRange::SingleMipAndLayer(uint32_t baseMipLevel,
+                                                         uint32_t baseArrayLayer,
+                                                         Aspect aspects) {
+        return {baseMipLevel, 1, baseArrayLayer, 1, aspects};
+    }
+
+}  // namespace dawn_native
diff --git a/src/dawn_native/Subresource.h b/src/dawn_native/Subresource.h
new file mode 100644
index 0000000..b2f7d40
--- /dev/null
+++ b/src/dawn_native/Subresource.h
@@ -0,0 +1,78 @@
+// Copyright 2020 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.
+
+#ifndef DAWNNATIVE_SUBRESOURCE_H_
+#define DAWNNATIVE_SUBRESOURCE_H_
+
+#include "dawn_native/EnumClassBitmasks.h"
+#include "dawn_native/dawn_platform.h"
+
+namespace dawn_native {
+
+    // Note: Subresource indices are computed by iterating the aspects in increasing order.
+    // D3D12 uses these directly, so the order much match D3D12's indices.
+    //  - Depth/Stencil textures have Depth as Plane 0, and Stencil as Plane 1.
+    enum class Aspect : uint8_t {
+        None = 0x0,
+        Color = 0x1,
+        Depth = 0x2,
+        Stencil = 0x4,
+    };
+
+    template <>
+    struct EnumBitmaskSize<Aspect> {
+        static constexpr unsigned value = 3;
+    };
+
+    // Convert the TextureAspect to an Aspect mask for the format. ASSERTs if the aspect
+    // does not exist in the format.
+    // Also ASSERTs if "All" is selected and results in more than one aspect.
+    Aspect ConvertSingleAspect(const Format& format, wgpu::TextureAspect aspect);
+
+    // Convert the TextureAspect to an Aspect mask for the format. ASSERTs if the aspect
+    // does not exist in the format.
+    Aspect ConvertAspect(const Format& format, wgpu::TextureAspect aspect);
+
+    // Try to convert the TextureAspect to an Aspect mask for the format. May return
+    // Aspect::None.
+    Aspect TryConvertAspect(const Format& format, wgpu::TextureAspect aspect);
+
+    struct SubresourceRange {
+        uint32_t baseMipLevel;
+        uint32_t levelCount;
+        uint32_t baseArrayLayer;
+        uint32_t layerCount;
+        Aspect aspects;
+
+        static SubresourceRange SingleMipAndLayer(uint32_t baseMipLevel,
+                                                  uint32_t baseArrayLayer,
+                                                  Aspect aspects);
+    };
+
+    // Helper function to use aspects as linear indices in arrays.
+    uint8_t GetAspectIndex(Aspect aspect);
+    uint8_t GetAspectCount(Aspect aspects);
+
+}  // namespace dawn_native
+
+namespace wgpu {
+
+    template <>
+    struct IsDawnBitmask<dawn_native::Aspect> {
+        static constexpr bool enable = true;
+    };
+
+}  // namespace wgpu
+
+#endif  // DAWNNATIVE_SUBRESOURCE_H_
diff --git a/src/dawn_native/Texture.cpp b/src/dawn_native/Texture.cpp
index fc751dc..7e62d73 100644
--- a/src/dawn_native/Texture.cpp
+++ b/src/dawn_native/Texture.cpp
@@ -211,11 +211,6 @@
             return {};
         }
 
-        uint8_t GetPlaneIndex(Aspect aspect) {
-            ASSERT(HasOneBit(aspect));
-            return static_cast<uint8_t>(Log2(static_cast<uint32_t>(aspect)));
-        }
-
     }  // anonymous namespace
 
     MaybeError ValidateTextureDescriptor(const DeviceBase* device,
@@ -351,36 +346,6 @@
         }
     }
 
-    Aspect ConvertSingleAspect(const Format& format, wgpu::TextureAspect aspect) {
-        Aspect aspectMask = ConvertAspect(format, aspect);
-        ASSERT(HasOneBit(aspectMask));
-        return aspectMask;
-    }
-
-    Aspect ConvertAspect(const Format& format, wgpu::TextureAspect aspect) {
-        Aspect aspectMask = TryConvertAspect(format, aspect);
-        ASSERT(aspectMask != Aspect::None);
-        return aspectMask;
-    }
-
-    Aspect TryConvertAspect(const Format& format, wgpu::TextureAspect aspect) {
-        switch (aspect) {
-            case wgpu::TextureAspect::All:
-                return format.aspects;
-            case wgpu::TextureAspect::DepthOnly:
-                return format.aspects & Aspect::Depth;
-            case wgpu::TextureAspect::StencilOnly:
-                return format.aspects & Aspect::Stencil;
-        }
-    }
-
-    // static
-    SubresourceRange SubresourceRange::SingleMipAndLayer(uint32_t baseMipLevel,
-                                                         uint32_t baseArrayLayer,
-                                                         Aspect aspects) {
-        return {baseMipLevel, 1, baseArrayLayer, 1, aspects};
-    }
-
     // TextureBase
 
     TextureBase::TextureBase(DeviceBase* device,
@@ -394,13 +359,7 @@
           mSampleCount(descriptor->sampleCount),
           mUsage(descriptor->usage),
           mState(state) {
-        uint8_t planeIndex = 0;
-        for (Aspect aspect : IterateEnumMask(mFormat.aspects)) {
-            mPlaneIndices[GetPlaneIndex(aspect)] = planeIndex++;
-        }
-
-        uint32_t subresourceCount =
-            mMipLevelCount * mSize.depth * static_cast<uint32_t>(planeIndex);
+        uint32_t subresourceCount = mMipLevelCount * mSize.depth * GetAspectCount(mFormat.aspects);
         mIsSubresourceContentInitializedAtIndex = std::vector<bool>(subresourceCount, false);
 
         // Add readonly storage usage if the texture has a storage usage. The validation rules in
@@ -492,8 +451,7 @@
                           std::numeric_limits<uint32_t>::max() / kMaxTexture2DArrayLayers,
                       "texture size overflows uint32_t");
         return mipLevel +
-               GetNumMipLevels() *
-                   (arraySlice + GetArrayLayers() * mPlaneIndices[GetPlaneIndex(aspect)]);
+               GetNumMipLevels() * (arraySlice + GetArrayLayers() * GetAspectIndex(aspect));
     }
 
     bool TextureBase::IsSubresourceContentInitialized(const SubresourceRange& range) const {
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index 29a34c1..18c3e78 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -17,10 +17,10 @@
 
 #include "common/ityp_array.h"
 #include "common/ityp_bitset.h"
-#include "dawn_native/EnumClassBitmasks.h"
 #include "dawn_native/Error.h"
 #include "dawn_native/Forward.h"
 #include "dawn_native/ObjectBase.h"
+#include "dawn_native/Subresource.h"
 
 #include "dawn_native/dawn_platform.h"
 
@@ -28,34 +28,6 @@
 
 namespace dawn_native {
 
-    // Note: Subresource indices are computed by iterating the aspects in increasing order.
-    // D3D12 uses these directly, so the order much match D3D12's indices.
-    //  - Depth/Stencil textures have Depth as Plane 0, and Stencil as Plane 1.
-    enum class Aspect : uint8_t {
-        None = 0x0,
-        Color = 0x1,
-        Depth = 0x2,
-        Stencil = 0x4,
-    };
-
-    template <>
-    struct EnumBitmaskSize<Aspect> {
-        static constexpr unsigned value = 3;
-    };
-
-}  // namespace dawn_native
-
-namespace wgpu {
-
-    template <>
-    struct IsDawnBitmask<dawn_native::Aspect> {
-        static constexpr bool enable = true;
-    };
-
-}  // namespace wgpu
-
-namespace dawn_native {
-
     MaybeError ValidateTextureDescriptor(const DeviceBase* device,
                                          const TextureDescriptor* descriptor);
     MaybeError ValidateTextureViewDescriptor(const TextureBase* texture,
@@ -73,31 +45,6 @@
         wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Storage |
         wgpu::TextureUsage::RenderAttachment;
 
-    // Convert the TextureAspect to an Aspect mask for the format. ASSERTs if the aspect
-    // does not exist in the format.
-    // Also ASSERTs if "All" is selected and results in more than one aspect.
-    Aspect ConvertSingleAspect(const Format& format, wgpu::TextureAspect aspect);
-
-    // Convert the TextureAspect to an Aspect mask for the format. ASSERTs if the aspect
-    // does not exist in the format.
-    Aspect ConvertAspect(const Format& format, wgpu::TextureAspect aspect);
-
-    // Try to convert the TextureAspect to an Aspect mask for the format. May return
-    // Aspect::None.
-    Aspect TryConvertAspect(const Format& format, wgpu::TextureAspect aspect);
-
-    struct SubresourceRange {
-        uint32_t baseMipLevel;
-        uint32_t levelCount;
-        uint32_t baseArrayLayer;
-        uint32_t layerCount;
-        Aspect aspects;
-
-        static SubresourceRange SingleMipAndLayer(uint32_t baseMipLevel,
-                                                  uint32_t baseArrayLayer,
-                                                  Aspect aspects);
-    };
-
     class TextureBase : public ObjectBase {
       public:
         enum class TextureState { OwnedInternal, OwnedExternal, Destroyed };
@@ -161,7 +108,6 @@
 
         // TODO(natlee@microsoft.com): Use a more optimized data structure to save space
         std::vector<bool> mIsSubresourceContentInitializedAtIndex;
-        std::array<uint8_t, EnumBitmaskSize<Aspect>::value> mPlaneIndices;
     };
 
     class TextureViewBase : public ObjectBase {