// ============================================= // Aster: device.h // Copyright (c) 2020-2024 Anish Bhobe // ============================================= #pragma once #include "context.h" #include "global.h" #include "physical_device.h" #include "window.h" #include #include #include #include struct Queues { vk::raii::Queue graphics{ nullptr }; vk::raii::Queue present{ nullptr }; vk::raii::Queue transfer{ nullptr }; Option compute; }; template struct SubmitTask; class Device { public: Device(const Device &_other) = delete; Device(Device &&_other) noexcept; 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(); template requires vk::isVulkanHandleType::value void set_object_name(const T &_obj, const std::string_view &_name) const { try { device.setDebugUtilsObjectNameEXT({ .objectType = _obj.objectType, .objectHandle = get_vk_handle(_obj), .pObjectName = _name.data(), }); } catch (const std::exception &err) { WARN("Debug Utils name setting failed with "s + err.what()); } } // // [[nodiscard]] // Res alloc_temp_command_buffer(vk::CommandPool _pool) const; // // [[nodiscard]] Res> upload_data(const Borrowed& _host_buffer, Buffer&& _staging_buffer); // [[nodiscard]] Res> upload_data(const Borrowed& _host_buffer, const std::span& _data); // Res<> update_data(const Borrowed& _host_buffer, const std::span& _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 // struct SubmitTask { // vk::Fence fence; // Borrowed device{}; // T payload; // std::vector cmd; // vk::CommandPool pool; // // [[nodiscard]] // static Res> create(const Borrowed& _device, T&& _payload, vk::Queue _queue, vk::CommandPool _pool, const std::vector& _cmd, const std::vector& _wait_on = {}, const std::vector& _signal_to = {}) { // // SubmitTask task; // if (auto res = task.submit(_device, std::forward(_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, T&& _payload, vk::Queue _queue, vk::CommandPool _pool, std::vector _cmd, std::vector _wait_on = {}, std::vector _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(_wait_on.size()), // .pWaitSemaphores = _wait_on.data(), // .commandBufferCount = cast(_cmd.size()), // .pCommandBuffers = _cmd.data(), // .signalSemaphoreCount = cast(_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); // 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(cmd.size()), cmd.data()); // return {}; // } // }; // // template <> // struct SubmitTask { // vk::Fence fence; // Borrowed device; // std::vector cmd; // vk::CommandPool pool; // // [[nodiscard]] // static Res> create(const Borrowed& _device, vk::Queue _queue, vk::CommandPool _pool, const std::vector& _cmd, const std::vector& _wait_on = {}, const vk::PipelineStageFlags& _wait_stage = vk::PipelineStageFlagBits::eBottomOfPipe, const std::vector& _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); // 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(cmd.size()), cmd.data()); // return {}; // } // // private: // [[nodiscard]] // Res<> submit(const Borrowed& _device, vk::Queue _queue, vk::CommandPool _pool, std::vector _cmd, std::vector _wait_on = {}, // const vk::PipelineStageFlags& _wait_stage = vk::PipelineStageFlagBits::eBottomOfPipe, std::vector _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(_wait_on.size()), // .pWaitSemaphores = _wait_on.data(), // .pWaitDstStageMask = &_wait_stage, // .commandBufferCount = cast(_cmd.size()), // .pCommandBuffers = _cmd.data(), // .signalSemaphoreCount = cast(_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 {}; // } // }; //