// Copyright (c) 2016 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_implementation.h" #include #include #include "base/logging.h" #include "base/macros.h" #include "gpu/vulkan/vulkan_platform.h" #if defined(VK_USE_PLATFORM_XLIB_KHR) #include "ui/gfx/x/x11_types.h" #endif // defined(VK_USE_PLATFORM_XLIB_KHR) VKAPI_ATTR VkBool32 VKAPI_CALL VulkanErrorCallback( VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) { LOG(ERROR) << pMessage; return VK_TRUE; } VKAPI_ATTR VkBool32 VKAPI_CALL VulkanWarningCallback( VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location, int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) { LOG(WARNING) << pMessage; return VK_TRUE; } namespace gpu { struct VulkanInstance { VulkanInstance() {} void Initialize() { valid = InitializeVulkanInstance(); } bool InitializeVulkanInstance() { VkResult result = VK_SUCCESS; VkApplicationInfo app_info = {}; app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; app_info.pApplicationName = "Chromium"; app_info.apiVersion = VK_MAKE_VERSION(1, 0, 2); std::vector enabled_ext_names; enabled_ext_names.push_back(VK_KHR_SURFACE_EXTENSION_NAME); #if defined(VK_USE_PLATFORM_XLIB_KHR) enabled_ext_names.push_back(VK_KHR_XLIB_SURFACE_EXTENSION_NAME); #endif uint32_t num_instance_exts = 0; result = vkEnumerateInstanceExtensionProperties(nullptr, &num_instance_exts, nullptr); if (VK_SUCCESS != result) { DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties(NULL) failed: " << result; return false; } std::vector instance_exts(num_instance_exts); result = vkEnumerateInstanceExtensionProperties(nullptr, &num_instance_exts, instance_exts.data()); if (VK_SUCCESS != result) { DLOG(ERROR) << "vkEnumerateInstanceExtensionProperties() failed: " << result; return false; } bool debug_report_enabled = false; for (const VkExtensionProperties& ext_property : instance_exts) { if (strcmp(ext_property.extensionName, VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) { debug_report_enabled = true; enabled_ext_names.push_back(VK_EXT_DEBUG_REPORT_EXTENSION_NAME); } } std::vector enabled_layer_names; #if DCHECK_IS_ON() uint32_t num_instance_layers = 0; result = vkEnumerateInstanceLayerProperties(&num_instance_layers, nullptr); if (VK_SUCCESS != result) { DLOG(ERROR) << "vkEnumerateInstanceLayerProperties(NULL) failed: " << result; return false; } std::vector instance_layers(num_instance_layers); result = vkEnumerateInstanceLayerProperties(&num_instance_layers, instance_layers.data()); if (VK_SUCCESS != result) { DLOG(ERROR) << "vkEnumerateInstanceLayerProperties() failed: " << result; return false; } std::unordered_set desired_layers({ "VK_LAYER_LUNARG_standard_validation", }); for (const VkLayerProperties& layer_property : instance_layers) { if (desired_layers.find(layer_property.layerName) != desired_layers.end()) enabled_layer_names.push_back(layer_property.layerName); } #endif VkInstanceCreateInfo instance_create_info = {}; instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; instance_create_info.pApplicationInfo = &app_info; instance_create_info.enabledLayerCount = enabled_layer_names.size(); instance_create_info.ppEnabledLayerNames = enabled_layer_names.data(); instance_create_info.enabledExtensionCount = enabled_ext_names.size(); instance_create_info.ppEnabledExtensionNames = enabled_ext_names.data(); result = vkCreateInstance(&instance_create_info, nullptr, &vk_instance); if (VK_SUCCESS != result) { DLOG(ERROR) << "vkCreateInstance() failed: " << result; return false; } // Register our error logging function. if (debug_report_enabled) { PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT = reinterpret_cast (vkGetInstanceProcAddr(vk_instance, "vkCreateDebugReportCallbackEXT")); DCHECK(vkCreateDebugReportCallbackEXT); 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) { 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) { DLOG(ERROR) << "vkCreateDebugReportCallbackEXT(WARN) failed: " << result; return false; } } return true; } bool valid = false; VkInstance vk_instance = VK_NULL_HANDLE; #if DCHECK_IS_ON() VkDebugReportCallbackEXT error_callback = VK_NULL_HANDLE; VkDebugReportCallbackEXT warning_callback = VK_NULL_HANDLE; #endif }; static VulkanInstance* vulkan_instance = nullptr; bool InitializeVulkan() { DCHECK(!vulkan_instance); vulkan_instance = new VulkanInstance; vulkan_instance->Initialize(); return vulkan_instance->valid; } VkInstance GetVulkanInstance() { DCHECK(vulkan_instance); DCHECK(vulkan_instance->valid); return vulkan_instance->vk_instance; } } // namespace gpu