Moved BufferManager to handles again.
This commit is contained in:
parent
058a6512ea
commit
300fa7449c
|
|
@ -3,6 +3,7 @@
|
|||
cmake_minimum_required(VERSION 3.13)
|
||||
|
||||
add_subdirectory("core")
|
||||
add_subdirectory("systems")
|
||||
add_subdirectory("util")
|
||||
|
||||
target_sources(aster_core
|
||||
|
|
|
|||
|
|
@ -11,11 +11,14 @@
|
|||
|
||||
namespace systems
|
||||
{
|
||||
|
||||
using BufferHandle = Handle<Buffer>;
|
||||
|
||||
class BufferManager final : public Manager<Buffer>
|
||||
{
|
||||
public:
|
||||
BufferManager(const Device *device, const u32 maxCount);
|
||||
|
||||
Ref CreateStorageBuffer(usize size, cstr name = nullptr);
|
||||
Handle CreateStorageBuffer(usize size, cstr name = nullptr);
|
||||
};
|
||||
} // namespace systems
|
||||
|
|
|
|||
|
|
@ -7,55 +7,53 @@
|
|||
|
||||
#include "aster/aster.h"
|
||||
|
||||
#include <EASTL/intrusive_ptr.h>
|
||||
|
||||
struct Device;
|
||||
|
||||
|
||||
template <typename T>
|
||||
requires std::is_default_constructible_v<T>
|
||||
concept IsDeviceDestructible = requires(T a, Device *p) {
|
||||
{ a.Destroy(p) } -> std::convertible_to<void>;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
requires IsDeviceDestructible<T>
|
||||
class Handle;
|
||||
|
||||
template <typename T>
|
||||
requires std::is_default_constructible_v<T> && IsDeviceDestructible<T>
|
||||
class Manager
|
||||
{
|
||||
using InternalType = T;
|
||||
friend Handle<T>;
|
||||
|
||||
public:
|
||||
struct Type : InternalType
|
||||
using Type = T;
|
||||
using Handle = Handle<Type>;
|
||||
static_assert(sizeof(Handle) == sizeof(u32));
|
||||
|
||||
static Manager *
|
||||
Instance()
|
||||
{
|
||||
void
|
||||
AddRef()
|
||||
{
|
||||
m_Instance->AddRef(this);
|
||||
}
|
||||
assert(m_Instance);
|
||||
|
||||
void
|
||||
Release()
|
||||
{
|
||||
m_Instance->Release(this);
|
||||
}
|
||||
|
||||
u32
|
||||
GetIndex()
|
||||
{
|
||||
return m_Instance->GetIndex(this);
|
||||
}
|
||||
};
|
||||
static_assert(sizeof(Type) == sizeof(InternalType));
|
||||
|
||||
using Ref = eastl::intrusive_ptr<Type>;
|
||||
|
||||
static Manager *Instance();
|
||||
return m_Instance;
|
||||
}
|
||||
|
||||
explicit Manager(const Device *device, const u32 maxCount)
|
||||
: m_MaxCount{maxCount}
|
||||
, m_FreeHead{0}
|
||||
, m_Device{device}
|
||||
{
|
||||
assert(!m_Instance);
|
||||
|
||||
m_Data = new Type[m_MaxCount];
|
||||
m_RefCount = new u32[m_MaxCount];
|
||||
m_RefCount = new std::atomic<u32>[m_MaxCount];
|
||||
|
||||
for (u32 i = 0; i < m_MaxCount; ++i)
|
||||
{
|
||||
m_RefCount[i] = (i + 1);
|
||||
*Recast<u32 *>(&m_Data[i]) = (i + 1);
|
||||
}
|
||||
|
||||
m_Instance = this;
|
||||
}
|
||||
|
||||
virtual ~Manager()
|
||||
|
|
@ -79,69 +77,219 @@ class Manager
|
|||
|
||||
PIN_MEMORY(Manager);
|
||||
|
||||
void
|
||||
AddRef(Type *p)
|
||||
{
|
||||
auto index = GetIndex(p);
|
||||
|
||||
++m_RefCount[index];
|
||||
}
|
||||
|
||||
void
|
||||
Release(Type *p)
|
||||
{
|
||||
assert(p->IsValid());
|
||||
|
||||
auto index = GetIndex(p);
|
||||
|
||||
auto rc = --m_RefCount[index];
|
||||
|
||||
// Overflow case.
|
||||
assert(rc != MaxValue<u32>);
|
||||
if (rc == 0)
|
||||
{
|
||||
p->Destroy(m_Device);
|
||||
|
||||
m_RefCount[index] = m_FreeHead;
|
||||
m_FreeHead = index;
|
||||
}
|
||||
}
|
||||
|
||||
u32
|
||||
GetIndex(Type *p)
|
||||
{
|
||||
auto index = p - m_Data;
|
||||
assert(index >= 0 && index < m_MaxCount);
|
||||
|
||||
return Cast<u32>(index);
|
||||
}
|
||||
|
||||
private:
|
||||
Type *m_Data = nullptr;
|
||||
u32 *m_RefCount = nullptr;
|
||||
Type *m_Data = nullptr; // Data also keeps the freelist during 'not use'.
|
||||
std::atomic<u32> *m_RefCount = nullptr;
|
||||
u32 m_MaxCount = 0;
|
||||
u32 m_FreeHead = 0;
|
||||
|
||||
static Manager *m_Instance;
|
||||
|
||||
void
|
||||
AddRef(const u32 index)
|
||||
{
|
||||
assert(index < m_MaxCount);
|
||||
++m_RefCount[index];
|
||||
}
|
||||
|
||||
void
|
||||
Release(const u32 index)
|
||||
{
|
||||
assert(index < m_MaxCount);
|
||||
const u32 rc = --m_RefCount[index];
|
||||
assert(rc != MaxValue<u32>);
|
||||
if (rc == 0)
|
||||
{
|
||||
m_Data[index].Destroy(m_Device);
|
||||
}
|
||||
}
|
||||
|
||||
Type *
|
||||
Fetch(const u32 index)
|
||||
{
|
||||
assert(index < m_MaxCount);
|
||||
return &m_Data[index];
|
||||
}
|
||||
|
||||
protected:
|
||||
const Device *m_Device;
|
||||
|
||||
void
|
||||
SetInstance(Manager *instance)
|
||||
{
|
||||
assert(!m_Instance);
|
||||
m_Instance = instance;
|
||||
}
|
||||
|
||||
Ref
|
||||
std::pair<Handle, Type *>
|
||||
Alloc()
|
||||
{
|
||||
ERROR_IF(m_FreeHead >= m_MaxCount, "Max buffers allocated.") THEN_ABORT(-1);
|
||||
|
||||
const auto index = m_FreeHead;
|
||||
m_FreeHead = m_RefCount[index];
|
||||
m_RefCount[index] = 0;
|
||||
return Ref{&m_Data[index]};
|
||||
Type *pAlloc = &m_Data[index];
|
||||
m_FreeHead = *Recast<u32 *>(pAlloc);
|
||||
return {Handle{index}, pAlloc};
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
requires IsDeviceDestructible<T>
|
||||
class Ref
|
||||
{
|
||||
public:
|
||||
using Type = T;
|
||||
using Handle = Handle<Type>;
|
||||
using Manager = Manager<Type>;
|
||||
|
||||
protected:
|
||||
Handle m_Handle;
|
||||
Type *m_Pointer = nullptr;
|
||||
|
||||
friend Handle;
|
||||
|
||||
void
|
||||
InitPtr()
|
||||
{
|
||||
m_Pointer = m_Handle.Fetch();
|
||||
}
|
||||
|
||||
public:
|
||||
Type *
|
||||
Get()
|
||||
{
|
||||
assert(m_Pointer);
|
||||
return m_Pointer;
|
||||
}
|
||||
|
||||
const Type *
|
||||
Get() const
|
||||
{
|
||||
assert(m_Pointer);
|
||||
return m_Pointer;
|
||||
}
|
||||
|
||||
Type *
|
||||
operator->()
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
const Type *
|
||||
operator->() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
Type &
|
||||
operator*()
|
||||
{
|
||||
return *Get();
|
||||
}
|
||||
|
||||
const Type &
|
||||
operator*() const
|
||||
{
|
||||
return Get();
|
||||
}
|
||||
|
||||
// The only constructor requires a valid construction.
|
||||
explicit Ref(Handle &&handle)
|
||||
: m_Handle{handle}
|
||||
{
|
||||
InitPtr();
|
||||
}
|
||||
|
||||
// The only constructor requires a valid construction.
|
||||
explicit Ref(const Handle &&handle)
|
||||
: m_Handle{handle}
|
||||
{
|
||||
InitPtr();
|
||||
}
|
||||
|
||||
Ref(const Ref &other) = default;
|
||||
Ref(Ref &&other) noexcept = default;
|
||||
Ref &operator=(const Ref &other) = default;
|
||||
Ref &operator=(Ref &&other) noexcept = default;
|
||||
~Ref() = default;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
requires IsDeviceDestructible<T>
|
||||
class Handle
|
||||
{
|
||||
public:
|
||||
using Type = T;
|
||||
using Manager = Manager<Type>;
|
||||
|
||||
protected:
|
||||
constexpr static u32 INVALID_HANDLE = MaxValue<u32>;
|
||||
u32 m_Internal = INVALID_HANDLE;
|
||||
|
||||
// The only constructor requires a valid construction.
|
||||
explicit Handle(const u32 index)
|
||||
: m_Internal{index}
|
||||
{
|
||||
AddRef();
|
||||
}
|
||||
|
||||
friend Manager;
|
||||
friend Ref<T>;
|
||||
|
||||
public:
|
||||
Handle(const Handle &other)
|
||||
: m_Internal(other.m_Internal)
|
||||
{
|
||||
AddRef();
|
||||
}
|
||||
|
||||
Handle(Handle &&other) noexcept
|
||||
{
|
||||
std::swap(this->m_Internal, other.m_Internal);
|
||||
}
|
||||
|
||||
Handle &
|
||||
operator=(const Handle &other)
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
m_Internal = other.m_Internal;
|
||||
AddRef();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Handle &
|
||||
operator=(Handle &&other) noexcept
|
||||
{
|
||||
if (this == &other)
|
||||
return *this;
|
||||
std::swap(m_Internal, other.m_Internal);
|
||||
return *this;
|
||||
}
|
||||
|
||||
~Handle()
|
||||
{
|
||||
if (m_Internal != INVALID_HANDLE)
|
||||
{
|
||||
Release();
|
||||
}
|
||||
}
|
||||
|
||||
Ref<T>
|
||||
ToPointer()
|
||||
{
|
||||
return Ref{std::move(*this)};
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
AddRef()
|
||||
{
|
||||
Manager::Instance()->AddRef(m_Internal);
|
||||
}
|
||||
|
||||
void
|
||||
Release()
|
||||
{
|
||||
Manager::Instance()->Release(m_Internal);
|
||||
}
|
||||
|
||||
Type *
|
||||
Fetch()
|
||||
{
|
||||
return Manager::Instance()->Fetch(m_Internal);
|
||||
}
|
||||
};
|
||||
|
|
|
|||
Loading…
Reference in New Issue