mirror of https://github.com/AxioDL/boo.git
Object tracker bug fixes; optional metal binary shader compilation
This commit is contained in:
parent
021143fd89
commit
3a7987bb21
|
@ -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; }
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
namespace boo
|
||||
{
|
||||
class BaseGraphicsData;
|
||||
struct BaseGraphicsData;
|
||||
|
||||
class GLDataFactory : public IGraphicsDataFactory
|
||||
{
|
||||
|
|
|
@ -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) {}
|
||||
};
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
{
|
||||
|
|
|
@ -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
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue