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;
public:
ObjToken() = default;
ObjToken(SubCls* obj) : m_obj(obj) { m_obj->increment(); }
ObjToken(const ObjToken& other) : m_obj(other.m_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) { if (m_obj) m_obj->increment(); }
ObjToken(ObjToken&& other) : m_obj(other.m_obj) { other.m_obj = nullptr; }
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)
{ 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)
{ if (m_obj) m_obj->decrement(); m_obj = other.m_obj; other.m_obj = nullptr; return *this; }
~ObjToken() { if (m_obj) m_obj->decrement(); }
@ -40,6 +40,7 @@ public:
SubCls& operator*() const { return *m_obj; }
template<class T> T* cast() const { return static_cast<T*>(m_obj); }
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
{
class BaseGraphicsData;
struct BaseGraphicsData;
class GLDataFactory : public IGraphicsDataFactory
{

View File

@ -139,12 +139,13 @@ ENABLE_BITWISE_ENUM(VertexSemantic)
/** Used to create IVertexFormat */
struct VertexElementDescriptor
{
IGraphicsBuffer* vertBuffer = nullptr;
IGraphicsBuffer* indexBuffer = nullptr;
ObjToken<IGraphicsBuffer> vertBuffer;
ObjToken<IGraphicsBuffer> indexBuffer;
VertexSemantic semantic;
int semanticIdx = 0;
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) {}
};

View File

@ -9,6 +9,7 @@
namespace boo
{
struct BaseGraphicsData;
class MetalDataFactory : public IGraphicsDataFactory
{
@ -17,7 +18,9 @@ public:
{
friend class MetalDataFactoryImpl;
MetalDataFactory& m_parent;
Context(MetalDataFactory& parent) : m_parent(parent) {}
ObjToken<BaseGraphicsData> m_data;
Context(MetalDataFactory& parent);
~Context();
public:
Platform platform() const { return Platform::Metal; }
const SystemChar* platformName() const { return _S("Metal"); }
@ -40,7 +43,9 @@ public:
size_t baseVert = 0, size_t baseInst = 0);
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,
ZTest depthTest, bool depthWrite, bool colorWrite,
bool alphaWrite, CullMode culling);

View File

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

View File

@ -34,7 +34,8 @@ class GLDataFactoryImpl : public GLDataFactory, public GraphicsDataFactoryHead
uint32_t m_drawSamples;
std::unordered_map<uint64_t, std::unique_ptr<GLShareableShader>> m_sharedShaders;
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; }
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)
: GraphicsDataNode<IGraphicsBufferS>(parent)
{
Log.report(logvisor::Info, "Create static buffer %p\n", this);
m_target = USE_TABLE[int(use)];
glGenBuffers(1, &m_buf);
glBindBuffer(m_target, m_buf);
glBufferData(m_target, sz, data, GL_STATIC_DRAW);
}
public:
~GLGraphicsBufferS() {glDeleteBuffers(1, &m_buf); Log.report(logvisor::Info, "Delete static buffer %p\n", this); }
~GLGraphicsBufferS() { glDeleteBuffers(1, &m_buf); }
void bindVertex() const
{glBindBuffer(GL_ARRAY_BUFFER, m_buf);}
@ -94,7 +94,6 @@ class GLGraphicsBufferD : public GraphicsDataNode<IGraphicsBufferD, DataCls>
: GraphicsDataNode<IGraphicsBufferD, DataCls>(parent),
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);
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);
}
}
void update(int b);
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* map(size_t sz);
void unmap();
void 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;
}
}
void bindVertex(int b);
void bindIndex(int b);
void bindUniform(size_t idx, int b);
void bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, 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 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>
@ -217,7 +242,7 @@ class GLTextureS : public GraphicsDataNode<ITextureS>
}
}
public:
~GLTextureS() {glDeleteTextures(1, &m_tex);}
~GLTextureS() { glDeleteTextures(1, &m_tex); }
void bind(size_t idx) const
{
@ -274,7 +299,7 @@ class GLTextureSA : public GraphicsDataNode<ITextureSA>
}
}
public:
~GLTextureSA() {glDeleteTextures(1, &m_tex);}
~GLTextureSA() { glDeleteTextures(1, &m_tex); }
void bind(size_t idx) const
{
@ -294,16 +319,76 @@ class GLTextureD : public GraphicsDataNode<ITextureD>
size_t m_width = 0;
size_t m_height = 0;
int m_validMask = 0;
GLTextureD(const ObjToken<BaseGraphicsData>& parent, size_t width, size_t height, TextureFormat fmt, TextureClampMode clampMode);
void update(int b);
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);
}
}
public:
~GLTextureD();
~GLTextureD() { glDeleteTextures(3, m_texs); }
void load(const void* data, size_t sz);
void* map(size_t sz);
void unmap();
void 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 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
@ -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,
TextureClampMode clampMode, size_t colorBindCount, size_t depthBindCount);
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
{
@ -673,16 +763,14 @@ ObjToken<IShaderPipeline> GLDataFactory::Context::newShaderPipeline
struct GLVertexFormat : GraphicsDataNode<IVertexFormat>
{
GLCommandQueue* m_q;
GLuint m_vao[3] = {};
size_t m_elementCount;
GLuint m_baseVert, m_baseInst;
std::unique_ptr<VertexElementDescriptor[]> m_elements;
GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements,
std::vector<VertexElementDescriptor> m_elements;
GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q,
size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst);
~GLVertexFormat();
void bind(int idx) const {glBindVertexArray(m_vao[idx]);}
~GLVertexFormat() { glDeleteVertexArrays(3, m_vao); }
void bind(int idx) const { glBindVertexArray(m_vao[idx]); }
};
struct GLShaderDataBinding : GraphicsDataNode<IShaderDataBinding>
@ -735,7 +823,7 @@ struct GLShaderDataBinding : GraphicsDataNode<IShaderDataBinding>
m_texs.reserve(texCount);
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
@ -817,9 +905,6 @@ GLDataFactory::Context::newShaderDataBinding(const ObjToken<IShaderPipeline>& pi
ubufOffs, ubufSizes, texCount, texs, texBindIdx, depthBind)};
}
GLDataFactoryImpl::GLDataFactoryImpl(IGraphicsContext* parent, uint32_t drawSamples)
: m_parent(parent), m_drawSamples(drawSamples) {}
GLDataFactory::Context::Context(GLDataFactory& 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 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];
if ((desc->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
instStride += SEMANTIC_SIZE_TABLE[int(desc->semantic & VertexSemantic::SemanticMask)];
const VertexElementDescriptor& desc = fmt->m_elements[i];
if ((desc.semantic & VertexSemantic::Instanced) != VertexSemantic::None)
instStride += SEMANTIC_SIZE_TABLE[int(desc.semantic & VertexSemantic::SemanticMask)];
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)
@ -990,28 +1075,28 @@ struct GLCommandQueue : IGraphicsCommandQueue
glBindVertexArray(fmt->m_vao[b]);
IGraphicsBuffer* lastVBO = 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];
if (desc->vertBuffer != lastVBO)
const VertexElementDescriptor& desc = fmt->m_elements[i];
if (desc.vertBuffer.get() != lastVBO)
{
lastVBO = desc->vertBuffer;
lastVBO = desc.vertBuffer.get();
if (lastVBO->dynamic())
static_cast<GLGraphicsBufferD<BaseGraphicsData>*>(lastVBO)->bindVertex(b);
else
static_cast<GLGraphicsBufferS*>(lastVBO)->bindVertex();
}
if (desc->indexBuffer != lastEBO)
if (desc.indexBuffer.get() != lastEBO)
{
lastEBO = desc->indexBuffer;
lastEBO = desc.indexBuffer.get();
if (lastEBO->dynamic())
static_cast<GLGraphicsBufferD<BaseGraphicsData>*>(lastEBO)->bindIndex(b);
else
static_cast<GLGraphicsBufferS*>(lastEBO)->bindIndex();
}
glEnableVertexAttribArray(i);
int maskedSem = int(desc->semantic & VertexSemantic::SemanticMask);
if ((desc->semantic & VertexSemantic::Instanced) != VertexSemantic::None)
int maskedSem = int(desc.semantic & VertexSemantic::SemanticMask);
if ((desc.semantic & VertexSemantic::Instanced) != VertexSemantic::None)
{
glVertexAttribPointer(i, SEMANTIC_COUNT_TABLE[maskedSem],
SEMANTIC_TYPE_TABLE[maskedSem], GL_TRUE, instStride, (void*)instOffset);
@ -1350,39 +1435,12 @@ struct GLCommandQueue : IGraphicsCommandQueue
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)
{
std::unique_lock<std::mutex> lk(m_mt);
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()
{
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>
GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t 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>
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);
}
GLTextureR::~GLTextureR()
{
glDeleteTextures(2, m_texs);
glDeleteTextures(MAX_BIND_TEXS * 2, m_bindTexs[0]);
m_q->delFBO(this);
}
ObjToken<ITextureR>
GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureClampMode clampMode,
size_t colorBindingCount, size_t depthBindingCount)
@ -1631,20 +1569,17 @@ GLDataFactory::Context::newRenderTexture(size_t width, size_t height, TextureCla
return retval;
}
GLVertexFormat::GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q, size_t elementCount,
const VertexElementDescriptor* elements,
GLVertexFormat::GLVertexFormat(const ObjToken<BaseGraphicsData>& parent, GLCommandQueue* q,
size_t elementCount, const VertexElementDescriptor* elements,
size_t baseVert, size_t baseInst)
: GraphicsDataNode<IVertexFormat>(parent),
m_q(q),
m_elementCount(elementCount),
m_elements(new VertexElementDescriptor[elementCount]),
m_baseVert(baseVert), m_baseInst(baseInst)
{
m_elements.reserve(elementCount);
for (size_t i=0 ; i<elementCount ; ++i)
m_elements[i] = elements[i];
m_q->addVertexFormat(this);
m_elements.push_back(elements[i]);
q->addVertexFormat(this);
}
GLVertexFormat::~GLVertexFormat() { m_q->delVertexFormat(this); }
ObjToken<IVertexFormat> GLDataFactory::Context::newVertexFormat
(size_t elementCount, const VertexElementDescriptor* elements,

File diff suppressed because it is too large Load Diff

View File

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

View File

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