Add render resource handling for geometry

This commit is contained in:
Georg Hagen
2024-08-21 14:33:45 +02:00
parent b13c1c54ae
commit 2d08b3ab91
6 changed files with 59 additions and 68 deletions

View File

@@ -45,8 +45,8 @@ namespace OpenVulkano
public: public:
RenderResourcePtr() = default; RenderResourcePtr() = default;
RenderResourcePtr(const RenderResourcePtr& ignored) { /* Do not copy, copy will be created by renderer */ } RenderResourcePtr(const RenderResourcePtr& ignored) noexcept { /* Do not copy, copy will be created by renderer */ }
RenderResourcePtr(RenderResourcePtr&& move) : renderObject(move.renderObject) { move.renderObject = nullptr; } RenderResourcePtr(RenderResourcePtr&& move) noexcept : renderObject(move.renderObject) { move.renderObject = nullptr; }
~RenderResourcePtr() ~RenderResourcePtr()
{ {
@@ -67,6 +67,14 @@ namespace OpenVulkano
operator T() { return static_cast<T>(renderObject); } operator T() { return static_cast<T>(renderObject); }
operator bool() const { return renderObject; } operator bool() const { return renderObject; }
RenderResourcePtr& operator =(RenderResourcePtr&& move) noexcept
{
if (renderObject) renderObject->Release();
renderObject = move.renderObject;
move.renderObject = nullptr;
return *this;
}
}; };
inline void IRenderResourceHelper::UpdateRenderResource(RenderResourcePtr* resource) inline void IRenderResourceHelper::UpdateRenderResource(RenderResourcePtr* resource)
@@ -94,7 +102,7 @@ namespace OpenVulkano
IRenderResource(const IRenderResource<API_INDEPENDENT_CLASS>& copy) = delete; IRenderResource(const IRenderResource<API_INDEPENDENT_CLASS>& copy) = delete;
IRenderResource(IRenderResource<API_INDEPENDENT_CLASS>&& move) IRenderResource(IRenderResource<API_INDEPENDENT_CLASS>&& move) noexcept
: m_owner(move.m_owner) : m_owner(move.m_owner)
{ {
if (m_owner) if (m_owner)
@@ -139,8 +147,8 @@ namespace OpenVulkano
protected: protected:
RenderResourceHolder() = default; RenderResourceHolder() = default;
RenderResourceHolder(const RenderResourceHolder& ignored) {} RenderResourceHolder(const RenderResourceHolder& ignored) noexcept {}
RenderResourceHolder(RenderResourceHolder&& move) RenderResourceHolder(RenderResourceHolder&& move) noexcept
: renderResource(std::move(move.renderResource)) : renderResource(std::move(move.renderResource))
{ {
if (IRenderResource<T>* renderRes = renderResource) if (IRenderResource<T>* renderRes = renderResource)
@@ -158,5 +166,20 @@ namespace OpenVulkano
operator RT() const { return renderResource; } operator RT() const { return renderResource; }
bool HasRenderResource() const { return renderResource; } bool HasRenderResource() const { return renderResource; }
RenderResourceHolder& operator =(RenderResourceHolder&& move) noexcept
{
renderResource = std::move(move.renderResource);
if (IRenderResource<T>* renderRes = renderResource)
renderRes->UpdateAddress(static_cast<T*>(this));
return *this;
}
void Swap(RenderResourceHolder& other) noexcept
{
RenderResourceHolder tmp(std::move(*this));
*this = std::move(other);
other = std::move(tmp);
}
}; };
} }

View File

