Device and PhysicalDevice refactored.
This commit is contained in:
parent
7f8e18ff97
commit
31efa504a3
|
|
@ -1,13 +1,36 @@
|
|||
#include "constants.h"
|
||||
#include "glfw_context.h"
|
||||
#include "physical_device.h"
|
||||
#include "window.h"
|
||||
#include <iostream>
|
||||
|
||||
bool suitable_device(const PhysicalDevice *physical_device) {
|
||||
constexpr auto required_support = QueueSupportFlags{} | QueueSupportFlagBits::eGraphics | QueueSupportFlagBits::ePresent | QueueSupportFlagBits::eTransfer;
|
||||
|
||||
return physical_device->properties.deviceType != vk::PhysicalDeviceType::eCpu &&
|
||||
!physical_device->surface_formats.empty() &&
|
||||
!physical_device->present_modes.empty() &&
|
||||
cast<bool>(physical_device->queue_support & required_support);
|
||||
}
|
||||
|
||||
PhysicalDevice find_suitable_device(PhysicalDevices &&_physical_devices) {
|
||||
for (auto physdev : _physical_devices) {
|
||||
VERBOSE(fmt::format("Checking device: {}", physdev.properties.deviceName.data()));
|
||||
if (suitable_device(&physdev)) {
|
||||
VERBOSE(fmt::format("Found suitable device {}.", physdev.properties.deviceName.data()));
|
||||
return physdev;
|
||||
}
|
||||
}
|
||||
throw std::runtime_error("No suitable physical device found.");
|
||||
}
|
||||
|
||||
int main(int, char **) {
|
||||
GlfwContext glfw = {};
|
||||
Context context = { "Aster", VERSION };
|
||||
Window window = { "Aster1", &context, { 640, 480 } };
|
||||
|
||||
PhysicalDevice physical_device = find_suitable_device({ &window, &context });
|
||||
INFO(fmt::format("Using Device {}", physical_device.properties.deviceName.data()));
|
||||
|
||||
while (window.poll()) {
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,7 +15,6 @@
|
|||
Device::Device(Device &&_other) noexcept :
|
||||
physical_device{ std::move(_other.physical_device) },
|
||||
device{ std::exchange(_other.device, nullptr) },
|
||||
queues{ _other.queues },
|
||||
allocator{ std::exchange(_other.allocator, nullptr) },
|
||||
name{ std::move(_other.name) } {}
|
||||
|
||||
|
|
@ -24,31 +23,23 @@ Device &Device::operator=(Device &&_other) noexcept {
|
|||
return *this;
|
||||
physical_device = std::move(_other.physical_device);
|
||||
device = std::exchange(_other.device, nullptr);
|
||||
queues = _other.queues;
|
||||
allocator = std::exchange(_other.allocator, nullptr);
|
||||
name = std::move(_other.name);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Device::Device(const std::string_view &_name, Context *_context, const PhysicalDevice &_physical_device_info, const vk::PhysicalDeviceFeatures &_enabled_features) :
|
||||
Device::Device(const std::string_view &_name, Context *_context, const PhysicalDevice &_physical_device_info, const vk::PhysicalDeviceFeatures &_enabled_features, std::set<QueueAllocation> &&_enabled_queues) :
|
||||
physical_device{ _physical_device_info },
|
||||
name{ _name } {
|
||||
const auto &physical_device = _physical_device_info.device;
|
||||
const auto &queue_families = _physical_device_info.queue_families;
|
||||
|
||||
// Logical Device
|
||||
std::map<u32, u16> unique_queue_families;
|
||||
unique_queue_families[queue_families.graphics_idx]++;
|
||||
unique_queue_families[queue_families.present_idx]++;
|
||||
unique_queue_families[queue_families.transfer_idx]++;
|
||||
unique_queue_families[queue_families.compute_idx]++;
|
||||
|
||||
std::array<f32, 4> queue_priority = { 1.0f, 1.0f, 1.0f, 1.0f };
|
||||
std::vector queue_priority(_enabled_queues.size(), 1.0f);
|
||||
std::vector<vk::DeviceQueueCreateInfo> queue_create_infos;
|
||||
queue_create_infos.reserve(unique_queue_families.size());
|
||||
for (auto &[index_, count_] : unique_queue_families) {
|
||||
queue_create_infos.reserve(_enabled_queues.size());
|
||||
for (auto &[family_, count_] : _enabled_queues) {
|
||||
queue_create_infos.push_back({
|
||||
.queueFamilyIndex = index_,
|
||||
.queueFamilyIndex = family_,
|
||||
.queueCount = count_,
|
||||
.pQueuePriorities = queue_priority.data(),
|
||||
});
|
||||
|
|
@ -69,7 +60,7 @@ Device::Device(const std::string_view &_name, Context *_context, const PhysicalD
|
|||
}
|
||||
INFO("Logical Device Created!");
|
||||
|
||||
VmaAllocatorCreateInfo allocator_create_info = {
|
||||
const VmaAllocatorCreateInfo allocator_create_info = {
|
||||
.physicalDevice = *physical_device,
|
||||
.device = *device,
|
||||
.instance = *_context->instance,
|
||||
|
|
@ -85,54 +76,7 @@ Device::Device(const std::string_view &_name, Context *_context, const PhysicalD
|
|||
|
||||
INFO(fmt::format("Created Device '{}' Successfully", _name));
|
||||
|
||||
// Setup queues
|
||||
{
|
||||
u32 compute_idx = --unique_queue_families[queue_families.compute_idx];
|
||||
u32 transfer_idx = --unique_queue_families[queue_families.transfer_idx];
|
||||
u32 present_idx = --unique_queue_families[queue_families.present_idx];
|
||||
u32 graphics_idx = --unique_queue_families[queue_families.graphics_idx];
|
||||
|
||||
queues.graphics = device.getQueue(queue_families.graphics_idx, graphics_idx);
|
||||
queues.present = device.getQueue(queue_families.present_idx, present_idx);
|
||||
queues.transfer = device.getQueue(queue_families.transfer_idx, transfer_idx);
|
||||
queues.compute = device.getQueue(queue_families.graphics_idx, compute_idx);
|
||||
INFO(fmt::format("Graphics Queue Index: ({}, {})", queue_families.graphics_idx, graphics_idx));
|
||||
INFO(fmt::format("Present Queue Index: ({}, {})", queue_families.present_idx, present_idx));
|
||||
INFO(fmt::format("Transfer Queue Index: ({}, {})", queue_families.transfer_idx, transfer_idx));
|
||||
INFO(fmt::format("Compute Queue Index: ({}, {})", queue_families.compute_idx, compute_idx));
|
||||
}
|
||||
|
||||
// transfer_cmd_pool = device.createCommandPool({
|
||||
// .flags = vk::CommandPoolCreateFlagBits::eTransient,
|
||||
// .queueFamilyIndex = queue_families.transfer_idx,
|
||||
// });
|
||||
// if (failed(result)) {
|
||||
// allocator.destroy();
|
||||
// device.destroy();
|
||||
// return Err::make(fmt::format("Transfer command pool creation failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// VERBOSE("Transfer Command Pool Created");
|
||||
//
|
||||
// vk::CommandPool graphics_cmd_pool;
|
||||
// tie(result, graphics_cmd_pool) = device.createCommandPool({
|
||||
// .flags = vk::CommandPoolCreateFlagBits::eTransient | vk::CommandPoolCreateFlagBits::eResetCommandBuffer,
|
||||
// .queueFamilyIndex = queue_families.graphics_idx,
|
||||
// });
|
||||
// if (failed(result)) {
|
||||
// device.destroyCommandPool(transfer_cmd_pool);
|
||||
// allocator.destroy();
|
||||
// device.destroy();
|
||||
// return Err::make(fmt::format("Graphics command pool creation failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// VERBOSE("Graphics Command Pool Created");
|
||||
|
||||
// transfer_cmd_pool,
|
||||
// graphics_cmd_pool
|
||||
// };
|
||||
|
||||
set_name(_name);
|
||||
// final_device.set_object_name(transfer_cmd_pool, "Async transfer command pool");
|
||||
// final_device.set_object_name(graphics_cmd_pool, "Single use Graphics command pool");
|
||||
}
|
||||
|
||||
Device::~Device() {
|
||||
|
|
@ -141,85 +85,6 @@ Device::~Device() {
|
|||
}
|
||||
INFO("Device '" + name + "' Destroyed");
|
||||
}
|
||||
//
|
||||
// Res<vk::CommandBuffer> Device::alloc_temp_command_buffer(vk::CommandPool _pool) const {
|
||||
// vk::CommandBuffer cmd;
|
||||
// vk::CommandBufferAllocateInfo cmd_buf_alloc_info = {
|
||||
// .commandPool = _pool,
|
||||
// .level = vk::CommandBufferLevel::ePrimary,
|
||||
// .commandBufferCount = 1,
|
||||
// };
|
||||
// if (const auto result = device.allocateCommandBuffers(&cmd_buf_alloc_info, &cmd); failed(result)) {
|
||||
// return Err::make(fmt::format("Temp Command buffer allocation failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// return cmd;
|
||||
// }
|
||||
//
|
||||
// Res<SubmitTask<Buffer>> Device::upload_data(const Borrowed<Buffer> &_host_buffer, Buffer &&_staging_buffer) {
|
||||
// ERROR_IF(!(_host_buffer->usage & vk::BufferUsageFlagBits::eTransferDst), fmt::format("Buffer {} is not a transfer dst. Use vk::BufferUsageFlagBits::eTransferDst during creation", _host_buffer->name.data()))
|
||||
// ELSE_IF_ERROR(!(_staging_buffer.usage & vk::BufferUsageFlagBits::eTransferSrc), fmt::format("Buffer {} is not a transfer src. Use vk::BufferUsageFlagBits::eTransferSrc during creation", _staging_buffer.name.data()))
|
||||
// ELSE_IF_WARN(_host_buffer->memory_usage != vma::MemoryUsage::eGpuOnly, fmt::format("Memory {} is not GPU only. Upload not required", _host_buffer->name.data()))
|
||||
// ELSE_IF_WARN(_host_buffer->memory_usage != vma::MemoryUsage::eCpuOnly, fmt::format("Memory {} is not CPU only. Staging should ideally be a CPU only buffer", _staging_buffer.name.data()));
|
||||
//
|
||||
// vk::CommandBuffer cmd;
|
||||
// vk::CommandBufferAllocateInfo allocate_info = {
|
||||
// .commandPool = transfer_cmd_pool,
|
||||
// .level = vk::CommandBufferLevel::ePrimary,
|
||||
// .commandBufferCount = 1,
|
||||
// };
|
||||
//
|
||||
// auto result = device.allocateCommandBuffers(&allocate_info, &cmd);
|
||||
// if (failed(result)) {
|
||||
// return Err::make(fmt::format("Transfer command pool allocation failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// set_object_name(cmd, fmt::format("{} transfer command", _host_buffer->name.data()));
|
||||
//
|
||||
// result = cmd.begin({
|
||||
// .flags = vk::CommandBufferUsageFlagBits::eOneTimeSubmit,
|
||||
// });
|
||||
// if (failed(result)) {
|
||||
// return Err::make(fmt::format("Command buffer begin failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
//
|
||||
// cmd.copyBuffer(_staging_buffer.buffer, _host_buffer->buffer, { { .srcOffset = 0, .dstOffset = 0, .size = cast<u32>(_staging_buffer.size) } });
|
||||
// result = cmd.end();
|
||||
// if (failed(result)) {
|
||||
// return Err::make(fmt::format("Command buffer end failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
//
|
||||
// return SubmitTask<Buffer>::create(borrow(this), std::move(_staging_buffer), queues.transfer, transfer_cmd_pool, { cmd });
|
||||
// }
|
||||
//
|
||||
// Res<SubmitTask<Buffer>> Device::upload_data(const Borrowed<Buffer> &_host_buffer, const std::span<u8> &_data) {
|
||||
// ERROR_IF(!(_host_buffer->usage & vk::BufferUsageFlagBits::eTransferDst), fmt::format("Buffer {} is not a transfer dst. Use vk::BufferUsageFlagBits::eTransferDst during creation", _host_buffer->name.data()))
|
||||
// ELSE_IF_WARN(_host_buffer->memory_usage != vma::MemoryUsage::eGpuOnly, fmt::format("Memory {} is not GPU only. Upload not required", _host_buffer->name.data()));
|
||||
//
|
||||
// if (auto res = Buffer::create("_stage " + _host_buffer->name, borrow(this), _data.size(), vk::BufferUsageFlagBits::eTransferSrc, vma::MemoryUsage::eCpuOnly)) {
|
||||
// return Err::make("Staging buffer creation failed", std::move(res.error()));
|
||||
// } else {
|
||||
// if (auto result = update_data(borrow(res.value()), _data)) {
|
||||
// return upload_data(_host_buffer, std::move(res.value()));
|
||||
// } else {
|
||||
// return Err::make(std::move(result.error()));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Res<> Device::update_data(const Borrowed<Buffer> &_host_buffer, const std::span<u8> &_data) const {
|
||||
// if (_host_buffer->memory_usage != vma::MemoryUsage::eCpuToGpu &&
|
||||
// _host_buffer->memory_usage != vma::MemoryUsage::eCpuOnly) {
|
||||
// return Err::make("Memory is not on CPU so mapping can't be done. Use upload_data" CODE_LOC);
|
||||
// }
|
||||
//
|
||||
// auto [result, mapped_memory] = allocator.mapMemory(_host_buffer->allocation);
|
||||
// if (failed(result)) {
|
||||
// return Err::make(fmt::format("Memory mapping failed with {}" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// memcpy(mapped_memory, _data.data(), _data.size());
|
||||
// allocator.unmapMemory(_host_buffer->allocation);
|
||||
//
|
||||
// return {};
|
||||
// }
|
||||
|
||||
void Device::set_name(const std::string_view &_name) {
|
||||
VERBOSE(fmt::format("Device {} -> {}", name.data(), _name.data()));
|
||||
|
|
|
|||
|
|
@ -11,20 +11,16 @@
|
|||
#include "window.h"
|
||||
|
||||
#include <iterator>
|
||||
#include <set>
|
||||
#include <span>
|
||||
#include <string_view>
|
||||
#include <utility>
|
||||
|
||||
struct Queues {
|
||||
vk::raii::Queue graphics{ nullptr };
|
||||
vk::raii::Queue present{ nullptr };
|
||||
vk::raii::Queue transfer{ nullptr };
|
||||
Option<vk::raii::Queue> compute;
|
||||
struct QueueAllocation {
|
||||
u32 family;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
struct SubmitTask;
|
||||
|
||||
class Device {
|
||||
public:
|
||||
Device(const Device &_other) = delete;
|
||||
|
|
@ -32,7 +28,7 @@ public:
|
|||
Device &operator=(const Device &_other) = delete;
|
||||
Device &operator=(Device &&_other) noexcept;
|
||||
|
||||
Device(const std::string_view &_name, Context *_context, const PhysicalDevice &_physical_device_info, const vk::PhysicalDeviceFeatures &_enabled_features);
|
||||
Device(const std::string_view &_name, Context *_context, const PhysicalDevice &_physical_device_info, const vk::PhysicalDeviceFeatures &_enabled_features, std::set<QueueAllocation> &&_enabled_queues);
|
||||
|
||||
~Device();
|
||||
|
||||
|
|
@ -49,153 +45,13 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// Res<vk::CommandBuffer> alloc_temp_command_buffer(vk::CommandPool _pool) const;
|
||||
//
|
||||
// [[nodiscard]] Res<SubmitTask<Buffer>> upload_data(const Borrowed<Buffer>& _host_buffer, Buffer&& _staging_buffer);
|
||||
// [[nodiscard]] Res<SubmitTask<Buffer>> upload_data(const Borrowed<Buffer>& _host_buffer, const std::span<u8>& _data);
|
||||
// Res<> update_data(const Borrowed<Buffer>& _host_buffer, const std::span<u8>& _data) const;
|
||||
|
||||
// fields
|
||||
PhysicalDevice physical_device;
|
||||
vk::raii::Device device{ nullptr };
|
||||
Queues queues;
|
||||
VmaAllocator allocator;
|
||||
|
||||
// vk::CommandPool transfer_cmd_pool;
|
||||
// vk::CommandPool graphics_cmd_pool;
|
||||
|
||||
std::string name;
|
||||
|
||||
private:
|
||||
void set_name(const std::string_view &_name);
|
||||
};
|
||||
//
|
||||
// template <typename T = void>
|
||||
// struct SubmitTask {
|
||||
// vk::Fence fence;
|
||||
// Borrowed<Device> device{};
|
||||
// T payload;
|
||||
// std::vector<vk::CommandBuffer> cmd;
|
||||
// vk::CommandPool pool;
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// static Res<SubmitTask<T>> create(const Borrowed<Device>& _device, T&& _payload, vk::Queue _queue, vk::CommandPool _pool, const std::vector<vk::CommandBuffer>& _cmd, const std::vector<vk::Semaphore>& _wait_on = {}, const std::vector<vk::Semaphore>& _signal_to = {}) {
|
||||
//
|
||||
// SubmitTask<T> task;
|
||||
// if (auto res = task.submit(_device, std::forward<T>(_payload), _queue, _pool, _cmd, _wait_on, _signal_to)) {
|
||||
// return std::move(task);
|
||||
// } else {
|
||||
// return Err::make(std::move(res.error()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// Res<> submit(const Borrowed<Device>& _device, T&& _payload, vk::Queue _queue, vk::CommandPool _pool, std::vector<vk::CommandBuffer> _cmd, std::vector<vk::Semaphore> _wait_on = {}, std::vector<vk::Semaphore> _signal_to = {}) {
|
||||
// device = _device;
|
||||
// auto [result, _fence] = device->device.createFence({});
|
||||
// if (failed(result)) {
|
||||
// return Err::make(std::fmt("Fence creation failed with %s" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// fence = _fence;
|
||||
// payload = std::move(_payload);
|
||||
// cmd = _cmd;
|
||||
// pool = _pool;
|
||||
//
|
||||
// result = _queue.submit({
|
||||
// {
|
||||
// .waitSemaphoreCount = cast<u32>(_wait_on.size()),
|
||||
// .pWaitSemaphores = _wait_on.data(),
|
||||
// .commandBufferCount = cast<u32>(_cmd.size()),
|
||||
// .pCommandBuffers = _cmd.data(),
|
||||
// .signalSemaphoreCount = cast<u32>(_signal_to.size()),
|
||||
// .pSignalSemaphores = _signal_to.data(),
|
||||
// }
|
||||
// },
|
||||
// _fence);
|
||||
// if (failed(result)) {
|
||||
// return Err::make(std::fmt("Submit failed with %s" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
//
|
||||
// return {};
|
||||
// }
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// Res<> wait_and_destroy() {
|
||||
// return this->destroy();
|
||||
// }
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// Res<> destroy() {
|
||||
// const auto result = device->device.waitForFences({ fence }, true, max_value<u64>);
|
||||
// if (failed(result)) return Err::make(std::fmt("Fence wait failed with %s" CODE_LOC, to_cstr(result)), result);
|
||||
// device->device.destroyFence(fence);
|
||||
// device->device.freeCommandBuffers(pool, cast<u32>(cmd.size()), cmd.data());
|
||||
// return {};
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// template <>
|
||||
// struct SubmitTask<void> {
|
||||
// vk::Fence fence;
|
||||
// Borrowed<Device> device;
|
||||
// std::vector<vk::CommandBuffer> cmd;
|
||||
// vk::CommandPool pool;
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// static Res<SubmitTask<>> create(const Borrowed<Device>& _device, vk::Queue _queue, vk::CommandPool _pool, const std::vector<vk::CommandBuffer>& _cmd, const std::vector<vk::Semaphore>& _wait_on = {}, const vk::PipelineStageFlags& _wait_stage = vk::PipelineStageFlagBits::eBottomOfPipe, const std::vector<vk::Semaphore>& _signal_to = {}) {
|
||||
//
|
||||
// SubmitTask<> task;
|
||||
// if (auto res = task.submit(_device, _queue, _pool, _cmd, _wait_on, _wait_stage, _signal_to)) {
|
||||
// return std::move(task);
|
||||
// } else {
|
||||
// return Err::make(std::move(res.error()));
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// Res<> wait_and_destroy() {
|
||||
// return this->destroy();
|
||||
// }
|
||||
//
|
||||
// [[nodiscard]]
|
||||
// Res<> destroy() {
|
||||
// const auto result = device->device.waitForFences({ fence }, true, max_value<u64>);
|
||||
// if (failed(result)) return Err::make(std::fmt("Fence wait failed with %s", to_cstr(result)), result);
|
||||
// device->device.destroyFence(fence);
|
||||
// device->device.freeCommandBuffers(pool, cast<u32>(cmd.size()), cmd.data());
|
||||
// return {};
|
||||
// }
|
||||
//
|
||||
// private:
|
||||
// [[nodiscard]]
|
||||
// Res<> submit(const Borrowed<Device>& _device, vk::Queue _queue, vk::CommandPool _pool, std::vector<vk::CommandBuffer> _cmd, std::vector<vk::Semaphore> _wait_on = {},
|
||||
// const vk::PipelineStageFlags& _wait_stage = vk::PipelineStageFlagBits::eBottomOfPipe, std::vector<vk::Semaphore> _signal_to = {}) {
|
||||
// device = _device;
|
||||
// auto [result, _fence] = device->device.createFence({});
|
||||
// if (failed(result)) {
|
||||
// return Err::make(std::fmt("Fence creation failed with %s" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
// fence = _fence;
|
||||
// cmd = _cmd;
|
||||
// pool = _pool;
|
||||
// result = _queue.submit({
|
||||
// vk::SubmitInfo{
|
||||
// .waitSemaphoreCount = cast<u32>(_wait_on.size()),
|
||||
// .pWaitSemaphores = _wait_on.data(),
|
||||
// .pWaitDstStageMask = &_wait_stage,
|
||||
// .commandBufferCount = cast<u32>(_cmd.size()),
|
||||
// .pCommandBuffers = _cmd.data(),
|
||||
// .signalSemaphoreCount = cast<u32>(_signal_to.size()),
|
||||
// .pSignalSemaphores = _signal_to.data(),
|
||||
// } },
|
||||
// _fence);
|
||||
// if (failed(result)) {
|
||||
// return Err::make(std::fmt("Submit failed with %s" CODE_LOC, to_cstr(result)), result);
|
||||
// }
|
||||
//
|
||||
// return {};
|
||||
// }
|
||||
// };
|
||||
//
|
||||
|
|
@ -5,59 +5,45 @@
|
|||
|
||||
#include "physical_device.h"
|
||||
|
||||
QueueFamilyIndices PhysicalDevice::get_queue_families(const Window *_window, const vk::raii::PhysicalDevice *_device) {
|
||||
QueueFamilyIndices indices;
|
||||
std::vector<QueueFamilyInfo> PhysicalDevice::get_queue_families(const Window *_window) const {
|
||||
auto queue_families_ = device.getQueueFamilyProperties();
|
||||
|
||||
auto queue_families_ = _device->getQueueFamilyProperties();
|
||||
std::vector<QueueFamilyInfo> queue_family_infos;
|
||||
queue_family_infos.reserve(queue_families_.size());
|
||||
|
||||
u32 family_index = 0;
|
||||
for (const auto &queue_family : queue_families_) {
|
||||
u32 this_family_count = 0;
|
||||
VERBOSE(fmt::format("Queue({}): {}", family_index, to_string(queue_family.queueFlags).data()));
|
||||
QueueSupportFlags support;
|
||||
|
||||
if (!indices.has_graphics() && (queue_family.queueFlags & vk::QueueFlagBits::eGraphics)) {
|
||||
if (queue_family.queueCount > this_family_count) {
|
||||
indices.graphics_idx = family_index;
|
||||
++this_family_count;
|
||||
} else {
|
||||
continue;
|
||||
if (queue_family.queueFlags & vk::QueueFlagBits::eGraphics) {
|
||||
support |= QueueSupportFlagBits::eGraphics;
|
||||
}
|
||||
if (queue_family.queueFlags & vk::QueueFlagBits::eCompute) {
|
||||
support |= QueueSupportFlagBits::eCompute;
|
||||
}
|
||||
|
||||
if (!indices.has_compute() && (queue_family.queueFlags & vk::QueueFlagBits::eCompute)) {
|
||||
if (queue_family.queueCount > this_family_count) {
|
||||
indices.compute_idx = family_index;
|
||||
++this_family_count;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!indices.has_transfer() && (queue_family.queueFlags & vk::QueueFlagBits::eTransfer)) {
|
||||
if (queue_family.queueCount > this_family_count) {
|
||||
indices.transfer_idx = family_index;
|
||||
++this_family_count;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (queue_family.queueFlags & vk::QueueFlagBits::eTransfer) {
|
||||
support |= QueueSupportFlagBits::eTransfer;
|
||||
}
|
||||
|
||||
try {
|
||||
if (!indices.has_present() && _device->getSurfaceSupportKHR(family_index, *_window->surface)) {
|
||||
if (queue_family.queueCount > this_family_count) {
|
||||
indices.present_idx = family_index;
|
||||
++this_family_count;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
if (device.getSurfaceSupportKHR(family_index, *_window->surface)) {
|
||||
support |= QueueSupportFlagBits::ePresent;
|
||||
}
|
||||
} catch (const std::exception &err) {
|
||||
ERROR("Failure in finding surface support, all possibilities fatal. Failed with "s + err.what());
|
||||
throw;
|
||||
}
|
||||
|
||||
VERBOSE(fmt::format("Queue({}): {}", family_index, to_string(support)));
|
||||
|
||||
queue_family_infos.push_back({
|
||||
.index = family_index,
|
||||
.count = queue_family.queueCount,
|
||||
.queue_support = support,
|
||||
});
|
||||
|
||||
++family_index;
|
||||
}
|
||||
|
||||
return indices;
|
||||
return queue_family_infos;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,28 +8,43 @@
|
|||
#include "global.h"
|
||||
#include "window.h"
|
||||
|
||||
struct QueueFamilyIndices {
|
||||
static constexpr u32 invalid_value = 0xFFFFFFFFu;
|
||||
enum class QueueSupportFlagBits {
|
||||
eGraphics = 0b0000'0001,
|
||||
eTransfer = 0b0000'0010,
|
||||
eCompute = 0b0000'0100,
|
||||
ePresent = 0b0000'1000,
|
||||
};
|
||||
|
||||
u32 graphics_idx{ invalid_value };
|
||||
u32 present_idx{ invalid_value };
|
||||
u32 compute_idx{ invalid_value };
|
||||
u32 transfer_idx{ invalid_value };
|
||||
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
||||
|
||||
[[nodiscard]] b8 has_graphics() const {
|
||||
return graphics_idx != invalid_value;
|
||||
inline std::string to_string(QueueSupportFlags queue_support) {
|
||||
if (! queue_support)
|
||||
return {};
|
||||
|
||||
std::string result = "";
|
||||
if (queue_support & QueueSupportFlagBits::eGraphics) {
|
||||
result += "Graphics | ";
|
||||
}
|
||||
if (queue_support & QueueSupportFlagBits::eTransfer) {
|
||||
result += "Transfer | ";
|
||||
}
|
||||
if (queue_support & QueueSupportFlagBits::eCompute) {
|
||||
result += "Compute | ";
|
||||
}
|
||||
if (queue_support & QueueSupportFlagBits::ePresent) {
|
||||
result += "Present | ";
|
||||
}
|
||||
|
||||
[[nodiscard]] b8 has_present() const {
|
||||
return present_idx != invalid_value;
|
||||
return "{ " + result.substr( 0, result.size() - 3 ) + " }";
|
||||
}
|
||||
|
||||
[[nodiscard]] b8 has_compute() const {
|
||||
return compute_idx != invalid_value;
|
||||
}
|
||||
struct QueueFamilyInfo {
|
||||
u32 index;
|
||||
u32 count;
|
||||
QueueSupportFlags queue_support;
|
||||
|
||||
[[nodiscard]] b8 has_transfer() const {
|
||||
return transfer_idx != invalid_value;
|
||||
[[nodiscard]] bool has_support(const QueueSupportFlags &support) const {
|
||||
return cast<bool>(queue_support & support);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -37,15 +52,33 @@ struct PhysicalDevice {
|
|||
vk::raii::PhysicalDevice device;
|
||||
vk::PhysicalDeviceProperties properties;
|
||||
vk::PhysicalDeviceFeatures features;
|
||||
QueueFamilyIndices queue_families;
|
||||
std::vector<vk::SurfaceFormatKHR> surface_formats;
|
||||
std::vector<vk::PresentModeKHR> present_modes;
|
||||
std::vector<QueueFamilyInfo> queue_family_infos;
|
||||
QueueSupportFlags queue_support;
|
||||
|
||||
PhysicalDevice(const Window *const _window, vk::raii::PhysicalDevice _device) :
|
||||
PhysicalDevice(const Window *const _window, vk::raii::PhysicalDevice &&_device) :
|
||||
device{ std::move(_device) } {
|
||||
properties = device.getProperties();
|
||||
features = device.getFeatures();
|
||||
queue_families = get_queue_families(_window, &device);
|
||||
surface_formats = device.getSurfaceFormatsKHR(*_window->surface);
|
||||
present_modes = device.getSurfacePresentModesKHR(*_window->surface);
|
||||
queue_family_infos = get_queue_families(_window);
|
||||
for (auto [family, count, support] : queue_family_infos) {
|
||||
queue_support |= support;
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
[[nodiscard]] static QueueFamilyIndices get_queue_families(const Window *_window, const vk::raii::PhysicalDevice *_device);
|
||||
std::vector<QueueFamilyInfo> get_queue_families(const Window *_window) const;
|
||||
};
|
||||
|
||||
struct PhysicalDevices : std::vector<PhysicalDevice> {
|
||||
PhysicalDevices(const Window *const _window, const Context *_context) {
|
||||
auto phys_devs = vk::raii::PhysicalDevices(_context->instance);
|
||||
reserve(phys_devs.size());
|
||||
|
||||
for (auto physdev : phys_devs) {
|
||||
emplace_back(_window, std::move(physdev));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue