Move all the implementations of Toggle to Toggles.cpp

This patch moves all the code related to Toggle from Instance.cpp to
Toggles.cpp to make the code in Instance.cpp cleaner.

BUG=dawn:56

Change-Id: Ica2a779569478a58ddf21e632a211c0c5b889b00
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/9580
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Reviewed-by: Austin Eng <enga@chromium.org>
Commit-Queue: Jiawei Shao <jiawei.shao@intel.com>
diff --git a/BUILD.gn b/BUILD.gn
index 78c2c04..7d33abb 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -183,6 +183,7 @@
     "src/dawn_native/Texture.cpp",
     "src/dawn_native/Texture.h",
     "src/dawn_native/ToBackend.h",
+    "src/dawn_native/Toggles.cpp",
     "src/dawn_native/Toggles.h",
     "src/dawn_native/dawn_platform.h",
   ]
diff --git a/src/dawn_native/Device.cpp b/src/dawn_native/Device.cpp
index d32f02ab..2306cf0 100644
--- a/src/dawn_native/Device.cpp
+++ b/src/dawn_native/Device.cpp
@@ -506,17 +506,7 @@
     }
 
     std::vector<const char*> DeviceBase::GetTogglesUsed() const {
-        std::vector<const char*> togglesNameInUse(mTogglesSet.toggleBitset.count());
-
-        uint32_t index = 0;
-        for (uint32_t i : IterateBitSet(mTogglesSet.toggleBitset)) {
-            const char* toggleName =
-                GetAdapter()->GetInstance()->ToggleEnumToName(static_cast<Toggle>(i));
-            togglesNameInUse[index] = toggleName;
-            ++index;
-        }
-
-        return togglesNameInUse;
+        return mTogglesSet.GetEnabledToggleNames();
     }
 
     bool DeviceBase::IsToggleEnabled(Toggle toggle) const {
diff --git a/src/dawn_native/Instance.cpp b/src/dawn_native/Instance.cpp
index f686a06..c106ad1 100644
--- a/src/dawn_native/Instance.cpp
+++ b/src/dawn_native/Instance.cpp
@@ -49,47 +49,6 @@
     }
 #endif  // defined(DAWN_ENABLE_BACKEND_VULKAN)
 
