blob: 808ed8450484ca94d529f098b5206cb4b1502d10 [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 <string>
#include <vector>
#include <vulkan/vulkan.h>
#include "base/macros.h"
#if defined(VK_USE_PLATFORM_XLIB_KHR)
#include "ui/gfx/x/x11_types.h"
#endif // defined(VK_USE_PLATFORM_XLIB_KHR)
namespace gpu {
struct VulkanInstance {
VulkanInstance() : valid(false) {}
void Initialize() {
valid = InitializeVulkanInstance() && InitializeVulkanDevice();
}
bool InitializeVulkanInstance() {
VkResult status = 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);
const char* instance_extensions[] = {
VK_KHR_SURFACE_EXTENSION_NAME,
#if defined(VK_USE_PLATFORM_XLIB_KHR)
VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
#endif // defined(VK_USE_PLATFORM_XLIB_KHR)
};
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instance_create_info.pApplicationInfo = &app_info;
instance_create_info.ppEnabledExtensionNames = instance_extensions;
instance_create_info.enabledExtensionCount = arraysize(instance_extensions);
status = vkCreateInstance(&instance_create_info, nullptr, &vk_instance);
DCHECK_EQ(VK_SUCCESS, status);
if (VK_SUCCESS != status)
return false;
return true;
}
bool InitializeVulkanDevice() {
VkResult status = VK_SUCCESS;
uint32_t device_count = 0;
status = vkEnumeratePhysicalDevices(vk_instance, &device_count, nullptr);
if (VK_SUCCESS != status || device_count == 0)
return false;
std::vector<VkPhysicalDevice> devices(device_count);
status =
vkEnumeratePhysicalDevices(vk_instance, &device_count, devices.data());
if (VK_SUCCESS != status) {
LOG(ERROR) << "vkEnumeratePhysicalDevices() failed: " << status;
return false;
}
// TODO(dyen): Enable this once vkGetPhysicalDeviceXlibPresentationSupportKHR()
// is properly supported in the driver.
#if 0 && defined(VK_USE_PLATFORM_XLIB_KHR)
Display* xdisplay = gfx::GetXDisplay();
VisualID visual_id =
XVisualIDFromVisual(DefaultVisual(xdisplay, DefaultScreen(xdisplay)));
#endif // defined(VK_USE_PLATFORM_XLIB_KHR)
int device_index = -1;
int queue_index = -1;
for (size_t i = 0; i < devices.size(); ++i) {
const VkPhysicalDevice& device = devices[i];
uint32_t queue_count = 0;
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count, nullptr);
if (queue_count) {
std::vector<VkQueueFamilyProperties> queue_properties(queue_count);
vkGetPhysicalDeviceQueueFamilyProperties(device, &queue_count,
queue_properties.data());
for (size_t n = 0; n < queue_properties.size(); ++n) {
if ((queue_properties[n].queueFlags & VK_QUEUE_GRAPHICS_BIT) == 0)
continue;
// TODO(dyen): Enable this once vkGetPhysicalDeviceXlibPresentationSupportKHR()
// is properly supported in the driver.
#if 1
#elif defined(VK_USE_PLATFORM_XLIB_KHR)
if (!vkGetPhysicalDeviceXlibPresentationSupportKHR(
device, n, xdisplay, visual_id)) {
continue;
}
#else
#error Non-Supported Vulkan implementation.
#endif
queue_index = static_cast<int>(n);
break;
}
if (-1 != queue_index) {
device_index = static_cast<int>(i);
break;
}
}
}
if (queue_index == -1)
return false;
float queue_priority = 0.0f;
VkDeviceQueueCreateInfo queue_create_info = {};
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
queue_create_info.queueFamilyIndex = queue_index;
queue_create_info.queueCount = 1;
queue_create_info.pQueuePriorities = &queue_priority;
const char* device_extensions[] = {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
VkDeviceCreateInfo device_create_info = {};
device_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
device_create_info.queueCreateInfoCount = 1;
device_create_info.pQueueCreateInfos = &queue_create_info;
device_create_info.enabledExtensionCount = arraysize(device_extensions);
device_create_info.ppEnabledExtensionNames = device_extensions;
status = vkCreateDevice(devices[device_index], &device_create_info, nullptr,
&vk_device);
if (VK_SUCCESS != status)
return false;
vkGetDeviceQueue(vk_device, queue_index, 0, &vk_queue);
return true;
}
bool valid;
VkInstance vk_instance;
VkDevice vk_device;
VkQueue vk_queue;
};
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;
}
VkDevice GetVulkanDevice() {
DCHECK(vulkan_instance);
DCHECK(vulkan_instance->valid);
return vulkan_instance->vk_device;
}
VkQueue GetVulkanQueue() {
DCHECK(vulkan_instance);
DCHECK(vulkan_instance->valid);
return vulkan_instance->vk_queue;
}
} // namespace gpu