diff options
Diffstat (limited to 'gfx/angle/checkout/src/common/vulkan')
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_ |