light/modules/renderer/private/vk/context/device.cpp

175 lines
4.9 KiB
C++

#include <renderer/vk/context/device.hpp>
#include <renderer/vk/context/instance.hpp>
#include <renderer/vk/context/surface.hpp>
#include <renderer/vk/debug/validation.hpp>
namespace lt::renderer::vk {
Device::Device(const Surface &surface)
{
ensure(surface.vk(), "Failed to initialize vk::Device: null vulkan surface");
initialize_physical_device();
initialize_queue_indices(surface);
initialize_logical_device();
Instance::load_device_functions(m_device);
vk_get_device_queue(m_device, m_graphics_queue_family_index, 0, &m_graphics_queue);
vk_get_device_queue(m_device, m_present_queue_family_index, 0, &m_present_queue);
if (m_present_queue.get() == m_graphics_queue.get())
{
set_object_name(m_device, m_present_queue.get(), "unified queue");
}
else
{
set_object_name(m_device, m_graphics_queue.get(), "graphics queue");
set_object_name(m_device, m_present_queue.get(), "present queue");
}
}
Device::~Device()
{
if (m_device)
{
vkc(vk_device_wait_idle(m_device));
vk_destroy_device(m_device, nullptr);
}
}
void Device::initialize_physical_device()
{
auto count = 0u;
vkc(vk_enumerate_physical_devices(Instance::get(), &count, nullptr));
ensure(count != 0u, "Failed to find any physical devices with Vulkan support");
auto devices = std::vector<VkPhysicalDevice>(count);
vkc(vk_enumerate_physical_devices(Instance::get(), &count, devices.data()));
for (auto &device : devices)
{
auto properties = VkPhysicalDeviceProperties {};
auto features = VkPhysicalDeviceFeatures {};
vk_get_physical_device_properties(device, &properties);
vk_get_physical_device_features(device, &features);
if (properties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU
&& features.geometryShader)
{
m_physical_device = device;
}
}
ensure(m_physical_device, "Failed to find any suitable Vulkan physical device");
}
void Device::initialize_logical_device()
{
const float priorities = .0f;
auto queue_infos = std::vector<VkDeviceQueueCreateInfo> {};
auto queue_families = std::set { m_graphics_queue_family_index, m_present_queue_family_index };
for (auto queue_family : queue_families)
{
queue_infos.emplace_back(
VkDeviceQueueCreateInfo {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.queueFamilyIndex = queue_family,
.queueCount = 1u,
.pQueuePriorities = &priorities,
}
);
}
auto physical_device_features = VkPhysicalDeviceFeatures {};
auto extensions = std::vector<const char *> {
VK_KHR_SWAPCHAIN_EXTENSION_NAME,
};
auto device_info = VkDeviceCreateInfo {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
.queueCreateInfoCount = static_cast<uint32_t>(queue_infos.size()),
.pQueueCreateInfos = queue_infos.data(),
.enabledExtensionCount = static_cast<uint32_t>(extensions.size()),
.ppEnabledExtensionNames = extensions.data(),
.pEnabledFeatures = &physical_device_features,
};
ensure(
!vk_create_device(m_physical_device, &device_info, nullptr, &m_device),
"Failed to create logical vulkan device"
);
}
[[nodiscard]] auto Device::find_suitable_queue_family() const -> uint32_t
{
// auto count = 0u;
// vk_get_physical_device_queue_family_properties(m_physical_device, &count, nullptr);
// ensure(count != 0u, "Failed to find any physical devices with Vulkan support");
//
// auto families = std::vector<VkQueueFamilyProperties>(count);
// vk_get_physical_device_queue_family_properties(m_physical_device, &count, families.data());
//
// const auto required_flags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT;
// for (auto idx = 0u; auto &family : families)
// {
// if ((family.queueFlags & required_flags) == required_flags)
// {
// return idx;
// }
// }
//
// ensure(false, "Failed to find a suitable Vulkan queue family");
// return 0;
}
void Device::initialize_queue_indices(const Surface &surface)
{
auto count = uint32_t { 0u };
vk_get_physical_device_queue_family_properties(m_physical_device, &count, nullptr);
auto properties = std::vector<VkQueueFamilyProperties>(count);
vk_get_physical_device_queue_family_properties(m_physical_device, &count, properties.data());
for (auto idx = uint32_t { 0u }; const auto &property : properties)
{
if (property.queueFlags & VK_QUEUE_GRAPHICS_BIT)
{
m_graphics_queue_family_index = idx;
}
auto has_presentation_support = VkBool32 { false };
vkc(vk_get_physical_device_surface_support(
m_physical_device,
idx,
surface.vk(),
&has_presentation_support
));
if (has_presentation_support)
{
m_present_queue_family_index = idx;
}
++idx;
if (m_graphics_queue_family_index != VK_QUEUE_FAMILY_IGNORED
&& m_present_queue_family_index != VK_QUEUE_FAMILY_IGNORED)
{
break;
}
}
ensure(
m_graphics_queue_family_index != VK_QUEUE_FAMILY_IGNORED,
"Failed to find graphics queue family"
);
ensure(
m_present_queue_family_index != VK_QUEUE_FAMILY_IGNORED,
"Failed to find presentation queue family"
);
}
} // namespace lt::renderer::vk