New object management architecture for OpenGL subsystem (more platforms to come)

This commit is contained in:
Jack Andersen
2017-11-02 23:39:26 -10:00
parent 90e2df40dd
commit 021143fd89
10 changed files with 692 additions and 889 deletions

View File

@@ -6,63 +6,219 @@
#include <atomic>
#include <vector>
#include <mutex>
#include "boo/graphicsdev/IGraphicsDataFactory.hpp"
namespace boo
{
class IGraphicsDataPriv : public IGraphicsData
struct BaseGraphicsData;
struct BaseGraphicsPool;
template<class NodeCls, class DataCls = BaseGraphicsData>
struct GraphicsDataNode;
/** Inherited by data factory implementations to track the head data and pool nodes */
struct GraphicsDataFactoryHead
{
std::atomic_int m_refCount = {1};
public:
void increment() { m_refCount++; }
void decrement()
{
if (m_refCount.fetch_sub(1) == 1)
delete this;
}
std::mutex m_dataMutex;
BaseGraphicsData* m_dataHead = nullptr;
BaseGraphicsPool* m_poolHead = nullptr;
};
class IShaderDataBindingPriv : public IShaderDataBinding
/** Private generalized data container class.
* Keeps head pointers to all graphics objects by type
*/
struct BaseGraphicsData : IObj
{
IGraphicsDataPriv* m_parent;
std::vector<IGraphicsDataPriv*> m_depDatas;
GraphicsDataFactoryHead& m_head;
BaseGraphicsData* m_next;
BaseGraphicsData* m_prev = nullptr;
GraphicsDataNode<IShaderPipeline, BaseGraphicsData>* m_SPs = nullptr;
GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>* m_SBinds = nullptr;
GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>* m_SBufs = nullptr;
GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>* m_DBufs = nullptr;
GraphicsDataNode<ITextureS, BaseGraphicsData>* m_STexs = nullptr;
GraphicsDataNode<ITextureSA, BaseGraphicsData>* m_SATexs = nullptr;
GraphicsDataNode<ITextureD, BaseGraphicsData>* m_DTexs = nullptr;
GraphicsDataNode<ITextureR, BaseGraphicsData>* m_RTexs = nullptr;
GraphicsDataNode<IVertexFormat, BaseGraphicsData>* m_VFmts = nullptr;
template<class T> GraphicsDataNode<T, BaseGraphicsData>*& getHead();
public:
IShaderDataBindingPriv(IGraphicsDataPriv* p) : m_parent(p) {}
class Token
explicit BaseGraphicsData(GraphicsDataFactoryHead& head)
: m_head(head)
{
IGraphicsDataPriv* m_data = nullptr;
public:
Token() = default;
Token(const IShaderDataBindingPriv* p)
: m_data(p->m_parent) { m_data->increment(); }
Token& operator=(const Token&) = delete;
Token(const Token&) = delete;
Token& operator=(Token&& other)
{ m_data = other.m_data; other.m_data = nullptr; return *this; }
Token(Token&& other)
{ m_data = other.m_data; other.m_data = nullptr; }
~Token() { if (m_data) { m_data->decrement(); } }
};
Token lock() const { return Token(this); }
~IShaderDataBindingPriv()
{
for (IGraphicsDataPriv* dep : m_depDatas)
dep->decrement();
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
m_next = head.m_dataHead;
head.m_dataHead = this;
}
protected:
void addDepData(IGraphicsData* data)
~BaseGraphicsData()
{
IGraphicsDataPriv* d = static_cast<IGraphicsDataPriv*>(data);
if (d != m_parent)
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
if (m_prev)
{
m_depDatas.push_back(d);
d->increment();
if (m_next)
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
else
{
if (m_next)
m_next->m_prev = m_head.m_dataHead;
m_head.m_dataHead = m_next;
}
}
class iterator
{
BaseGraphicsData* m_node;
public:
using value_type = BaseGraphicsData;
using pointer = BaseGraphicsData*;
using reference = BaseGraphicsData&;
using iterator_category = std::bidirectional_iterator_tag;
explicit iterator(BaseGraphicsData* node) : m_node(node) {}
BaseGraphicsData& operator*() const { return *m_node; }
bool operator!=(const iterator& other) const { return m_node != other.m_node; }
iterator& operator++() { m_node = m_node->m_next; return *this; }
iterator& operator--() { m_node = m_node->m_prev; return *this; }
};
iterator begin() { return iterator(this); }
iterator end() { return iterator(nullptr); }
};
template <> GraphicsDataNode<IShaderPipeline, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderPipeline>() { return m_SPs; }
template <> GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderDataBinding>() { return m_SBinds; }
template <> GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>*&
BaseGraphicsData::getHead<IGraphicsBufferS>() { return m_SBufs; }
template <> GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>*&
BaseGraphicsData::getHead<IGraphicsBufferD>() { return m_DBufs; }
template <> GraphicsDataNode<ITextureS, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureS>() { return m_STexs; }
template <> GraphicsDataNode<ITextureSA, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureSA>() { return m_SATexs; }
template <> GraphicsDataNode<ITextureD, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureD>() { return m_DTexs; }
template <> GraphicsDataNode<ITextureR, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureR>() { return m_RTexs; }
template <> GraphicsDataNode<IVertexFormat, BaseGraphicsData>*&
BaseGraphicsData::getHead<IVertexFormat>() { return m_VFmts; }
/** Private generalized pool container class.
* Keeps head pointer to exactly one dynamic buffer while otherwise conforming to IGraphicsData
*/
struct BaseGraphicsPool : IObj
{
GraphicsDataFactoryHead& m_head;
BaseGraphicsPool* m_next;
BaseGraphicsPool* m_prev = nullptr;
GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>* m_DBufs = nullptr;
template<class T> GraphicsDataNode<T, BaseGraphicsPool>*& getHead();
explicit BaseGraphicsPool(GraphicsDataFactoryHead& head)
: m_head(head)
{
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
m_next = head.m_poolHead;
head.m_poolHead = this;
}
~BaseGraphicsPool()
{
std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
if (m_prev)
{
if (m_next)
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
else
{
if (m_next)
m_next->m_prev = m_head.m_poolHead;
m_head.m_poolHead = m_next;
}
}
class iterator
{
BaseGraphicsPool* m_node;
public:
using value_type = BaseGraphicsPool;
using pointer = BaseGraphicsPool*;
using reference = BaseGraphicsPool&;
using iterator_category = std::bidirectional_iterator_tag;
explicit iterator(BaseGraphicsPool* node) : m_node(node) {}
BaseGraphicsPool& operator*() const { return *m_node; }
bool operator!=(const iterator& other) const { return m_node != other.m_node; }
iterator& operator++() { m_node = m_node->m_next; return *this; }
iterator& operator--() { m_node = m_node->m_prev; return *this; }
};
iterator begin() { return iterator(this); }
iterator end() { return iterator(nullptr); }
};
template <> GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>*&
BaseGraphicsPool::getHead<IGraphicsBufferD>() { return m_DBufs; }
/** Private generalised graphics object node.
* Keeps a strong reference to the data pool that it's a member of;
* as well as doubly-linked pointers to same-type sibling objects
*/
template<class NodeCls, class DataCls>
struct GraphicsDataNode : NodeCls
{
ObjToken<DataCls> m_data;
GraphicsDataNode<NodeCls, DataCls>* m_next;
GraphicsDataNode<NodeCls, DataCls>* m_prev = nullptr;
explicit GraphicsDataNode(const ObjToken<DataCls>& data)
: m_data(data)
{
std::lock_guard<std::mutex> lk(m_data->m_head.m_dataMutex);
m_next = data->template getHead<NodeCls>();
data->template getHead<NodeCls>() = this;
}
~GraphicsDataNode()
{
std::lock_guard<std::mutex> lk(m_data->m_head.m_dataMutex);
if (m_prev)
{
if (m_next)
m_next->m_prev = m_prev;
m_prev->m_next = m_next;
}
else
{
if (m_next)
m_next->m_prev = m_data->template getHead<NodeCls>();
m_data->template getHead<NodeCls>() = m_next;
}
}
class iterator
{
GraphicsDataNode<NodeCls, DataCls>* m_node;
public:
using value_type = NodeCls;
using pointer = NodeCls*;
using reference = NodeCls&;
using iterator_category = std::bidirectional_iterator_tag;
explicit iterator(GraphicsDataNode<NodeCls, DataCls>* node) : m_node(node) {}
NodeCls& operator*() const { return *m_node; }
bool operator!=(const iterator& other) const { return m_node != other.m_node; }
iterator& operator++() { m_node = m_node->m_next; return *this; }
iterator& operator--() { m_node = m_node->m_prev; return *this; }
};
iterator begin() { return iterator(this); }
iterator end() { return iterator(nullptr); }
};
template <class FactoryImpl, class ShaderImpl>