blob: 731842bb4ed8417589af72b40b4d985e8b7e4cbf [file] [log] [blame]
// 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 <unordered_set>
#include <vector>
#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<const char*> 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);
#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
enabled_ext_names.push_back(VK_KHR_ANDROID_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<VkExtensionProperties> 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<const char*> 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<VkLayerProperties> 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<std::string> 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;
}
#if DCHECK_IS_ON()
// Register our error logging function.
if (debug_report_enabled) {
PFN_vkCreateDebugReportCallbackEXT vkCreateDebugReportCallbackEXT =
reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>
(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;
}
}
#endif
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;
}
bool VulkanSupported() {
DCHECK(vulkan_instance);
return vulkan_instance->valid;
}
VkInstance GetVulkanInstance() {
DCHECK(vulkan_instance);
DCHECK(vulkan_instance->valid);
return vulkan_instance->vk_instance;
}
} // namespace gpu