@@ -20,20 +20,17 @@
namespace OpenVulkano::Scene namespace OpenVulkano::Scene
{ {
Geometry::Geometry(const Geometry& other) Geometry::Geometry(const Geometry& other)
: vertexCount(other.vertexCount), indexCount(other.indexCount)
, vertices(other.vertices ? new Vertex[other.vertexCount] : nullptr)
, indices(other.indices ? malloc(static_cast<size_t>(Utils::EnumAsInt(other.indexType)) * other.indexCount) : nullptr)
, indexType(other.indexType)
, ownsMemory(other.ownsMemory), freeAfterUpload(other.freeAfterUpload)
, aabb(other.aabb)
{ {
this->vertexCount = other.vertexCount;
this->indexCount = other.indexCount;
this->indexType = other.indexType;
this->aabb = other.aabb;
this->ownsMemory = other.ownsMemory;
this->freeAfterUpload = other.freeAfterUpload;
this->renderGeo = nullptr;
this->vertices = new Vertex[vertexCount];
if (other.vertices) if (other.vertices)
{ {
std::copy(other.vertices, other.vertices + other.vertexCount, this->vertices); std::copy(other.vertices, other.vertices + other.vertexCount, this->vertices);
} }
this->indices = malloc(static_cast<size_t>(Utils::EnumAsInt(other.indexType)) * other.indexCount);
if (other.indices) if (other.indices)
{ {
if (other.indexType == VertexIndexType::UINT16) if (other.indexType == VertexIndexType::UINT16)
@@ -59,20 +56,13 @@ namespace OpenVulkano::Scene
} }
Geometry::Geometry(Geometry&& other) noexcept Geometry::Geometry(Geometry&& other) noexcept
: RenderResourceHolder<Geometry>(std::move(other)), vertexCount(other.vertexCount), indexCount(other.indexCount)
, vertices(other.vertices), indices(other.indices), indexType(other.indexType)
, ownsMemory(other.ownsMemory), freeAfterUpload(other.freeAfterUpload), aabb(other.aabb)
{ {
this->vertexCount = other.vertexCount;
this->indexCount = other.indexCount;
this->indexType = other.indexType;
this->ownsMemory = other.ownsMemory;
this->freeAfterUpload = other.freeAfterUpload;
this->aabb = std::move(other.aabb);
this->vertices = other.vertices;
this->indices = other.indices;
this->renderGeo = other.renderGeo;
other.vertexCount = other.indexCount = 0; other.vertexCount = other.indexCount = 0;
other.vertices = nullptr; other.vertices = nullptr;
other.indices = nullptr; other.indices = nullptr;
other.renderGeo = nullptr;
} }
Geometry& Geometry::operator=(Geometry&& other) noexcept Geometry& Geometry::operator=(Geometry&& other) noexcept
@@ -88,11 +78,10 @@ namespace OpenVulkano::Scene
this->aabb = std::move(other.aabb); this->aabb = std::move(other.aabb);
this->vertices = other.vertices; this->vertices = other.vertices;
this->indices = other.indices; this->indices = other.indices;
this->renderGeo = other.renderGeo; RenderResourceHolder<Geometry>::operator=(std::move(other));
other.vertexCount = other.indexCount = 0; other.vertexCount = other.indexCount = 0;
other.vertices = nullptr; other.vertices = nullptr;
other.indices = nullptr; other.indices = nullptr;
other.renderGeo = nullptr;
} }
return *this; return *this;
} }
@@ -104,26 +93,25 @@ namespace OpenVulkano::Scene
void Geometry::Swap(Geometry& other) noexcept void Geometry::Swap(Geometry& other) noexcept
{ {
RenderResourceHolder<Geometry>::Swap(other);
std::swap(this->vertexCount, other.vertexCount); std::swap(this->vertexCount, other.vertexCount);
std::swap(this->indexCount, other.indexCount); std::swap(this->indexCount, other.indexCount);
std::swap(this->aabb, other.aabb); std::swap(this->aabb, other.aabb);
std::swap(this->indexType, other.indexType); std::swap(this->indexType, other.indexType);
std::swap(this->vertices, other.vertices); std::swap(this->vertices, other.vertices);
std::swap(this->indices, other.indices); std::swap(this->indices, other.indices);
std::swap(this->renderGeo, other.renderGeo);
std::swap(this->ownsMemory, other.ownsMemory); std::swap(this->ownsMemory, other.ownsMemory);
std::swap(this->freeAfterUpload, other.freeAfterUpload); std::swap(this->freeAfterUpload, other.freeAfterUpload);
} }
void Geometry::Init(uint32_t vertexCount, uint32_t indexCount) void Geometry::Init(uint32_t vertexCount, uint32_t indexCount)
{ {
if (this->vertexCount || this->indexCount) throw std::runtime_error("Geometry is already initialized."); if (HasRenderResource() || this->vertexCount || this->indexCount) throw std::runtime_error("Geometry is already initialized.");
this->vertexCount = vertexCount; this->vertexCount = vertexCount;
this->indexCount = indexCount; this->indexCount = indexCount;
indexType = (vertexCount > UINT16_MAX) ? VertexIndexType::UINT32 : VertexIndexType::UINT16; indexType = (vertexCount > UINT16_MAX) ? VertexIndexType::UINT32 : VertexIndexType::UINT16;
vertices = new Vertex[vertexCount]; vertices = new Vertex[vertexCount];
indices = malloc(static_cast<size_t>(Utils::EnumAsInt(indexType)) * indexCount); indices = malloc(static_cast<size_t>(Utils::EnumAsInt(indexType)) * indexCount);
renderGeo = nullptr;
} }
void Geometry::InitFromFile(const std::string& file) void Geometry::InitFromFile(const std::string& file)
@@ -212,10 +200,9 @@ namespace OpenVulkano::Scene
indexCount = 0; indexCount = 0;
Free(); Free();
} }
if (renderGeo) if (HasRenderResource())
{ {
renderGeo->Close(); GetRenderResource().Release();
renderGeo = nullptr;
} }
} }

