diff --git a/include/vkcv/Handles.hpp b/include/vkcv/Handles.hpp index ad48a1ecbd41f75286cc33e88e62699468a5f11f..7b500ea514f1034e9822f9c12936b5e63ba3225e 100644 --- a/include/vkcv/Handles.hpp +++ b/include/vkcv/Handles.hpp @@ -5,13 +5,63 @@ * @brief Central header file for all possible handles that the framework will hand out. */ -#include <cstdint> +#include <iostream> namespace vkcv { + class Handle { + friend std::ostream& operator << (std::ostream& out, const Handle& handle); + + private: + uint64_t m_id; + + protected: + Handle(); + + explicit Handle(uint64_t id); + + [[nodiscard]] + uint64_t getId() const; + + public: + virtual ~Handle() = default; + + Handle(const Handle& other) = default; + Handle(Handle&& other) = default; + + Handle& operator=(const Handle& other) = default; + Handle& operator=(Handle&& other) = default; + + explicit operator bool() const; + bool operator!() const; + + }; + + std::ostream& operator << (std::ostream& out, const Handle& handle); + // Handle returned for any buffer created with the core/context objects - struct BufferHandle {uint64_t id;}; - struct PassHandle {uint64_t id;}; - struct PipelineHandle {uint64_t id;}; - struct ResourcesHandle {uint64_t id;}; + class BufferHandle : public Handle { + friend class BufferManager; + private: + using Handle::Handle; + }; + + class PassHandle : public Handle { + friend class PassManager; + private: + using Handle::Handle; + }; + + class PipelineHandle : public Handle { + friend class PipelineManager; + private: + using Handle::Handle; + }; + + class ResourcesHandle : public Handle { + friend class DescriptorManager; + private: + using Handle::Handle; + }; + } diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp index 275c87cf67f059c5896272639363733634e26ca2..b9458e4c20cbe8fa2670bcf782f7485966647b6b 100644 --- a/projects/first_triangle/src/main.cpp +++ b/projects/first_triangle/src/main.cpp @@ -78,7 +78,7 @@ int main(int argc, const char** argv) { vkcv::PassConfig trianglePassDefinition({present_color_attachment}); vkcv::PassHandle trianglePass = core.createPass(trianglePassDefinition); - if (trianglePass.id == 0) + if (!trianglePass) { std::cout << "Error. Could not create renderpass. Exiting." << std::endl; return EXIT_FAILURE; @@ -90,7 +90,8 @@ int main(int argc, const char** argv) { const vkcv::PipelineConfig trianglePipelineDefinition(triangleShaderProgram, windowWidth, windowHeight, trianglePass); vkcv::PipelineHandle trianglePipeline = core.createGraphicsPipeline(trianglePipelineDefinition); - if (trianglePipeline.id == 0) + + if (!trianglePipeline) { std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl; return EXIT_FAILURE; @@ -111,7 +112,7 @@ int main(int argc, const char** argv) { sets.push_back(set); auto resourceHandle = core.createResourceDescription(sets); - std::cout << "Resource " << resourceHandle.id << " created." << std::endl; + std::cout << "Resource " << resourceHandle << " created." << std::endl; } /* diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp index e9b5112888782ae5be373f8a63777b7fc3503713..afff7d4b3e3fc78a6dbb7535162857f21812721c 100644 --- a/src/vkcv/BufferManager.cpp +++ b/src/vkcv/BufferManager.cpp @@ -9,7 +9,7 @@ namespace vkcv { BufferManager::BufferManager() noexcept : - m_core(nullptr), m_buffers(), m_stagingBuffer(BufferHandle{ UINT64_MAX }) + m_core(nullptr), m_buffers(), m_stagingBuffer(BufferHandle()) { } @@ -22,8 +22,8 @@ namespace vkcv { } BufferManager::~BufferManager() noexcept { - for (size_t id = 0; id < m_buffers.size(); id++) { - destroyBuffer(BufferHandle{ id }); + for (uint64_t id = 0; id < m_buffers.size(); id++) { + destroyBuffer(BufferHandle(id)); } } @@ -179,7 +179,7 @@ namespace vkcv { } vk::Buffer BufferManager::getBuffer(const BufferHandle& handle) const { - const uint64_t id = handle.id; + const uint64_t id = handle.getId(); if (id >= m_buffers.size()) { return nullptr; @@ -191,7 +191,7 @@ namespace vkcv { } vk::DeviceMemory BufferManager::getDeviceMemory(const BufferHandle& handle) const { - const uint64_t id = handle.id; + const uint64_t id = handle.getId(); if (id >= m_buffers.size()) { return nullptr; @@ -203,7 +203,7 @@ namespace vkcv { } void BufferManager::fillBuffer(const BufferHandle& handle, void *data, size_t size, size_t offset) { - const uint64_t id = handle.id; + const uint64_t id = handle.getId(); if (size == 0) { size = SIZE_MAX; @@ -232,7 +232,7 @@ namespace vkcv { memcpy(mapped, data, max_size); device.unmapMemory(buffer.m_memory); } else { - auto& stagingBuffer = m_buffers[ m_stagingBuffer.id ]; + auto& stagingBuffer = m_buffers[ m_stagingBuffer.getId() ]; StagingStepInfo info; info.data = data; @@ -253,7 +253,7 @@ namespace vkcv { } void* BufferManager::mapBuffer(const BufferHandle& handle, size_t offset, size_t size) { - const uint64_t id = handle.id; + const uint64_t id = handle.getId(); if (size == 0) { size = SIZE_MAX; @@ -281,7 +281,7 @@ namespace vkcv { } void BufferManager::unmapBuffer(const BufferHandle& handle) { - const uint64_t id = handle.id; + const uint64_t id = handle.getId(); if (id >= m_buffers.size()) { return; @@ -300,7 +300,7 @@ namespace vkcv { } void BufferManager::destroyBuffer(const BufferHandle& handle) { - const uint64_t id = handle.id; + const uint64_t id = handle.getId(); if (id >= m_buffers.size()) { return; diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index bcebb142af2f29c23e77185112cbb83a827e41ba..c42db30fb4d8d72e340a9db53afb3fcf6d1058d0 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -8,7 +8,7 @@ namespace vkcv descriptorSetLayouts{std::move(layouts)} {} DescriptorManager::DescriptorManager(vk::Device device) noexcept: - m_Device{ device }, m_NextResourceDescriptionID{ 1 } + m_Device{ device }, m_NextResourceDescriptionID{ 0 } { /** * Allocate a set size for the initial pool, namely 1000 units of each descriptor type below. @@ -64,7 +64,7 @@ namespace vkcv if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &layout) != vk::Result::eSuccess) { std::cout << "FAILED TO CREATE DESCRIPTOR SET LAYOUT" << std::endl; - return ResourcesHandle{0}; + return ResourcesHandle(); }; vk_setLayouts.push_back(layout); } @@ -79,11 +79,11 @@ namespace vkcv for(const auto &layout : vk_setLayouts) m_Device.destroy(layout); - return ResourcesHandle{0}; + return ResourcesHandle(); }; m_ResourceDescriptions.emplace_back(vk_sets, vk_setLayouts); - return ResourcesHandle{m_NextResourceDescriptionID++}; + return ResourcesHandle(m_NextResourceDescriptionID++); } vk::DescriptorType DescriptorManager::convertDescriptorTypeFlag(DescriptorType type) { diff --git a/src/vkcv/Handles.cpp b/src/vkcv/Handles.cpp index 1337a132ae0b8721bd2776e24212f73dfb94ae46..bd465d4e71da31c554d82ceb4b8bce7b0ee04129 100644 --- a/src/vkcv/Handles.cpp +++ b/src/vkcv/Handles.cpp @@ -1 +1,33 @@ #include "vkcv/Handles.hpp" + +namespace vkcv { + + Handle::Handle() : + m_id(UINT64_MAX) + {} + + Handle::Handle(uint64_t id) : + m_id(id) + {} + + uint64_t Handle::getId() const { + return m_id; + } + + Handle::operator bool() const { + return (m_id < UINT64_MAX); + } + + bool Handle::operator!() const { + return (m_id == UINT64_MAX); + } + + std::ostream& operator << (std::ostream& out, const Handle& handle) { + if (handle) { + return out << "[Handle: " << handle.getId() << "]"; + } else { + return out << "[Handle: none]"; + } + } + +} diff --git a/src/vkcv/PassManager.cpp b/src/vkcv/PassManager.cpp index 820bf3ff8a84edb9d070c22c60327cf7cb661ee7..d69024a805f45cda549365c7cc97fc57f59ef926 100644 --- a/src/vkcv/PassManager.cpp +++ b/src/vkcv/PassManager.cpp @@ -50,7 +50,7 @@ namespace vkcv PassManager::PassManager(vk::Device device) noexcept : m_Device{device}, m_RenderPasses{}, - m_NextPassId{1} + m_NextPassId(0) {} PassManager::~PassManager() noexcept @@ -59,7 +59,7 @@ namespace vkcv m_Device.destroy(pass); m_RenderPasses.clear(); - m_NextPassId = 1; + m_NextPassId = 0; } PassHandle PassManager::createPass(const PassConfig &config) @@ -122,14 +122,14 @@ namespace vkcv vk::RenderPass vkObject{nullptr}; if(m_Device.createRenderPass(&passInfo, nullptr, &vkObject) != vk::Result::eSuccess) - return PassHandle{0}; + return PassHandle(); m_RenderPasses.push_back(vkObject); - return PassHandle{m_NextPassId++}; + return PassHandle(m_NextPassId++); } vk::RenderPass PassManager::getVkPass(const PassHandle &handle) const { - return m_RenderPasses[handle.id - 1]; + return m_RenderPasses[handle.getId()]; } } diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp index 576cb47397a29184160423fdba6d1a09104a5566..c253aafd0438a64b2312fc4737d9b52d2b37f2e8 100644 --- a/src/vkcv/PipelineManager.cpp +++ b/src/vkcv/PipelineManager.cpp @@ -7,7 +7,7 @@ namespace vkcv m_Device{device}, m_Pipelines{}, m_PipelineLayouts{}, - m_NextPipelineId{1} + m_NextPipelineId{0} {} PipelineManager::~PipelineManager() noexcept @@ -20,7 +20,7 @@ namespace vkcv m_Pipelines.clear(); m_PipelineLayouts.clear(); - m_NextPipelineId = 1; + m_NextPipelineId = 0; } PipelineHandle PipelineManager::createPipeline(const PipelineConfig &config, const vk::RenderPass &pass) @@ -30,7 +30,7 @@ namespace vkcv if (!(existsVertexShader && existsFragmentShader)) { std::cout << "Core::createGraphicsPipeline requires vertex and fragment shader code" << std::endl; - return PipelineHandle{0}; + return PipelineHandle(); } // vertex shader stage @@ -38,7 +38,7 @@ namespace vkcv vk::ShaderModuleCreateInfo vertexModuleInfo({}, vertexCode.size(), reinterpret_cast<uint32_t*>(vertexCode.data())); vk::ShaderModule vertexModule{}; if (m_Device.createShaderModule(&vertexModuleInfo, nullptr, &vertexModule) != vk::Result::eSuccess) - return PipelineHandle{0}; + return PipelineHandle(); vk::PipelineShaderStageCreateInfo pipelineVertexShaderStageInfo( {}, @@ -55,7 +55,7 @@ namespace vkcv if (m_Device.createShaderModule(&fragmentModuleInfo, nullptr, &fragmentModule) != vk::Result::eSuccess) { m_Device.destroy(vertexModule); - return PipelineHandle{0}; + return PipelineHandle(); } vk::PipelineShaderStageCreateInfo pipelineFragmentShaderStageInfo( @@ -153,7 +153,7 @@ namespace vkcv { m_Device.destroy(vertexModule); m_Device.destroy(fragmentModule); - return PipelineHandle{0}; + return PipelineHandle(); } // graphics pipeline create @@ -183,7 +183,7 @@ namespace vkcv { m_Device.destroy(vertexModule); m_Device.destroy(fragmentModule); - return PipelineHandle{0}; + return PipelineHandle(); } m_Device.destroy(vertexModule); @@ -191,16 +191,16 @@ namespace vkcv m_Pipelines.push_back(vkPipeline); m_PipelineLayouts.push_back(vkPipelineLayout); - return PipelineHandle{m_NextPipelineId++}; + return PipelineHandle(m_NextPipelineId++); } vk::Pipeline PipelineManager::getVkPipeline(const PipelineHandle &handle) const { - return m_Pipelines.at(handle.id -1); + return m_Pipelines.at(handle.getId()); } vk::PipelineLayout PipelineManager::getVkPipelineLayout(const PipelineHandle &handle) const { - return m_PipelineLayouts.at(handle.id - 1); + return m_PipelineLayouts.at(handle.getId()); } } \ No newline at end of file