summaryrefslogtreecommitdiffstats
path: root/gfx/angle/checkout/src/common/vulkan
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/checkout/src/common/vulkan')
-rw-r--r--gfx/angle/checkout/src/common/vulkan/libvulkan_loader.cpp57
-rw-r--r--gfx/angle/checkout/src/common/vulkan/libvulkan_loader.h23
-rw-r--r--gfx/angle/checkout/src/common/vulkan/vk_google_filtering_precision.h57
-rw-r--r--gfx/angle/checkout/src/common/vulkan/vk_headers.h163
-rw-r--r--gfx/angle/checkout/src/common/vulkan/vulkan_icd.cpp349
-rw-r--r--gfx/angle/checkout/src/common/vulkan/vulkan_icd.h72
6 files changed, 721 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/common/vulkan/libvulkan_loader.cpp b/gfx/angle/checkout/src/common/vulkan/libvulkan_loader.cpp
new file mode 100644
index 0000000000..dafe092732
--- /dev/null
+++ b/gfx/angle/checkout/src/common/vulkan/libvulkan_loader.cpp
@@ -0,0 +1,57 @@
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// libvulkan_loader.cpp:
+// Helper functions for the loading Vulkan libraries.
+//
+
+#include "common/vulkan/libvulkan_loader.h"
+
+#include "common/system_utils.h"
+
+namespace angle
+{
+namespace vk
+{
+void *OpenLibVulkan()
+{
+ constexpr const char *kLibVulkanNames[] = {
+#if defined(ANGLE_PLATFORM_WINDOWS)
+ "vulkan-1.dll",
+#elif defined(ANGLE_PLATFORM_APPLE)
+ "libvulkan.dylib",
+ "libvulkan.1.dylib",
+ "libMoltenVK.dylib"
+#else
+ "libvulkan.so",
+ "libvulkan.so.1",
+#endif
+ };
+
+ constexpr SearchType kSearchTypes[] = {
+// On Android, Fuchsia and GGP we use the system libvulkan.
+#if defined(ANGLE_USE_CUSTOM_LIBVULKAN)
+ SearchType::ModuleDir,
+#else
+ SearchType::SystemDir,
+#endif // defined(ANGLE_USE_CUSTOM_LIBVULKAN)
+ };
+
+ for (angle::SearchType searchType : kSearchTypes)
+ {
+ for (const char *libraryName : kLibVulkanNames)
+ {
+ void *library = OpenSystemLibraryWithExtension(libraryName, searchType);
+ if (library)
+ {
+ return library;
+ }
+ }
+ }
+
+ return nullptr;
+}
+} // namespace vk
+} // namespace angle
diff --git a/gfx/angle/checkout/src/common/vulkan/libvulkan_loader.h b/gfx/angle/checkout/src/common/vulkan/libvulkan_loader.h
new file mode 100644
index 0000000000..1a73c87b68
--- /dev/null
+++ b/gfx/angle/checkout/src/common/vulkan/libvulkan_loader.h
@@ -0,0 +1,23 @@
+//
+// Copyright 2021 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// libvulkan_loader.h:
+// Helper functions for the loading Vulkan libraries.
+//
+
+#include <memory>
+
+#ifndef LIBANGLE_COMMON_VULKAN_LIBVULKAN_LOADER_H_
+# define LIBANGLE_COMMON_VULKAN_LIBVULKAN_LOADER_H_
+
+namespace angle
+{
+namespace vk
+{
+void *OpenLibVulkan();
+}
+} // namespace angle
+
+#endif // LIBANGLE_COMMON_VULKAN_LIBVULKAN_LOADER_H_
diff --git a/gfx/angle/checkout/src/common/vulkan/vk_google_filtering_precision.h b/gfx/angle/checkout/src/common/vulkan/vk_google_filtering_precision.h
new file mode 100644
index 0000000000..934dc793c6
--- /dev/null
+++ b/gfx/angle/checkout/src/common/vulkan/vk_google_filtering_precision.h
@@ -0,0 +1,57 @@
+// Copyright 2020 The SwiftShader Authors. All Rights Reserved.
+//
+// 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 CUSTOM_VK_GOOGLE_SAMPLER_FILTERING_PRECISION_H_
+#define CUSTOM_VK_GOOGLE_SAMPLER_FILTERING_PRECISION_H_
+
+#include "vk_headers.h"
+
+// THIS FILE SHOULD BE DELETED IF VK_GOOGLE_sampler_filtering_precision IS EVER ADDED TO THE VULKAN
+// HEADERS
+#ifdef VK_GOOGLE_sampler_filtering_precision
+# error \
+ "VK_GOOGLE_sampler_filtering_precision is already defined in the Vulkan headers, you can delete this file"
+#endif
+
+static constexpr VkStructureType VK_STRUCTURE_TYPE_SAMPLER_FILTERING_PRECISION_GOOGLE =
+ static_cast<VkStructureType>(1000264000);
+
+#define VK_GOOGLE_sampler_filtering_precision 1
+#define VK_GOOGLE_SAMPLER_FILTERING_PRECISION_SPEC_VERSION 1
+#define VK_GOOGLE_SAMPLER_FILTERING_PRECISION_EXTENSION_NAME "VK_GOOGLE_sampler_filtering_precision"
+
+const int TEXTURE_FILTERING_HINT_CHROMIUM = 0x8AF0;
+
+typedef enum VkSamplerFilteringPrecisionModeGOOGLE
+{
+ VK_SAMPLER_FILTERING_PRECISION_MODE_LOW_GOOGLE = 0,
+ VK_SAMPLER_FILTERING_PRECISION_MODE_HIGH_GOOGLE = 1,
+ VK_SAMPLER_FILTERING_PRECISION_MODE_BEGIN_RANGE_GOOGLE =
+ VK_SAMPLER_FILTERING_PRECISION_MODE_LOW_GOOGLE,
+ VK_SAMPLER_FILTERING_PRECISION_MODE_END_RANGE_GOOGLE =
+ VK_SAMPLER_FILTERING_PRECISION_MODE_HIGH_GOOGLE,
+ VK_SAMPLER_FILTERING_PRECISION_MODE_RANGE_SIZE_GOOGLE =
+ (VK_SAMPLER_FILTERING_PRECISION_MODE_HIGH_GOOGLE -
+ VK_SAMPLER_FILTERING_PRECISION_MODE_LOW_GOOGLE + 1),
+ VK_SAMPLER_FILTERING_PRECISION_MODE_MAX_ENUM_GOOGLE = 0x7FFFFFFF
+} VkSamplerFilteringPrecisionModeGOOGLE;
+
+typedef struct VkSamplerFilteringPrecisionGOOGLE
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkSamplerFilteringPrecisionModeGOOGLE samplerFilteringPrecisionMode;
+} VkSamplerFilteringPrecisionGOOGLE;
+
+#endif // CUSTOM_VK_GOOGLE_SAMPLER_FILTERING_PRECISION_H_
diff --git a/gfx/angle/checkout/src/common/vulkan/vk_headers.h b/gfx/angle/checkout/src/common/vulkan/vk_headers.h
new file mode 100644
index 0000000000..a16938a872
--- /dev/null
+++ b/gfx/angle/checkout/src/common/vulkan/vk_headers.h
@@ -0,0 +1,163 @@
+//
+// Copyright 2016 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// vk_headers:
+// This file should be included to ensure the vulkan headers are included
+//
+
+#ifndef LIBANGLE_RENDERER_VULKAN_VK_HEADERS_H_
+#define LIBANGLE_RENDERER_VULKAN_VK_HEADERS_H_
+
+#if ANGLE_SHARED_LIBVULKAN
+# include "third_party/volk/volk.h"
+#else
+# include <vulkan/vulkan.h>
+#endif
+
+// For the unreleased VK_GOOGLEX_multisampled_render_to_single_sampled
+#if !defined(VK_GOOGLEX_multisampled_render_to_single_sampled)
+# define VK_GOOGLEX_multisampled_render_to_single_sampled 1
+# define VK_GOOGLEX_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_SPEC_VERSION 1
+# define VK_GOOGLEX_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_EXTENSION_NAME \
+ "VK_GOOGLEX_multisampled_render_to_single_sampled"
+
+# define VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_FEATURES_GOOGLEX \
+ ((VkStructureType)(1000376000))
+# define VK_STRUCTURE_TYPE_MULTISAMPLED_RENDER_TO_SINGLE_SAMPLED_INFO_GOOGLEX \
+ ((VkStructureType)(1000376001))
+
+typedef struct VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesGOOGLEX
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkBool32 multisampledRenderToSingleSampled;
+} VkPhysicalDeviceMultisampledRenderToSingleSampledFeaturesGOOGLEX;
+
+typedef struct VkMultisampledRenderToSingleSampledInfoGOOGLEX
+{
+ VkStructureType sType;
+ const void *pNext;
+ VkBool32 multisampledRenderToSingleSampledEnable;
+ VkSampleCountFlagBits rasterizationSamples;
+ VkResolveModeFlagBits depthResolveMode;
+ VkResolveModeFlagBits stencilResolveMode;
+} VkMultisampledRenderToSingleSampledInfoGOOGLEX;
+#endif /* VK_GOOGLEX_multisampled_render_to_single_sampled */
+
+#if !defined(ANGLE_SHARED_LIBVULKAN)
+
+namespace rx
+{
+// VK_EXT_debug_utils
+extern PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessengerEXT;
+extern PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessengerEXT;
+extern PFN_vkCmdBeginDebugUtilsLabelEXT vkCmdBeginDebugUtilsLabelEXT;
+extern PFN_vkCmdEndDebugUtilsLabelEXT vkCmdEndDebugUtilsLabelEXT;
+extern PFN_vkCmdInsertDebugUtilsLabelEXT vkCmdInsertDebugUtilsLabelEXT;
+extern PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectNameEXT;
+
+// VK_EXT_debug_report
+extern PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT;
+extern PFN_vkDestroyDebugReportCallbackEXT vkDestroyDebugReportCallbackEXT;
+
+// VK_KHR_get_physical_device_properties2
+extern PFN_vkGetPhysicalDeviceProperties2KHR vkGetPhysicalDeviceProperties2KHR;
+extern PFN_vkGetPhysicalDeviceFeatures2KHR vkGetPhysicalDeviceFeatures2KHR;
+extern PFN_vkGetPhysicalDeviceMemoryProperties2KHR vkGetPhysicalDeviceMemoryProperties2KHR;
+
+// VK_KHR_external_semaphore_fd
+extern PFN_vkImportSemaphoreFdKHR vkImportSemaphoreFdKHR;
+
+// VK_EXT_external_memory_host
+extern PFN_vkGetMemoryHostPointerPropertiesEXT vkGetMemoryHostPointerPropertiesEXT;
+
+// VK_EXT_host_query_reset
+extern PFN_vkResetQueryPoolEXT vkResetQueryPoolEXT;
+
+// VK_EXT_transform_feedback
+extern PFN_vkCmdBindTransformFeedbackBuffersEXT vkCmdBindTransformFeedbackBuffersEXT;
+extern PFN_vkCmdBeginTransformFeedbackEXT vkCmdBeginTransformFeedbackEXT;
+extern PFN_vkCmdEndTransformFeedbackEXT vkCmdEndTransformFeedbackEXT;
+extern PFN_vkCmdBeginQueryIndexedEXT vkCmdBeginQueryIndexedEXT;
+extern PFN_vkCmdEndQueryIndexedEXT vkCmdEndQueryIndexedEXT;
+extern PFN_vkCmdDrawIndirectByteCountEXT vkCmdDrawIndirectByteCountEXT;
+
+// VK_KHR_get_memory_requirements2
+extern PFN_vkGetBufferMemoryRequirements2KHR vkGetBufferMemoryRequirements2KHR;
+extern PFN_vkGetImageMemoryRequirements2KHR vkGetImageMemoryRequirements2KHR;
+
+// VK_KHR_bind_memory2
+extern PFN_vkBindBufferMemory2KHR vkBindBufferMemory2KHR;
+extern PFN_vkBindImageMemory2KHR vkBindImageMemory2KHR;
+
+// VK_KHR_external_fence_capabilities
+extern PFN_vkGetPhysicalDeviceExternalFencePropertiesKHR
+ vkGetPhysicalDeviceExternalFencePropertiesKHR;
+
+// VK_KHR_external_fence_fd
+extern PFN_vkGetFenceFdKHR vkGetFenceFdKHR;
+extern PFN_vkImportFenceFdKHR vkImportFenceFdKHR;
+
+// VK_KHR_external_semaphore_capabilities
+extern PFN_vkGetPhysicalDeviceExternalSemaphorePropertiesKHR
+ vkGetPhysicalDeviceExternalSemaphorePropertiesKHR;
+
+// VK_KHR_sampler_ycbcr_conversion
+extern PFN_vkCreateSamplerYcbcrConversionKHR vkCreateSamplerYcbcrConversionKHR;
+extern PFN_vkDestroySamplerYcbcrConversionKHR vkDestroySamplerYcbcrConversionKHR;
+
+// VK_KHR_create_renderpass2
+extern PFN_vkCreateRenderPass2KHR vkCreateRenderPass2KHR;
+
+# if defined(ANGLE_PLATFORM_FUCHSIA)
+// VK_FUCHSIA_imagepipe_surface
+extern PFN_vkCreateImagePipeSurfaceFUCHSIA vkCreateImagePipeSurfaceFUCHSIA;
+# endif
+
+# if defined(ANGLE_PLATFORM_ANDROID)
+extern PFN_vkGetAndroidHardwareBufferPropertiesANDROID vkGetAndroidHardwareBufferPropertiesANDROID;
+extern PFN_vkGetMemoryAndroidHardwareBufferANDROID vkGetMemoryAndroidHardwareBufferANDROID;
+# endif
+
+# if defined(ANGLE_PLATFORM_GGP)
+extern PFN_vkCreateStreamDescriptorSurfaceGGP vkCreateStreamDescriptorSurfaceGGP;
+# endif // defined(ANGLE_PLATFORM_GGP)
+
+// VK_KHR_shared_presentable_image
+extern PFN_vkGetSwapchainStatusKHR vkGetSwapchainStatusKHR;
+
+// VK_EXT_extended_dynamic_state
+extern PFN_vkCmdBindVertexBuffers2EXT vkCmdBindVertexBuffers2EXT;
+extern PFN_vkCmdSetCullModeEXT vkCmdSetCullModeEXT;
+extern PFN_vkCmdSetDepthBoundsTestEnableEXT vkCmdSetDepthBoundsTestEnableEXT;
+extern PFN_vkCmdSetDepthCompareOpEXT vkCmdSetDepthCompareOpEXT;
+extern PFN_vkCmdSetDepthTestEnableEXT vkCmdSetDepthTestEnableEXT;
+extern PFN_vkCmdSetDepthWriteEnableEXT vkCmdSetDepthWriteEnableEXT;
+extern PFN_vkCmdSetFrontFaceEXT vkCmdSetFrontFaceEXT;
+extern PFN_vkCmdSetPrimitiveTopologyEXT vkCmdSetPrimitiveTopologyEXT;
+extern PFN_vkCmdSetScissorWithCountEXT vkCmdSetScissorWithCountEXT;
+extern PFN_vkCmdSetStencilOpEXT vkCmdSetStencilOpEXT;
+extern PFN_vkCmdSetStencilTestEnableEXT vkCmdSetStencilTestEnableEXT;
+extern PFN_vkCmdSetViewportWithCountEXT vkCmdSetViewportWithCountEXT;
+
+// VK_EXT_extended_dynamic_state2
+extern PFN_vkCmdSetDepthBiasEnableEXT vkCmdSetDepthBiasEnableEXT;
+extern PFN_vkCmdSetLogicOpEXT vkCmdSetLogicOpEXT;
+extern PFN_vkCmdSetPatchControlPointsEXT vkCmdSetPatchControlPointsEXT;
+extern PFN_vkCmdSetPrimitiveRestartEnableEXT vkCmdSetPrimitiveRestartEnableEXT;
+extern PFN_vkCmdSetRasterizerDiscardEnableEXT vkCmdSetRasterizerDiscardEnableEXT;
+
+// VK_KHR_fragment_shading_rate
+extern PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR vkGetPhysicalDeviceFragmentShadingRatesKHR;
+extern PFN_vkCmdSetFragmentShadingRateKHR vkCmdSetFragmentShadingRateKHR;
+
+// VK_GOOGLE_display_timing
+extern PFN_vkGetPastPresentationTimingGOOGLE vkGetPastPresentationTimingGOOGLE;
+
+} // namespace rx
+
+#endif // ANGLE_SHARED_LIBVULKAN
+
+#endif // LIBANGLE_RENDERER_VULKAN_VK_HEADERS_H_
diff --git a/gfx/angle/checkout/src/common/vulkan/vulkan_icd.cpp b/gfx/angle/checkout/src/common/vulkan/vulkan_icd.cpp
new file mode 100644
index 0000000000..22502c0457
--- /dev/null
+++ b/gfx/angle/checkout/src/common/vulkan/vulkan_icd.cpp
@@ -0,0 +1,349 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// vulkan_icd.cpp : Helper for creating vulkan instances & selecting physical device.
+
+#include "common/vulkan/vulkan_icd.h"
+
+#include <functional>
+#include <vector>
+
+#include "common/Optional.h"
+#include "common/bitset_utils.h"
+#include "common/debug.h"
+#include "common/system_utils.h"
+
+#include "common/vulkan/vk_google_filtering_precision.h"
+
+namespace
+{
+void ResetEnvironmentVar(const char *variableName, const Optional<std::string> &value)
+{
+ if (!value.valid())
+ {
+ return;
+ }
+
+ if (value.value().empty())
+ {
+ angle::UnsetEnvironmentVar(variableName);
+ }
+ else
+ {
+ angle::SetEnvironmentVar(variableName, value.value().c_str());
+ }
+}
+} // namespace
+
+namespace angle
+{
+
+namespace vk
+{
+
+namespace
+{
+
+[[maybe_unused]] const std::string WrapICDEnvironment(const char *icdEnvironment)
+{
+ // The libraries are bundled into the module directory
+ std::string ret = ConcatenatePath(angle::GetModuleDirectory(), icdEnvironment);
+ return ret;
+}
+
+[[maybe_unused]] constexpr char kLoaderLayersPathEnv[] = "VK_LAYER_PATH";
+[[maybe_unused]] constexpr char kLayerEnablesEnv[] = "VK_LAYER_ENABLES";
+
+constexpr char kLoaderICDFilenamesEnv[] = "VK_ICD_FILENAMES";
+constexpr char kANGLEPreferredDeviceEnv[] = "ANGLE_PREFERRED_DEVICE";
+constexpr char kValidationLayersCustomSTypeListEnv[] = "VK_LAYER_CUSTOM_STYPE_LIST";
+constexpr char kNoDeviceSelect[] = "NODEVICE_SELECT";
+
+constexpr uint32_t kMockVendorID = 0xba5eba11;
+constexpr uint32_t kMockDeviceID = 0xf005ba11;
+constexpr char kMockDeviceName[] = "Vulkan Mock Device";
+
+constexpr uint32_t kGoogleVendorID = 0x1AE0;
+constexpr uint32_t kSwiftShaderDeviceID = 0xC0DE;
+constexpr char kSwiftShaderDeviceName[] = "SwiftShader Device";
+
+using ICDFilterFunc = std::function<bool(const VkPhysicalDeviceProperties &)>;
+
+ICDFilterFunc GetFilterForICD(vk::ICD preferredICD)
+{
+ switch (preferredICD)
+ {
+ case vk::ICD::Mock:
+ return [](const VkPhysicalDeviceProperties &deviceProperties) {
+ return ((deviceProperties.vendorID == kMockVendorID) &&
+ (deviceProperties.deviceID == kMockDeviceID) &&
+ (strcmp(deviceProperties.deviceName, kMockDeviceName) == 0));
+ };
+ case vk::ICD::SwiftShader:
+ return [](const VkPhysicalDeviceProperties &deviceProperties) {
+ return ((deviceProperties.vendorID == kGoogleVendorID) &&
+ (deviceProperties.deviceID == kSwiftShaderDeviceID) &&
+ (strncmp(deviceProperties.deviceName, kSwiftShaderDeviceName,
+ strlen(kSwiftShaderDeviceName)) == 0));
+ };
+ default:
+ const std::string anglePreferredDevice =
+ angle::GetEnvironmentVar(kANGLEPreferredDeviceEnv);
+ return [anglePreferredDevice](const VkPhysicalDeviceProperties &deviceProperties) {
+ return (anglePreferredDevice == deviceProperties.deviceName);
+ };
+ }
+}
+
+} // namespace
+
+// If we're loading the validation layers, we could be running from any random directory.
+// Change to the executable directory so we can find the layers, then change back to the
+// previous directory to be safe we don't disrupt the application.
+ScopedVkLoaderEnvironment::ScopedVkLoaderEnvironment(bool enableValidationLayers, vk::ICD icd)
+ : mEnableValidationLayers(enableValidationLayers),
+ mICD(icd),
+ mChangedCWD(false),
+ mChangedICDEnv(false),
+ mChangedNoDeviceSelect(false)
+{
+// Changing CWD and setting environment variables makes no sense on Android,
+// since this code is a part of Java application there.
+// Android Vulkan loader doesn't need this either.
+#if !defined(ANGLE_PLATFORM_ANDROID) && !defined(ANGLE_PLATFORM_GGP)
+ if (icd == vk::ICD::Mock)
+ {
+ if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_MOCK_ICD_JSON).c_str()))
+ {
+ ERR() << "Error setting environment for Mock/Null Driver.";
+ }
+ }
+# if defined(ANGLE_VK_SWIFTSHADER_ICD_JSON)
+ else if (icd == vk::ICD::SwiftShader)
+ {
+ if (!setICDEnvironment(WrapICDEnvironment(ANGLE_VK_SWIFTSHADER_ICD_JSON).c_str()))
+ {
+ ERR() << "Error setting environment for SwiftShader.";
+ }
+ }
+# endif // defined(ANGLE_VK_SWIFTSHADER_ICD_JSON)
+
+# if !defined(ANGLE_PLATFORM_MACOS)
+ if (mEnableValidationLayers || icd != vk::ICD::Default)
+ {
+ const auto &cwd = angle::GetCWD();
+ if (!cwd.valid())
+ {
+ ERR() << "Error getting CWD for Vulkan layers init.";
+ mEnableValidationLayers = false;
+ mICD = vk::ICD::Default;
+ }
+ else
+ {
+ mPreviousCWD = cwd.value();
+ std::string moduleDir = angle::GetModuleDirectory();
+ mChangedCWD = angle::SetCWD(moduleDir.c_str());
+ if (!mChangedCWD)
+ {
+ ERR() << "Error setting CWD for Vulkan layers init.";
+ mEnableValidationLayers = false;
+ mICD = vk::ICD::Default;
+ }
+ }
+ }
+# endif // defined(ANGLE_PLATFORM_MACOS)
+
+ // Override environment variable to use the ANGLE layers.
+ if (mEnableValidationLayers)
+ {
+# if defined(ANGLE_VK_LAYERS_DIR)
+ if (!angle::PrependPathToEnvironmentVar(kLoaderLayersPathEnv, ANGLE_VK_LAYERS_DIR))
+ {
+ ERR() << "Error setting environment for Vulkan layers init.";
+ mEnableValidationLayers = false;
+ }
+# endif // defined(ANGLE_VK_LAYERS_DIR)
+
+ if (!angle::PrependPathToEnvironmentVar(
+ kLayerEnablesEnv, "VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION"))
+ {
+ ERR() << "Error setting synchronization validation environment for Vulkan validation "
+ "layers init.";
+ }
+
+ if (!setCustomExtensionsEnvironment())
+ {
+ ERR() << "Error setting custom list for custom extensions for Vulkan layers init.";
+ mEnableValidationLayers = false;
+ }
+ }
+#endif // !defined(ANGLE_PLATFORM_ANDROID)
+
+ if (IsMSan() || IsASan())
+ {
+ // device select layer cause memory sanitizer false positive, so disable
+ // it for msan build.
+ mPreviousNoDeviceSelectEnv = angle::GetEnvironmentVar(kNoDeviceSelect);
+ angle::SetEnvironmentVar(kNoDeviceSelect, "1");
+ mChangedNoDeviceSelect = true;
+ }
+}
+
+ScopedVkLoaderEnvironment::~ScopedVkLoaderEnvironment()
+{
+ if (mChangedCWD)
+ {
+#if !defined(ANGLE_PLATFORM_ANDROID)
+ ASSERT(mPreviousCWD.valid());
+ angle::SetCWD(mPreviousCWD.value().c_str());
+#endif // !defined(ANGLE_PLATFORM_ANDROID)
+ }
+ if (mChangedICDEnv)
+ {
+ ResetEnvironmentVar(kLoaderICDFilenamesEnv, mPreviousICDEnv);
+ }
+
+ ResetEnvironmentVar(kValidationLayersCustomSTypeListEnv, mPreviousCustomExtensionsEnv);
+
+ if (mChangedNoDeviceSelect)
+ {
+ ResetEnvironmentVar(kNoDeviceSelect, mPreviousNoDeviceSelectEnv);
+ }
+}
+
+bool ScopedVkLoaderEnvironment::setICDEnvironment(const char *icd)
+{
+ // Override environment variable to use built Mock ICD
+ // ANGLE_VK_ICD_JSON gets set to the built mock ICD in BUILD.gn
+ mPreviousICDEnv = angle::GetEnvironmentVar(kLoaderICDFilenamesEnv);
+ mChangedICDEnv = angle::SetEnvironmentVar(kLoaderICDFilenamesEnv, icd);
+
+ if (!mChangedICDEnv)
+ {
+ mICD = vk::ICD::Default;
+ }
+ return mChangedICDEnv;
+}
+
+bool ScopedVkLoaderEnvironment::setCustomExtensionsEnvironment()
+{
+ struct CustomExtension
+ {
+ VkStructureType type;
+ size_t size;
+ };
+
+ CustomExtension customExtensions[] = {
+
+ {VK_STRUCTURE_TYPE_SAMPLER_FILTERING_PRECISION_GOOGLE,
+ sizeof(VkSamplerFilteringPrecisionGOOGLE)},
+
+ };
+
+ mPreviousCustomExtensionsEnv = angle::GetEnvironmentVar(kValidationLayersCustomSTypeListEnv);
+
+ std::stringstream strstr;
+ for (CustomExtension &extension : customExtensions)
+ {
+ if (strstr.tellp() != std::streampos(0))
+ {
+ strstr << angle::GetPathSeparatorForEnvironmentVar();
+ }
+
+ strstr << extension.type << angle::GetPathSeparatorForEnvironmentVar() << extension.size;
+ }
+
+ return angle::PrependPathToEnvironmentVar(kValidationLayersCustomSTypeListEnv,
+ strstr.str().c_str());
+}
+
+void ChoosePhysicalDevice(PFN_vkGetPhysicalDeviceProperties pGetPhysicalDeviceProperties,
+ const std::vector<VkPhysicalDevice> &physicalDevices,
+ vk::ICD preferredICD,
+ uint32_t preferredVendorID,
+ uint32_t preferredDeviceID,
+ VkPhysicalDevice *physicalDeviceOut,
+ VkPhysicalDeviceProperties *physicalDevicePropertiesOut)
+{
+ ASSERT(!physicalDevices.empty());
+
+ ICDFilterFunc filter = GetFilterForICD(preferredICD);
+
+ const bool shouldChooseByID = (preferredVendorID != 0 || preferredDeviceID != 0);
+
+ for (const VkPhysicalDevice &physicalDevice : physicalDevices)
+ {
+ pGetPhysicalDeviceProperties(physicalDevice, physicalDevicePropertiesOut);
+ if (filter(*physicalDevicePropertiesOut))
+ {
+ *physicalDeviceOut = physicalDevice;
+ return;
+ }
+
+ if (shouldChooseByID)
+ {
+ // NOTE: If the system has multiple GPUs with the same vendor and
+ // device IDs, this will arbitrarily select one of them.
+ bool matchVendorID = true;
+ bool matchDeviceID = true;
+
+ if (preferredVendorID != 0 &&
+ preferredVendorID != physicalDevicePropertiesOut->vendorID)
+ {
+ matchVendorID = false;
+ }
+
+ if (preferredDeviceID != 0 &&
+ preferredDeviceID != physicalDevicePropertiesOut->deviceID)
+ {
+ matchDeviceID = false;
+ }
+
+ if (matchVendorID && matchDeviceID)
+ {
+ *physicalDeviceOut = physicalDevice;
+ return;
+ }
+ }
+ }
+
+ Optional<VkPhysicalDevice> integratedDevice;
+ VkPhysicalDeviceProperties integratedDeviceProperties;
+ for (const VkPhysicalDevice &physicalDevice : physicalDevices)
+ {
+ pGetPhysicalDeviceProperties(physicalDevice, physicalDevicePropertiesOut);
+ // If discrete GPU exists, uses it by default.
+ if (physicalDevicePropertiesOut->deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+ {
+ *physicalDeviceOut = physicalDevice;
+ return;
+ }
+ if (physicalDevicePropertiesOut->deviceType == VK_PHYSICAL_DEVICE_TYPE_INTEGRATED_GPU &&
+ !integratedDevice.valid())
+ {
+ integratedDevice = physicalDevice;
+ integratedDeviceProperties = *physicalDevicePropertiesOut;
+ continue;
+ }
+ }
+
+ // If only integrated GPU exists, use it by default.
+ if (integratedDevice.valid())
+ {
+ *physicalDeviceOut = integratedDevice.value();
+ *physicalDevicePropertiesOut = integratedDeviceProperties;
+ return;
+ }
+
+ WARN() << "Preferred device ICD not found. Using default physicalDevice instead.";
+ // Fallback to the first device.
+ *physicalDeviceOut = physicalDevices[0];
+ pGetPhysicalDeviceProperties(*physicalDeviceOut, physicalDevicePropertiesOut);
+}
+
+} // namespace vk
+
+} // namespace angle
diff --git a/gfx/angle/checkout/src/common/vulkan/vulkan_icd.h b/gfx/angle/checkout/src/common/vulkan/vulkan_icd.h
new file mode 100644
index 0000000000..b2921f8203
--- /dev/null
+++ b/gfx/angle/checkout/src/common/vulkan/vulkan_icd.h
@@ -0,0 +1,72 @@
+//
+// Copyright 2020 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+// vulkan_icd.h : Helper for creating vulkan instances & selecting physical device.
+
+#ifndef COMMON_VULKAN_VULKAN_ICD_H_
+#define COMMON_VULKAN_VULKAN_ICD_H_
+
+#include <string>
+
+#include "common/Optional.h"
+#include "common/angleutils.h"
+#include "common/vulkan/vk_headers.h"
+
+namespace angle
+{
+
+namespace vk
+{
+
+enum class ICD
+{
+ Default,
+ Mock,
+ SwiftShader,
+};
+
+struct SimpleDisplayWindow
+{
+ uint16_t width;
+ uint16_t height;
+};
+
+class [[nodiscard]] ScopedVkLoaderEnvironment : angle::NonCopyable
+{
+ public:
+ ScopedVkLoaderEnvironment(bool enableValidationLayers, vk::ICD icd);
+ ~ScopedVkLoaderEnvironment();
+
+ bool canEnableValidationLayers() const { return mEnableValidationLayers; }
+ vk::ICD getEnabledICD() const { return mICD; }
+
+ private:
+ bool setICDEnvironment(const char *icd);
+ bool setCustomExtensionsEnvironment();
+
+ bool mEnableValidationLayers;
+ vk::ICD mICD;
+ bool mChangedCWD;
+ Optional<std::string> mPreviousCWD;
+ bool mChangedICDEnv;
+ Optional<std::string> mPreviousICDEnv;
+ Optional<std::string> mPreviousCustomExtensionsEnv;
+ bool mChangedNoDeviceSelect;
+ Optional<std::string> mPreviousNoDeviceSelectEnv;
+};
+
+void ChoosePhysicalDevice(PFN_vkGetPhysicalDeviceProperties pGetPhysicalDeviceProperties,
+ const std::vector<VkPhysicalDevice> &physicalDevices,
+ vk::ICD preferredICD,
+ uint32_t preferredVendorID,
+ uint32_t preferredDeviceID,
+ VkPhysicalDevice *physicalDeviceOut,
+ VkPhysicalDeviceProperties *physicalDevicePropertiesOut);
+
+} // namespace vk
+
+} // namespace angle
+
+#endif // COMMON_VULKAN_VULKAN_ICD_H_