View File

@@ -7,6 +7,7 @@
#pragma once #pragma once
#include "Base/ICloseable.hpp" #include "Base/ICloseable.hpp"
#include "Base/Render/RenderResource.hpp"
#include "Math/AABB.hpp" #include "Math/AABB.hpp"
#include "Base/Utils.hpp" #include "Base/Utils.hpp"
#include <string> #include <string>
@@ -24,7 +25,7 @@ namespace OpenVulkano
UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t) UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t)
}; };
class Geometry : public ICloseable class Geometry : public RenderResourceHolder<Geometry>, public ICloseable
{ {
public: public:
uint32_t vertexCount = 0, indexCount = 0; uint32_t vertexCount = 0, indexCount = 0;
@@ -33,7 +34,6 @@ namespace OpenVulkano
VertexIndexType indexType = VertexIndexType::UINT16; VertexIndexType indexType = VertexIndexType::UINT16;
bool ownsMemory = true, freeAfterUpload = true; bool ownsMemory = true, freeAfterUpload = true;
Math::AABB aabb; Math::AABB aabb;
ICloseable* renderGeo = nullptr;
public: public:
Geometry() = default; Geometry() = default;
Geometry(const Geometry& other); Geometry(const Geometry& other);

View File

@@ -153,7 +153,7 @@ namespace OpenVulkano::Vulkan
VulkanGeometry* ResourceManager::PrepareGeometry(Scene::Geometry* geometry) VulkanGeometry* ResourceManager::PrepareGeometry(Scene::Geometry* geometry)
{ {
const std::unique_lock lock(mutex); const std::unique_lock lock(mutex);
if(!geometry->renderGeo) if(!geometry->HasRenderResource())
{ {
ManagedBuffer::Ptr vertexBuffer = ManagedBuffer::Ptr vertexBuffer =
CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices()); CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices());
@@ -162,14 +162,13 @@ namespace OpenVulkano::Vulkan
indexBuffer = CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices()); indexBuffer = CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices());
VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer); VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer);
geometries.emplace_back(vkGeo); geometries.emplace_back(vkGeo);
geometry->renderGeo = vkGeo;
if (geometry->ownsMemory && geometry->freeAfterUpload) if (geometry->ownsMemory && geometry->freeAfterUpload)
{ {
geometry->Free(); geometry->Free();
} }
return vkGeo; return vkGeo;
} }
return dynamic_cast<VulkanGeometry*>(geometry->renderGeo); return geometry->GetRenderResource();
} }
void ResourceManager::PrepareMaterial(Scene::Material* material) void ResourceManager::PrepareMaterial(Scene::Material* material)

