Overridable constants vulkan implementation and tests

Add vulkan backend implementations and tests.
Disabled some tests that fail due to tint missing
features and issues.

Bug: dawn:1041, tint:1155
Change-Id: Iac161317450cff59627e08b1228bffde4cef71da
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/64981
Commit-Queue: Shrek Shao <shrekshao@google.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/dawn_native/vulkan/UtilsVulkan.cpp b/src/dawn_native/vulkan/UtilsVulkan.cpp
index b04c0a4..6d73eec 100644
--- a/src/dawn_native/vulkan/UtilsVulkan.cpp
+++ b/src/dawn_native/vulkan/UtilsVulkan.cpp
@@ -17,6 +17,8 @@
 #include "common/Assert.h"
 #include "dawn_native/EnumMaskIterator.h"
 #include "dawn_native/Format.h"
+#include "dawn_native/Pipeline.h"
+#include "dawn_native/ShaderModule.h"
 #include "dawn_native/vulkan/DeviceVk.h"
 #include "dawn_native/vulkan/Forward.h"
 #include "dawn_native/vulkan/TextureVk.h"
@@ -195,4 +197,63 @@
             device->fn.SetDebugUtilsObjectNameEXT(device->GetVkDevice(), &objectNameInfo);
         }
     }
+
+    VkSpecializationInfo* GetVkSpecializationInfo(
+        const ProgrammableStage& programmableStage,
+        VkSpecializationInfo* specializationInfo,
+        std::vector<SpecializationDataEntry>* specializationDataEntries,
+        std::vector<VkSpecializationMapEntry>* specializationMapEntries) {
+        ASSERT(specializationInfo);
+        ASSERT(specializationDataEntries);
+        ASSERT(specializationMapEntries);
+
+        if (programmableStage.constants.size() == 0) {
+            return nullptr;
+        }
+
+        const EntryPointMetadata& entryPointMetaData =
+            programmableStage.module->GetEntryPoint(programmableStage.entryPoint);
+
+        for (const auto& pipelineConstant : programmableStage.constants) {
+            const std::string& name = pipelineConstant.first;
+            double value = pipelineConstant.second;
+
+            // This is already validated so `name` must exist
+            const auto& moduleConstant = entryPointMetaData.overridableConstants.at(name);
+
+            specializationMapEntries->push_back(
+                VkSpecializationMapEntry{moduleConstant.id,
+                                         static_cast<uint32_t>(specializationDataEntries->size() *
+                                                               sizeof(SpecializationDataEntry)),
+                                         sizeof(SpecializationDataEntry)});
+
+            SpecializationDataEntry entry;
+            switch (moduleConstant.type) {
+                case EntryPointMetadata::OverridableConstant::Type::Boolean:
+                    entry.b = static_cast<bool>(value);
+                    break;
+                case EntryPointMetadata::OverridableConstant::Type::Float32:
+                    entry.f32 = static_cast<float>(value);
+                    break;
+                case EntryPointMetadata::OverridableConstant::Type::Int32:
+                    entry.i32 = static_cast<int32_t>(value);
+                    break;
+                case EntryPointMetadata::OverridableConstant::Type::Uint32:
+                    entry.u32 = static_cast<uint32_t>(value);
+                    break;
+                default:
+                    UNREACHABLE();
+            }
+            specializationDataEntries->push_back(entry);
+        }
+
+        specializationInfo->mapEntryCount = static_cast<uint32_t>(specializationMapEntries->size());
+        specializationInfo->pMapEntries = specializationMapEntries->data();
+        specializationInfo->dataSize =
+            specializationDataEntries->size() * sizeof(SpecializationDataEntry);
+        specializationInfo->pData = specializationDataEntries->data();
+
+        return specializationInfo;
+    }
+
 }}  // namespace dawn_native::vulkan