123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468 |
- // Copyright (c) 2018 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #include "gpu/vulkan/vulkan_instance.h"
- #include <vector>
- #include "base/containers/flat_set.h"
- #include "base/logging.h"
- #include "base/numerics/safe_conversions.h"
- #include "build/build_config.h"
- #include "gpu/vulkan/vulkan_crash_keys.h"
- #include "gpu/vulkan/vulkan_device_queue.h"
- #include "gpu/vulkan/vulkan_function_pointers.h"
- #include "gpu/vulkan/vulkan_util.h"
- #include "ui/gl/gl_angle_util_vulkan.h"
- #include "ui/gl/gl_switches.h"
- namespace gpu {
- namespace {
- #if DCHECK_IS_ON()
- const char* kSkippedErrors[] = {
- // http://anglebug.com/4583
- "VUID-VkGraphicsPipelineCreateInfo-blendEnable-02023",
- };
- VKAPI_ATTR VkBool32 VKAPI_CALL
- VulkanErrorCallback(VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT object_type,
- uint64_t object,
- size_t location,
- int32_t message_code,
- const char* layer_prefix,
- const char* message,
- void* user_data) {
- static base::flat_set<const char*> hitted_errors;
- for (const char* error : kSkippedErrors) {
- if (strstr(message, error) != nullptr) {
- if (hitted_errors.find(error) != hitted_errors.end())
- return VK_FALSE;
- hitted_errors.insert(error);
- }
- }
- LOG(ERROR) << message;
- return VK_FALSE;
- }
- VKAPI_ATTR VkBool32 VKAPI_CALL
- VulkanWarningCallback(VkDebugReportFlagsEXT flags,
- VkDebugReportObjectTypeEXT object_type,
- uint64_t object,
- size_t location,
- int32_t message_code,
- const char* layer_prefix,
- const char* message,
- void* user_data) {
- LOG(WARNING) << message;
- return VK_FALSE;
- }
- #endif // DCHECK_IS_ON()
- } // namespace
- VulkanInstance::VulkanInstance()
- : is_from_angle_(base::FeatureList::IsEnabled(features::kVulkanFromANGLE)) {
- }
- VulkanInstance::~VulkanInstance() {
- Destroy();
- }
- bool VulkanInstance::Initialize(
- const base::FilePath& vulkan_loader_library_path,
- const std::vector<const char*>& required_extensions,
- const std::vector<const char*>& required_layers) {
- if (!BindUnassignedFunctionPointers(vulkan_loader_library_path))
- return false;
- return InitializeInstace(required_extensions, required_layers);
- }
- bool VulkanInstance::BindUnassignedFunctionPointers(
- const base::FilePath& vulkan_loader_library_path) {
- VulkanFunctionPointers* vulkan_function_pointers =
- gpu::GetVulkanFunctionPointers();
- if (is_from_angle_) {
- PFN_vkGetInstanceProcAddr proc = gl::QueryVkGetInstanceProcAddrFromANGLE();
- if (!proc) {
- LOG(ERROR) << "Failed to get vkGetInstanceProcAddr pointer from ANGLE.";
- return false;
- }
- if (!vulkan_function_pointers
- ->BindUnassociatedFunctionPointersFromGetProcAddr(proc)) {
- return false;
- }
- } else {
- base::NativeLibraryLoadError error;
- loader_library_ =
- base::LoadNativeLibrary(vulkan_loader_library_path, &error);
- if (!loader_library_) {
- LOG(ERROR) << "Failed to load '" << vulkan_loader_library_path
- << "': " << error.ToString();
- return false;
- }
- if (!vulkan_function_pointers
- ->BindUnassociatedFunctionPointersFromLoaderLib(loader_library_)) {
- return false;
- }
- }
- return true;
- }
- bool VulkanInstance::InitializeInstace(
- const std::vector<const char*>& required_extensions,
- const std::vector<const char*>& required_layers) {
- if (is_from_angle_)
- return InitializeFromANGLE(required_extensions, required_layers);
- return CreateInstance(required_extensions, required_layers);
- }
- bool VulkanInstance::CreateInstance(
- const std::vector<const char*>& required_extensions,
- const std::vector<const char*>& required_layers) {
- DCHECK(!vk_instance_);
- if (!CollectBasicInfo(required_layers))
- return false;
- vulkan_info_.used_api_version = kVulkanRequiredApiVersion;
- VkApplicationInfo app_info = {};
- app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
- app_info.pApplicationName = "Chromium";
- app_info.apiVersion = vulkan_info_.used_api_version;
- vulkan_info_.enabled_instance_extensions = required_extensions;
- for (const VkExtensionProperties& ext_property :
- vulkan_info_.instance_extensions) {
- if (strcmp(ext_property.extensionName,
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
- debug_report_enabled_ = true;
- vulkan_info_.enabled_instance_extensions.push_back(
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
- }
- }
- #if DCHECK_IS_ON()
- for (const char* enabled_extension :
- vulkan_info_.enabled_instance_extensions) {
- bool found = false;
- for (const VkExtensionProperties& ext_property :
- vulkan_info_.instance_extensions) {
- if (strcmp(ext_property.extensionName, enabled_extension) == 0) {
- found = true;
- break;
- }
- }
- if (!found) {
- DLOG(ERROR) << "Required extension " << enabled_extension
- << " missing from enumerated Vulkan extensions. "
- "vkCreateInstance will likely fail.";
- }
- }
- #endif
- VkInstanceCreateInfo instance_create_info = {
- VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO, // sType
- nullptr, // pNext
- 0, // flags
- &app_info, // pApplicationInfo
- base::checked_cast<uint32_t>(required_layers.size()),
- // enableLayerCount
- required_layers.data(), // ppEnabledLayerNames
- base::checked_cast<uint32_t>(
- vulkan_info_.enabled_instance_extensions.size()),
- // enabledExtensionCount
- vulkan_info_.enabled_instance_extensions.data(),
- // ppEnabledExtensionNames
- };
- VkResult result =
- vkCreateInstance(&instance_create_info, nullptr, &owned_vk_instance_);
- if (VK_SUCCESS != result) {
- DLOG(ERROR) << "vkCreateInstance() failed: " << result;
- return false;
- }
- vk_instance_ = owned_vk_instance_;
- gfx::ExtensionSet enabled_extensions(
- std::begin(vulkan_info_.enabled_instance_extensions),
- std::end(vulkan_info_.enabled_instance_extensions));
- VulkanFunctionPointers* vulkan_function_pointers =
- gpu::GetVulkanFunctionPointers();
- if (!vulkan_function_pointers->BindInstanceFunctionPointers(
- vk_instance_, vulkan_info_.used_api_version, enabled_extensions)) {
- return false;
- }
- #if DCHECK_IS_ON()
- // Register our error logging function.
- if (debug_report_enabled_) {
- VkDebugReportCallbackCreateInfoEXT cb_create_info = {};
- cb_create_info.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
- cb_create_info.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT;
- cb_create_info.pfnCallback = &VulkanErrorCallback;
- result = vkCreateDebugReportCallbackEXT(vk_instance_, &cb_create_info,
- nullptr, &error_callback_);
- if (VK_SUCCESS != result) {
- error_callback_ = VK_NULL_HANDLE;
- DLOG(ERROR) << "vkCreateDebugReportCallbackEXT(ERROR) failed: " << result;
- return false;
- }
- cb_create_info.flags = VK_DEBUG_REPORT_WARNING_BIT_EXT |
- VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
- cb_create_info.pfnCallback = &VulkanWarningCallback;
- result = vkCreateDebugReportCallbackEXT(vk_instance_, &cb_create_info,
- nullptr, &warning_callback_);
- if (VK_SUCCESS != result) {
- warning_callback_ = VK_NULL_HANDLE;
- DLOG(ERROR) << "vkCreateDebugReportCallbackEXT(WARN) failed: " << result;
- return false;
- }
- }
- #endif
- if (!CollectDeviceInfo())
- return false;
- return true;
- }
- bool VulkanInstance::InitializeFromANGLE(
- const std::vector<const char*>& required_extensions,
- const std::vector<const char*>& required_layers) {
- vk_instance_ = gl::QueryVkInstanceFromANGLE();
- if (vk_instance_ == VK_NULL_HANDLE)
- return false;
- uint32_t api_version = gl::QueryVkVersionFromANGLE();
- if (api_version < kVulkanRequiredApiVersion)
- return false;
- if (!CollectBasicInfo({}))
- return false;
- vulkan_info_.used_api_version = api_version;
- auto extensions = gl::QueryVkInstanceExtensionsFromANGLE();
- DCHECK(!extensions.empty());
- for (const auto& extension : extensions)
- vulkan_info_.enabled_instance_extensions.push_back(extension.data());
- VulkanFunctionPointers* vulkan_function_pointers =
- gpu::GetVulkanFunctionPointers();
- if (!vulkan_function_pointers->BindInstanceFunctionPointers(
- vk_instance_, vulkan_info_.used_api_version, extensions)) {
- return false;
- }
- VkPhysicalDevice physical_device = gl::QueryVkPhysicalDeviceFromANGLE();
- if (physical_device == VK_NULL_HANDLE)
- return false;
- if (!CollectDeviceInfo(physical_device))
- return false;
- return true;
- }
- bool VulkanInstance::CollectBasicInfo(
- const std::vector<const char*>& required_layers) {
- VkResult result = vkEnumerateInstanceVersion(&vulkan_info_.api_version);
- if (result != VK_SUCCESS) {
- DLOG(ERROR) << "vkEnumerateInstanceVersion() failed: " << result;
- return false;
- }
- if (vulkan_info_.api_version < kVulkanRequiredApiVersion)
- return false;
- gpu::crash_keys::vulkan_api_version.Set(
- VkVersionToString(vulkan_info_.api_version));
- // Query the extensions from all layers, including ones that are implicitly
- // available (identified by passing a null ptr as the layer name).
- std::vector<const char*> all_required_layers = required_layers;
- // Include the extension properties provided by the Vulkan implementation as
- // part of the enumeration.
- all_required_layers.push_back(nullptr);
- for (const char* layer_name : all_required_layers) {
- uint32_t num_instance_exts = 0;
- result = vkEnumerateInstanceExtensionProperties(
- layer_name, &num_instance_exts, nullptr);
- if (VK_SUCCESS != result) {
- DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties(" << layer_name
- << ") failed: " << result;
- return false;
- }
- const size_t previous_extension_count =
- vulkan_info_.instance_extensions.size();
- vulkan_info_.instance_extensions.resize(previous_extension_count +
- num_instance_exts);
- result = vkEnumerateInstanceExtensionProperties(
- layer_name, &num_instance_exts,
- &vulkan_info_.instance_extensions.data()[previous_extension_count]);
- if (VK_SUCCESS != result) {
- DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties(" << layer_name
- << ") failed: " << result;
- return false;
- }
- }
- for (const VkExtensionProperties& ext_property :
- vulkan_info_.instance_extensions) {
- if (strcmp(ext_property.extensionName,
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
- debug_report_enabled_ = true;
- vulkan_info_.enabled_instance_extensions.push_back(
- VK_EXT_DEBUG_REPORT_EXTENSION_NAME);
- }
- }
- uint32_t num_instance_layers = 0;
- result = vkEnumerateInstanceLayerProperties(&num_instance_layers, nullptr);
- if (VK_SUCCESS != result) {
- DLOG(ERROR) << "vkEnumerateInstanceLayerProperties(NULL) failed: "
- << result;
- return false;
- }
- vulkan_info_.instance_layers.resize(num_instance_layers);
- result = vkEnumerateInstanceLayerProperties(
- &num_instance_layers, vulkan_info_.instance_layers.data());
- if (VK_SUCCESS != result) {
- DLOG(ERROR) << "vkEnumerateInstanceLayerProperties() failed: " << result;
- return false;
- }
- return true;
- }
- bool VulkanInstance::CollectDeviceInfo(VkPhysicalDevice physical_device) {
- std::vector<VkPhysicalDevice> physical_devices;
- if (physical_device == VK_NULL_HANDLE) {
- uint32_t count = 0;
- VkResult result = vkEnumeratePhysicalDevices(vk_instance_, &count, nullptr);
- if (result != VK_SUCCESS) {
- DLOG(ERROR) << "vkEnumeratePhysicalDevices failed: " << result;
- return false;
- }
- if (!count) {
- DLOG(ERROR) << "vkEnumeratePhysicalDevices returns zero device.";
- return false;
- }
- physical_devices.resize(count);
- result = vkEnumeratePhysicalDevices(vk_instance_, &count,
- physical_devices.data());
- if (VK_SUCCESS != result) {
- DLOG(ERROR) << "vkEnumeratePhysicalDevices() failed: " << result;
- return false;
- }
- } else {
- physical_devices.push_back(physical_device);
- }
- vulkan_info_.physical_devices.reserve(physical_devices.size());
- for (VkPhysicalDevice device : physical_devices) {
- vulkan_info_.physical_devices.emplace_back();
- auto& info = vulkan_info_.physical_devices.back();
- info.device = device;
- vkGetPhysicalDeviceProperties(device, &info.properties);
- uint32_t count = 0;
- VkResult result = vkEnumerateDeviceExtensionProperties(
- device, nullptr /* pLayerName */, &count, nullptr);
- DLOG_IF(ERROR, result != VK_SUCCESS)
- << "vkEnumerateDeviceExtensionProperties failed: " << result;
- info.extensions.resize(count);
- result = vkEnumerateDeviceExtensionProperties(
- device, nullptr /* pLayerName */, &count, info.extensions.data());
- DLOG_IF(ERROR, result != VK_SUCCESS)
- << "vkEnumerateDeviceExtensionProperties failed: " << result;
- // The API version of the VkInstance might be different than the supported
- // API version of the VkPhysicalDevice, so we need to check the GPU's
- // API version instead of just testing to see if
- // vkGetPhysicalDeviceProperties2 and vkGetPhysicalDeviceFeatures2 are
- // non-null.
- static_assert(kVulkanRequiredApiVersion >= VK_API_VERSION_1_1, "");
- if (info.properties.apiVersion >= kVulkanRequiredApiVersion) {
- info.driver_properties = VkPhysicalDeviceDriverProperties{
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DRIVER_PROPERTIES,
- };
- VkPhysicalDeviceProperties2 properties2 = {
- .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
- .pNext = &info.driver_properties,
- };
- vkGetPhysicalDeviceProperties2(device, &properties2);
- VkPhysicalDeviceSamplerYcbcrConversionFeatures ycbcr_conversion_features =
- {VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_SAMPLER_YCBCR_CONVERSION_FEATURES};
- VkPhysicalDeviceProtectedMemoryFeatures protected_memory_feature = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES};
- VkPhysicalDeviceFeatures2 features_2 = {
- VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2};
- features_2.pNext = &ycbcr_conversion_features;
- ycbcr_conversion_features.pNext = &protected_memory_feature;
- vkGetPhysicalDeviceFeatures2(device, &features_2);
- info.features = features_2.features;
- info.feature_sampler_ycbcr_conversion =
- ycbcr_conversion_features.samplerYcbcrConversion;
- info.feature_protected_memory = protected_memory_feature.protectedMemory;
- }
- count = 0;
- vkGetPhysicalDeviceQueueFamilyProperties(device, &count, nullptr);
- if (count) {
- info.queue_families.resize(count);
- vkGetPhysicalDeviceQueueFamilyProperties(device, &count,
- info.queue_families.data());
- }
- }
- return true;
- }
- void VulkanInstance::Destroy() {
- #if DCHECK_IS_ON()
- if (debug_report_enabled_ && (error_callback_ != VK_NULL_HANDLE ||
- warning_callback_ != VK_NULL_HANDLE)) {
- if (error_callback_ != VK_NULL_HANDLE) {
- vkDestroyDebugReportCallbackEXT(vk_instance_, error_callback_, nullptr);
- error_callback_ = VK_NULL_HANDLE;
- }
- if (warning_callback_ != VK_NULL_HANDLE) {
- vkDestroyDebugReportCallbackEXT(vk_instance_, warning_callback_, nullptr);
- warning_callback_ = VK_NULL_HANDLE;
- }
- }
- #endif
- if (owned_vk_instance_ != VK_NULL_HANDLE) {
- vkDestroyInstance(owned_vk_instance_, nullptr);
- owned_vk_instance_ = VK_NULL_HANDLE;
- }
- vk_instance_ = VK_NULL_HANDLE;
- if (loader_library_) {
- base::UnloadNativeLibrary(loader_library_);
- loader_library_ = nullptr;
- }
- }
- } // namespace gpu
|