diff --git a/openVulkanoCpp/Scene/Node.hpp b/openVulkanoCpp/Scene/Node.hpp index 3a8882a..8f82e84 100644 --- a/openVulkanoCpp/Scene/Node.hpp +++ b/openVulkanoCpp/Scene/Node.hpp @@ -59,6 +59,8 @@ namespace openVulkanoCpp void SetMatrix(const Math::Matrix4f& mat); + [[nodiscard]] Math::Matrix3f GetRotationMatrix() const { return static_cast(localMat); } + [[nodiscard]] const Math::Matrix4f& GetMatrix() const { return localMat; } [[nodiscard]] const Math::Matrix4f& GetWorldMatrix() const { return worldMat; } diff --git a/openVulkanoCpp/Vulkan/Renderer.cpp b/openVulkanoCpp/Vulkan/Renderer.cpp index 6fa0ee6..10428d1 100644 --- a/openVulkanoCpp/Vulkan/Renderer.cpp +++ b/openVulkanoCpp/Vulkan/Renderer.cpp @@ -150,10 +150,11 @@ namespace openVulkanoCpp::Vulkan { Scene::Drawable* drawable = *drawablePointer; Scene::Geometry* mesh = drawable->mesh; + VulkanGeometry* renderGeo = dynamic_cast(mesh->renderGeo); if (mesh != lastGeo) { - if (!mesh->renderGeo) resourceManager.PrepareGeometry(mesh); - dynamic_cast(mesh->renderGeo)->Record(cmdHelper->cmdBuffer, currentImageId); + if (!mesh->renderGeo) renderGeo = resourceManager.PrepareGeometry(mesh); + renderGeo->RecordBind(cmdHelper->cmdBuffer); lastGeo = mesh; } for(Scene::Node* node : drawable->nodes) @@ -164,7 +165,7 @@ namespace openVulkanoCpp::Vulkan dynamic_cast(node->renderNode)->Record(cmdHelper->cmdBuffer, currentImageId); lastNode = node; } - cmdHelper->cmdBuffer.drawIndexed(mesh->GetIndexCount(), 1, 0, 0, 0); + renderGeo->RecordDraw(cmdHelper->cmdBuffer); } } cmdHelper->cmdBuffer.end(); diff --git a/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp b/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp index 4f54f3a..27c2d22 100644 --- a/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ManagedResource.hpp @@ -10,172 +10,169 @@ #include -namespace openVulkanoCpp +namespace openVulkanoCpp::Vulkan { - namespace Vulkan + struct MemoryAllocation { - struct MemoryAllocation + vk::DeviceMemory memory; + size_t used; + const size_t size; + const uint32_t type; + const vk::Device device; + void* mapped; + + private: + uint32_t mappedCount; + static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31; + + public: + MemoryAllocation(size_t size, uint32_t type, vk::Device device): + memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0) { - vk::DeviceMemory memory; - size_t used; - const size_t size; - const uint32_t type; - const vk::Device device; - void* mapped; + } - private: - uint32_t mappedCount; - static constexpr uint32_t CHILD_MAPPED_FLAG = 1u << 31; + [[nodiscard]] size_t FreeSpace() const + { + return size - used; + } - public: - MemoryAllocation(size_t size, uint32_t type, vk::Device device): - memory(nullptr), used(0), size(size), type(type), device(device), mapped(nullptr), mappedCount(0) + void HandleChildMappingValidation() const; + + void* Map() + { + HandleChildMappingValidation(); + if (!mapped) { + mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags()); } + mappedCount++; + return mapped; + } - [[nodiscard]] size_t FreeSpace() const + void UnMap() + { + if (mappedCount > 0) { - return size - used; - } - - void HandleChildMappingValidation() const; - - void* Map() - { - HandleChildMappingValidation(); - if (!mapped) - { - mapped = device.mapMemory(memory, 0, size, vk::MemoryMapFlags()); - } - mappedCount++; - return mapped; - } - - void UnMap() - { - if (mappedCount > 0) - { - mappedCount--; - if (mappedCount == 0) - { - device.unmapMemory(memory); - } - } - } - - bool IsChildMapped() const - { - return mappedCount & CHILD_MAPPED_FLAG; - } - - void* MapChild(size_t offset, vk::DeviceSize size) - { - HandleChildMappingValidation(); - mappedCount |= CHILD_MAPPED_FLAG; - mappedCount++; - return device.mapMemory(memory, offset, size, vk::MemoryMapFlags()); - } - - void UnMapChild() - { - mappedCount &= ~CHILD_MAPPED_FLAG; mappedCount--; if (mappedCount == 0) { device.unmapMemory(memory); } } - }; + } - struct ManagedBuffer + [[nodiscard]] bool IsChildMapped() const { - MemoryAllocation* allocation; - vk::DeviceSize offset, size; - vk::Buffer buffer; - vk::BufferUsageFlags usage; - vk::MemoryPropertyFlags properties; - void* mapped = nullptr; + return mappedCount & CHILD_MAPPED_FLAG; + } - bool IsLast() const + void* MapChild(size_t offset, vk::DeviceSize size) + { + HandleChildMappingValidation(); + mappedCount |= CHILD_MAPPED_FLAG; + mappedCount++; + return device.mapMemory(memory, offset, size, vk::MemoryMapFlags()); + } + + void UnMapChild() + { + mappedCount &= ~CHILD_MAPPED_FLAG; + mappedCount--; + if (mappedCount == 0) { - return (offset + size == allocation->used); + device.unmapMemory(memory); } + } + }; - bool IsMapped() const - { - return mapped || allocation->mapped; - } + struct ManagedBuffer + { + MemoryAllocation* allocation; + vk::DeviceSize offset, size; + vk::Buffer buffer; + vk::BufferUsageFlags usage; + vk::MemoryPropertyFlags properties; + void* mapped = nullptr; - /** - * \brief Maps the buffer into the memory of the host. - * \tparam T The type of the buffers data. - * \param offset The offset from where to map the buffer. - * \param size The size to be mapped. VK_WHOLE_SIZE to map the whole buffer. - * \pparam longTermMapping If the mapping is intended to be held long term. Short term mappings must be freed before mapping a different region in the same memory allocation for them to work reliable with all drivers. - * \return The pointer to the mapped buffer. - */ - template - T* Map(size_t offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE, bool longTermMapping = true) + [[nodiscard]] bool IsLast() const + { + return (offset + size == allocation->used); + } + + [[nodiscard]] bool IsMapped() const + { + return mapped || allocation->mapped; + } + + /** + * \brief Maps the buffer into the memory of the host. + * \tparam T The type of the buffers data. + * \param offset The offset from where to map the buffer. + * \param size The size to be mapped. VK_WHOLE_SIZE to map the whole buffer. + * \pparam longTermMapping If the mapping is intended to be held long term. Short term mappings must be freed before mapping a different region in the same memory allocation for them to work reliable with all drivers. + * \return The pointer to the mapped buffer. + */ + template + T* Map(size_t offset = 0, vk::DeviceSize size = VK_WHOLE_SIZE, bool longTermMapping = true) + { + if (!mapped) { - if (!mapped) + if (allocation->mapped || longTermMapping) { - if (allocation->mapped || longTermMapping) - { - mapped = static_cast(allocation->Map()) + offset + this->offset; - } - else - { - if (size == VK_WHOLE_SIZE) size = this->size; - mapped = allocation->MapChild(this->offset + offset, size); - } - - return static_cast(mapped); - } - } - - /** - * \brief Un-maps the buffer from the host. - */ - void UnMap() - { - if (mapped) - { - if (allocation->mapped) - { - allocation->UnMap(); - } - else - { - allocation->UnMapChild(); - } - mapped = nullptr; - } - } - - void Copy(void* data) - { - if (mapped) - { - memcpy(mapped, data, size); + mapped = static_cast(allocation->Map()) + offset + this->offset; } else { - void* dataMapped = Map(0, VK_WHOLE_SIZE, false); - memcpy(dataMapped, data, size); - UnMap(); + if (size == VK_WHOLE_SIZE) size = this->size; + mapped = allocation->MapChild(this->offset + offset, size); } - } - void Copy(void* data, uint32_t size, uint32_t offset) + return static_cast(mapped); + } + } + + /** + * \brief Un-maps the buffer from the host. + */ + void UnMap() + { + if (mapped) { - if(mapped) memcpy(static_cast(mapped) + offset, data, size); + if (allocation->mapped) + { + allocation->UnMap(); + } else { - void* dataMapped = Map(offset, size, false); - memcpy(dataMapped, data, size); - UnMap(); + allocation->UnMapChild(); } + mapped = nullptr; } - }; - } + } + + void Copy(void* data) + { + if (mapped) + { + memcpy(mapped, data, size); + } + else + { + void* dataMapped = Map(0, VK_WHOLE_SIZE, false); + memcpy(dataMapped, data, size); + UnMap(); + } + } + + void Copy(void* data, uint32_t size, uint32_t offset) + { + if(mapped) memcpy(static_cast(mapped) + offset, data, size); + else + { + void* dataMapped = Map(offset, size, false); + memcpy(dataMapped, data, size); + UnMap(); + } + } + }; } diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp index fa1ec6b..fa8d068 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.cpp @@ -12,6 +12,8 @@ namespace openVulkanoCpp::Vulkan { + ResourceManager* ResourceManager::INSTANCE; + ResourceManager::ResourceManager() = default; ResourceManager::~ResourceManager() noexcept @@ -39,6 +41,8 @@ namespace openVulkanoCpp::Vulkan toFree.resize(buffers); transferQueue = this->device.getQueue(context->device->queueIndices.transfer, 0); + + INSTANCE = this; } void ResourceManager::Close() @@ -82,17 +86,18 @@ namespace openVulkanoCpp::Vulkan } } - void ResourceManager::PrepareGeometry(Scene::Geometry* geometry) + VulkanGeometry* ResourceManager::PrepareGeometry(Scene::Geometry* geometry) { const std::unique_lock lock(mutex); if(!geometry->renderGeo) { - VulkanGeometry* vkGeometry = new VulkanGeometry(); ManagedBuffer* vertexBuffer = CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices()); ManagedBuffer* indexBuffer = CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices()); - vkGeometry->Init(geometry, vertexBuffer->buffer, indexBuffer->buffer); - geometry->renderGeo = vkGeometry; + VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer); + geometry->renderGeo = vkGeo; + return vkGeo; } + return dynamic_cast(geometry->renderGeo); } void ResourceManager::PrepareMaterial(Scene::Material* material) @@ -131,6 +136,13 @@ namespace openVulkanoCpp::Vulkan } } + ManagedBuffer* ResourceManager::CreateSharedMemoryBuffer(const size_t size) + { + const std::unique_lock lock(mutex); + ManagedBuffer* buffer = CreateBuffer(size, vk::BufferUsageFlagBits::eVertexBuffer, vk::MemoryPropertyFlagBits::eHostCoherent); + return buffer; + } + void ResourceManager::RemoveShader(VulkanShader* shader) { Utils::Remove(shaders, shader); diff --git a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp index b802ad8..646daf5 100644 --- a/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp +++ b/openVulkanoCpp/Vulkan/Resources/ResourceManager.hpp @@ -23,6 +23,8 @@ namespace openVulkanoCpp namespace Vulkan { + class VulkanGeometry; + class ResourceManager : virtual public ICloseable, virtual public IShaderOwner { Context* context; @@ -42,7 +44,10 @@ namespace openVulkanoCpp int buffers = -1, currentBuffer = -1; public: + static ResourceManager* INSTANCE; + ResourceManager(); + virtual ~ResourceManager() noexcept; void Init(Context* context, int buffers = 2); @@ -55,7 +60,7 @@ namespace openVulkanoCpp void Resize(); - void PrepareGeometry(Scene::Geometry* geometry); + VulkanGeometry* PrepareGeometry(Scene::Geometry* geometry); void PrepareMaterial(Scene::Material* material); @@ -63,6 +68,8 @@ namespace openVulkanoCpp void RemoveShader(VulkanShader* shader) override; + ManagedBuffer* CreateSharedMemoryBuffer(size_t size); + protected: // Allocation management void FreeBuffer(ManagedBuffer* buffer); diff --git a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp index 1dde553..c449da5 100644 --- a/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp +++ b/openVulkanoCpp/Vulkan/Scene/VulkanGeometry.hpp @@ -9,40 +9,52 @@ #include "IRecordable.hpp" #include "Scene/Scene.hpp" -namespace openVulkanoCpp +namespace openVulkanoCpp::Vulkan { - namespace Vulkan + class VulkanGeometry final : virtual public ICloseable { - class VulkanGeometry : virtual public IRecordable, virtual public ICloseable + Scene::Geometry* m_geometry; + ManagedBuffer* m_vertexBuffer; + ManagedBuffer* m_indexBuffer; + vk::IndexType m_indexType; + vk::DeviceSize m_offsets = 0; + + public: + VulkanGeometry() : m_geometry(nullptr), m_vertexBuffer(nullptr) + , m_indexBuffer(nullptr), m_indexType(vk::IndexType::eUint32) + {} + + VulkanGeometry(Scene::Geometry* geo, ManagedBuffer* vertexBuffer, ManagedBuffer* indexBuffer) + : m_geometry(geo), m_vertexBuffer(vertexBuffer), m_indexBuffer(indexBuffer) + , m_indexType((geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32) + {} + + ~VulkanGeometry() override { - Scene::Geometry* geometry = nullptr; - vk::Buffer vertexBuffer, indexBuffer; - vk::IndexType indexType; - vk::DeviceSize* offsets = new vk::DeviceSize(); + if (m_vertexBuffer) VulkanGeometry::Close(); + } - public: - VulkanGeometry() = default; - virtual ~VulkanGeometry() { if (vertexBuffer) VulkanGeometry::Close(); }; + void Init(Scene::Geometry* geo, ManagedBuffer* vertexBuffer, ManagedBuffer* indexBuffer) + { + m_geometry = geo; + m_vertexBuffer = vertexBuffer; + m_indexBuffer = indexBuffer; + m_indexType = (geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32; + } - void Init(Scene::Geometry* geo, vk::Buffer vertexBuffer, vk::Buffer indexBuffer) - { - this->geometry = geo; - offsets[0] = 0; - indexType = (geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32; - this->vertexBuffer = vertexBuffer; - this->indexBuffer = indexBuffer; - } + void RecordBind(vk::CommandBuffer& cmdBuffer) + { + cmdBuffer.bindVertexBuffers(0, 1, &m_vertexBuffer->buffer, &m_offsets); + cmdBuffer.bindIndexBuffer(m_indexBuffer->buffer, 0, m_indexType); + } - void Record(vk::CommandBuffer& cmdBuffer, uint32_t bufferId) override - { - cmdBuffer.bindVertexBuffers(0, 1, &vertexBuffer, offsets); - cmdBuffer.bindIndexBuffer(indexBuffer, 0, indexType); - } + void RecordDraw(vk::CommandBuffer& cmdBuffer) + { + cmdBuffer.drawIndexed(m_geometry->GetIndexCount(), 1, 0, 0, 0); + } - void Close() override - { - - } - }; - } + void Close() override + { + } + }; }