Merge branch 'wip'

This commit is contained in:
2024-09-12 22:17:37 +02:00
24 changed files with 346 additions and 244 deletions

View File

@@ -0,0 +1,185 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <concepts>
#include <utility>
#include <type_traits>
namespace OpenVulkano
{
namespace Vulkan
{
class MetalBackedTexture;
}
class RenderResourcePtr;
class IRenderResourceHelper
{
friend class RenderResourcePtr;
protected:
void UpdateRenderResource(RenderResourcePtr* resource);
void ResetRenderResource(RenderResourcePtr* resource);
virtual void DoRelease() = 0;
virtual void Release() = 0;
};
template <class T>
concept Renderable = std::is_convertible_v<T, RenderResourcePtr&>;
class RenderResourcePtr final
{
friend class IRenderResourceHelper;
friend class Vulkan::MetalBackedTexture;
IRenderResourceHelper* renderObject = nullptr;
public:
RenderResourcePtr() = default;
RenderResourcePtr(const RenderResourcePtr& ignored) noexcept { /* Do not copy, copy will be created by renderer */ }
RenderResourcePtr(RenderResourcePtr&& move) noexcept : renderObject(move.renderObject) { move.renderObject = nullptr; }
~RenderResourcePtr()
{
Release();
}
void Release()
{
if (!renderObject) return;
renderObject->DoRelease();
renderObject = nullptr;
}
template<class T>
T* As() { return static_cast<T*>(renderObject); }
template<class T>
operator T() { return static_cast<T>(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)
{
if (resource)
resource->renderObject = this;
}
inline void IRenderResourceHelper::ResetRenderResource(RenderResourcePtr* resource)
{
if (resource)
resource->renderObject = nullptr;
}
template<Renderable API_INDEPENDENT_CLASS>
class IRenderResource : public IRenderResourceHelper
{
API_INDEPENDENT_CLASS* m_owner;
protected:
IRenderResource(API_INDEPENDENT_CLASS* owner) : m_owner(owner)
{
if (m_owner) UpdateRenderResource(GetOwnerResource());
}
IRenderResource(const IRenderResource<API_INDEPENDENT_CLASS>& copy) = delete;
IRenderResource(IRenderResource<API_INDEPENDENT_CLASS>&& move) noexcept
: m_owner(move.m_owner)
{
if (m_owner)
{
UpdateRenderResource(GetOwnerResource());
}
move.m_owner = nullptr;
}
RenderResourcePtr* GetOwnerResource() { if (!m_owner) return nullptr; else return &static_cast<RenderResourcePtr&>(*m_owner); }
void DoRelease() final override
{
m_owner = nullptr;
Release();
}
public:
virtual ~IRenderResource()
{
if (m_owner) ResetRenderResource(GetOwnerResource());
}
void UpdateAddress(API_INDEPENDENT_CLASS* owner)
{
m_owner = owner;
}
operator API_INDEPENDENT_CLASS*() const { return m_owner; }
API_INDEPENDENT_CLASS* GetOwner() const { return m_owner; }
};
/**
* This is a convenience class to create a Renderable class.
* You can also just create a RenderResource instance a conversion operator inside your own class to make it Renderable; and you probably want to delete your move constructor in that case.
*/
template <class T>
class RenderResourceHolder
{
RenderResourcePtr renderResource;
protected:
RenderResourceHolder() = default;
RenderResourceHolder(const RenderResourceHolder& ignored) noexcept {}
RenderResourceHolder(RenderResourceHolder&& move) noexcept
: renderResource(std::move(move.renderResource))
{
if (IRenderResource<T>* renderRes = renderResource)
renderRes->UpdateAddress(static_cast<T*>(this));
}
~RenderResourceHolder() = default;
public:
operator RenderResourcePtr&() { return renderResource; }
RenderResourcePtr& GetRenderResource() const { return const_cast<RenderResourceHolder*>(this)->renderResource; }
template<Renderable RT>
operator RT() 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

@@ -13,10 +13,9 @@
namespace OpenVulkano::Scene
{
class Camera : public Node
class Camera : public RenderResourceHolder<Camera>, public Node
{
public:
ICloseable* renderCamera = nullptr;
static constexpr inline size_t SIZE = sizeof(Math::Matrix4f) * 3 + sizeof(Math::Vector4f) + sizeof(float) * 12;
static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER_DYNAMIC, 1, ShaderProgramType::ALL_GRAPHICS };
@@ -36,10 +35,7 @@ namespace OpenVulkano::Scene
{
}
~Camera() override
{
//if (renderCamera) renderCamera->Close();
}
~Camera() override = default;
void Init(float width, float height, float nearPlane, float farPlane)
{
@@ -152,6 +148,10 @@ namespace OpenVulkano::Scene
float GetWidth() const { return m_width; }
float GetHeight() const { return m_height; }
Math::Vector2f GetSize() const { return { m_width, m_height }; }
using RenderResourceHolder<Camera>::GetRenderResource;
using RenderResourceHolder<Camera>::HasRenderResource;
using RenderResourceHolder<Camera>::operator RenderResourcePtr&;
};
class PerspectiveCamera : public Camera

View File

@@ -11,21 +11,18 @@
namespace OpenVulkano::Scene
{
Geometry::Geometry(const Geometry& other)
{
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];
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)
{
if (other.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.indexType == VertexIndexType::UINT16)
@@ -50,21 +47,14 @@ namespace OpenVulkano::Scene
return *this;
}
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.vertices = nullptr;
other.indices = nullptr;
other.renderGeo = nullptr;
}
Geometry& Geometry::operator=(Geometry&& other) noexcept
@@ -80,11 +70,10 @@ namespace OpenVulkano::Scene
this->aabb = std::move(other.aabb);
this->vertices = other.vertices;
this->indices = other.indices;
this->renderGeo = other.renderGeo;
RenderResourceHolder<Geometry>::operator=(std::move(other));
other.vertexCount = other.indexCount = 0;
other.vertices = nullptr;
other.indices = nullptr;
other.renderGeo = nullptr;
}
return *this;
}
@@ -95,27 +84,26 @@ namespace OpenVulkano::Scene
}
void Geometry::Swap(Geometry& other) noexcept
{
{
RenderResourceHolder<Geometry>::Swap(other);
std::swap(this->vertexCount, other.vertexCount);
std::swap(this->indexCount, other.indexCount);
std::swap(this->aabb, other.aabb);
std::swap(this->indexType, other.indexType);
std::swap(this->vertices, other.vertices);
std::swap(this->indices, other.indices);
std::swap(this->renderGeo, other.renderGeo);
std::swap(this->ownsMemory, other.ownsMemory);
std::swap(this->freeAfterUpload, other.freeAfterUpload);
}
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->indexCount = indexCount;
indexType = (vertexCount > UINT16_MAX) ? VertexIndexType::UINT32 : VertexIndexType::UINT16;
vertices = new Vertex[vertexCount];
indices = malloc(static_cast<size_t>(Utils::EnumAsInt(indexType)) * indexCount);
renderGeo = nullptr;
}
void Geometry::SetIndices(const uint32_t* data, uint32_t size, uint32_t dstOffset) const
@@ -140,10 +128,9 @@ namespace OpenVulkano::Scene
indexCount = 0;
Free();
}
if (renderGeo)
if (HasRenderResource())
{
renderGeo->Close();
renderGeo = nullptr;
GetRenderResource().Release();
}
}