View File

@@ -20,13 +20,12 @@ namespace OpenVulkano::Vulkan
{ {
SimpleDrawable* drawable = static_cast<SimpleDrawable*>(instance); SimpleDrawable* drawable = static_cast<SimpleDrawable*>(instance);
Geometry* mesh = drawable->GetMesh(); Geometry* mesh = drawable->GetMesh();
VulkanGeometry* renderGeo = static_cast<VulkanGeometry*>(mesh->renderGeo); VulkanGeometry* renderGeo = mesh->GetRenderResource();
if (!renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh); if (!renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh);
renderGeo->RecordBind(drawContext->commandBuffer); renderGeo->RecordBind(drawContext->commandBuffer);
if (drawable->GetBuffer()) if (drawable->GetBuffer())
{ {
VulkanUniformBuffer* vkBuffer = drawable->GetBuffer()->GetRenderResource(); VulkanUniformBuffer* vkBuffer = drawable->GetBuffer()->GetRenderResource();
if (!vkBuffer) if (!vkBuffer)
{ {

View File

@@ -13,36 +13,21 @@
namespace OpenVulkano::Vulkan namespace OpenVulkano::Vulkan
{ {
class VulkanGeometry final : public ICloseable class VulkanGeometry final : public IRenderResource<Scene::Geometry>
{ {
Scene::Geometry* m_geometry;
ManagedBuffer::Ptr m_vertexBuffer; ManagedBuffer::Ptr m_vertexBuffer;
ManagedBuffer::Ptr m_indexBuffer; ManagedBuffer::Ptr m_indexBuffer;
vk::IndexType m_indexType; vk::IndexType m_indexType;
vk::DeviceSize m_offsets = 0; vk::DeviceSize m_offsets = 0;
public: public:
VulkanGeometry() : m_geometry(nullptr), m_vertexBuffer(nullptr)
, m_indexBuffer(nullptr), m_indexType(vk::IndexType::eUint32)
{}
VulkanGeometry(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer) VulkanGeometry(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer)
: m_geometry(geo), m_vertexBuffer(std::move(vertexBuffer)), m_indexBuffer(std::move(indexBuffer)) : IRenderResource<Scene::Geometry>(geo)
, m_vertexBuffer(std::move(vertexBuffer)), m_indexBuffer(std::move(indexBuffer))
, m_indexType((geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32) , m_indexType((geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32)
{} {}
~VulkanGeometry() override ~VulkanGeometry() override = default;
{
if (m_vertexBuffer) VulkanGeometry::Close();
}
void Init(Scene::Geometry* geo, ManagedBuffer::Ptr& vertexBuffer, ManagedBuffer::Ptr& indexBuffer)
{
m_geometry = geo;
m_vertexBuffer = std::move(vertexBuffer);
m_indexBuffer = std::move(indexBuffer);
m_indexType = (geo->indexType == Scene::VertexIndexType::UINT16) ? vk::IndexType::eUint16 : vk::IndexType::eUint32;
}
void RecordBind(vk::CommandBuffer& cmdBuffer) void RecordBind(vk::CommandBuffer& cmdBuffer)
{ {
@@ -52,15 +37,13 @@ namespace OpenVulkano::Vulkan
void RecordDraw(vk::CommandBuffer& cmdBuffer) void RecordDraw(vk::CommandBuffer& cmdBuffer)
{ {
if (m_geometry->GetIndexCount()) { cmdBuffer.drawIndexed(m_geometry->GetIndexCount(), 1, 0, 0, 0); } if (GetOwner()->GetIndexCount()) { cmdBuffer.drawIndexed(GetOwner()->GetIndexCount(), 1, 0, 0, 0); }
else { cmdBuffer.draw(m_geometry->GetVertexCount(), 1, 0, 0); } else { cmdBuffer.draw(GetOwner()->GetVertexCount(), 1, 0, 0); }
} }
void Close() override void Release() override
{ {
m_geometry->renderGeo = nullptr; //TODO
m_vertexBuffer.reset();
m_indexBuffer.reset();
} }
}; };
} }