Object tracker bug fixes; optional metal binary shader compilation

This commit is contained in:
Jack Andersen 2017-11-04 20:12:49 -10:00
parent 021143fd89
commit 3a7987bb21
9 changed files with 619 additions and 518 deletions

View File

@ -25,13 +25,13 @@ class ObjToken
SubCls* m_obj = nullptr; SubCls* m_obj = nullptr;
public: public:
ObjToken() = default; ObjToken() = default;
ObjToken(SubCls* obj) : m_obj(obj) { m_obj->increment(); } ObjToken(SubCls* obj) : m_obj(obj) { if (m_obj) m_obj->increment(); }
ObjToken(const ObjToken& other) : m_obj(other.m_obj) { m_obj->increment(); } ObjToken(const ObjToken& other) : m_obj(other.m_obj) { if (m_obj) m_obj->increment(); }
ObjToken(ObjToken&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; } ObjToken(ObjToken&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; }
ObjToken& operator=(SubCls* obj) ObjToken& operator=(SubCls* obj)
{ if (m_obj) m_obj->decrement(); m_obj = obj; m_obj->increment(); return *this; } { if (m_obj) m_obj->decrement(); m_obj = obj; if (m_obj) m_obj->increment(); return *this; }
ObjToken& operator=(const ObjToken& other) ObjToken& operator=(const ObjToken& other)
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; m_obj->increment(); return *this; } { if (m_obj) m_obj->decrement(); m_obj = other.m_obj; if (m_obj) m_obj->increment(); return *this; }
ObjToken& operator=(ObjToken&& other) ObjToken& operator=(ObjToken&& other)
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; other.m_obj = nullptr; return *this; } { if (m_obj) m_obj->decrement(); m_obj = other.m_obj; other.m_obj = nullptr; return *this; }
~ObjToken() { if (m_obj) m_obj->decrement(); } ~ObjToken() { if (m_obj) m_obj->decrement(); }
@ -40,6 +40,7 @@ public:
SubCls& operator*() const { return *m_obj; } SubCls& operator*() const { return *m_obj; }
template<class T> T* cast() const { return static_cast<T*>(m_obj); } template<class T> T* cast() const { return static_cast<T*>(m_obj); }
operator bool() const { return m_obj != nullptr; } operator bool() const { return m_obj != nullptr; }
void reset() { if (m_obj) m_obj->decrement(); m_obj = nullptr; }
}; };
} }

View File