View File

@@ -7,6 +7,7 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Base/Render/RenderResource.hpp"
#include "Math/AABB.hpp"
#include "Base/Utils.hpp"
#include "Vertex.hpp"
@@ -21,7 +22,7 @@ namespace OpenVulkano
UINT16 = sizeof(uint16_t), UINT32 = sizeof(uint32_t)
};
class Geometry : public ICloseable
class Geometry : public RenderResourceHolder<Geometry>, public ICloseable
{
friend class MeshLoader;
public:
@@ -31,7 +32,6 @@ namespace OpenVulkano
VertexIndexType indexType = VertexIndexType::UINT16;
bool ownsMemory = true, freeAfterUpload = true;
Math::AABB aabb;
ICloseable* renderGeo = nullptr;
public:
Geometry() = default;
Geometry(const Geometry& other);

View File

@@ -37,7 +37,7 @@ namespace OpenVulkano::Scene
void Node::Close()
{
children.clear();
if (renderNode) renderNode->Close();
GetRenderResource().Release();
parent = nullptr;
scene = nullptr;
enabled = false;

View File

@@ -7,6 +7,7 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Base/Render/RenderResource.hpp"
#include "Math/Math.hpp"
#include "Math/Pose.hpp"
#include "Drawable.hpp"
@@ -19,7 +20,7 @@ namespace OpenVulkano::Scene
{
class Scene;
class Node : public ICloseable
class Node : public RenderResourceHolder<Node>, public ICloseable
{
friend Scene;
@@ -33,7 +34,6 @@ namespace OpenVulkano::Scene
std::vector<Node*> children;
std::vector<Drawable*> drawables;
UpdateFrequency matrixUpdateFrequency = UpdateFrequency::Never;
ICloseable* renderNode = nullptr;
bool enabled = true;
public:

View File

@@ -8,6 +8,7 @@
#include "Base/ICloseable.hpp"
#include "Base/Utils.hpp"
#include "Base/Render/RenderResource.hpp"
#include "VertexInputDescription.hpp"
#include "ShaderProgramType.hpp"
#include "DescriptorInputDescription.hpp"
@@ -81,7 +82,7 @@ namespace OpenVulkano::Scene
class Shader final : public ICloseable
class Shader final : public RenderResourceHolder<Shader>, public ICloseable
{
public:
std::vector<ShaderProgram> shaderPrograms{};
@@ -90,7 +91,6 @@ namespace OpenVulkano::Scene
std::vector<PushConstantRange> pushConstantRanges;
Topology topology = Topology::TRIANGLE_LIST;
CullMode cullMode = CullMode::BACK;
ICloseable* renderShader = nullptr;
CompareOp depthCompareOp = CompareOp::LESS;
bool alphaBlend = false; // TODO allow fine control over blending
bool depthTest = true;
@@ -98,7 +98,7 @@ namespace OpenVulkano::Scene
bool dynamicViewport = true; // If disabled the swapchains fullscreen viewport will always be used, regardless of framebuffer or viewport
Shader() = default;
~Shader() override { if (renderShader) Shader::Close(); }
~Shader() override { Shader::Close(); }
Shader& AddShaderProgram(const ShaderProgram& shaderProgram)
{
@@ -165,14 +165,14 @@ namespace OpenVulkano::Scene
void Close() override
{
renderShader->Close();
renderShader = nullptr;
if (HasRenderResource())
GetRenderResource().Release();
}
private:
void CheckShaderInitState() const
{
if (renderShader) throw std::runtime_error("Shader already initialized!");
if (HasRenderResource()) throw std::runtime_error("Shader already initialized!");
}
};
}

View File

@@ -8,27 +8,19 @@
#include "UpdateFrequency.hpp"
#include "SamplerConfig.hpp"
#include "Base/ICloseable.hpp"
#include "Base/Render/RenderResource.hpp"
#include "Math/Math.hpp"
#include "DataFormat.hpp"
#include "Scene/Shader/DescriptorInputDescription.hpp"
namespace OpenVulkano::Scene
{
class Texture;
struct RenderTexture
{
Texture* m_texture = nullptr;
};
class Texture
class Texture : public RenderResourceHolder<Texture>
{
public:
static Texture PLACEHOLDER;
static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_COMBINED_IMAGE_SAMPLER, 1, ShaderProgramType::ALL_GRAPHICS };
RenderTexture* renderTexture = nullptr;
void* textureBuffer = nullptr;
size_t size = 0;
Math::Vector3ui resolution = {0,0,0};
@@ -41,13 +33,7 @@ namespace OpenVulkano::Scene
: m_samplerConfig(samplerConfig)
{ if (placeholder) MakePlaceholder(); }
~Texture()
{
if (renderTexture)
{
renderTexture->m_texture = nullptr;
}
}
~Texture() = default;
void MakePlaceholder(uint32_t width = 32, uint32_t height = 32,
Math::Vector4uc color1 = {248, 123, 255, 255}, Math::Vector4uc color2 = {250, 19, 255, 255});

View File

@@ -6,20 +6,19 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Base/Render/RenderResource.hpp"
#include "Scene/Shader/DescriptorInputDescription.hpp"
#include "Scene/UpdateFrequency.hpp"
namespace OpenVulkano::Scene
{
class UniformBuffer
class UniformBuffer : public RenderResourceHolder<UniformBuffer>
{
public:
static constexpr inline DescriptorSetLayoutBinding DESCRIPTOR_SET_LAYOUT_BINDING = { 0, DescriptorSetLayoutBinding::Type::TYPE_UNIFORM_BUFFER, 1, ShaderProgramType::ALL_GRAPHICS };
DescriptorSetLayoutBinding binding;
uint32_t setId;
ICloseable* renderBuffer = nullptr;
size_t size = 0;
const void* data = nullptr;
UpdateFrequency updateFrequency = UpdateFrequency::Never;

View File

@@ -19,7 +19,6 @@ namespace OpenVulkano::Vulkan
resolution = { static_cast<uint32_t>(mtlTexture.width), static_cast<uint32_t>(mtlTexture.height), static_cast<uint32_t>(mtlTexture.depth) };
format = DataFormat::GetFromMetalPixelFormat(static_cast<int>(mtlTexture.pixelFormat));
m_vulkanTexture.m_texture = this;
m_vulkanTexture.device = resManager->GetDevice();
m_vulkanTexture.format = format;
m_vulkanTexture.extent = reinterpret_cast<vk::Extent3D&>(resolution);
@@ -57,7 +56,8 @@ namespace OpenVulkano::Vulkan
m_vulkanTexture.m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(Scene::SamplerConfig::DEFAULT));
m_vulkanTexture.SetDescriptorSet(resManager, resManager->GetDescriptorLayoutSet(binding), binding);
renderTexture = &m_vulkanTexture;
GetRenderResource().renderObject = &m_vulkanTexture;
m_vulkanTexture.UpdateAddress(this);
if (!ownsTexture) m_metalTexture = nullptr;
}

View File

@@ -33,7 +33,7 @@ namespace OpenVulkano::Vulkan
~ManagedBuffer()
{
allocation->device.destroy(buffer);
if (allocation) [[likely]] allocation->device.destroy(buffer);
}
[[nodiscard]] bool IsLast() const

View File

@@ -23,6 +23,8 @@ namespace OpenVulkano::Vulkan
{
if (memPool->FreeBuffer(buffer)) return;
}
Logger::RENDER->error("Attempted to released buffer to pool, but owning pool no longer exists!");
buffer->allocation = nullptr; // Allocation is no longer valid since owning pool is gone already
delete buffer;
}

View File

@@ -98,6 +98,7 @@ namespace OpenVulkano::Vulkan
{
transferQueue.waitIdle();
transferQueue = nullptr;
OnShutdown(this); // Notify all custom resources that it's time to die
geometries.clear();
nodes.clear();
textures.clear();
@@ -153,7 +154,7 @@ namespace OpenVulkano::Vulkan
VulkanGeometry* ResourceManager::PrepareGeometry(Scene::Geometry* geometry)
{
const std::unique_lock lock(mutex);
if(!geometry->renderGeo)
if(!geometry->HasRenderResource())
{
ManagedBuffer::Ptr vertexBuffer =
CreateDeviceOnlyBufferWithData(sizeof(Vertex) * geometry->GetVertexCount(), vk::BufferUsageFlagBits::eVertexBuffer, geometry->GetVertices());
@@ -162,19 +163,18 @@ namespace OpenVulkano::Vulkan
indexBuffer = CreateDeviceOnlyBufferWithData(Utils::EnumAsInt(geometry->indexType) * geometry->GetIndexCount(), vk::BufferUsageFlagBits::eIndexBuffer, geometry->GetIndices());
VulkanGeometry* vkGeo = new VulkanGeometry(geometry, vertexBuffer, indexBuffer);
geometries.emplace_back(vkGeo);
geometry->renderGeo = vkGeo;
if (geometry->ownsMemory && geometry->freeAfterUpload)
{
geometry->Free();
}
return vkGeo;
}
return dynamic_cast<VulkanGeometry*>(geometry->renderGeo);
return geometry->GetRenderResource();
}
void ResourceManager::PrepareMaterial(Scene::Material* material)
{
if (material->texture && !material->texture->renderTexture)
if (material->texture && !material->texture->HasRenderResource())
{
PrepareTexture(material->texture);
}
@@ -183,7 +183,7 @@ namespace OpenVulkano::Vulkan
VulkanNode* ResourceManager::PrepareNode(Scene::Node* node)
{
const std::unique_lock lock(mutex);
if (!node->renderNode)
if (!node->HasRenderResource())
{
UniformBuffer* uBuffer = new UniformBuffer();
ManagedBuffer::Ptr buffer;
@@ -193,29 +193,28 @@ namespace OpenVulkano::Vulkan
if (node->GetUpdateFrequency() != Scene::UpdateFrequency::Never)
{
frameSize = allocSize;
vkNode = new VulkanNodeDynamic();
vkNode = new VulkanNodeDynamic(node, uBuffer);
const uint32_t imgs = context->swapChain.GetImageCount();
buffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
buffer->Map();
}
else
{
vkNode = new VulkanNode();
buffer = CreateDeviceOnlyBufferWithData(Scene::Node::SIZE, vk::BufferUsageFlagBits::eUniformBuffer, &node->worldMat);
vkNode = new VulkanNode(node, uBuffer);
}
uBuffer->Init(std::move(buffer), frameSize, allocSize, GetDescriptorLayoutSet(Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Node::DESCRIPTOR_SET_LAYOUT_BINDING, 0);
vkNode->Init(node, uBuffer);
node->renderNode = vkNode;
nodes.emplace_back(vkNode);
return vkNode;
}
return static_cast<VulkanNode*>(node->renderNode);
return node->GetRenderResource();
}
VulkanCamera* ResourceManager::PrepareCamera(Scene::Camera* camera)
{
const std::unique_lock lock(mutex);
if (!camera->renderCamera)
if (!camera->HasRenderResource())
{
const vk::DeviceSize allocSize = Utils::Align(Scene::Camera::SIZE, uniformBufferAlignment);
const uint32_t imgs = context->swapChain.GetImageCount();
@@ -223,12 +222,10 @@ namespace OpenVulkano::Vulkan
buffer->Map();
UniformBuffer* uBuffer = new UniformBuffer();
uBuffer->Init(std::move(buffer), allocSize, allocSize, GetDescriptorLayoutSet(Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING), Scene::Camera::DESCRIPTOR_SET_LAYOUT_BINDING, 1);
VulkanCamera* vkCam = new VulkanCamera();
vkCam->Init(camera, uBuffer);
VulkanCamera* vkCam = new VulkanCamera(camera, uBuffer);
cameras.emplace_back(vkCam);
camera->renderCamera = vkCam;
}
return static_cast<VulkanCamera*>(camera->renderCamera);
return static_cast<VulkanCamera*>(camera->GetRenderResource());
}
UniformBuffer* ResourceManager::CreateUniformBuffer(const DescriptorSetLayoutBinding& binding, size_t size, void* data, uint32_t setId, bool hostVis)
@@ -278,6 +275,7 @@ namespace OpenVulkano::Vulkan
find_if(shaders.begin(), shaders.end(),
[&](auto& obj){ return obj.get() == shader; }
);
object->get()->owner = nullptr;
shaders.erase(object);
}
@@ -309,9 +307,8 @@ namespace OpenVulkano::Vulkan
VulkanShader* ResourceManager::CreateShader(Scene::Shader* shader)
{
const std::unique_lock lock(mutex);
if (shader->renderShader) return static_cast<VulkanShader*>(shader->renderShader);
VulkanShader* vkShader = new VulkanShader();
vkShader->Init(context, shader, this);
if (shader->HasRenderResource()) return static_cast<VulkanShader*>(shader->GetRenderResource());
VulkanShader* vkShader = new VulkanShader(context, shader, this);
shaders.emplace_back(vkShader);
return vkShader;
}
@@ -319,7 +316,7 @@ namespace OpenVulkano::Vulkan
VulkanTexture* ResourceManager::PrepareTexture(Scene::Texture* texture)
{
const std::unique_lock lock(mutex);
if (texture->renderTexture) return static_cast<VulkanTexture*>(texture->renderTexture);
if (texture->HasRenderResource()) return static_cast<VulkanTexture*>(texture->GetRenderResource());
VulkanTexture* vkTexture;
if (texture->updateFrequency == Scene::UpdateFrequency::Never)
vkTexture = new VulkanTexture();
@@ -336,31 +333,29 @@ namespace OpenVulkano::Vulkan
VulkanUniformBuffer* ResourceManager::PrepareUniformBuffer(Scene::UniformBuffer* buffer)
{
const std::unique_lock lock(mutex);
if (buffer->renderBuffer) return static_cast<VulkanUniformBuffer*>(buffer->renderBuffer);
if (buffer->HasRenderResource()) return static_cast<VulkanUniformBuffer*>(buffer->GetRenderResource());
VulkanUniformBuffer* vkBuffer;
ManagedBuffer::Ptr mBuffer;
const vk::DeviceSize allocSize = Utils::Align(buffer->size, uniformBufferAlignment);
UniformBuffer* uBuffer = new UniformBuffer();
if (buffer->GetUpdateFrequency() != Scene::UpdateFrequency::Never)
{
vkBuffer = new VulkanUniformBufferDynamic();
const uint32_t imgs = context->swapChain.GetImageCount();
mBuffer = memPool.CreateBuffer(imgs * allocSize, vk::BufferUsageFlagBits::eUniformBuffer, vk::MemoryPropertyFlagBits::eHostCoherent | vk::MemoryPropertyFlagBits::eHostVisible);
mBuffer->Map();
vkBuffer = new VulkanUniformBufferDynamic(buffer, uBuffer);
}
else
{
vkBuffer = new VulkanUniformBuffer();
mBuffer = CreateDeviceOnlyBufferWithData(buffer->size, vk::BufferUsageFlagBits::eUniformBuffer, buffer->data);
buffer->updated = false;
vkBuffer = new VulkanUniformBuffer(buffer, uBuffer);
}
UniformBuffer* uBuffer = new UniformBuffer();
const uint64_t s = mBuffer->size;
uBuffer->Init(std::move(mBuffer), 0, s, GetDescriptorLayoutSet(buffer->binding), buffer->binding, buffer->setId);
vkBuffer->Init(buffer, uBuffer);
uniforms.emplace_back(vkBuffer);
return vkBuffer;
}

View File

@@ -14,6 +14,7 @@
#include "IShaderOwner.hpp"
#include "MemoryPool.hpp"
#include "Base/Wrapper.hpp"
#include "Base/Event.hpp"
#include "Base/Render/IResourceManager.hpp"
#include "Vulkan/Image.hpp"
#include "Scene/Shader/DescriptorInputDescription.hpp"
@@ -134,6 +135,8 @@ namespace OpenVulkano
vk::DescriptorSetLayout* GetDescriptorLayoutSet(const DescriptorSetLayoutBinding& descriptorSetLayoutBinding);
VulkanShader* CreateShader(Scene::Shader* shader);
Event<ResourceManager*> OnShutdown;
};
}
}

View File

@@ -19,12 +19,12 @@ namespace OpenVulkano::Vulkan
ArBackgroundDrawable* bgDrawable = static_cast<ArBackgroundDrawable*>(instance);
bgDrawable->Tick();
const Texture* texture = bgDrawable->GetTexture();
VulkanTexture* vkTexture = static_cast<VulkanTexture*>(texture->renderTexture);
VulkanTexture* vkTexture = texture->GetRenderResource();
if (!vkTexture)
{
vkTexture = drawContext->renderer->GetResourceManager().PrepareTexture(const_cast<Texture*>(texture));
}
VulkanUniformBuffer* vkBuffer = static_cast<VulkanUniformBuffer*>(bgDrawable->GetBuffer().renderBuffer);
VulkanUniformBuffer* vkBuffer = bgDrawable->GetBuffer().GetRenderResource();
if (!vkBuffer)
{
vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(&bgDrawable->GetBuffer());

View File

@@ -6,7 +6,6 @@
#include "Scene/SimpleDrawable.hpp"
#include "Scene/Material.hpp"
#include "Scene/UniformBuffer.hpp"
#include "VulkanGeometry.hpp"
#include "VulkanNode.hpp"
#include "Vulkan/VulkanDrawContext.hpp"
@@ -21,14 +20,13 @@ namespace OpenVulkano::Vulkan
{
SimpleDrawable* drawable = static_cast<SimpleDrawable*>(instance);
Geometry* mesh = drawable->GetMesh();
VulkanGeometry* renderGeo = static_cast<VulkanGeometry*>(mesh->renderGeo);
VulkanGeometry* renderGeo = mesh->GetRenderResource();
if (!renderGeo) renderGeo = drawContext->renderer->GetResourceManager().PrepareGeometry(mesh);
renderGeo->RecordBind(drawContext->commandBuffer);
if (drawable->GetBuffer())
{
VulkanUniformBuffer* vkBuffer = static_cast<VulkanUniformBuffer*>(drawable->GetBuffer()->renderBuffer);
VulkanUniformBuffer* vkBuffer = drawable->GetBuffer()->GetRenderResource();
if (!vkBuffer)
{
vkBuffer = drawContext->renderer->GetResourceManager().PrepareUniformBuffer(drawable->GetBuffer());
@@ -40,11 +38,11 @@ namespace OpenVulkano::Vulkan
{
if (Texture* texture = material->texture)
{
VulkanTexture* renderTexture = static_cast<VulkanTexture*>(texture->renderTexture);
VulkanTexture* renderTexture = texture->GetRenderResource();
if (!renderTexture)
{
drawContext->renderer->GetResourceManager().PrepareMaterial(drawable->GetMaterial());
renderTexture = static_cast<VulkanTexture*>(texture->renderTexture);
renderTexture = texture->GetRenderResource();
}
renderTexture->Record(drawContext);
}

View File

@@ -6,41 +6,34 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Scene/Camera.hpp"
#include "IRecordable.hpp"
#include "Vulkan/Resources/UniformBuffer.hpp"
namespace OpenVulkano::Vulkan
{
class VulkanCamera : public ICloseable, public IRecordable
class VulkanCamera : public IRenderResource<Scene::Camera>, public IRecordable
{
Scene::Camera* m_camera = nullptr;
UniformBuffer* m_buffer = nullptr;
const Unique<UniformBuffer> m_buffer;
public:
~VulkanCamera() override { if (m_camera) VulkanCamera::Close(); }
VulkanCamera(Scene::Camera* camera, UniformBuffer* uniformBuffer)
: IRenderResource<Scene::Camera>(camera), m_buffer(uniformBuffer)
{}
void Init(Scene::Camera* camera, UniformBuffer* uniformBuffer)
{
m_camera = camera;
m_buffer = uniformBuffer;
}
~VulkanCamera() override = default;
void Record(VulkanDrawContext* context) override
{
m_buffer->Update(m_camera->GetData(), Scene::Camera::SIZE, context->currentImageId);
m_buffer->Update(GetCamera()->GetData(), Scene::Camera::SIZE, context->currentImageId);
m_buffer->Record(context);
}
void Close() override
{
m_camera->renderCamera = nullptr;
m_buffer->Close();
m_camera = nullptr;
delete m_buffer;
}
[[nodiscard]] Scene::Camera* GetCamera() const { return m_camera; }
[[nodiscard]] Scene::Camera* GetCamera() const { return GetOwner(); }
void Release() override
{
/* TODO */
}
};
}

View File

@@ -13,36 +13,21 @@
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_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::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)
{}
~VulkanGeometry() override
{
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;
}
~VulkanGeometry() override = default;
void RecordBind(vk::CommandBuffer& cmdBuffer)
{
@@ -52,15 +37,13 @@ namespace OpenVulkano::Vulkan
void RecordDraw(vk::CommandBuffer& cmdBuffer)
{
if (m_geometry->GetIndexCount()) { cmdBuffer.drawIndexed(m_geometry->GetIndexCount(), 1, 0, 0, 0); }
else { cmdBuffer.draw(m_geometry->GetVertexCount(), 1, 0, 0); }
if (GetOwner()->GetIndexCount()) { cmdBuffer.drawIndexed(GetOwner()->GetIndexCount(), 1, 0, 0, 0); }
else { cmdBuffer.draw(GetOwner()->GetVertexCount(), 1, 0, 0); }
}
void Close() override
void Release() override
{
m_geometry->renderGeo = nullptr;
m_vertexBuffer.reset();
m_indexBuffer.reset();
//TODO
}
};
}

View File

@@ -6,28 +6,23 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "Base/Render/RenderResource.hpp"
#include "IRecordable.hpp"
#include "Scene/Camera.hpp"
#include "Vulkan/Resources/UniformBuffer.hpp"
namespace OpenVulkano::Vulkan
{
class VulkanNode : public IRecordable, public ICloseable
class VulkanNode : public IRenderResource<Scene::Node>, public IRecordable
{
public:
Scene::Node* node = nullptr;
UniformBuffer* buffer = nullptr;
Unique<UniformBuffer> buffer = nullptr;
~VulkanNode() override
{
if (node) VulkanNode::Close();
}
~VulkanNode() override = default;
virtual void Init(Scene::Node* node, UniformBuffer* uniformBuffer)
VulkanNode(Scene::Node* node, UniformBuffer* uniformBuffer)
: IRenderResource<Scene::Node>(node), buffer(uniformBuffer)
{
this->node = node;
this->buffer = uniformBuffer;
}
void Record(VulkanDrawContext* context) override
@@ -35,12 +30,9 @@ namespace OpenVulkano::Vulkan
buffer->Record(context);
}
void Close() override
void Release() override
{
if (node) node->renderNode = nullptr;
delete buffer;
node = nullptr;
buffer = nullptr;
//TODO
}
};
@@ -48,18 +40,16 @@ namespace OpenVulkano::Vulkan
{
//uint32_t lastUpdate = -1;
void Init(Scene::Node* node, UniformBuffer* uniformBuffer) override
{
VulkanNode::Init(node, uniformBuffer);
//lastUpdate = -1;
}
VulkanNodeDynamic(Scene::Node* node, UniformBuffer* uniformBuffer)
: VulkanNode(node, uniformBuffer)
{}
void Record(VulkanDrawContext* context) override
{
//if(context->currentImageId != lastUpdate) //TODO fix
{
//lastUpdate = bufferId;
buffer->Update(&node->worldMat, sizeof(Math::Matrix4f), context->currentImageId);
buffer->Update(&GetOwner()->worldMat, sizeof(Math::Matrix4f), context->currentImageId);
}
buffer->Record(context);
}

View File

@@ -17,7 +17,8 @@ namespace OpenVulkano::Vulkan
VulkanShader::~VulkanShader()
{
if (shader) Close();
if (owner) owner->RemoveShader(this);
owner = nullptr;
device.destroyPipeline(pipeline);
for(auto& shaderModule : shaderModules)
{
@@ -28,12 +29,9 @@ namespace OpenVulkano::Vulkan
device.destroyDescriptorSetLayout(descriptorSetLayout);
}
void VulkanShader::Init(Context* context, Scene::Shader* shader, IShaderOwner* owner)
VulkanShader::VulkanShader(Context* context, Scene::Shader* shader, IShaderOwner* owner)
: IRenderResource<Scene::Shader>(shader), device(context->device->device), owner(owner), context(context)
{
this->device = context->device->device;
this->shader = shader;
this->owner = owner;
this->context = context;
shaderModules.reserve(shader->shaderPrograms.size());
shaderStageCreateInfo.resize(shader->shaderPrograms.size());
int i = 0;
@@ -45,11 +43,11 @@ namespace OpenVulkano::Vulkan
i++;
}
BuildPipeline();
shader->renderShader = this;
}
void VulkanShader::BuildPipeline()
{
Scene::Shader* shader = GetOwner();
std::vector<vk::VertexInputBindingDescription> vertexBindDesc;
std::vector<vk::VertexInputAttributeDescription> attributeDescriptions;
vertexBindDesc.reserve(shader->vertexInputDescriptions.size());
@@ -129,14 +127,6 @@ namespace OpenVulkano::Vulkan
context->commandBuffer.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
}
void VulkanShader::Close()
{
shader->renderShader = nullptr;
shader = nullptr;
if (owner) owner->RemoveShader(this);
owner = nullptr;
}
void VulkanShader::CreatePipelineLayout()
{
if (!descriptorSetLayouts.empty())
@@ -150,6 +140,7 @@ namespace OpenVulkano::Vulkan
descriptorSetLayouts.push_back(device.createDescriptorSetLayout({ {}, layoutBindings1.size(), layoutBindings1.data() }));
descriptorSetLayouts.push_back(device.createDescriptorSetLayout({ {}, layoutBindings2.size(), layoutBindings2.data() }));
Scene::Shader* shader = GetOwner();
for(const auto& set : shader->descriptorSets)
{
vk::DescriptorSetLayoutCreateInfo createInfo { {}, static_cast<uint32_t>(set.size()), reinterpret_cast<const vk::DescriptorSetLayoutBinding*>(set.data()) };
@@ -159,4 +150,9 @@ namespace OpenVulkano::Vulkan
vk::PipelineLayoutCreateInfo plci = {{}, static_cast<uint32_t>(descriptorSetLayouts.size()), descriptorSetLayouts.data(), static_cast<uint32_t>(shader->pushConstantRanges.size()), pcRanges };
pipelineLayout = this->device.createPipelineLayout(plci);
}
void VulkanShader::Release()
{
if (owner) owner->RemoveShader(this);
}
}

View File

@@ -7,26 +7,20 @@
#pragma once
#include "IRecordable.hpp"
#include "Base/ICloseable.hpp"
#include "Scene/Shader/Shader.hpp"
#include <vulkan/vulkan.hpp>
#include <vector>
namespace OpenVulkano
{
namespace Scene
{
class Shader;
}
namespace Vulkan
{
class Context;
class IShaderOwner;
class VulkanShader final : public ICloseable, public IRecordable
class VulkanShader final : public IRenderResource<Scene::Shader>, public IRecordable
{
public:
Scene::Shader* shader = nullptr;
vk::Device device;
std::vector<vk::ShaderModule> shaderModules; // TODO manage live time somewhere else to allow sharing of shader programs
std::vector<vk::PipelineShaderStageCreateInfo> shaderStageCreateInfo;
@@ -36,17 +30,15 @@ namespace OpenVulkano
IShaderOwner* owner = nullptr;
Context* context = nullptr;
VulkanShader() = default;
VulkanShader(Context* context, Scene::Shader* shader, IShaderOwner* owner);
~VulkanShader() override;
void Init(Context* context, Scene::Shader* shader, IShaderOwner* owner);
void Resize();
void Record(VulkanDrawContext* context) override;
void Close() override;
void Release() override;
private:
void BuildPipeline();

View File

@@ -16,28 +16,29 @@
namespace OpenVulkano::Vulkan
{
class VulkanTexture : public Scene::RenderTexture, public IRecordable, public Image
class VulkanTexture : public IRenderResource<Scene::Texture>, public IRecordable, public Image
{
public:
vk::Sampler m_sampler;
vk::DescriptorSet m_descriptorSet;
VulkanTexture() : IRenderResource<Scene::Texture>(nullptr) {}
virtual void Init(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
m_texture = texture;
Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z });
resManager->CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
resManager->CopyDataToImage(texture->size, texture->textureBuffer, this);
texture->updated = false;
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(*texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;
UpdateAddress(texture);
UpdateRenderResource(GetOwnerResource());
}
void InitSharedMem(ResourceManager* resManager, Scene::Texture* texture, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
{
m_texture = texture;
Image::Init(resManager->GetContext()->device.get(), texture->format, { texture->resolution.x, texture->resolution.y, texture->resolution.z }, vk::MemoryPropertyFlagBits::eDeviceLocal | vk::MemoryPropertyFlagBits::eHostVisible);
texture->updated = false;
texture->textureBuffer = Map();
@@ -45,7 +46,8 @@ namespace OpenVulkano::Vulkan
m_sampler = resManager->CreateSampler(reinterpret_cast<const vk::SamplerCreateInfo&>(*texture->m_samplerConfig));
SetDescriptorSet(resManager, descriptorSetLayout, binding);
texture->renderTexture = this;
UpdateAddress(texture);
UpdateRenderResource(GetOwnerResource());
}
virtual ~VulkanTexture() override
@@ -55,9 +57,8 @@ namespace OpenVulkano::Vulkan
void Close() override
{
ResetRenderResource(GetOwnerResource());
Image::Close();
if (m_texture) m_texture->renderTexture = nullptr;
m_texture = nullptr;
}
void SetDescriptorSet(ResourceManager* resManager, vk::DescriptorSetLayout* descriptorSetLayout, const DescriptorSetLayoutBinding& binding)
@@ -75,7 +76,7 @@ namespace OpenVulkano::Vulkan
void Record(VulkanDrawContext* context) override
{
int setId = -1, i = 0;
for (const auto& descriptorSet : context->GetShader()->shader->descriptorSets)
for (const auto& descriptorSet : context->GetShader()->GetOwner()->descriptorSets)
{
for (const auto& descriptor : descriptorSet)
{
@@ -106,6 +107,11 @@ namespace OpenVulkano::Vulkan
{
context->commandBuffer.bindDescriptorSets(vk::PipelineBindPoint::eGraphics, context->GetShader()->pipelineLayout, setId, 1, &m_descriptorSet, 0, nullptr);
}
void Release() override
{
//TODO
}
};
class VulkanTextureDynamic : public VulkanTexture
@@ -118,20 +124,20 @@ namespace OpenVulkano::Vulkan
void Record(VulkanDrawContext* context) override
{
if(m_texture->updated)
if(GetOwner()->updated)
{
context->renderer->GetResourceManager().CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
m_texture->updated = false;
context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this);
GetOwner()->updated = false;
}
VulkanTexture::Record(context);
}
void Record(VulkanDrawContext* context, int setId) override
{
if(m_texture->updated)
if(GetOwner()->updated)
{
context->renderer->GetResourceManager().CopyDataToImage(m_texture->size, m_texture->textureBuffer, this);
m_texture->updated = false;
context->renderer->GetResourceManager().CopyDataToImage(GetOwner()->size, GetOwner()->textureBuffer, this);
GetOwner()->updated = false;
}
VulkanTexture::Record(context, setId);
}

View File

@@ -6,42 +6,31 @@
#pragma once
#include "Base/ICloseable.hpp"
#include "IRecordable.hpp"
#include "Scene/UniformBuffer.hpp"
#include "Vulkan/Resources/UniformBuffer.hpp"
namespace OpenVulkano::Vulkan
{
class VulkanUniformBuffer : public IRecordable, public ICloseable
class VulkanUniformBuffer : public IRenderResource<Scene::UniformBuffer>, public IRecordable
{
public:
Scene::UniformBuffer* uBuffer = nullptr;
UniformBuffer* buffer = nullptr;
Unique<UniformBuffer> buffer = nullptr;
~VulkanUniformBuffer() override
{
if (uBuffer) VulkanUniformBuffer::Close();
}
~VulkanUniformBuffer() override = default;
virtual void Init(Scene::UniformBuffer* uBuffer, UniformBuffer* uniformBuffer)
{
this->uBuffer = uBuffer;
this->buffer = uniformBuffer;
uBuffer->renderBuffer = this;
}
VulkanUniformBuffer(Scene::UniformBuffer* sceneBuffer, UniformBuffer* uniformBuffer)
: IRenderResource<Scene::UniformBuffer>(sceneBuffer), buffer(uniformBuffer)
{}
void Record(VulkanDrawContext* context) override
{
buffer->Record(context);
}
void Close() override
void Release() override
{
if (uBuffer) uBuffer->renderBuffer = nullptr;
delete buffer;
uBuffer = nullptr;
buffer = nullptr;
//TODO
}
};
@@ -49,18 +38,16 @@ namespace OpenVulkano::Vulkan
{
uint32_t lastUpdate = 0;
void Init(Scene::UniformBuffer* buffer, UniformBuffer* uniformBuffer) override
{
VulkanUniformBuffer::Init(buffer, uniformBuffer);
lastUpdate = -1;
}
VulkanUniformBufferDynamic(Scene::UniformBuffer* sceneBuffer, UniformBuffer* uniformBuffer)
: VulkanUniformBuffer(sceneBuffer, uniformBuffer)
{}
void Record(VulkanDrawContext* context) override
{
if(uBuffer->updated) //TODO fix
if(GetOwner()->updated) //TODO fix
{
uBuffer->updated = false;
buffer->Update(uBuffer->data, uBuffer->size, context->currentImageId);
GetOwner()->updated = false;
buffer->Update(GetOwner()->data, GetOwner()->size, context->currentImageId);
}
buffer->Record(context);
}

View File

@@ -14,7 +14,7 @@ namespace OpenVulkano::Vulkan
{
void VulkanDrawContext::EncodeShader(Scene::Shader* shader)
{
VulkanShader* vkShader = static_cast<VulkanShader*>(shader->renderShader);
VulkanShader* vkShader = shader->GetRenderResource();
if (!vkShader)
{
vkShader = renderer->GetResourceManager().CreateShader(shader);
@@ -34,7 +34,7 @@ namespace OpenVulkano::Vulkan
void VulkanDrawContext::EncodeNode(Scene::Node* node)
{
VulkanNode* vkNode = static_cast<VulkanNode*>(node->renderNode);
VulkanNode* vkNode = node->GetRenderResource();
if (!vkNode)
{
vkNode = renderer->GetResourceManager().PrepareNode(node);
@@ -44,8 +44,8 @@ namespace OpenVulkano::Vulkan
void VulkanDrawContext::SetCamera(Scene::Camera* camera)
{
if (!camera->renderCamera) m_lastCamera = ResourceManager::INSTANCE->PrepareCamera(camera);
else m_lastCamera = static_cast<VulkanCamera*>(camera->renderCamera);
if (!camera->HasRenderResource()) m_lastCamera = ResourceManager::INSTANCE->PrepareCamera(camera);
else m_lastCamera = camera->GetRenderResource();
if (m_lastShader) m_lastCamera->Record(this);
}
}