Rephrase Format::aspect enum as an enum class mask
Format::aspect should be a mask so that it is easier to iterate over
and test if an aspect is present.
This CL also re-exports wgpu's EnumClassBitMask helpers in dawn_native.
It also adds an EnumMaskIterator which wraps BitSetIterator to allow
iterating over the enums in an enum mask.
Bug: dawn:439
Change-Id: I08180a45b27c6031e2f80b0fa1801716677fd813
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/24682
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Jiawei Shao <jiawei.shao@intel.com>
Commit-Queue: Austin Eng <enga@chromium.org>
diff --git a/src/dawn_native/BUILD.gn b/src/dawn_native/BUILD.gn
index daee013..a16e8de 100644
--- a/src/dawn_native/BUILD.gn
+++ b/src/dawn_native/BUILD.gn
@@ -192,6 +192,8 @@
"DynamicUploader.h",
"EncodingContext.cpp",
"EncodingContext.h",
+ "EnumClassBitmasks.h",
+ "EnumMaskIterator.h",
"Error.cpp",
"Error.h",
"ErrorData.cpp",
diff --git a/src/dawn_native/CMakeLists.txt b/src/dawn_native/CMakeLists.txt
index 779ef2c..9befcd7 100644
--- a/src/dawn_native/CMakeLists.txt
+++ b/src/dawn_native/CMakeLists.txt
@@ -67,6 +67,8 @@
"DynamicUploader.h"
"EncodingContext.cpp"
"EncodingContext.h"
+ "EnumClassBitmasks.h"
+ "EnumMaskIterator.h"
"Error.cpp"
"Error.h"
"ErrorData.cpp"
diff --git a/src/dawn_native/EnumClassBitmasks.h b/src/dawn_native/EnumClassBitmasks.h
new file mode 100644
index 0000000..2072b60
--- /dev/null
+++ b/src/dawn_native/EnumClassBitmasks.h
@@ -0,0 +1,41 @@
+// 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_ENUMCLASSBITMASK_H_
+#define DAWNNATIVE_ENUMCLASSBITMASK_H_
+
+#include "dawn/EnumClassBitmasks.h"
+
+namespace dawn_native {
+
+ // EnumClassBitmmasks is a WebGPU helper in the wgpu:: namespace.
+ // Re-export it in the dawn_native namespace.
+
+ // Specify this for usage with EnumMaskIterator
+ template <typename T>
+ struct EnumBitmaskSize {
+ static constexpr unsigned value = 0;
+ };
+
+ using wgpu::operator|;
+ using wgpu::operator&;
+ using wgpu::operator^;
+ using wgpu::operator~;
+ using wgpu::operator&=;
+ using wgpu::operator|=;
+ using wgpu::operator^=;
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_ENUMCLASSBITMASK_H_
diff --git a/src/dawn_native/EnumMaskIterator.h b/src/dawn_native/EnumMaskIterator.h
new file mode 100644
index 0000000..85fde10
--- /dev/null
+++ b/src/dawn_native/EnumMaskIterator.h
@@ -0,0 +1,80 @@
+// 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_ENUMMASKITERATOR_H_
+#define DAWNNATIVE_ENUMMASKITERATOR_H_
+
+#include "common/BitSetIterator.h"
+#include "dawn_native/EnumClassBitmasks.h"
+
+namespace dawn_native {
+
+ template <typename T>
+ class EnumMaskIterator final {
+ static constexpr size_t N = EnumBitmaskSize<T>::value;
+ static_assert(N > 0, "");
+
+ using U = std::underlying_type_t<T>;
+
+ public:
+ EnumMaskIterator(const T& mask) : mBitSetIterator(std::bitset<N>(static_cast<U>(mask))) {
+ }
+
+ class Iterator final {
+ public:
+ Iterator(const typename BitSetIterator<N, U>::Iterator& iter) : mIter(iter) {
+ }
+
+ Iterator& operator++() {
+ ++mIter;
+ return *this;
+ }
+
+ bool operator==(const Iterator& other) const {
+ return mIter == other.mIter;
+ }
+
+ bool operator!=(const Iterator& other) const {
+ return mIter != other.mIter;
+ }
+
+ T operator*() const {
+ U value = *mIter;
+ return static_cast<T>(U(1) << value);
+ }
+
+ private:
+ typename BitSetIterator<N, U>::Iterator mIter;
+ };
+
+ Iterator begin() const {
+ return Iterator(mBitSetIterator.begin());
+ }
+
+ Iterator end() const {
+ return Iterator(mBitSetIterator.end());
+ }
+
+ private:
+ BitSetIterator<N, U> mBitSetIterator;
+ };
+
+ template <typename T>
+ EnumMaskIterator<T> IterateEnumMask(const T& mask) {
+ return EnumMaskIterator<T>(mask);
+ }
+
+} // namespace dawn_native
+
+#endif // DAWNNATIVE_ENUMMASKITERATOR_H_
diff --git a/src/dawn_native/Format.cpp b/src/dawn_native/Format.cpp
index 9c7fa58..d80db78 100644
--- a/src/dawn_native/Format.cpp
+++ b/src/dawn_native/Format.cpp
@@ -13,8 +13,10 @@
// limitations under the License.
#include "dawn_native/Format.h"
+
#include "dawn_native/Device.h"
#include "dawn_native/Extensions.h"
+#include "dawn_native/Texture.h"
#include <bitset>
@@ -58,19 +60,19 @@
}
bool Format::IsColor() const {
- return aspect == Aspect::Color;
+ return aspects == Aspect::Color;
}
bool Format::HasDepth() const {
- return aspect == Depth || aspect == DepthStencil;
+ return (aspects & Aspect::Depth) != 0;
}
bool Format::HasStencil() const {
- return aspect == Stencil || aspect == DepthStencil;
+ return (aspects & Aspect::Stencil) != 0;
}
bool Format::HasDepthOrStencil() const {
- return aspect != Color;
+ return (aspects & (Aspect::Depth | Aspect::Stencil)) != 0;
}
bool Format::HasComponentType(Type componentType) const {
@@ -98,7 +100,6 @@
std::bitset<kKnownFormatCount> formatsSet;
using Type = Format::Type;
- using Aspect = Format::Aspect;
auto AddFormat = [&table, &formatsSet](Format format) {
size_t index = ComputeFormatIndex(format.format);
@@ -121,7 +122,7 @@
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
internalFormat.supportsStorageUsage = supportsStorageUsage;
- internalFormat.aspect = Aspect::Color;
+ internalFormat.aspects = Aspect::Color;
internalFormat.type = type;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = 1;
@@ -129,7 +130,7 @@
AddFormat(internalFormat);
};
- auto AddDepthStencilFormat = [&AddFormat](wgpu::TextureFormat format, Format::Aspect aspect,
+ auto AddDepthStencilFormat = [&AddFormat](wgpu::TextureFormat format, Aspect aspects,
uint32_t byteSize) {
Format internalFormat;
internalFormat.format = format;
@@ -137,7 +138,7 @@
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
internalFormat.supportsStorageUsage = false;
- internalFormat.aspect = aspect;
+ internalFormat.aspects = aspects;
internalFormat.type = Type::Other;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = 1;
@@ -153,7 +154,7 @@
internalFormat.isCompressed = false;
internalFormat.isSupported = true;
internalFormat.supportsStorageUsage = false;
- internalFormat.aspect = Aspect::Depth;
+ internalFormat.aspects = Aspect::Depth;
internalFormat.type = type;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = 1;
@@ -169,7 +170,7 @@
internalFormat.isCompressed = true;
internalFormat.isSupported = isSupported;
internalFormat.supportsStorageUsage = false;
- internalFormat.aspect = Aspect::Color;
+ internalFormat.aspects = Aspect::Color;
internalFormat.type = Type::Float;
internalFormat.blockByteSize = byteSize;
internalFormat.blockWidth = width;
@@ -232,7 +233,8 @@
AddDepthStencilFormat(wgpu::TextureFormat::Depth24Plus, Aspect::Depth, 4);
// TODO(cwallez@chromium.org): It isn't clear if this format should be copyable
// because its size isn't well defined, is it 4, 5 or 8?
- AddDepthStencilFormat(wgpu::TextureFormat::Depth24PlusStencil8, Aspect::DepthStencil, 4);
+ AddDepthStencilFormat(wgpu::TextureFormat::Depth24PlusStencil8,
+ Aspect::Depth | Aspect::Stencil, 4);
// BC compressed formats
bool isBCFormatSupported = device->IsExtensionEnabled(Extension::TextureCompressionBC);
diff --git a/src/dawn_native/Format.h b/src/dawn_native/Format.h
index 82b40d8..a8907ad 100644
--- a/src/dawn_native/Format.h
+++ b/src/dawn_native/Format.h
@@ -17,12 +17,16 @@
#include "dawn_native/dawn_platform.h"
+#include "common/ityp_bitset.h"
#include "dawn_native/Error.h"
+#include "dawn_native/EnumClassBitmasks.h"
+
#include <array>
namespace dawn_native {
+ enum class Aspect : uint8_t;
class DeviceBase;
// The number of formats Dawn knows about. Asserts in BuildFormatTable ensure that this is the
@@ -31,14 +35,7 @@
// A wgpu::TextureFormat along with all the information about it necessary for validation.
struct Format {
- enum Aspect {
- Color,
- Depth,
- Stencil,
- DepthStencil,
- };
-
- enum Type {
+ enum class Type {
Float,
Sint,
Uint,
@@ -51,8 +48,8 @@
// A format can be known but not supported because it is part of a disabled extension.
bool isSupported;
bool supportsStorageUsage;
- Aspect aspect;
Type type;
+ Aspect aspects;
uint32_t blockByteSize;
uint32_t blockWidth;
diff --git a/src/dawn_native/ShaderModule.cpp b/src/dawn_native/ShaderModule.cpp
index 04b6dfc..6ad0c45 100644
--- a/src/dawn_native/ShaderModule.cpp
+++ b/src/dawn_native/ShaderModule.cpp
@@ -39,14 +39,14 @@
Format::Type SpirvCrossBaseTypeToFormatType(spirv_cross::SPIRType::BaseType spirvBaseType) {
switch (spirvBaseType) {
case spirv_cross::SPIRType::Float:
- return Format::Float;
+ return Format::Type::Float;
case spirv_cross::SPIRType::Int:
- return Format::Sint;
+ return Format::Type::Sint;
case spirv_cross::SPIRType::UInt:
- return Format::Uint;
+ return Format::Type::Uint;
default:
UNREACHABLE();
- return Format::Other;
+ return Format::Type::Other;
}
}
@@ -463,7 +463,7 @@
UNREACHABLE();
}
- mFragmentOutputFormatBaseTypes.fill(Format::Other);
+ mFragmentOutputFormatBaseTypes.fill(Format::Type::Other);
if (GetDevice()->IsToggleEnabled(Toggle::UseSpvcParser)) {
mSpvcContext.SetUseSpvcParser(true);
}
diff --git a/src/dawn_native/Texture.h b/src/dawn_native/Texture.h
index 7c476ba..300b370 100644
--- a/src/dawn_native/Texture.h
+++ b/src/dawn_native/Texture.h
@@ -15,6 +15,8 @@
#ifndef DAWNNATIVE_TEXTURE_H_
#define DAWNNATIVE_TEXTURE_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"
@@ -24,6 +26,31 @@
#include <vector>
namespace dawn_native {
+
+ enum class Aspect : uint8_t {
+ 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,
diff --git a/src/dawn_native/metal/RenderPipelineMTL.mm b/src/dawn_native/metal/RenderPipelineMTL.mm
index 2164c1a..25c7869 100644
--- a/src/dawn_native/metal/RenderPipelineMTL.mm
+++ b/src/dawn_native/metal/RenderPipelineMTL.mm
@@ -371,7 +371,7 @@
descriptorMTL.colorAttachments[i].pixelFormat =
MetalPixelFormat(GetColorAttachmentFormat(i));
const ColorStateDescriptor* descriptor = GetColorStateDescriptor(i);
- bool isDeclaredInFragmentShader = fragmentOutputBaseTypes[i] != Format::Other;
+ bool isDeclaredInFragmentShader = fragmentOutputBaseTypes[i] != Format::Type::Other;
ComputeBlendDesc(descriptorMTL.colorAttachments[i], descriptor,
isDeclaredInFragmentShader);
}
diff --git a/src/dawn_native/opengl/CommandBufferGL.cpp b/src/dawn_native/opengl/CommandBufferGL.cpp
index 951999f..8bb099c 100644
--- a/src/dawn_native/opengl/CommandBufferGL.cpp
+++ b/src/dawn_native/opengl/CommandBufferGL.cpp
@@ -630,22 +630,16 @@
gl.BindFramebuffer(GL_READ_FRAMEBUFFER, readFBO);
GLenum glAttachment = 0;
- switch (format.aspect) {
- case Format::Aspect::Color:
- glAttachment = GL_COLOR_ATTACHMENT0;
- break;
- case Format::Aspect::Depth:
- glAttachment = GL_DEPTH_ATTACHMENT;
- break;
- case Format::Aspect::Stencil:
- glAttachment = GL_STENCIL_ATTACHMENT;
- break;
- case Format::Aspect::DepthStencil:
- glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
- break;
- default:
- UNREACHABLE();
- break;
+ if (format.aspects == (Aspect::Depth | Aspect::Stencil)) {
+ glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ } else if (format.aspects == Aspect::Depth) {
+ glAttachment = GL_DEPTH_ATTACHMENT;
+ } else if (format.aspects == Aspect::Stencil) {
+ glAttachment = GL_STENCIL_ATTACHMENT;
+ } else if (format.aspects == Aspect::Color) {
+ glAttachment = GL_COLOR_ATTACHMENT0;
+ } else {
+ UNREACHABLE();
}
gl.BindBuffer(GL_PIXEL_PACK_BUFFER, buffer->GetHandle());
@@ -880,19 +874,14 @@
GLenum glAttachment = 0;
// TODO(kainino@chromium.org): it may be valid to just always use
// GL_DEPTH_STENCIL_ATTACHMENT here.
- switch (format.aspect) {
- case Format::Aspect::Depth:
- glAttachment = GL_DEPTH_ATTACHMENT;
- break;
- case Format::Aspect::Stencil:
- glAttachment = GL_STENCIL_ATTACHMENT;
- break;
- case Format::Aspect::DepthStencil:
- glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
- break;
- default:
- UNREACHABLE();
- break;
+ if (format.aspects == (Aspect::Depth | Aspect::Stencil)) {
+ glAttachment = GL_DEPTH_STENCIL_ATTACHMENT;
+ } else if (format.aspects == Aspect::Depth) {
+ glAttachment = GL_DEPTH_ATTACHMENT;
+ } else if (format.aspects == Aspect::Stencil) {
+ glAttachment = GL_STENCIL_ATTACHMENT;
+ } else {
+ UNREACHABLE();
}
if (textureView->GetTexture()->GetArrayLayers() == 1) {
diff --git a/src/dawn_native/vulkan/RenderPipelineVk.cpp b/src/dawn_native/vulkan/RenderPipelineVk.cpp
index d75a6a3..271aaaa 100644
--- a/src/dawn_native/vulkan/RenderPipelineVk.cpp
+++ b/src/dawn_native/vulkan/RenderPipelineVk.cpp
@@ -429,7 +429,7 @@
descriptor->fragmentStage->module->GetFragmentOutputBaseTypes();
for (uint32_t i : IterateBitSet(GetColorAttachmentsMask())) {
const ColorStateDescriptor* colorStateDescriptor = GetColorStateDescriptor(i);
- bool isDeclaredInFragmentShader = fragmentOutputBaseTypes[i] != Format::Other;
+ bool isDeclaredInFragmentShader = fragmentOutputBaseTypes[i] != Format::Type::Other;
colorBlendAttachments[i] =
ComputeColorDesc(colorStateDescriptor, isDeclaredInFragmentShader);
}
diff --git a/src/dawn_native/vulkan/TextureVk.cpp b/src/dawn_native/vulkan/TextureVk.cpp
index d710c95..3c7ffe8 100644
--- a/src/dawn_native/vulkan/TextureVk.cpp
+++ b/src/dawn_native/vulkan/TextureVk.cpp
@@ -17,6 +17,7 @@
#include "common/Assert.h"
#include "common/Math.h"
#include "dawn_native/DynamicUploader.h"
+#include "dawn_native/EnumMaskIterator.h"
#include "dawn_native/Error.h"
#include "dawn_native/VulkanBackend.h"
#include "dawn_native/vulkan/AdapterVk.h"
@@ -193,20 +194,25 @@
}
// Computes which Vulkan texture aspects are relevant for the given Dawn format
- VkImageAspectFlags VulkanAspectMask(const Format& format) {
- switch (format.aspect) {
- case Format::Aspect::Color:
- return VK_IMAGE_ASPECT_COLOR_BIT;
- case Format::Aspect::Depth:
- return VK_IMAGE_ASPECT_DEPTH_BIT;
- case Format::Aspect::Stencil:
- return VK_IMAGE_ASPECT_STENCIL_BIT;
- case Format::Aspect::DepthStencil:
- return VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
- default:
- UNREACHABLE();
- return 0;
+ VkImageAspectFlags VulkanAspectMask(const Aspect& aspects) {
+ VkImageAspectFlags flags = 0;
+ for (Aspect aspect : IterateEnumMask(aspects)) {
+ switch (aspect) {
+ case Aspect::Color:
+ flags |= VK_IMAGE_ASPECT_COLOR_BIT;
+ break;
+ case Aspect::Depth:
+ flags |= VK_IMAGE_ASPECT_DEPTH_BIT;
+ break;
+ case Aspect::Stencil:
+ flags |= VK_IMAGE_ASPECT_STENCIL_BIT;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
}
+ return flags;
}
VkImageMemoryBarrier BuildMemoryBarrier(const Format& format,
@@ -222,7 +228,7 @@
barrier.oldLayout = VulkanImageLayout(lastUsage, format);
barrier.newLayout = VulkanImageLayout(usage, format);
barrier.image = image;
- barrier.subresourceRange.aspectMask = VulkanAspectMask(format);
+ barrier.subresourceRange.aspectMask = VulkanAspectMask(format.aspects);
barrier.subresourceRange.baseMipLevel = range.baseMipLevel;
barrier.subresourceRange.levelCount = range.levelCount;
barrier.subresourceRange.baseArrayLayer = range.baseArrayLayer;
@@ -664,7 +670,7 @@
}
VkImageAspectFlags Texture::GetVkAspectMask() const {
- return VulkanAspectMask(GetFormat());
+ return VulkanAspectMask(GetFormat().aspects);
}
void Texture::TweakTransitionForExternalUsage(CommandRecordingContext* recordingContext,
@@ -1007,7 +1013,7 @@
createInfo.format = VulkanImageFormat(device, descriptor->format);
createInfo.components = VkComponentMapping{VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G,
VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A};
- createInfo.subresourceRange.aspectMask = VulkanAspectMask(GetFormat());
+ createInfo.subresourceRange.aspectMask = VulkanAspectMask(GetFormat().aspects);
createInfo.subresourceRange.baseMipLevel = descriptor->baseMipLevel;
createInfo.subresourceRange.levelCount = descriptor->mipLevelCount;
createInfo.subresourceRange.baseArrayLayer = descriptor->baseArrayLayer;
diff --git a/src/tests/BUILD.gn b/src/tests/BUILD.gn
index 06875e6..b69dcd0 100644
--- a/src/tests/BUILD.gn
+++ b/src/tests/BUILD.gn
@@ -156,6 +156,7 @@
"unittests/BuddyMemoryAllocatorTests.cpp",
"unittests/CommandAllocatorTests.cpp",
"unittests/EnumClassBitmasksTests.cpp",
+ "unittests/EnumMaskIteratorTests.cpp",
"unittests/ErrorTests.cpp",
"unittests/ExtensionTests.cpp",
"unittests/GetProcAddressTests.cpp",
diff --git a/src/tests/unittests/EnumMaskIteratorTests.cpp b/src/tests/unittests/EnumMaskIteratorTests.cpp
new file mode 100644
index 0000000..46c351d
--- /dev/null
+++ b/src/tests/unittests/EnumMaskIteratorTests.cpp
@@ -0,0 +1,72 @@
+// 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/EnumMaskIterator.h"
+
+#include "gtest/gtest.h"
+
+namespace dawn_native {
+
+ enum class TestAspect : uint8_t {
+ Color = 1,
+ Depth = 2,
+ Stencil = 4,
+ };
+
+ template <>
+ struct EnumBitmaskSize<TestAspect> {
+ static constexpr unsigned value = 3;
+ };
+
+} // namespace dawn_native
+
+namespace wgpu {
+
+ template <>
+ struct IsDawnBitmask<dawn_native::TestAspect> {
+ static constexpr bool enable = true;
+ };
+
+} // namespace wgpu
+
+namespace dawn_native {
+
+ static_assert(EnumBitmaskSize<TestAspect>::value == 3, "");
+
+ TEST(EnumMaskIteratorTests, None) {
+ for (TestAspect aspect : IterateEnumMask(static_cast<TestAspect>(0))) {
+ FAIL();
+ DAWN_UNUSED(aspect);
+ }
+ }
+
+ TEST(EnumMaskIteratorTests, All) {
+ TestAspect expected[] = {TestAspect::Color, TestAspect::Depth, TestAspect::Stencil};
+ uint32_t i = 0;
+ TestAspect aspects = TestAspect::Color | TestAspect::Depth | TestAspect::Stencil;
+ for (TestAspect aspect : IterateEnumMask(aspects)) {
+ EXPECT_EQ(aspect, expected[i++]);
+ }
+ }
+
+ TEST(EnumMaskIteratorTests, Partial) {
+ TestAspect expected[] = {TestAspect::Color, TestAspect::Stencil};
+ uint32_t i = 0;
+ TestAspect aspects = TestAspect::Stencil | TestAspect::Color;
+ for (TestAspect aspect : IterateEnumMask(aspects)) {
+ EXPECT_EQ(aspect, expected[i++]);
+ }
+ }
+
+} // namespace dawn_native