Device and PhysicalDevice refactored.
This commit is contained in:
parent
7f8e18ff97
commit
31efa504a3
|
|
@ -1,13 +1,36 @@
|
||||||
#include "constants.h"
|
#include "constants.h"
|
||||||
#include "glfw_context.h"
|
#include "glfw_context.h"
|
||||||
|
#include "physical_device.h"
|
||||||
#include "window.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 **) {
|
int main(int, char **) {
|
||||||
GlfwContext glfw = {};
|
GlfwContext glfw = {};
|
||||||
Context context = { "Aster", VERSION };
|
Context context = { "Aster", VERSION };
|
||||||
Window window = { "Aster1", &context, { 640, 480 } };
|
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()) {
|
while (window.poll()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@
|
||||||
Device::Device(Device &&_other) noexcept :
|
Device::Device(Device &&_other) noexcept :
|
||||||
physical_device{ std::move(_other.physical_device) },
|
physical_device{ std::move(_other.physical_device) },
|
||||||
device{ std::exchange(_other.device, nullptr) },
|
device{ std::exchange(_other.device, nullptr) },
|
||||||
queues{ _other.queues },
|
|
||||||
allocator{ std::exchange(_other.allocator, nullptr) },
|
allocator{ std::exchange(_other.allocator, nullptr) },
|
||||||
name{ std::move(_other.name) } {}
|
name{ std::move(_other.name) } {}
|
||||||
|
|
||||||
|
|
@ -24,31 +23,23 @@ Device &Device::operator=(Device &&_other) noexcept {
|
||||||
return *this;
|
return *this;
|
||||||
physical_device = std::move(_other.physical_device);
|
physical_device = std::move(_other.physical_device);
|
||||||
device = std::exchange(_other.device, nullptr);
|
device = std::exchange(_other.device, nullptr);
|
||||||
queues = _other.queues;
|
|
||||||
allocator = std::exchange(_other.allocator, nullptr);
|
allocator = std::exchange(_other.allocator, nullptr);
|
||||||
name = std::move(_other.name);
|
name = std::move(_other.name);
|
||||||
return *this;
|
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 },
|
physical_device{ _physical_device_info },
|
||||||
name{ _name } {
|
name{ _name } {
|
||||||
const auto &physical_device = _physical_device_info.device;
|
const auto &physical_device = _physical_device_info.device;
|
||||||
const auto &queue_families = _physical_device_info.queue_families;
|
|
||||||
|
|
||||||
// Logical Device
|
// Logical Device
|
||||||
std::map<u32, u16> unique_queue_families;
|
std::vector queue_priority(_enabled_queues.size(), 1.0f);
|
||||||
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<vk::DeviceQueueCreateInfo> queue_create_infos;
|
std::vector<vk::DeviceQueueCreateInfo> queue_create_infos;
|
||||||
queue_create_infos.reserve(unique_queue_families.size());
|
queue_create_infos.reserve(_enabled_queues.size());
|
||||||
for (auto &[index_, count_] : unique_queue_families) {
|
for (auto &[family_, count_] : _enabled_queues) {
|
||||||
queue_create_infos.push_back({
|
queue_create_infos.push_back({
|
||||||
.queueFamilyIndex = index_,
|
.queueFamilyIndex = family_,
|
||||||
.queueCount = count_,
|
.queueCount = count_,
|
||||||
.pQueuePriorities = queue_priority.data(),
|
.pQueuePriorities = queue_priority.data(),
|
||||||
});
|
});
|
||||||
|
|
@ -69,7 +60,7 @@ Device::Device(const std::string_view &_name, Context *_context, const PhysicalD
|
||||||
}
|
}
|
||||||
INFO("Logical Device Created!");
|
INFO("Logical Device Created!");
|
||||||
|
|
||||||
VmaAllocatorCreateInfo allocator_create_info = {
|
const VmaAllocatorCreateInfo allocator_create_info = {
|
||||||
.physicalDevice = *physical_device,
|
.physicalDevice = *physical_device,
|
||||||
.device = *device,
|
.device = *device,
|
||||||
.instance = *_context->instance,
|
.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));
|
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);
|
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() {
|
Device::~Device() {
|
||||||
|
|
@ -141,85 +85,6 @@ Device::~Device() {
|
||||||
}
|
}
|
||||||
INFO("Device '" + name + "' Destroyed");
|
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) {
|
void Device::set_name(const std::string_view &_name) {
|
||||||
VERBOSE(fmt::format("Device {} -> {}", name.data(), _name.data()));
|
VERBOSE(fmt::format("Device {} -> {}", name.data(), _name.data()));
|
||||||
|
|
|
||||||
|
|
@ -11,20 +11,16 @@
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <set>
|
||||||
#include <span>
|
#include <span>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
struct Queues {
|
struct QueueAllocation {
|
||||||
vk::raii::Queue graphics{ nullptr };
|
u32 family;
|
||||||
vk::raii::Queue present{ nullptr };
|
u32 count;
|
||||||
vk::raii::Queue transfer{ nullptr };
|
|
||||||
Option<vk::raii::Queue> compute;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct SubmitTask;
|
|
||||||
|
|
||||||
class Device {
|
class Device {
|
||||||
public:
|
public:
|
||||||
Device(const Device &_other) = delete;
|
Device(const Device &_other) = delete;
|
||||||
|
|
@ -32,7 +28,7 @@ public:
|
||||||
Device &operator=(const Device &_other) = delete;
|
Device &operator=(const Device &_other) = delete;
|
||||||
Device &operator=(Device &&_other) noexcept;
|
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();
|
~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
|
// fields
|
||||||
PhysicalDevice physical_device;
|
PhysicalDevice physical_device;
|
||||||
vk::raii::Device device{ nullptr };
|
vk::raii::Device device{ nullptr };
|
||||||
Queues queues;
|
|
||||||
VmaAllocator allocator;
|
VmaAllocator allocator;
|
||||||
|
|
||||||
// vk::CommandPool transfer_cmd_pool;
|
|
||||||
// vk::CommandPool graphics_cmd_pool;
|
|
||||||
|
|
||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void set_name(const std::string_view &_name);
|
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"
|
#include "physical_device.h"
|
||||||
|
|
||||||
QueueFamilyIndices PhysicalDevice::get_queue_families(const Window *_window, const vk::raii::PhysicalDevice *_device) {
|
std::vector<QueueFamilyInfo> PhysicalDevice::get_queue_families(const Window *_window) const {
|
||||||
QueueFamilyIndices indices;
|
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;
|
u32 family_index = 0;
|
||||||
for (const auto &queue_family : queue_families_) {
|
for (const auto &queue_family : queue_families_) {
|
||||||
u32 this_family_count = 0;
|
QueueSupportFlags support;
|
||||||
VERBOSE(fmt::format("Queue({}): {}", family_index, to_string(queue_family.queueFlags).data()));
|
|
||||||
|
|
||||||
if (!indices.has_graphics() && (queue_family.queueFlags & vk::QueueFlagBits::eGraphics)) {
|
if (queue_family.queueFlags & vk::QueueFlagBits::eGraphics) {
|
||||||
if (queue_family.queueCount > this_family_count) {
|
support |= QueueSupportFlagBits::eGraphics;
|
||||||
indices.graphics_idx = family_index;
|
|
||||||
++this_family_count;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (queue_family.queueFlags & vk::QueueFlagBits::eCompute) {
|
||||||
if (!indices.has_compute() && (queue_family.queueFlags & vk::QueueFlagBits::eCompute)) {
|
support |= QueueSupportFlagBits::eCompute;
|
||||||
if (queue_family.queueCount > this_family_count) {
|
|
||||||
indices.compute_idx = family_index;
|
|
||||||
++this_family_count;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
if (queue_family.queueFlags & vk::QueueFlagBits::eTransfer) {
|
||||||
if (!indices.has_transfer() && (queue_family.queueFlags & vk::QueueFlagBits::eTransfer)) {
|
support |= QueueSupportFlagBits::eTransfer;
|
||||||
if (queue_family.queueCount > this_family_count) {
|
|
||||||
indices.transfer_idx = family_index;
|
|
||||||
++this_family_count;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!indices.has_present() && _device->getSurfaceSupportKHR(family_index, *_window->surface)) {
|
if (device.getSurfaceSupportKHR(family_index, *_window->surface)) {
|
||||||
if (queue_family.queueCount > this_family_count) {
|
support |= QueueSupportFlagBits::ePresent;
|
||||||
indices.present_idx = family_index;
|
|
||||||
++this_family_count;
|
|
||||||
} else {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (const std::exception &err) {
|
} catch (const std::exception &err) {
|
||||||
ERROR("Failure in finding surface support, all possibilities fatal. Failed with "s + err.what());
|
ERROR("Failure in finding surface support, all possibilities fatal. Failed with "s + err.what());
|
||||||
throw;
|
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;
|
++family_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
return indices;
|
return queue_family_infos;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -8,28 +8,43 @@
|
||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include "window.h"
|
#include "window.h"
|
||||||
|
|
||||||
struct QueueFamilyIndices {
|
enum class QueueSupportFlagBits {
|
||||||
static constexpr u32 invalid_value = 0xFFFFFFFFu;
|
eGraphics = 0b0000'0001,
|
||||||
|
eTransfer = 0b0000'0010,
|
||||||
|
eCompute = 0b0000'0100,
|
||||||
|
ePresent = 0b0000'1000,
|
||||||
|
};
|
||||||
|
|
||||||
u32 graphics_idx{ invalid_value };
|
using QueueSupportFlags = vk::Flags<QueueSupportFlagBits>;
|
||||||
u32 present_idx{ invalid_value };
|
|
||||||
u32 compute_idx{ invalid_value };
|
|
||||||
u32 transfer_idx{ invalid_value };
|
|
||||||
|
|
||||||
[[nodiscard]] b8 has_graphics() const {
|
inline std::string to_string(QueueSupportFlags queue_support) {
|
||||||
return graphics_idx != invalid_value;
|
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 "{ " + result.substr( 0, result.size() - 3 ) + " }";
|
||||||
return present_idx != invalid_value;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
[[nodiscard]] b8 has_compute() const {
|
struct QueueFamilyInfo {
|
||||||
return compute_idx != invalid_value;
|
u32 index;
|
||||||
}
|
u32 count;
|
||||||
|
QueueSupportFlags queue_support;
|
||||||
|
|
||||||
[[nodiscard]] b8 has_transfer() const {
|
[[nodiscard]] bool has_support(const QueueSupportFlags &support) const {
|
||||||
return transfer_idx != invalid_value;
|
return cast<bool>(queue_support & support);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -37,15 +52,33 @@ struct PhysicalDevice {
|
||||||
vk::raii::PhysicalDevice device;
|
vk::raii::PhysicalDevice device;
|
||||||
vk::PhysicalDeviceProperties properties;
|
vk::PhysicalDeviceProperties properties;
|
||||||
vk::PhysicalDeviceFeatures features;
|
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) } {
|
device{ std::move(_device) } {
|
||||||
properties = device.getProperties();
|
properties = device.getProperties();
|
||||||
features = device.getFeatures();
|
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:
|
std::vector<QueueFamilyInfo> get_queue_families(const Window *_window) const;
|
||||||
[[nodiscard]] static QueueFamilyIndices get_queue_families(const Window *_window, const vk::raii::PhysicalDevice *_device);
|
};
|
||||||
|
|
||||||
|
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