175 lines
		
	
	
	
		
			4.9 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			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
 |