Merge branch 'wip'
This commit is contained in:
185
openVulkanoCpp/Base/Render/RenderResource.hpp
Normal file
185
openVulkanoCpp/Base/Render/RenderResource.hpp
Normal 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);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user