project-aster/aster/physical_device.cpp

153 lines
5.1 KiB
C++

// =============================================
// Aster: physical_device.cpp
// Copyright (c) 2020-2024 Anish Bhobe
// =============================================
#include "physical_device.h"
#include "context.h"
#include "window.h"
[[nodiscard]] eastl::vector<vk::SurfaceFormatKHR>
getSurfaceFormats(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
{
// vk::Result::eIncomplete should not occur in this function. The rest are errors. Thus, abort is allowed.
u32 count = 0;
vk::Result result = physicalDevice.getSurfaceFormatsKHR(surface, &count, nullptr);
ERROR_IF(failed(result), "Could not get surface formats. Cause: {}", result)
THEN_ABORT(result);
eastl::vector<vk::SurfaceFormatKHR> surfaceFormats(count);
result = physicalDevice.getSurfaceFormatsKHR(surface, &count, surfaceFormats.data());
ERROR_IF(failed(result), "Could not get surface formats. Cause: {}", result)
THEN_ABORT(result);
return surfaceFormats;
}
[[nodiscard]] eastl::vector<vk::PresentModeKHR>
getSurfacePresentModes(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
{
// vk::Result::eIncomplete should not occur in this function. The rest are errors. Thus, abort is allowed.
u32 count = 0;
vk::Result result = physicalDevice.getSurfacePresentModesKHR(surface, &count, nullptr);
ERROR_IF(failed(result), "Could not get present modes. Cause: {}", result)
THEN_ABORT(result);
eastl::vector<vk::PresentModeKHR> presentModes(count);
result = physicalDevice.getSurfacePresentModesKHR(surface, &count, presentModes.data());
ERROR_IF(failed(result), "Could not get present modes. Cause: {}", result)
THEN_ABORT(result);
return presentModes;
}
[[nodiscard]] bool
getQueuePresentSupport(const u32 queueFamilyIndex, vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
{
b32 supported = false;
const vk::Result result = physicalDevice.getSurfaceSupportKHR(queueFamilyIndex, surface, &supported);
ERROR_IF(failed(result), "Could not get queue family surface support. Cause: {}", result)
THEN_ABORT(result);
return supported;
}
[[nodiscard]] eastl::fixed_vector<vk::QueueFamilyProperties, 32>
getQueueFamilyProperties(const vk::PhysicalDevice physicalDevice)
{
// Devices rarely have more than 32 queue families. Thus fixed vector
u32 count = 0;
physicalDevice.getQueueFamilyProperties(&count, nullptr);
eastl::fixed_vector<vk::QueueFamilyProperties, 32> queueFamilyProperties(count);
physicalDevice.getQueueFamilyProperties(&count, queueFamilyProperties.data());
return queueFamilyProperties;
}
// Size 384 return.
[[nodiscard]] eastl::vector<QueueFamilyInfo>
getQueueFamilies(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
{
auto queueFamilyProperties = getQueueFamilyProperties(physicalDevice);
eastl::vector<QueueFamilyInfo> queueFamilyInfos;
queueFamilyInfos.reserve(queueFamilyProperties.size());
u32 familyIndex = 0;
for (auto qfp : queueFamilyProperties)
{
QueueSupportFlags support = {};
if (qfp.queueFlags | vk::QueueFlagBits::eGraphics)
{
support |= QueueSupportFlagBits::eGraphics;
}
if (qfp.queueFlags | vk::QueueFlagBits::eTransfer)
{
support |= QueueSupportFlagBits::eTransfer;
}
if (qfp.queueFlags | vk::QueueFlagBits::eCompute)
{
support |= QueueSupportFlagBits::eCompute;
}
if (getQueuePresentSupport(familyIndex, surface, physicalDevice))
{
support |= QueueSupportFlagBits::ePresent;
}
queueFamilyInfos.push_back({
.m_Index = familyIndex,
.m_Count = qfp.queueCount,
.m_Support = support,
});
familyIndex++;
}
return queueFamilyInfos;
}
PhysicalDevice::PhysicalDevice(const vk::SurfaceKHR surface, const vk::PhysicalDevice physicalDevice)
{
physicalDevice.getProperties(&m_DeviceProperties);
physicalDevice.getFeatures(&m_DeviceFeatures);
m_SurfaceFormats = getSurfaceFormats(surface, physicalDevice);
m_PresentModes = getSurfacePresentModes(surface, physicalDevice);
m_QueueFamilies = getQueueFamilies(surface, physicalDevice);
m_PhysicalDevice = physicalDevice;
}
eastl::fixed_vector<vk::PhysicalDevice, 8>
enumeratePhysicalDevices(const vk::Instance instance)
{
u32 count = 0;
vk::Result result = instance.enumeratePhysicalDevices(&count, nullptr);
ERROR_IF(failed(result), "Could not fetch vulkan devices. Cause: {}", result)
THEN_ABORT(result);
eastl::fixed_vector<vk::PhysicalDevice, 8> physicalDevices(count);
result = instance.enumeratePhysicalDevices(&count, physicalDevices.data());
ERROR_IF(failed(result), "Could not fetch vulkan devices. Cause: {}", result)
THEN_ABORT(result);
return physicalDevices;
}
PhysicalDevices::PhysicalDevices(const Window *window, const Context *context)
{
auto surface = window->m_Surface;
auto physicalDevices = enumeratePhysicalDevices(context->m_Instance);
for (auto physicalDevice : physicalDevices)
{
this->emplace_back(surface, physicalDevice);
}
}