mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2024-09-17 16:28:06 +03:00
e713de115c
Skia now uses GPU-accelerated painting on Linux if Vulkan is available. Most of the performance gain is currently negated by reading the GPU backend back into RAM to pass it to the Browser process. In the future, this could be improved by sharing GPU-allocated memory across the Browser and WebContent processes.
126 lines
4.1 KiB
C++
126 lines
4.1 KiB
C++
/*
|
|
* Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
|
|
*
|
|
* SPDX-License-Identifier: BSD-2-Clause
|
|
*/
|
|
|
|
#include <AK/Vector.h>
|
|
#include <LibCore/VulkanContext.h>
|
|
|
|
namespace Core {
|
|
|
|
ErrorOr<VkInstance> create_instance(uint32_t api_version)
|
|
{
|
|
VkInstance instance;
|
|
|
|
VkApplicationInfo app_info {};
|
|
app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
|
app_info.pApplicationName = "Ladybird";
|
|
app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
|
|
app_info.pEngineName = nullptr;
|
|
app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
|
|
app_info.apiVersion = api_version;
|
|
|
|
VkInstanceCreateInfo create_info {};
|
|
create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
|
create_info.pApplicationInfo = &app_info;
|
|
|
|
if (vkCreateInstance(&create_info, nullptr, &instance) != VK_SUCCESS) {
|
|
return Error::from_string_view("Application instance creation failed"sv);
|
|
}
|
|
|
|
return instance;
|
|
}
|
|
|
|
ErrorOr<VkPhysicalDevice> pick_physical_device(VkInstance instance)
|
|
{
|
|
uint32_t device_count = 0;
|
|
vkEnumeratePhysicalDevices(instance, &device_count, nullptr);
|
|
|
|
if (device_count == 0)
|
|
return Error::from_string_view("Can't find any physical devices available"sv);
|
|
|
|
Vector<VkPhysicalDevice> devices;
|
|
devices.resize(device_count);
|
|
vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
|
|
|
|
VkPhysicalDevice picked_device = VK_NULL_HANDLE;
|
|
// Pick discrete GPU or the first device in the list
|
|
for (auto const& device : devices) {
|
|
if (picked_device == VK_NULL_HANDLE)
|
|
picked_device = device;
|
|
|
|
VkPhysicalDeviceProperties device_properties;
|
|
vkGetPhysicalDeviceProperties(device, &device_properties);
|
|
if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
|
|
picked_device = device;
|
|
}
|
|
|
|
if (picked_device != VK_NULL_HANDLE)
|
|
return picked_device;
|
|
|
|
VERIFY_NOT_REACHED();
|
|
}
|
|
|
|
ErrorOr<VkDevice> create_logical_device(VkPhysicalDevice physical_device)
|
|
{
|
|
VkDevice device;
|
|
|
|
uint32_t queue_family_count = 0;
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr);
|
|
Vector<VkQueueFamilyProperties> queue_families;
|
|
queue_families.resize(queue_family_count);
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, queue_families.data());
|
|
|
|
int graphics_queue_family_index = -1;
|
|
for (int i = 0; i < static_cast<int>(queue_families.size()); i++) {
|
|
if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
|
|
graphics_queue_family_index = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
VkDeviceQueueCreateInfo queue_create_info {};
|
|
queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
queue_create_info.queueFamilyIndex = graphics_queue_family_index;
|
|
queue_create_info.queueCount = 1;
|
|
|
|
float const queue_priority = 1.0f;
|
|
queue_create_info.pQueuePriorities = &queue_priority;
|
|
|
|
VkPhysicalDeviceFeatures deviceFeatures {};
|
|
|
|
VkDeviceCreateInfo create_device_info {};
|
|
create_device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
|
|
create_device_info.pQueueCreateInfos = &queue_create_info;
|
|
create_device_info.queueCreateInfoCount = 1;
|
|
create_device_info.pEnabledFeatures = &deviceFeatures;
|
|
|
|
if (vkCreateDevice(physical_device, &create_device_info, nullptr, &device) != VK_SUCCESS) {
|
|
return Error::from_string_view("Logical device creation failed"sv);
|
|
}
|
|
|
|
return device;
|
|
}
|
|
|
|
ErrorOr<VulkanContext> create_vulkan_context()
|
|
{
|
|
uint32_t const api_version = VK_API_VERSION_1_0;
|
|
auto* instance = TRY(create_instance(api_version));
|
|
auto* physical_device = TRY(pick_physical_device(instance));
|
|
auto* logical_device = TRY(create_logical_device(physical_device));
|
|
|
|
VkQueue graphics_queue;
|
|
vkGetDeviceQueue(logical_device, 0, 0, &graphics_queue);
|
|
|
|
return VulkanContext {
|
|
.api_version = api_version,
|
|
.instance = instance,
|
|
.physical_device = physical_device,
|
|
.logical_device = logical_device,
|
|
.graphics_queue = graphics_queue,
|
|
};
|
|
}
|
|
|
|
}
|