165 lines
6.3 KiB
C++
165 lines
6.3 KiB
C++
#include "PhysicalDevice.hpp"
|
|
|
|
#include <set>
|
|
|
|
#include "Surface.hpp"
|
|
#include "Instance.hpp"
|
|
#include "DeviceFunctions/DeviceFunctions.hpp"
|
|
#include "Log/Log.hpp"
|
|
|
|
#include <string>
|
|
#include <stdexcept>
|
|
|
|
VkObjects::PhysicalDevice::QueueFamilyIndices VkObjects::PhysicalDevice::is_device_suitable(VkPhysicalDevice device, VkSurfaceKHR surface, const std::vector<const char*>& device_extensions)
|
|
{
|
|
VkPhysicalDeviceProperties device_properties;
|
|
VkPhysicalDeviceFeatures device_features;
|
|
vkGetPhysicalDeviceProperties(device, &device_properties);
|
|
vkGetPhysicalDeviceFeatures(device, &device_features);
|
|
|
|
if(check_device_extensions_support(device, device_extensions) == false)
|
|
throw std::runtime_error("Device not supported");
|
|
|
|
return find_queue_family_indices(device, surface);
|
|
}
|
|
|
|
bool VkObjects::PhysicalDevice::check_device_extensions_support(VkPhysicalDevice device, const std::vector<const char*>& device_extensions)
|
|
{
|
|
uint32_t extension_count;
|
|
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, nullptr))
|
|
std::vector<VkExtensionProperties> available_extensions(extension_count);
|
|
VK_CHECK(vkEnumerateDeviceExtensionProperties(device, nullptr, &extension_count, available_extensions.data()))
|
|
|
|
for (const auto& extension : device_extensions)
|
|
{
|
|
bool isFind = false;
|
|
for (const auto& i : available_extensions)
|
|
{
|
|
if (std::strcmp(i.extensionName, extension) == 0)
|
|
{
|
|
isFind = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!isFind)
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
VkObjects::PhysicalDevice::QueueFamilyIndices VkObjects::PhysicalDevice::find_queue_family_indices(
|
|
VkPhysicalDevice physical_device, VkSurfaceKHR surface)
|
|
{
|
|
QueueFamilyIndices queue_family_indices;
|
|
|
|
uint32_t queueFamilyCount = 0;
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, nullptr);
|
|
std::vector<VkQueueFamilyProperties> family_properties(queueFamilyCount);
|
|
vkGetPhysicalDeviceQueueFamilyProperties(physical_device, &queueFamilyCount, family_properties.data());
|
|
|
|
// Find graphics
|
|
for(uint32_t i = 0; i < family_properties.size(); ++i)
|
|
{
|
|
if (family_properties[i].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
|
{
|
|
queue_family_indices.graphics_family = i;
|
|
queue_family_indices.is_find_graphics_family = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (queue_family_indices.is_find_graphics_family == false)
|
|
throw std::runtime_error("Failed to find a graphics queue family");
|
|
|
|
// Find present
|
|
VkBool32 present_support = false;
|
|
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, queue_family_indices.graphics_family, surface, &present_support))
|
|
// Если графическая очередь поддерживет презентацию кадров, то используем её
|
|
if (present_support == VK_TRUE)
|
|
{
|
|
queue_family_indices.present_family = queue_family_indices.graphics_family;
|
|
queue_family_indices.is_find_present_family = true;
|
|
}
|
|
// иначе ищем другую подходящую очередь
|
|
else
|
|
{
|
|
for(uint32_t i = 0; i < family_properties.size(); ++i)
|
|
{
|
|
present_support = false;
|
|
VK_CHECK(vkGetPhysicalDeviceSurfaceSupportKHR(physical_device, i, surface, &present_support))
|
|
if (present_support == VK_TRUE)
|
|
{
|
|
queue_family_indices.present_family = i;
|
|
queue_family_indices.is_find_present_family = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (queue_family_indices.is_find_present_family == false)
|
|
throw std::runtime_error("Failed to find a present queue family");
|
|
|
|
// С начала пытаемся найти очередь специалезированную
|
|
// для копирования отличную от графической
|
|
for(uint32_t i = 0; i < family_properties.size(); ++i)
|
|
{
|
|
if (i == queue_family_indices.graphics_family)
|
|
continue;
|
|
if (family_properties[i].queueFlags & VK_QUEUE_TRANSFER_BIT)
|
|
{
|
|
queue_family_indices.transfer_family = i;
|
|
queue_family_indices.is_find_transfer_family = true;
|
|
}
|
|
}
|
|
// Если не находим, то используем графическую
|
|
if (queue_family_indices.is_find_transfer_family == false)
|
|
{
|
|
queue_family_indices.transfer_family = queue_family_indices.graphics_family;
|
|
queue_family_indices.is_find_transfer_family = true;
|
|
}
|
|
return queue_family_indices;
|
|
}
|
|
|
|
VkObjects::PhysicalDevice::PhysicalDevice(const Instance& instance,
|
|
const Surface& surface,
|
|
const std::vector<const char*>& device_extensions)
|
|
{
|
|
uint32_t device_count = 0;
|
|
std::vector<VkPhysicalDevice> devices;
|
|
VK_CHECK(vkEnumeratePhysicalDevices(instance.get_native(), &device_count, nullptr))
|
|
devices.resize(device_count);
|
|
VK_CHECK(vkEnumeratePhysicalDevices(instance.get_native(), &device_count, devices.data()))
|
|
|
|
for (const auto& device : devices)
|
|
{
|
|
try
|
|
{
|
|
queue_family_indices_ = is_device_suitable(device, surface.get_native(), device_extensions);
|
|
physical_device_ = device;
|
|
VkPhysicalDeviceProperties device_properties;
|
|
vkGetPhysicalDeviceProperties(physical_device_, &device_properties);
|
|
Loging::Log("Using device: " + std::string(device_properties.deviceName));
|
|
break;
|
|
}
|
|
catch(...)
|
|
{
|
|
}
|
|
}
|
|
|
|
if (VK_NULL_HANDLE == physical_device_)
|
|
throw std::runtime_error("No suitable device found");
|
|
}
|
|
|
|
std::vector<uint32_t> VkObjects::PhysicalDevice::get_unique_family_indices() const
|
|
{
|
|
std::set<uint32_t> set_indices = {queue_family_indices_.graphics_family,
|
|
queue_family_indices_.present_family,
|
|
queue_family_indices_.transfer_family};
|
|
|
|
std::vector<uint32_t> arr_indices;
|
|
arr_indices.reserve(set_indices.size());
|
|
for (auto& i : set_indices)
|
|
arr_indices.push_back(i);
|
|
return arr_indices;
|
|
}
|