-    namespace {
-
-        struct ToggleEnumAndInfo {
-            Toggle toggle;
-            ToggleInfo info;
-        };
-
-        using ToggleEnumAndInfoList =
-            std::array<ToggleEnumAndInfo, static_cast<size_t>(Toggle::EnumCount)>;
-
-        static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {
-            {{Toggle::EmulateStoreAndMSAAResolve,
-              {"emulate_store_and_msaa_resolve",
-               "Emulate storing into multisampled color attachments and doing MSAA resolve "
-               "simultaneously. This workaround is enabled by default on the Metal drivers that do "
-               "not support MTLStoreActionStoreAndMultisampleResolve. To support StoreOp::Store on "
-               "those platforms, we should do MSAA resolve in another render pass after ending the "
-               "previous one.",
-               "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
-             {Toggle::NonzeroClearResourcesOnCreationForTesting,
-              {"nonzero_clear_resources_on_creation_for_testing",
-               "Clears texture to full 1 bits as soon as they are created, but doesn't update "
-               "the tracking state of the texture. This way we can test the logic of clearing "
-               "textures that use recycled memory.",
-               "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}},
-             {Toggle::AlwaysResolveIntoZeroLevelAndLayer,
-              {"always_resolve_into_zero_level_and_layer",
-               "When the resolve target is a texture view that is created on the non-zero level or "
-               "layer of a texture, we first resolve into a temporarily 2D texture with only one "
-               "mipmap level and one array layer, and copy the result of MSAA resolve into the "
-               "true resolve target. This workaround is enabled by default on the Metal drivers "
-               "that have bugs when setting non-zero resolveLevel or resolveSlice.",
-               "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
-             {Toggle::LazyClearResourceOnFirstUse,
-              {"lazy_clear_resource_on_first_use",
-               "Clears resource to zero on first usage. This initializes the resource "
-               "so that no dirty bits from recycled memory is present in the new resource.",
-               "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}}}};
-
-    }  // anonymous namespace
-
     // InstanceBase
 
     void InstanceBase::DiscoverDefaultAdapters() {
@@ -119,51 +78,12 @@
         return !ConsumedError(DiscoverAdaptersInternal(options));
     }
 
-    const char* InstanceBase::ToggleEnumToName(Toggle toggle) {
-        ASSERT(toggle != Toggle::InvalidEnum);
-
-        const ToggleEnumAndInfo& toggleNameAndInfo =
-            kToggleNameAndInfoList[static_cast<size_t>(toggle)];
-        ASSERT(toggleNameAndInfo.toggle == toggle);
-        return toggleNameAndInfo.info.name;
-    }
-
     const ToggleInfo* InstanceBase::GetToggleInfo(const char* toggleName) {
-        ASSERT(toggleName);
-
-        EnsureToggleNameToEnumMapInitialized();
-
-        const auto& iter = mToggleNameToEnumMap.find(toggleName);
-        if (iter != mToggleNameToEnumMap.cend()) {
-            return &kToggleNameAndInfoList[static_cast<size_t>(iter->second)].info;
-        }
-        return nullptr;
+        return mTogglesInfo.GetToggleInfo(toggleName);
     }
 
     Toggle InstanceBase::ToggleNameToEnum(const char* toggleName) {
-        ASSERT(toggleName);
-
-        EnsureToggleNameToEnumMapInitialized();
-
-        const auto& iter = mToggleNameToEnumMap.find(toggleName);
-        if (iter != mToggleNameToEnumMap.cend()) {
-            return kToggleNameAndInfoList[static_cast<size_t>(iter->second)].toggle;
-        }
-        return Toggle::InvalidEnum;
-    }
-
-    void InstanceBase::EnsureToggleNameToEnumMapInitialized() {
-        if (mToggleNameToEnumMapInitialized) {
-            return;
-        }
-
-        for (size_t index = 0; index < kToggleNameAndInfoList.size(); ++index) {
-            const ToggleEnumAndInfo& toggleNameAndInfo = kToggleNameAndInfoList[index];
-            ASSERT(index == static_cast<size_t>(toggleNameAndInfo.toggle));
-            mToggleNameToEnumMap[toggleNameAndInfo.info.name] = toggleNameAndInfo.toggle;
-        }
-
-        mToggleNameToEnumMapInitialized = true;
+        return mTogglesInfo.ToggleNameToEnum(toggleName);
     }
 
     const std::vector<std::unique_ptr<AdapterBase>>& InstanceBase::GetAdapters() const {
diff --git a/src/dawn_native/Instance.h b/src/dawn_native/Instance.h
index 3743dd8..a3c5ebb 100644
--- a/src/dawn_native/Instance.h
+++ b/src/dawn_native/Instance.h
@@ -49,7 +49,6 @@
         const ToggleInfo* GetToggleInfo(const char* toggleName);
 
         Toggle ToggleNameToEnum(const char* toggleName);
-        const char* ToggleEnumToName(Toggle toggle);
 
         void EnableBackendValidation(bool enableBackendValidation);
         bool IsBackendValidationEnabled() const;
@@ -66,19 +65,16 @@
 
         MaybeError DiscoverAdaptersInternal(const AdapterDiscoveryOptionsBase* options);
 
-        void EnsureToggleNameToEnumMapInitialized();
-
         bool mBackendsConnected = false;
         bool mDiscoveredDefaultAdapters = false;
 
-        bool mToggleNameToEnumMapInitialized = false;
         bool mEnableBackendValidation = false;
         bool mBeginCaptureOnStartup = false;
 
         std::vector<std::unique_ptr<BackendConnection>> mBackends;
         std::vector<std::unique_ptr<AdapterBase>> mAdapters;
 
-        std::unordered_map<std::string, Toggle> mToggleNameToEnumMap;
+        TogglesInfo mTogglesInfo;
     };
 
 }  // namespace dawn_native
diff --git a/src/dawn_native/Toggles.cpp b/src/dawn_native/Toggles.cpp
new file mode 100644
index 0000000..382f77b
--- /dev/null
+++ b/src/dawn_native/Toggles.cpp
@@ -0,0 +1,135 @@
+// Copyright 2019 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 <array>
+
+#include "common/Assert.h"
+#include "common/BitSetIterator.h"
+#include "dawn_native/Toggles.h"
+
+namespace dawn_native {
+    namespace {
+
+        struct ToggleEnumAndInfo {
+            Toggle toggle;
+            ToggleInfo info;
+        };
+
+        using ToggleEnumAndInfoList =
+            std::array<ToggleEnumAndInfo, static_cast<size_t>(Toggle::EnumCount)>;
+
+        static constexpr ToggleEnumAndInfoList kToggleNameAndInfoList = {
+            {{Toggle::EmulateStoreAndMSAAResolve,
+              {"emulate_store_and_msaa_resolve",
+               "Emulate storing into multisampled color attachments and doing MSAA resolve "
+               "simultaneously. This workaround is enabled by default on the Metal drivers that do "
+               "not support MTLStoreActionStoreAndMultisampleResolve. To support StoreOp::Store on "
+               "those platforms, we should do MSAA resolve in another render pass after ending the "
+               "previous one.",
+               "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
+             {Toggle::NonzeroClearResourcesOnCreationForTesting,
+              {"nonzero_clear_resources_on_creation_for_testing",
+               "Clears texture to full 1 bits as soon as they are created, but doesn't update "
+               "the tracking state of the texture. This way we can test the logic of clearing "
+               "textures that use recycled memory.",
+               "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}},
+             {Toggle::AlwaysResolveIntoZeroLevelAndLayer,
+              {"always_resolve_into_zero_level_and_layer",
+               "When the resolve target is a texture view that is created on the non-zero level or "
+               "layer of a texture, we first resolve into a temporarily 2D texture with only one "
+               "mipmap level and one array layer, and copy the result of MSAA resolve into the "
+               "true resolve target. This workaround is enabled by default on the Metal drivers "
+               "that have bugs when setting non-zero resolveLevel or resolveSlice.",
+               "https://bugs.chromium.org/p/dawn/issues/detail?id=56"}},
+             {Toggle::LazyClearResourceOnFirstUse,
+              {"lazy_clear_resource_on_first_use",
+               "Clears resource to zero on first usage. This initializes the resource "
+               "so that no dirty bits from recycled memory is present in the new resource.",
+               "https://bugs.chromium.org/p/dawn/issues/detail?id=145"}}}};
+
+    }  // anonymous namespace
+
+    void TogglesSet::SetToggle(Toggle toggle, bool enabled) {
+        ASSERT(toggle != Toggle::InvalidEnum);
+        const size_t toggleIndex = static_cast<size_t>(toggle);
+        toggleBitset.set(toggleIndex, enabled);
+    }
+
+    bool TogglesSet::IsEnabled(Toggle toggle) const {
+        ASSERT(toggle != Toggle::InvalidEnum);
+        const size_t toggleIndex = static_cast<size_t>(toggle);
+        return toggleBitset.test(toggleIndex);
+    }
+
+    std::vector<const char*> TogglesSet::GetEnabledToggleNames() const {
+        std::vector<const char*> togglesNameInUse(toggleBitset.count());
+
+        uint32_t index = 0;
+        for (uint32_t i : IterateBitSet(toggleBitset)) {
+            const char* toggleName = ToggleEnumToName(static_cast<Toggle>(i));
+            togglesNameInUse[index] = toggleName;
+            ++index;
+        }
+
+        return togglesNameInUse;
+    }
+
+    const char* ToggleEnumToName(Toggle toggle) {
+        ASSERT(toggle != Toggle::InvalidEnum);
+
+        const ToggleEnumAndInfo& toggleNameAndInfo =
+            kToggleNameAndInfoList[static_cast<size_t>(toggle)];
+        ASSERT(toggleNameAndInfo.toggle == toggle);
+        return toggleNameAndInfo.info.name;
+    }
+
+    const ToggleInfo* TogglesInfo::GetToggleInfo(const char* toggleName) {
+        ASSERT(toggleName);
+
+        EnsureToggleNameToEnumMapInitialized();
+
+        const auto& iter = mToggleNameToEnumMap.find(toggleName);
+        if (iter != mToggleNameToEnumMap.cend()) {
+            return &kToggleNameAndInfoList[static_cast<size_t>(iter->second)].info;
+        }
+        return nullptr;
+    }
+
+    Toggle TogglesInfo::ToggleNameToEnum(const char* toggleName) {
+        ASSERT(toggleName);
+
+        EnsureToggleNameToEnumMapInitialized();
+
+        const auto& iter = mToggleNameToEnumMap.find(toggleName);
+        if (iter != mToggleNameToEnumMap.cend()) {
+            return kToggleNameAndInfoList[static_cast<size_t>(iter->second)].toggle;
+        }
+        return Toggle::InvalidEnum;
+    }
+
+    void TogglesInfo::EnsureToggleNameToEnumMapInitialized() {
+        if (mToggleNameToEnumMapInitialized) {
+            return;
+        }
+
+        for (size_t index = 0; index < kToggleNameAndInfoList.size(); ++index) {
+            const ToggleEnumAndInfo& toggleNameAndInfo = kToggleNameAndInfoList[index];
+            ASSERT(index == static_cast<size_t>(toggleNameAndInfo.toggle));
+            mToggleNameToEnumMap[toggleNameAndInfo.info.name] = toggleNameAndInfo.toggle;
+        }
+
+        mToggleNameToEnumMapInitialized = true;
+    }
+
+}  // namespace dawn_native
diff --git a/src/dawn_native/Toggles.h b/src/dawn_native/Toggles.h
index ac8b3dc..080bf2e 100644
--- a/src/dawn_native/Toggles.h
+++ b/src/dawn_native/Toggles.h
@@ -16,6 +16,8 @@
 #define DAWNNATIVE_TOGGLES_H_
 
 #include <bitset>
+#include <unordered_map>
+#include <vector>
 
 #include "dawn_native/DawnNative.h"
 
@@ -36,17 +38,25 @@
     struct TogglesSet {
         std::bitset<static_cast<size_t>(Toggle::EnumCount)> toggleBitset;
 
-        void SetToggle(Toggle toggle, bool enabled) {
-            ASSERT(toggle != Toggle::InvalidEnum);
-            const size_t toggleIndex = static_cast<size_t>(toggle);
-            toggleBitset.set(toggleIndex, enabled);
-        }
+        void SetToggle(Toggle toggle, bool enabled);
+        bool IsEnabled(Toggle toggle) const;
+        std::vector<const char*> GetEnabledToggleNames() const;
+    };
 
-        bool IsEnabled(Toggle toggle) const {
-            ASSERT(toggle != Toggle::InvalidEnum);
-            const size_t toggleIndex = static_cast<size_t>(toggle);
-            return toggleBitset.test(toggleIndex);
-        }
+    const char* ToggleEnumToName(Toggle toggle);
+
+    class TogglesInfo {
+      public:
+        // Used to query the details of a toggle. Return nullptr if toggleName is not a valid name
+        // of a toggle supported in Dawn.
+        const ToggleInfo* GetToggleInfo(const char* toggleName);
+        Toggle ToggleNameToEnum(const char* toggleName);
+
+      private:
+        void EnsureToggleNameToEnumMapInitialized();
+
+        bool mToggleNameToEnumMapInitialized = false;
+        std::unordered_map<std::string, Toggle> mToggleNameToEnumMap;
     };
 
 }  // namespace dawn_native