@ -8,7 +8,7 @@
namespace boo namespace boo
{ {
class BaseGraphicsData; struct BaseGraphicsData;
class GLDataFactory : public IGraphicsDataFactory class GLDataFactory : public IGraphicsDataFactory
{ {

View File

@ -139,12 +139,13 @@ ENABLE_BITWISE_ENUM(VertexSemantic)
/** Used to create IVertexFormat */ /** Used to create IVertexFormat */
struct VertexElementDescriptor struct VertexElementDescriptor
{ {
IGraphicsBuffer* vertBuffer = nullptr; ObjToken<IGraphicsBuffer> vertBuffer;
IGraphicsBuffer* indexBuffer = nullptr; ObjToken<IGraphicsBuffer> indexBuffer;
VertexSemantic semantic; VertexSemantic semantic;
int semanticIdx = 0; int semanticIdx = 0;
VertexElementDescriptor() = default; VertexElementDescriptor() = default;
VertexElementDescriptor(IGraphicsBuffer* v, IGraphicsBuffer* i, VertexSemantic s, int idx=0) VertexElementDescriptor(const ObjToken<IGraphicsBuffer>& v, const ObjToken<IGraphicsBuffer>& i,
VertexSemantic s, int idx=0)
: vertBuffer(v), indexBuffer(i), semantic(s), semanticIdx(idx) {} : vertBuffer(v), indexBuffer(i), semantic(s), semanticIdx(idx) {}
}; };

View File

@ -9,6 +9,7 @@
namespace boo namespace boo
{ {
struct BaseGraphicsData;
class MetalDataFactory : public IGraphicsDataFactory class MetalDataFactory : public IGraphicsDataFactory
{ {
@ -17,7 +18,9 @@ public:
{ {
friend class MetalDataFactoryImpl; friend class MetalDataFactoryImpl;
MetalDataFactory& m_parent; MetalDataFactory& m_parent;
Context(MetalDataFactory& parent) : m_parent(parent) {} ObjToken<BaseGraphicsData> m_data;
Context(MetalDataFactory& parent);
~Context();
public: public:
Platform platform() const { return Platform::Metal; } Platform platform() const { return Platform::Metal; }
const SystemChar* platformName() const { return _S("Metal"); } const SystemChar* platformName() const { return _S("Metal"); }
@ -40,7 +43,9 @@ public:
size_t baseVert = 0, size_t baseInst = 0); size_t baseVert = 0, size_t baseInst = 0);
ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource, ObjToken<IShaderPipeline> newShaderPipeline(const char* vertSource, const char* fragSource,
IVertexFormat* vtxFmt, unsigned targetSamples, std::vector<uint8_t>* vertBlobOut,
std::vector<uint8_t>* fragBlobOut,
const ObjToken<IVertexFormat>& vtxFmt, unsigned targetSamples,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
ZTest depthTest, bool depthWrite, bool colorWrite, ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling); bool alphaWrite, CullMode culling);

View File

@ -26,6 +26,24 @@ struct GraphicsDataFactoryHead
BaseGraphicsPool* m_poolHead = nullptr; BaseGraphicsPool* m_poolHead = nullptr;
}; };
/** Linked-list iterator shareable by data container types */
template<class T>
class DataIterator
{
T* m_node;
public:
using value_type = T;
using pointer = T*;
using reference = T&;
using iterator_category = std::bidirectional_iterator_tag;
explicit DataIterator(T* node) : m_node(node) {}
T& operator*() const { return *m_node; }
bool operator!=(const DataIterator& other) const { return m_node != other.m_node; }
DataIterator& operator++() { m_node = m_node->m_next; return *this; }
DataIterator& operator--() { m_node = m_node->m_prev; return *this; }
};
/** Private generalized data container class. /** Private generalized data container class.
* Keeps head pointers to all graphics objects by type * Keeps head pointers to all graphics objects by type
*/ */
@ -50,6 +68,8 @@ struct BaseGraphicsData : IObj
{ {
std::lock_guard<std::mutex> lk(m_head.m_dataMutex); std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
m_next = head.m_dataHead; m_next = head.m_dataHead;
if (m_next)
m_next->m_prev = this;
head.m_dataHead = this; head.m_dataHead = this;
} }
~BaseGraphicsData() ~BaseGraphicsData()
@ -64,52 +84,37 @@ struct BaseGraphicsData : IObj
else else
{ {
if (m_next) if (m_next)
m_next->m_prev = m_head.m_dataHead; m_next->m_prev = nullptr;
m_head.m_dataHead = m_next; m_head.m_dataHead = m_next;
} }
} }
class iterator using iterator = DataIterator<BaseGraphicsData>;
{
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 begin() { return iterator(this); }
iterator end() { return iterator(nullptr); } iterator end() { return iterator(nullptr); }
}; };
template <> GraphicsDataNode<IShaderPipeline, BaseGraphicsData>*& template <> inline GraphicsDataNode<IShaderPipeline, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderPipeline>() { return m_SPs; } BaseGraphicsData::getHead<IShaderPipeline>() { return m_SPs; }
template <> GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>*& template <> inline GraphicsDataNode<IShaderDataBinding, BaseGraphicsData>*&
BaseGraphicsData::getHead<IShaderDataBinding>() { return m_SBinds; } BaseGraphicsData::getHead<IShaderDataBinding>() { return m_SBinds; }
template <> GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>*& template <> inline GraphicsDataNode<IGraphicsBufferS, BaseGraphicsData>*&
BaseGraphicsData::getHead<IGraphicsBufferS>() { return m_SBufs; } BaseGraphicsData::getHead<IGraphicsBufferS>() { return m_SBufs; }
template <> GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>*& template <> inline GraphicsDataNode<IGraphicsBufferD, BaseGraphicsData>*&
BaseGraphicsData::getHead<IGraphicsBufferD>() { return m_DBufs; } BaseGraphicsData::getHead<IGraphicsBufferD>() { return m_DBufs; }
template <> GraphicsDataNode<ITextureS, BaseGraphicsData>*& template <> inline GraphicsDataNode<ITextureS, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureS>() { return m_STexs; } BaseGraphicsData::getHead<ITextureS>() { return m_STexs; }
template <> GraphicsDataNode<ITextureSA, BaseGraphicsData>*& template <> inline GraphicsDataNode<ITextureSA, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureSA>() { return m_SATexs; } BaseGraphicsData::getHead<ITextureSA>() { return m_SATexs; }
template <> GraphicsDataNode<ITextureD, BaseGraphicsData>*& template <> inline GraphicsDataNode<ITextureD, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureD>() { return m_DTexs; } BaseGraphicsData::getHead<ITextureD>() { return m_DTexs; }
template <> GraphicsDataNode<ITextureR, BaseGraphicsData>*& template <> inline GraphicsDataNode<ITextureR, BaseGraphicsData>*&
BaseGraphicsData::getHead<ITextureR>() { return m_RTexs; } BaseGraphicsData::getHead<ITextureR>() { return m_RTexs; }
template <> GraphicsDataNode<IVertexFormat, BaseGraphicsData>*& template <> inline GraphicsDataNode<IVertexFormat, BaseGraphicsData>*&
BaseGraphicsData::getHead<IVertexFormat>() { return m_VFmts; } BaseGraphicsData::getHead<IVertexFormat>() { return m_VFmts; }
/** Private generalized pool container class. /** Private generalized pool container class.
* Keeps head pointer to exactly one dynamic buffer while otherwise conforming to IGraphicsData * Keeps head pointer to exactly one dynamic buffer while otherwise conforming to BaseGraphicsData
*/ */
struct BaseGraphicsPool : IObj struct BaseGraphicsPool : IObj
{ {
@ -124,6 +129,8 @@ struct BaseGraphicsPool : IObj
{ {
std::lock_guard<std::mutex> lk(m_head.m_dataMutex); std::lock_guard<std::mutex> lk(m_head.m_dataMutex);
m_next = head.m_poolHead; m_next = head.m_poolHead;
if (m_next)
m_next->m_prev = this;
head.m_poolHead = this; head.m_poolHead = this;
} }
~BaseGraphicsPool() ~BaseGraphicsPool()
@ -138,32 +145,17 @@ struct BaseGraphicsPool : IObj
else else
{ {
if (m_next) if (m_next)
m_next->m_prev = m_head.m_poolHead; m_next->m_prev = nullptr;
m_head.m_poolHead = m_next; m_head.m_poolHead = m_next;
} }
} }
class iterator using iterator = DataIterator<BaseGraphicsPool>;
{
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 begin() { return iterator(this); }
iterator end() { return iterator(nullptr); } iterator end() { return iterator(nullptr); }
}; };
template <> GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>*& template <> inline GraphicsDataNode<IGraphicsBufferD, BaseGraphicsPool>*&
BaseGraphicsPool::getHead<IGraphicsBufferD>() { return m_DBufs; } BaseGraphicsPool::getHead<IGraphicsBufferD>() { return m_DBufs; }
/** Private generalised graphics object node. /** Private generalised graphics object node.
@ -182,6 +174,8 @@ struct GraphicsDataNode : NodeCls
{ {
std::lock_guard<std::mutex> lk(m_data->m_head.m_dataMutex); std::lock_guard<std::mutex> lk(m_data->m_head.m_dataMutex);
m_next = data->template getHead<NodeCls>(); m_next = data->template getHead<NodeCls>();
if (m_next)
m_next->m_prev = this;
data->template getHead<NodeCls>() = this; data->template getHead<NodeCls>() = this;
} }
~GraphicsDataNode() ~GraphicsDataNode()
@ -196,7 +190,7 @@ struct GraphicsDataNode : NodeCls
else else
{ {
if (m_next) if (m_next)
m_next->m_prev = m_data->template getHead<NodeCls>(); m_next->m_prev = nullptr;
m_data->template getHead<NodeCls>() = m_next; m_data->template getHead<NodeCls>() = m_next;
} }
} }
@ -221,6 +215,7 @@ struct GraphicsDataNode : NodeCls
iterator end() { return iterator(nullptr); } iterator end() { return iterator(nullptr); }
}; };
/** Hash table entry for owning sharable shader objects */
template <class FactoryImpl, class ShaderImpl> template <class FactoryImpl, class ShaderImpl>
class IShareableShader class IShareableShader
{ {

View File

@ -34,7 +34,8 @@ class GLDataFactoryImpl : public GLDataFactory, public GraphicsDataFactoryHead
uint32_t m_drawSamples; uint32_t m_drawSamples;
std::unordered_map<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders; std::unordered_map<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders;
public: public:
GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples); GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples)
: m_parent(parent), m_drawSamples(drawSamples) {}
Platform platform() const { return Platform::OpenGL; } Platform platform() const { return Platform::OpenGL; }
const SystemChar* platformName() const { return _S("OpenGL"); } const SystemChar* platformName() const { return _S("OpenGL"); }
@ -60,14 +61,13 @@ class GLGraphicsBufferS : public GraphicsDataNode<IGraphicsBufferS>
GLGraphicsBufferS(const ObjToken<BaseGraphicsData>& parent, BufferUse use, const void* data, size_t sz) GLGraphicsBufferS(const ObjToken<BaseGraphicsData>& parent, BufferUse use, const void* data, size_t sz)
: GraphicsDataNode<IGraphicsBufferS>(parent) : GraphicsDataNode<IGraphicsBufferS>(parent)
{ {
Log.report(logvisor::Info, "Create static buffer %p\n", this);
m_target = USE_TABLE[int(use)]; m_target = USE_TABLE[int(use)];
glGenBuffers(1, &m_buf); glGenBuffers(1, &m_buf);
glBindBuffer(m_target, m_buf); glBindBuffer(m_target, m_buf);
glBufferData(m_target, sz, data, GL_STATIC_DRAW); glBufferData(m_target, sz, data, GL_STATIC_DRAW);
} }
public: public:
~GLGraphicsBufferS() {glDeleteBuffers(1, &m_buf); Log.report(logvisor::Info, "Delete static buffer %p\n", this); } ~GLGraphicsBufferS() { glDeleteBuffers(1, &m_buf); }
void bindVertex() const void bindVertex() const
{glBindBuffer(GL_ARRAY_BUFFER, m_buf);} {glBindBuffer(GL_ARRAY_BUFFER, m_buf);}
@ -94,7 +94,6 @@ class GLGraphicsBufferD : public GraphicsDataNode<IGraphicsBufferD, DataCls>
: GraphicsDataNode<IGraphicsBufferD, DataCls>(parent), : GraphicsDataNode<IGraphicsBufferD, DataCls>(parent),
m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz) m_target(USE_TABLE[int(use)]), m_cpuBuf(new uint8_t[sz]), m_cpuSz(sz)
{ {
Log.report(logvisor::Info, "Create dynamic buffer %p\n", this);
glGenBuffers(3, m_bufs); glGenBuffers(3, m_bufs);
for (int i=0 ; i<3 ; ++i) for (int i=0 ; i<3 ; ++i)
{ {
@ -102,18 +101,44 @@ class GLGraphicsBufferD : public GraphicsDataNode<IGraphicsBufferD, DataCls>
glBufferData(m_target, m_cpuSz, nullptr, GL_STREAM_DRAW); glBufferData(m_target, m_cpuSz, nullptr, GL_STREAM_DRAW);
} }
} }
void update(int b);
public: public:
~GLGraphicsBufferD() {glDeleteBuffers(3, m_bufs); Log.report(logvisor::Info, "Delete dynamic buffer %p\n", this);} ~GLGraphicsBufferD() { glDeleteBuffers(3, m_bufs); }
void load(const void* data, size_t sz); void update(int b)
void* map(size_t sz); {
void unmap(); int slot = 1 << b;
if ((slot & m_validMask) == 0)
{
glBindBuffer(m_target, m_bufs[b]);
glBufferSubData(m_target, 0, m_cpuSz, m_cpuBuf.get());
m_validMask |= slot;
}
}
void bindVertex(int b); void load(const void* data, size_t sz)
void bindIndex(int b); {
void bindUniform(size_t idx, int b); size_t bufSz = std::min(sz, m_cpuSz);
void bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b); memcpy(m_cpuBuf.get(), data, bufSz);
m_validMask = 0;
}
void* map(size_t sz)
{
if (sz < m_cpuSz)
return nullptr;
return m_cpuBuf.get();
}
void unmap()
{
m_validMask = 0;
}
void bindVertex(int b)
{glBindBuffer(GL_ARRAY_BUFFER, m_bufs[b]);}
void bindIndex(int b)
{glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufs[b]);}
void bindUniform(size_t idx, int b)
{glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_bufs[b]);}
void bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b)
{glBindBufferRange(GL_UNIFORM_BUFFER, idx, m_bufs[b], off, size);}
}; };
ObjToken<IGraphicsBufferS> ObjToken<IGraphicsBufferS>
@ -294,16 +319,76 @@ class GLTextureD : public GraphicsDataNode<ITextureD>
size_t m_width = 0; size_t m_width = 0;
size_t m_height = 0; size_t m_height = 0;
int m_validMask = 0; int m_validMask = 0;
GLTextureD(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode); GLTextureD(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height,
void update(int b); TextureFormat fmt, TextureClampMode clampMode)
: GraphicsDataNode<ITextureD>(parent), m_width(width), m_height(height)
{
int pxPitch = 4;
switch (fmt)
{
case TextureFormat::RGBA8:
m_intFormat = GL_RGBA8;
m_format = GL_RGBA;
pxPitch = 4;
break;
case TextureFormat::I8:
m_intFormat = GL_R8;
m_format = GL_RED;
pxPitch = 1;
break;
default:
Log.report(logvisor::Fatal, "unsupported tex format");
}
m_cpuSz = width * height * pxPitch;
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
glGenTextures(3, m_texs);
for (int i=0 ; i<3 ; ++i)
{
glBindTexture(GL_TEXTURE_2D, m_texs[i]);
glTexImage2D(GL_TEXTURE_2D, 0, m_intFormat, width, height, 0, m_format, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
SetClampMode(GL_TEXTURE_2D, clampMode);
}
}
public: public:
~GLTextureD(); ~GLTextureD() { glDeleteTextures(3, m_texs); }
void load(const void* data, size_t sz); void update(int b)
void* map(size_t sz); {
void unmap(); int slot = 1 << b;
if ((slot & m_validMask) == 0)
{
glBindTexture(GL_TEXTURE_2D, m_texs[b]);
glTexImage2D(GL_TEXTURE_2D, 0, m_intFormat, m_width, m_height, 0, m_format, GL_UNSIGNED_BYTE, m_cpuBuf.get());
m_validMask |= slot;
}
}
void bind(size_t idx, int b); void load(const void* data, size_t sz)
{
size_t bufSz = std::min(sz, m_cpuSz);
memcpy(m_cpuBuf.get(), data, bufSz);
m_validMask = 0;
}
void* map(size_t sz)
{
if (sz > m_cpuSz)
return nullptr;
return m_cpuBuf.get();
}
void unmap()
{
m_validMask = 0;
}
void bind(size_t idx, int b)
{
glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(GL_TEXTURE_2D, m_texs[b]);
}
}; };
#define MAX_BIND_TEXS 4 #define MAX_BIND_TEXS 4
@ -323,7 +408,12 @@ class GLTextureR : public GraphicsDataNode<ITextureR>
GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples, GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t width, size_t height, size_t samples,
TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount); TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount);
public: public:
~GLTextureR(); ~GLTextureR()
{
glDeleteTextures(2, m_texs);
glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]);
glDeleteFramebuffers(1, &m_fbo);
}
void bind(size_t idx, int bindIdx, bool depth) const void bind(size_t idx, int bindIdx, bool depth) const
{ {
@ -673,15 +763,13 @@ ObjToken<IShaderPipeline> GLDataFactory::Context::newShaderPipeline
struct GLVertexFormat : GraphicsDataNode<IVertexFormat> struct GLVertexFormat : GraphicsDataNode<IVertexFormat>
{ {
GLCommandQueue* m_q;
GLuint m_vao[3] = {}; GLuint m_vao[3] = {};
size_t m_elementCount;
GLuint m_baseVert, m_baseInst; GLuint m_baseVert, m_baseInst;
std::unique_ptr<VertexElementDescriptor[]> m_elements; std::vector<VertexElementDescriptor> m_elements;
GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t elementCount, GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q,
const VertexElementDescriptor* elements, size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst); size_t baseVert, size_t baseInst);
~GLVertexFormat(); ~GLVertexFormat() { glDeleteVertexArrays(3, m_vao); }
void bind(int idx) const { glBindVertexArray(m_vao[idx]); } void bind(int idx) const { glBindVertexArray(m_vao[idx]); }
}; };
@ -735,7 +823,7 @@ struct GLShaderDataBinding : GraphicsDataNode<IShaderDataBinding>
m_texs.reserve(texCount); m_texs.reserve(texCount);
for (size_t i=0 ; i<texCount ; ++i) for (size_t i=0 ; i<texCount ; ++i)
{ {
m_texs[i] = {texs[i], bindTexIdx ? bindTexIdx[i] : 0, depthBind ? depthBind[i] : false}; m_texs.push_back({texs[i], bindTexIdx ? bindTexIdx[i] : 0, depthBind ? depthBind[i] : false});
} }
} }
void bind(int b) const void bind(int b) const
@ -817,9 +905,6 @@ GLDataFactory::Context::newShaderDataBinding(const ObjToken<IShaderPipeline>& pi
ubufOffs, ubufSizes, texCount, texs, texBindIdx, depthBind)}; ubufOffs, ubufSizes, texCount, texs, texBindIdx, depthBind)};
} }
GLDataFactoryImpl::GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples)
: m_parent(parent), m_drawSamples(drawSamples) {}
GLDataFactory::Context::Context(GLDataFactory& parent) GLDataFactory::Context::Context(GLDataFactory& parent)
: m_parent(parent), m_data(new BaseGraphicsData(static_cast<GLDataFactoryImpl&>(parent))) : m_parent(parent), m_data(new BaseGraphicsData(static_cast<GLDataFactoryImpl&>(parent)))
{} {}
@ -974,13 +1059,13 @@ struct GLCommandQueue : IGraphicsCommandQueue
size_t stride = 0; size_t stride = 0;
size_t instStride = 0; size_t instStride = 0;
for (size_t i=0 ; i<fmt->m_elementCount ; ++i) for (size_t i=0 ; i<fmt->m_elements.size() ; ++i)
{ {
const VertexElementDescriptor* desc = &fmt->m_elements[i]; const VertexElementDescriptor& desc = fmt->m_elements[i];
if ((desc->semantic & VertexSemantic::Instanced) != VertexSemantic::None) if ((desc.semantic & VertexSemantic::Instanced) != VertexSemantic::None)
instStride += SEMANTIC_SIZE_TABLE[int(desc->semantic & VertexSemantic::SemanticMask)]; instStride += SEMANTIC_SIZE_TABLE[int(desc.semantic & VertexSemantic::SemanticMask)];
else else
stride += SEMANTIC_SIZE_TABLE[int(desc->semantic & VertexSemantic::SemanticMask)]; stride += SEMANTIC_SIZE_TABLE[int(desc.semantic & VertexSemantic::SemanticMask)];
} }
for (int b=0 ; b<3 ; ++b) for (int b=0 ; b<3 ; ++b)
@ -990,28 +1075,28 @@ struct GLCommandQueue : IGraphicsCommandQueue
glBindVertexArray(fmt->m_vao[b]); glBindVertexArray(fmt->m_vao[b]);
IGraphicsBuffer* lastVBO = nullptr; IGraphicsBuffer* lastVBO = nullptr;
IGraphicsBuffer* lastEBO = nullptr; IGraphicsBuffer* lastEBO = nullptr;
for (size_t i=0 ; i<fmt->m_elementCount ; ++i) for (size_t i=0 ; i<fmt->m_elements.size() ; ++i)
{ {
const VertexElementDescriptor* desc = &fmt->m_elements[i]; const VertexElementDescriptor& desc = fmt->m_elements[i];
if (desc->vertBuffer != lastVBO) if (desc.vertBuffer.get() != lastVBO)
{ {
lastVBO = desc->vertBuffer; lastVBO = desc.vertBuffer.get();
if (lastVBO->dynamic()) if (lastVBO->dynamic())
static_cast<GLGraphicsBufferD<BaseGraphicsData>*>(lastVBO)->bindVertex(b); static_cast<GLGraphicsBufferD<BaseGraphicsData>*>(lastVBO)->bindVertex(b);
else else
static_cast<GLGraphicsBufferS*>(lastVBO)->bindVertex(); static_cast<GLGraphicsBufferS*>(lastVBO)->bindVertex();
} }
if (desc->indexBuffer != lastEBO) if (desc.indexBuffer.get() != lastEBO)
{ {
lastEBO = desc->indexBuffer; lastEBO = desc.indexBuffer.get();
if (lastEBO->dynamic()) if (lastEBO->dynamic())
static_cast<GLGraphicsBufferD<BaseGraphicsData>*>(lastEBO)->bindIndex(b); static_cast<GLGraphicsBufferD<BaseGraphicsData>*>(lastEBO)->bindIndex(b);
else else
static_cast<GLGraphicsBufferS*>(lastEBO)->bindIndex(); static_cast<GLGraphicsBufferS*>(lastEBO)->bindIndex();
} }
glEnableVertexAttribArray(i); glEnableVertexAttribArray(i);
int maskedSem = int(desc->semantic & VertexSemantic::SemanticMask); int maskedSem = int(desc.semantic & VertexSemantic::SemanticMask);
if ((desc->semantic & VertexSemantic::Instanced) != VertexSemantic::None) if ((desc.semantic & VertexSemantic::Instanced) != VertexSemantic::None)
{ {
glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[maskedSem], glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[maskedSem],
SEMANTIC_TYPE_TABLE[maskedSem], GL_TRUE, instStride, (void*)instOffset); SEMANTIC_TYPE_TABLE[maskedSem], GL_TRUE, instStride, (void*)instOffset);
@ -1350,39 +1435,12 @@ struct GLCommandQueue : IGraphicsCommandQueue
m_pendingFmtAdds.push_back(fmt); m_pendingFmtAdds.push_back(fmt);
} }
void delVertexFormat(const ObjToken<GLVertexFormat>& fmt)
{
#if 0
std::unique_lock<std::mutex> lk(m_mt);
bool foundAdd = false;
for (GLVertexFormat*& afmt : m_pendingFmtAdds)
if (afmt == fmt)
{
foundAdd = true;
afmt = nullptr;
break;
}
if (!foundAdd)
m_pendingFmtDels.push_back({fmt->m_vao[0], fmt->m_vao[1], fmt->m_vao[2]});
#endif
glDeleteVertexArrays(3, fmt->m_vao);
}
void addFBO(const ObjToken<ITextureR>& tex) void addFBO(const ObjToken<ITextureR>& tex)
{ {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
m_pendingFboAdds.push_back(tex); m_pendingFboAdds.push_back(tex);
} }
void delFBO(const ObjToken<ITextureR>& tex)
{
#if 0
std::unique_lock<std::mutex> lk(m_mt);
m_pendingFboDels.push_back(tex->m_fbo);
#endif
glDeleteFramebuffers(1, &tex.cast<GLTextureR>()->m_fbo);
}
void execute() void execute()
{ {
std::unique_lock<std::mutex> lk(m_mt); std::unique_lock<std::mutex> lk(m_mt);
@ -1432,125 +1490,12 @@ struct GLCommandQueue : IGraphicsCommandQueue
} }
}; };
template<class DataCls>
void GLGraphicsBufferD<DataCls>::update(int b)
{
int slot = 1 << b;
if ((slot & m_validMask) == 0)
{
glBindBuffer(m_target, m_bufs[b]);
glBufferSubData(m_target, 0, m_cpuSz, m_cpuBuf.get());
m_validMask |= slot;
}
}
template<class DataCls>
void GLGraphicsBufferD<DataCls>::load(const void* data, size_t sz)
{
size_t bufSz = std::min(sz, m_cpuSz);
memcpy(m_cpuBuf.get(), data, bufSz);
m_validMask = 0;
}
template<class DataCls>
void* GLGraphicsBufferD<DataCls>::map(size_t sz)
{
if (sz < m_cpuSz)
return nullptr;
return m_cpuBuf.get();
}
template<class DataCls>
void GLGraphicsBufferD<DataCls>::unmap()
{
m_validMask = 0;
}
template<class DataCls>
void GLGraphicsBufferD<DataCls>::bindVertex(int b)
{glBindBuffer(GL_ARRAY_BUFFER, m_bufs[b]);}
template<class DataCls>
void GLGraphicsBufferD<DataCls>::bindIndex(int b)
{glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufs[b]);}
template<class DataCls>
void GLGraphicsBufferD<DataCls>::bindUniform(size_t idx, int b)
{glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_bufs[b]);}
template<class DataCls>
void GLGraphicsBufferD<DataCls>::bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b)
{glBindBufferRange(GL_UNIFORM_BUFFER, idx, m_bufs[b], off, size);}
ObjToken<IGraphicsBufferD> ObjToken<IGraphicsBufferD>
GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count) GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
{ {
return {new GLGraphicsBufferD<BaseGraphicsData>(m_data, use, stride * count)}; return {new GLGraphicsBufferD<BaseGraphicsData>(m_data, use, stride * count)};
} }
GLTextureD::GLTextureD(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, TextureFormat fmt,
TextureClampMode clampMode)
: GraphicsDataNode<ITextureD>(parent), m_width(width), m_height(height)
{
int pxPitch = 4;
switch (fmt)
{
case TextureFormat::RGBA8:
m_intFormat = GL_RGBA8;
m_format = GL_RGBA;
pxPitch = 4;
break;
case TextureFormat::I8:
m_intFormat = GL_R8;
m_format = GL_RED;
pxPitch = 1;
break;
default:
Log.report(logvisor::Fatal, "unsupported tex format");
}
m_cpuSz = width * height * pxPitch;
m_cpuBuf.reset(new uint8_t[m_cpuSz]);
glGenTextures(3, m_texs);
for (int i=0 ; i<3 ; ++i)
{
glBindTexture(GL_TEXTURE_2D, m_texs[i]);
glTexImage2D(GL_TEXTURE_2D, 0, m_intFormat, width, height, 0, m_format, GL_UNSIGNED_BYTE, nullptr);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
SetClampMode(GL_TEXTURE_2D, clampMode);
}
}
GLTextureD::~GLTextureD() { glDeleteTextures(3, m_texs); }
void GLTextureD::update(int b)
{
int slot = 1 << b;
if ((slot & m_validMask) == 0)
{
glBindTexture(GL_TEXTURE_2D, m_texs[b]);
glTexImage2D(GL_TEXTURE_2D, 0, m_intFormat, m_width, m_height, 0, m_format, GL_UNSIGNED_BYTE, m_cpuBuf.get());
m_validMask |= slot;
}
}
void GLTextureD::load(const void* data, size_t sz)
{
size_t bufSz = std::min(sz, m_cpuSz);
memcpy(m_cpuBuf.get(), data, bufSz);
m_validMask = 0;
}
void* GLTextureD::map(size_t sz)
{
if (sz > m_cpuSz)
return nullptr;
return m_cpuBuf.get();
}
void GLTextureD::unmap()
{
m_validMask = 0;
}
void GLTextureD::bind(size_t idx, int b)
{
glActiveTexture(GL_TEXTURE0 + idx);
glBindTexture(GL_TEXTURE_2D, m_texs[b]);
}
ObjToken<ITextureD> ObjToken<ITextureD>
GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode) GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode)
{ {
@ -1612,13 +1557,6 @@ GLTextureR::GLTextureR(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue*
m_q->addFBO(this); m_q->addFBO(this);
} }
GLTextureR::~GLTextureR()
{
glDeleteTextures(2, m_texs);
glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]);
m_q->delFBO(this);
}
ObjToken<ITextureR> ObjToken<ITextureR>
GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureClampMode clampMode, GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindingCount, size_t depthBindingCount) size_t colorBindingCount, size_t depthBindingCount)
@ -1631,20 +1569,17 @@ GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureCla
return retval; return retval;
} }
GLVertexFormat::GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t elementCount, GLVertexFormat::GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q,
const VertexElementDescriptor* elements, size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst) size_t baseVert, size_t baseInst)
: GraphicsDataNode<IVertexFormat>(parent), : GraphicsDataNode<IVertexFormat>(parent),
m_q(q),
m_elementCount(elementCount),
m_elements(new VertexElementDescriptor[elementCount]),
m_baseVert(baseVert), m_baseInst(baseInst) m_baseVert(baseVert), m_baseInst(baseInst)
{ {
m_elements.reserve(elementCount);
for (size_t i=0 ; i<elementCount ; ++i) for (size_t i=0 ; i<elementCount ; ++i)
m_elements[i] = elements[i]; m_elements.push_back(elements[i]);
m_q->addVertexFormat(this); q->addVertexFormat(this);
} }
GLVertexFormat::~GLVertexFormat() { m_q->delVertexFormat(this); }
ObjToken<IVertexFormat> GLDataFactory::Context::newVertexFormat ObjToken<IVertexFormat> GLDataFactory::Context::newVertexFormat
(size_t elementCount, const VertexElementDescriptor* elements, (size_t elementCount, const VertexElementDescriptor* elements,

File diff suppressed because it is too large Load Diff

View File

@ -215,7 +215,6 @@ public:
~GraphicsContextCocoaGL() ~GraphicsContextCocoaGL()
{ {
m_commandQueue->stopRenderer(); m_commandQueue->stopRenderer();
m_dataFactory->destroyAllData();
delete m_commandQueue; delete m_commandQueue;
delete m_dataFactory; delete m_dataFactory;
printf("CONTEXT DESTROYED\n"); printf("CONTEXT DESTROYED\n");
@ -374,7 +373,6 @@ public:
~GraphicsContextCocoaMetal() ~GraphicsContextCocoaMetal()
{ {
m_commandQueue->stopRenderer(); m_commandQueue->stopRenderer();
m_dataFactory->destroyAllData();
delete m_commandQueue; delete m_commandQueue;
delete m_dataFactory; delete m_dataFactory;
m_metalCtx->m_windows.erase(m_parentWindow); m_metalCtx->m_windows.erase(m_parentWindow);

View File

@ -157,7 +157,7 @@ struct CTestWindowCallback : IWindowCallback
bool m_rectDirty = false; bool m_rectDirty = false;
bool m_windowInvalid = false; bool m_windowInvalid = false;
void resized(const SWindowRect& rect) void resized(const SWindowRect& rect, bool sync)
{ {
m_lastRect = rect; m_lastRect = rect;
m_rectDirty = true; m_rectDirty = true;
@ -247,8 +247,8 @@ struct TestApplicationCallback : IApplicationCallback
CTestWindowCallback windowCallback; CTestWindowCallback windowCallback;
bool running = true; bool running = true;
IShaderDataBinding* m_binding = nullptr; boo::ObjToken<IShaderDataBinding> m_binding;
ITextureR* m_renderTarget = nullptr; boo::ObjToken<ITextureR> m_renderTarget;
std::mutex m_mt; std::mutex m_mt;
std::condition_variable m_cv; std::condition_variable m_cv;
@ -256,13 +256,13 @@ struct TestApplicationCallback : IApplicationCallback
std::mutex m_initmt; std::mutex m_initmt;
std::condition_variable m_initcv; std::condition_variable m_initcv;
static GraphicsDataToken LoaderProc(TestApplicationCallback* self) static void LoaderProc(TestApplicationCallback* self)
{ {
std::unique_lock<std::mutex> lk(self->m_initmt); std::unique_lock<std::mutex> lk(self->m_initmt);
IGraphicsDataFactory* factory = self->mainWindow->getLoadContextDataFactory(); IGraphicsDataFactory* factory = self->mainWindow->getLoadContextDataFactory();
GraphicsDataToken data = factory->commitTransaction([&](IGraphicsDataFactory::Context& ctx) -> bool factory->commitTransaction([&](IGraphicsDataFactory::Context& ctx) -> bool
{ {
/* Create render target */ /* Create render target */
int x, y, w, h; int x, y, w, h;
@ -282,16 +282,15 @@ struct TestApplicationCallback : IApplicationCallback
{{0.5,-0.5},{1.0,0.0}}, {{0.5,-0.5},{1.0,0.0}},
{{-0.5,-0.5},{0.0,0.0}} {{-0.5,-0.5},{0.0,0.0}}
}; };
IGraphicsBuffer* vbo = auto vbo = ctx.newStaticBuffer(BufferUse::Vertex, quad, sizeof(Vert), 4);
ctx.newStaticBuffer(BufferUse::Vertex, quad, sizeof(Vert), 4);
/* Make vertex format */ /* Make vertex format */
VertexElementDescriptor descs[2] = VertexElementDescriptor descs[2] =
{ {
{vbo, nullptr, VertexSemantic::Position3}, {vbo.get(), nullptr, VertexSemantic::Position3},
{vbo, nullptr, VertexSemantic::UV2} {vbo.get(), nullptr, VertexSemantic::UV2}
}; };
IVertexFormat* vfmt = ctx.newVertexFormat(2, descs); auto vfmt = ctx.newVertexFormat(2, descs);
/* Make ramp texture */ /* Make ramp texture */
using Pixel = uint8_t[4]; using Pixel = uint8_t[4];
@ -304,11 +303,11 @@ struct TestApplicationCallback : IApplicationCallback
tex[i][j][2] = 0; tex[i][j][2] = 0;
tex[i][j][3] = 0xff; tex[i][j][3] = 0xff;
} }
ITexture* texture = boo::ObjToken<ITexture> texture = ctx.newStaticTexture(256, 256, 1, TextureFormat::RGBA8,
ctx.newStaticTexture(256, 256, 1, TextureFormat::RGBA8, boo::TextureClampMode::Repeat, tex, 256*256*4); boo::TextureClampMode::Repeat, tex, 256*256*4).get();
/* Make shader pipeline */ /* Make shader pipeline */
IShaderPipeline* pipeline = nullptr; boo::ObjToken<IShaderPipeline> pipeline;
auto plat = ctx.platform(); auto plat = ctx.platform();
if (plat == IGraphicsDataFactory::Platform::OpenGL) if (plat == IGraphicsDataFactory::Platform::OpenGL)
{ {
@ -437,7 +436,7 @@ struct TestApplicationCallback : IApplicationCallback
" return tex.sample(samp, d.out_uv);\n" " return tex.sample(samp, d.out_uv);\n"
"}\n"; "}\n";
pipeline = metalF.newShaderPipeline(VS, FS, vfmt, 1, pipeline = metalF.newShaderPipeline(VS, FS, nullptr, nullptr, vfmt, 1,
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips, BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
boo::ZTest::LEqual, true, true, true, boo::CullMode::None); boo::ZTest::LEqual, true, true, true, boo::CullMode::None);
} }
@ -445,7 +444,7 @@ struct TestApplicationCallback : IApplicationCallback
/* Make shader data binding */ /* Make shader data binding */
self->m_binding = self->m_binding =
ctx.newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, nullptr, ctx.newShaderDataBinding(pipeline, vfmt, vbo.get(), nullptr, nullptr, 0, nullptr, nullptr,
1, &texture, nullptr, nullptr); 1, &texture, nullptr, nullptr);
return true; return true;
@ -463,7 +462,6 @@ struct TestApplicationCallback : IApplicationCallback
if (!self->running) if (!self->running)
break; break;
} }
return data;
} }
int appMain(IApplication* app) int appMain(IApplication* app)