VulkanContext.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. /*
  2. * Copyright (c) 2024, Aliaksandr Kalenik <kalenik.aliaksandr@gmail.com>
  3. *
  4. * SPDX-License-Identifier: BSD-2-Clause
  5. */
  6. #include <AK/Format.h>
  7. #include <AK/Vector.h>
  8. #include <LibCore/VulkanContext.h>
  9. namespace Core {
  10. static ErrorOr<VkInstance> create_instance(uint32_t api_version)
  11. {
  12. VkInstance instance;
  13. VkApplicationInfo app_info {};
  14. app_info.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
  15. app_info.pApplicationName = "Ladybird";
  16. app_info.applicationVersion = VK_MAKE_VERSION(1, 0, 0);
  17. app_info.pEngineName = nullptr;
  18. app_info.engineVersion = VK_MAKE_VERSION(1, 0, 0);
  19. app_info.apiVersion = api_version;
  20. VkInstanceCreateInfo create_info {};
  21. create_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
  22. create_info.pApplicationInfo = &app_info;
  23. auto result = vkCreateInstance(&create_info, nullptr, &instance);
  24. if (result != VK_SUCCESS) {
  25. dbgln("vkCreateInstance returned {}", to_underlying(result));
  26. return Error::from_string_literal("Application instance creation failed");
  27. }
  28. return instance;
  29. }
  30. static ErrorOr<VkPhysicalDevice> pick_physical_device(VkInstance instance)
  31. {
  32. uint32_t device_count = 0;
  33. vkEnumeratePhysicalDevices(instance, &device_count, nullptr);
  34. if (device_count == 0)
  35. return Error::from_string_literal("Can't find any physical devices available");
  36. Vector<VkPhysicalDevice> devices;
  37. devices.resize(device_count);
  38. vkEnumeratePhysicalDevices(instance, &device_count, devices.data());
  39. VkPhysicalDevice picked_device = VK_NULL_HANDLE;
  40. // Pick discrete GPU or the first device in the list
  41. for (auto const& device : devices) {
  42. if (picked_device == VK_NULL_HANDLE)
  43. picked_device = device;
  44. VkPhysicalDeviceProperties device_properties;
  45. vkGetPhysicalDeviceProperties(device, &device_properties);
  46. if (device_properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
  47. picked_device = device;
  48. }
  49. if (picked_device != VK_NULL_HANDLE)
  50. return picked_device;
  51. VERIFY_NOT_REACHED();
  52. }
  53. static ErrorOr<VkDevice> create_logical_device(VkPhysicalDevice physical_device)
  54. {
  55. VkDevice device;
  56. uint32_t queue_family_count = 0;
  57. vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, nullptr);
  58. Vector<VkQueueFamilyProperties> queue_families;
  59. queue_families.resize(queue_family_count);
  60. vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queue_family_count, queue_families.data());
  61. int graphics_queue_family_index = -1;
  62. for (int i = 0; i < static_cast<int>(queue_families.size()); i++) {
  63. if (queue_families[i].queueFlags & VK_QUEUE_GRAPHICS_BIT) {
  64. graphics_queue_family_index = i;
  65. break;
  66. }
  67. }
  68. VkDeviceQueueCreateInfo queue_create_info {};
  69. queue_create_info.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
  70. queue_create_info.queueFamilyIndex = graphics_queue_family_index;
  71. queue_create_info.queueCount = 1;
  72. float const queue_priority = 1.0f;
  73. queue_create_info.pQueuePriorities = &queue_priority;
  74. VkPhysicalDeviceFeatures deviceFeatures {};
  75. VkDeviceCreateInfo create_device_info {};
  76. create_device_info.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
  77. create_device_info.pQueueCreateInfos = &queue_create_info;
  78. create_device_info.queueCreateInfoCount = 1;
  79. create_device_info.pEnabledFeatures = &deviceFeatures;
  80. if (vkCreateDevice(physical_device, &create_device_info, nullptr, &device) != VK_SUCCESS) {
  81. return Error::from_string_literal("Logical device creation failed");
  82. }
  83. return device;
  84. }
  85. ErrorOr<VulkanContext> create_vulkan_context()
  86. {
  87. uint32_t const api_version = VK_API_VERSION_1_0;
  88. auto* instance = TRY(create_instance(api_version));
  89. auto* physical_device = TRY(pick_physical_device(instance));
  90. auto* logical_device = TRY(create_logical_device(physical_device));
  91. VkQueue graphics_queue;
  92. vkGetDeviceQueue(logical_device, 0, 0, &graphics_queue);
  93. return VulkanContext {
  94. .api_version = api_version,
  95. .instance = instance,
  96. .physical_device = physical_device,
  97. .logical_device = logical_device,
  98. .graphics_queue = graphics_queue,
  99. };
  100. }
  101. }