Major GraphicsDataFactory lambda-API refactor

This commit is contained in:
Jack Andersen 2016-03-30 09:14:17 -10:00
parent 6cbd086204
commit bf6b4e37e8
6 changed files with 446 additions and 440 deletions

View File

@ -30,38 +30,45 @@ public:
Platform platform() const {return Platform::OGL;} Platform platform() const {return Platform::OGL;}
const SystemChar* platformName() const {return _S("OGL");} const SystemChar* platformName() const {return _S("OGL");}
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); class Context : public IGraphicsDataFactory::Context
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count); {
friend class GLDataFactory;
GLDataFactory& m_parent;
Context(GLDataFactory& parent) : m_parent(parent) {}
public:
Platform platform() const {return Platform::OGL;}
const SystemChar* platformName() const {return _S("OGL");}
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
const void* data, size_t sz); IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
GraphicsDataToken
newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz, ITextureS*& texOut);
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding);
bool bindingNeedsVertexFormat() const {return true;} ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements); const void* data, size_t sz);
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, bool bindingNeedsVertexFormat() const {return true;}
size_t texCount, const char* texArrayName, IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
size_t uniformBlockCount, const char** uniformBlockNames,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderDataBinding* IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
newShaderDataBinding(IShaderPipeline* pipeline, size_t texCount, const char* texArrayName,
IVertexFormat* vtxFormat, size_t uniformBlockCount, const char** uniformBlockNames,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo, BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
size_t ubufCount, IGraphicsBuffer** ubufs, bool depthTest, bool depthWrite, bool backfaceCulling);
size_t texCount, ITexture** texs);
void reset(); IShaderDataBinding*
GraphicsDataToken commit(); newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs);
};
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
}; };
} }

View File

@ -198,39 +198,53 @@ struct IGraphicsDataFactory
virtual Platform platform() const=0; virtual Platform platform() const=0;
virtual const SystemChar* platformName() const=0; virtual const SystemChar* platformName() const=0;
virtual IGraphicsBufferS* struct Context
newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0; {
virtual IGraphicsBufferD* virtual Platform platform() const=0;
newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0; virtual const SystemChar* platformName() const=0;
virtual ITextureS* virtual IGraphicsBufferS*
newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)=0;
const void* data, size_t sz)=0; virtual IGraphicsBufferD*
virtual GraphicsDataToken newDynamicBuffer(BufferUse use, size_t stride, size_t count)=0;
newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz, ITextureS*& texOut)=0;
virtual ITextureSA*
newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz)=0;
virtual ITextureD*
newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0;
virtual ITextureR*
newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding)=0;
virtual bool bindingNeedsVertexFormat() const=0; virtual ITextureS*
virtual IVertexFormat* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0; const void* data, size_t sz)=0;
virtual ITextureSA*
newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz)=0;
virtual ITextureD*
newDynamicTexture(size_t width, size_t height, TextureFormat fmt)=0;
virtual ITextureR*
newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding)=0;
virtual IShaderDataBinding* virtual bool bindingNeedsVertexFormat() const=0;
newShaderDataBinding(IShaderPipeline* pipeline, virtual IVertexFormat*
IVertexFormat* vtxFormat, newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)=0;
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs,
size_t texCount, ITexture** texs)=0;
virtual void reset()=0; virtual IShaderDataBinding*
virtual GraphicsDataToken commit()=0; newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs)=0;
IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs,
size_t texCount, ITexture** texs)
{
return newShaderDataBinding(pipeline, vtxFormat, vbo, instVbo, ibo,
ubufCount, ubufs, nullptr, nullptr, texCount, texs);
}
};
virtual GraphicsDataToken commitTransaction(const std::function<bool(Context& ctx)>&)=0;
private: private:
friend class GraphicsDataToken; friend class GraphicsDataToken;
@ -238,6 +252,8 @@ private:
virtual void destroyAllData()=0; virtual void destroyAllData()=0;
}; };
using FactoryCommitFunc = std::function<bool(IGraphicsDataFactory::Context& ctx)>;
/** Multiplatform TLS-pointer wrapper (for compilers without proper thread_local support) */ /** Multiplatform TLS-pointer wrapper (for compilers without proper thread_local support) */
template <class T> template <class T>
class ThreadLocalPtr class ThreadLocalPtr

View File

@ -87,48 +87,56 @@ public:
Platform platform() const {return Platform::Vulkan;} Platform platform() const {return Platform::Vulkan;}
const SystemChar* platformName() const {return _S("Vulkan");} const SystemChar* platformName() const {return _S("Vulkan");}
IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count); class Context : public IGraphicsDataFactory::Context
IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz);
GraphicsDataToken newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void *data, size_t sz, ITextureS*& texOut);
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding);
bool bindingNeedsVertexFormat() const {return false;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
std::vector<unsigned char>& pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling)
{ {
std::vector<unsigned int> vertBlob; friend class VulkanDataFactory;
std::vector<unsigned int> fragBlob; VulkanDataFactory& m_parent;
std::vector<unsigned char> pipelineBlob; Context(VulkanDataFactory& parent) : m_parent(parent) {}
return newShaderPipeline(vertSource, fragSource, vertBlob, fragBlob, pipelineBlob, public:
vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); Platform platform() const {return Platform::Vulkan;}
} const SystemChar* platformName() const {return _S("Vulkan");}
IShaderDataBinding* IGraphicsBufferS* newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count);
newShaderDataBinding(IShaderPipeline* pipeline, IGraphicsBufferD* newDynamicBuffer(BufferUse use, size_t stride, size_t count);
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs,
size_t texCount, ITexture** texs);
void reset(); ITextureS* newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
GraphicsDataToken commit(); const void* data, size_t sz);
ITextureSA* newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void* data, size_t sz);
ITextureD* newDynamicTexture(size_t width, size_t height, TextureFormat fmt);
ITextureR* newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding);
bool bindingNeedsVertexFormat() const {return false;}
IVertexFormat* newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource,
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
std::vector<unsigned char>& pipelineBlob, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling);
IShaderPipeline* newShaderPipeline(const char* vertSource, const char* fragSource, IVertexFormat* vtxFmt,
BlendFactor srcFac, BlendFactor dstFac, Primitive prim,
bool depthTest, bool depthWrite, bool backfaceCulling)
{
std::vector<unsigned int> vertBlob;
std::vector<unsigned int> fragBlob;
std::vector<unsigned char> pipelineBlob;
return newShaderPipeline(vertSource, fragSource, vertBlob, fragBlob, pipelineBlob,
vtxFmt, srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
}
IShaderDataBinding*
newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat,
IGraphicsBuffer* vbo, IGraphicsBuffer* instVbo, IGraphicsBuffer* ibo,
size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs);
};
GraphicsDataToken commitTransaction(const FactoryCommitFunc&);
}; };
} }

View File

@ -60,6 +60,8 @@ public:
{glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buf);} {glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_buf);}
void bindUniform(size_t idx) const void bindUniform(size_t idx) const
{glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_buf);} {glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_buf);}
void bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size) const
{glBindBufferRange(GL_UNIFORM_BUFFER, idx, m_buf, off, size);}
}; };
class GLGraphicsBufferD : public IGraphicsBufferD class GLGraphicsBufferD : public IGraphicsBufferD
@ -92,14 +94,13 @@ public:
void bindVertex(int b); void bindVertex(int b);
void bindIndex(int b); void bindIndex(int b);
void bindUniform(size_t idx, int b); void bindUniform(size_t idx, int b);
void bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b);
}; };
IGraphicsBufferS* IGraphicsBufferS*
GLDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) GLDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
{ {
GLGraphicsBufferS* retval = new GLGraphicsBufferS(use, data, stride * count); GLGraphicsBufferS* retval = new GLGraphicsBufferS(use, data, stride * count);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_SBufs.emplace_back(retval); m_deferredData->m_SBufs.emplace_back(retval);
return retval; return retval;
} }
@ -295,42 +296,19 @@ public:
}; };
ITextureS* ITextureS*
GLDataFactory::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt, GLDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz) const void* data, size_t sz)
{ {
GLTextureS* retval = new GLTextureS(width, height, mips, fmt, data, sz); GLTextureS* retval = new GLTextureS(width, height, mips, fmt, data, sz);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_STexs.emplace_back(retval); m_deferredData->m_STexs.emplace_back(retval);
return retval; return retval;
} }
GraphicsDataToken
GLDataFactory::newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt,
const void* data, size_t sz, ITextureS*& texOut)
{
GLTextureS* retval = new GLTextureS(width, height, mips, fmt, data, sz);
GLData* tokData = new struct GLData();
tokData->m_STexs.emplace_back(retval);
texOut = retval;
std::unique_lock<std::mutex> lk(m_committedMutex);
m_committedData.insert(tokData);
lk.unlock();
/* Let's go ahead and flush to ensure our data gets to the GPU
While this isn't strictly required, some drivers might behave
differently */
glFlush();
return GraphicsDataToken(this, tokData);
}
ITextureSA* ITextureSA*
GLDataFactory::newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt, GLDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers, TextureFormat fmt,
const void *data, size_t sz) const void *data, size_t sz)
{ {
GLTextureSA* retval = new GLTextureSA(width, height, layers, fmt, data, sz); GLTextureSA* retval = new GLTextureSA(width, height, layers, fmt, data, sz);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_SATexs.emplace_back(retval); m_deferredData->m_SATexs.emplace_back(retval);
return retval; return retval;
} }
@ -452,7 +430,7 @@ static const GLenum BLEND_FACTOR_TABLE[] =
GL_ONE_MINUS_SRC1_COLOR GL_ONE_MINUS_SRC1_COLOR
}; };
IShaderPipeline* GLDataFactory::newShaderPipeline IShaderPipeline* GLDataFactory::Context::newShaderPipeline
(const char* vertSource, const char* fragSource, (const char* vertSource, const char* fragSource,
size_t texCount, const char* texArrayName, size_t texCount, const char* texArrayName,
size_t uniformBlockCount, const char** uniformBlockNames, size_t uniformBlockCount, const char** uniformBlockNames,
@ -535,16 +513,14 @@ IShaderPipeline* GLDataFactory::newShaderPipeline
Log.report(logvisor::Error, "unable to find sampler variable '%s'", texArrayName); Log.report(logvisor::Error, "unable to find sampler variable '%s'", texArrayName);
else else
{ {
if (texCount > m_texUnis.size()) if (texCount > m_parent.m_texUnis.size())
for (size_t i=m_texUnis.size() ; i<texCount ; ++i) for (size_t i=m_parent.m_texUnis.size() ; i<texCount ; ++i)
m_texUnis.push_back(i); m_parent.m_texUnis.push_back(i);
glUniform1iv(texLoc, m_texUnis.size(), m_texUnis.data()); glUniform1iv(texLoc, m_parent.m_texUnis.size(), m_parent.m_texUnis.data());
} }
} }
GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader)); GLShaderPipeline* retval = new GLShaderPipeline(std::move(shader));
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_SPs.emplace_back(retval); m_deferredData->m_SPs.emplace_back(retval);
return retval; return retval;
} }
@ -567,17 +543,14 @@ struct GLShaderDataBinding : IShaderDataBinding
const GLVertexFormat* m_vtxFormat; const GLVertexFormat* m_vtxFormat;
size_t m_ubufCount; size_t m_ubufCount;
std::unique_ptr<IGraphicsBuffer*[]> m_ubufs; std::unique_ptr<IGraphicsBuffer*[]> m_ubufs;
std::vector<std::pair<size_t,size_t>> m_ubufOffs;
size_t m_texCount; size_t m_texCount;
std::unique_ptr<ITexture*[]> m_texs; std::unique_ptr<ITexture*[]> m_texs;
#ifndef NDEBUG
/* Debugging aids */
bool m_committed = false;
#endif
GLShaderDataBinding(IShaderPipeline* pipeline, GLShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat, IVertexFormat* vtxFormat,
size_t ubufCount, IGraphicsBuffer** ubufs, size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs) size_t texCount, ITexture** texs)
: m_pipeline(static_cast<GLShaderPipeline*>(pipeline)), : m_pipeline(static_cast<GLShaderPipeline*>(pipeline)),
m_vtxFormat(static_cast<GLVertexFormat*>(vtxFormat)), m_vtxFormat(static_cast<GLVertexFormat*>(vtxFormat)),
@ -586,29 +559,57 @@ struct GLShaderDataBinding : IShaderDataBinding
m_texCount(texCount), m_texCount(texCount),
m_texs(new ITexture*[texCount]) m_texs(new ITexture*[texCount])
{ {
if (ubufOffs && ubufSizes)
{
m_ubufOffs.reserve(ubufCount);
for (size_t i=0 ; i<ubufCount ; ++i)
m_ubufOffs.emplace_back(ubufOffs[i], ubufSizes[i]);
}
for (size_t i=0 ; i<ubufCount ; ++i) for (size_t i=0 ; i<ubufCount ; ++i)
{
#ifndef NDEBUG
if (!ubufs[i])
Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i));
#endif
m_ubufs[i] = ubufs[i]; m_ubufs[i] = ubufs[i];
}
for (size_t i=0 ; i<texCount ; ++i) for (size_t i=0 ; i<texCount ; ++i)
{
#ifndef NDEBUG
if (!texs[i])
Log.report(logvisor::Fatal, "null texture %d provided to newShaderDataBinding", int(i));
#endif
m_texs[i] = texs[i]; m_texs[i] = texs[i];
}
} }
void bind(int b) const void bind(int b) const
{ {
#ifndef NDEBUG
if (!m_committed)
Log.report(logvisor::Fatal,
"attempted to use uncommitted GLShaderDataBinding");
#endif
GLuint prog = m_pipeline->bind(); GLuint prog = m_pipeline->bind();
m_vtxFormat->bind(b); m_vtxFormat->bind(b);
for (size_t i=0 ; i<m_ubufCount ; ++i) if (m_ubufOffs.size())
{ {
IGraphicsBuffer* ubuf = m_ubufs[i]; for (size_t i=0 ; i<m_ubufCount ; ++i)
if (ubuf->dynamic()) {
static_cast<GLGraphicsBufferD*>(ubuf)->bindUniform(i, b); IGraphicsBuffer* ubuf = m_ubufs[i];
else const std::pair<size_t,size_t>& offset = m_ubufOffs[i];
static_cast<GLGraphicsBufferS*>(ubuf)->bindUniform(i); if (ubuf->dynamic())
glUniformBlockBinding(prog, m_pipeline->m_uniLocs.at(i), i); static_cast<GLGraphicsBufferD*>(ubuf)->bindUniformRange(i, offset.first, offset.second, b);
else
static_cast<GLGraphicsBufferS*>(ubuf)->bindUniformRange(i, offset.first, offset.second);
glUniformBlockBinding(prog, m_pipeline->m_uniLocs.at(i), i);
}
}
else
{
for (size_t i=0 ; i<m_ubufCount ; ++i)
{
IGraphicsBuffer* ubuf = m_ubufs[i];
if (ubuf->dynamic())
static_cast<GLGraphicsBufferD*>(ubuf)->bindUniform(i, b);
else
static_cast<GLGraphicsBufferS*>(ubuf)->bindUniform(i);
glUniformBlockBinding(prog, m_pipeline->m_uniLocs.at(i), i);
}
} }
for (size_t i=0 ; i<m_texCount ; ++i) for (size_t i=0 ; i<m_texCount ; ++i)
{ {
@ -634,16 +635,15 @@ struct GLShaderDataBinding : IShaderDataBinding
}; };
IShaderDataBinding* IShaderDataBinding*
GLDataFactory::newShaderDataBinding(IShaderPipeline* pipeline, GLDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* vtxFormat, IVertexFormat* vtxFormat,
IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*, IGraphicsBuffer*,
size_t ubufCount, IGraphicsBuffer** ubufs, size_t ubufCount, IGraphicsBuffer** ubufs,
size_t texCount, ITexture** texs) const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs)
{ {
GLShaderDataBinding* retval = GLShaderDataBinding* retval =
new GLShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, texCount, texs); new GLShaderDataBinding(pipeline, vtxFormat, ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_SBinds.emplace_back(retval); m_deferredData->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
@ -651,22 +651,23 @@ GLDataFactory::newShaderDataBinding(IShaderPipeline* pipeline,
GLDataFactory::GLDataFactory(IGraphicsContext* parent, uint32_t drawSamples) GLDataFactory::GLDataFactory(IGraphicsContext* parent, uint32_t drawSamples)
: m_parent(parent), m_drawSamples(drawSamples) {} : m_parent(parent), m_drawSamples(drawSamples) {}
void GLDataFactory::reset()
{
delete m_deferredData.get();
m_deferredData.reset();
}
GraphicsDataToken GLDataFactory::commit() GraphicsDataToken GLDataFactory::commitTransaction(const FactoryCommitFunc& trans)
{ {
if (!m_deferredData.get()) if (m_deferredData.get())
Log.report(logvisor::Fatal, "nested commitTransaction usage detected");
m_deferredData.reset(new GLData());
GLDataFactory::Context ctx(*this);
if (!trans(ctx))
{
delete m_deferredData.get();
m_deferredData.reset();
return GraphicsDataToken(this, nullptr); return GraphicsDataToken(this, nullptr);
}
std::unique_lock<std::mutex> lk(m_committedMutex); std::unique_lock<std::mutex> lk(m_committedMutex);
GLData* retval = m_deferredData.get(); GLData* retval = m_deferredData.get();
#ifndef NDEBUG
for (std::unique_ptr<GLShaderDataBinding>& b : retval->m_SBinds)
b->m_committed = true;
#endif
m_deferredData.reset(); m_deferredData.reset();
m_committedData.insert(retval); m_committedData.insert(retval);
lk.unlock(); lk.unlock();
@ -1057,10 +1058,6 @@ struct GLCommandQueue : IGraphicsCommandQueue
void setShaderDataBinding(IShaderDataBinding* binding) void setShaderDataBinding(IShaderDataBinding* binding)
{ {
#ifndef NDEBUG
if (!binding)
Log.report(logvisor::Fatal, "binding may not be empty");
#endif
std::vector<Command>& cmds = m_cmdBufs[m_fillBuf]; std::vector<Command>& cmds = m_cmdBufs[m_fillBuf];
cmds.emplace_back(Command::Op::SetShaderDataBinding); cmds.emplace_back(Command::Op::SetShaderDataBinding);
cmds.back().binding = binding; cmds.back().binding = binding;
@ -1281,13 +1278,13 @@ void GLGraphicsBufferD::bindIndex(int b)
{glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufs[b]);} {glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_bufs[b]);}
void GLGraphicsBufferD::bindUniform(size_t idx, int b) void GLGraphicsBufferD::bindUniform(size_t idx, int b)
{glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_bufs[b]);} {glBindBufferBase(GL_UNIFORM_BUFFER, idx, m_bufs[b]);}
void GLGraphicsBufferD::bindUniformRange(size_t idx, GLintptr off, GLsizeiptr size, int b)
{glBindBufferRange(GL_UNIFORM_BUFFER, idx, m_bufs[b], off, size);}
IGraphicsBufferD* IGraphicsBufferD*
GLDataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count) GLDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
{ {
GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count); GLGraphicsBufferD* retval = new GLGraphicsBufferD(use, stride * count);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_DBufs.emplace_back(retval); m_deferredData->m_DBufs.emplace_back(retval);
return retval; return retval;
} }
@ -1360,11 +1357,9 @@ void GLTextureD::bind(size_t idx, int b)
} }
ITextureD* ITextureD*
GLDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) GLDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
{ {
GLTextureD* retval = new GLTextureD(width, height, fmt); GLTextureD* retval = new GLTextureD(width, height, fmt);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_DTexs.emplace_back(retval); m_deferredData->m_DTexs.emplace_back(retval);
return retval; return retval;
} }
@ -1430,15 +1425,13 @@ GLTextureR::~GLTextureR()
} }
ITextureR* ITextureR*
GLDataFactory::newRenderTexture(size_t width, size_t height, GLDataFactory::Context::newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding) bool enableShaderColorBinding, bool enableShaderDepthBinding)
{ {
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent.m_parent->getCommandQueue());
GLTextureR* retval = new GLTextureR(q, width, height, m_drawSamples, GLTextureR* retval = new GLTextureR(q, width, height, m_parent.m_drawSamples,
enableShaderColorBinding, enableShaderDepthBinding); enableShaderColorBinding, enableShaderDepthBinding);
q->resizeRenderTexture(retval, width, height); q->resizeRenderTexture(retval, width, height);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_RTexs.emplace_back(retval); m_deferredData->m_RTexs.emplace_back(retval);
return retval; return retval;
} }
@ -1455,13 +1448,11 @@ GLVertexFormat::GLVertexFormat(GLCommandQueue* q, size_t elementCount,
} }
GLVertexFormat::~GLVertexFormat() {m_q->delVertexFormat(this);} GLVertexFormat::~GLVertexFormat() {m_q->delVertexFormat(this);}
IVertexFormat* GLDataFactory::newVertexFormat IVertexFormat* GLDataFactory::Context::newVertexFormat
(size_t elementCount, const VertexElementDescriptor* elements) (size_t elementCount, const VertexElementDescriptor* elements)
{ {
GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent->getCommandQueue()); GLCommandQueue* q = static_cast<GLCommandQueue*>(m_parent.m_parent->getCommandQueue());
GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements); GLVertexFormat* retval = new struct GLVertexFormat(q, elementCount, elements);
if (!m_deferredData.get())
m_deferredData.reset(new struct GLData());
m_deferredData->m_VFmts.emplace_back(retval); m_deferredData->m_VFmts.emplace_back(retval);
return retval; return retval;
} }

View File

@ -773,6 +773,7 @@ class VulkanGraphicsBufferS : public IGraphicsBufferS
ThrowIfFailed(vkCreateBuffer(ctx->m_dev, &bufInfo, nullptr, &m_bufferInfo.buffer)); ThrowIfFailed(vkCreateBuffer(ctx->m_dev, &bufInfo, nullptr, &m_bufferInfo.buffer));
} }
public: public:
size_t size() const {return m_sz;}
size_t m_stride; size_t m_stride;
size_t m_count; size_t m_count;
VkDescriptorBufferInfo m_bufferInfo; VkDescriptorBufferInfo m_bufferInfo;
@ -2047,6 +2048,7 @@ struct VulkanShaderDataBinding : IShaderDataBinding
IGraphicsBuffer* m_ibuf; IGraphicsBuffer* m_ibuf;
size_t m_ubufCount; size_t m_ubufCount;
std::unique_ptr<IGraphicsBuffer*[]> m_ubufs; std::unique_ptr<IGraphicsBuffer*[]> m_ubufs;
std::vector<VkDescriptorBufferInfo> m_ubufOffs;
size_t m_texCount; size_t m_texCount;
std::unique_ptr<ITexture*[]> m_texs; std::unique_ptr<ITexture*[]> m_texs;
@ -2067,6 +2069,7 @@ struct VulkanShaderDataBinding : IShaderDataBinding
IShaderPipeline* pipeline, IShaderPipeline* pipeline,
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf, IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
size_t ubufCount, IGraphicsBuffer** ubufs, size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs) size_t texCount, ITexture** texs)
: m_ctx(ctx), : m_ctx(ctx),
m_pipeline(static_cast<VulkanShaderPipeline*>(pipeline)), m_pipeline(static_cast<VulkanShaderPipeline*>(pipeline)),
@ -2078,10 +2081,28 @@ struct VulkanShaderDataBinding : IShaderDataBinding
m_texCount(texCount), m_texCount(texCount),
m_texs(new ITexture*[texCount]) m_texs(new ITexture*[texCount])
{ {
if (ubufOffs && ubufSizes)
{
m_ubufOffs.reserve(ubufCount);
for (size_t i=0 ; i<ubufCount ; ++i)
m_ubufOffs.push_back({VK_NULL_HANDLE, ubufOffs[i], ubufSizes[i]});
}
for (size_t i=0 ; i<ubufCount ; ++i) for (size_t i=0 ; i<ubufCount ; ++i)
{
#ifndef NDEBUG
if (!ubufs[i])
Log.report(logvisor::Fatal, "null uniform-buffer %d provided to newShaderDataBinding", int(i));
#endif
m_ubufs[i] = ubufs[i]; m_ubufs[i] = ubufs[i];
}
for (size_t i=0 ; i<texCount ; ++i) for (size_t i=0 ; i<texCount ; ++i)
{
#ifndef NDEBUG
if (!texs[i])
Log.report(logvisor::Fatal, "null texture %d provided to newShaderDataBinding", int(i));
#endif
m_texs[i] = texs[i]; m_texs[i] = texs[i];
}
size_t totalDescs = ubufCount + texCount; size_t totalDescs = ubufCount + texCount;
if (totalDescs > 0) if (totalDescs > 0)
@ -2151,22 +2172,49 @@ struct VulkanShaderDataBinding : IShaderDataBinding
} }
size_t binding = 0; size_t binding = 0;
for (size_t i=0 ; i<BOO_GLSL_MAX_UNIFORM_COUNT ; ++i) if (m_ubufOffs.size())
{ {
if (i<m_ubufCount) for (size_t i=0 ; i<BOO_GLSL_MAX_UNIFORM_COUNT ; ++i)
{ {
writes[totalWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET; if (i<m_ubufCount)
writes[totalWrites].pNext = nullptr; {
writes[totalWrites].dstSet = m_descSets[b]; writes[totalWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[totalWrites].descriptorCount = 1; writes[totalWrites].pNext = nullptr;
writes[totalWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC; writes[totalWrites].dstSet = m_descSets[b];
writes[totalWrites].pBufferInfo = GetBufferGPUResource(m_ubufs[i], b); writes[totalWrites].descriptorCount = 1;
writes[totalWrites].dstArrayElement = 0; writes[totalWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
writes[totalWrites].dstBinding = binding; const VkDescriptorBufferInfo* origInfo = GetBufferGPUResource(m_ubufs[i], b);
++totalWrites; VkDescriptorBufferInfo& modInfo = m_ubufOffs[i];
modInfo.buffer = origInfo->buffer;
modInfo.offset += origInfo->offset;
writes[totalWrites].pBufferInfo = &modInfo;
writes[totalWrites].dstArrayElement = 0;
writes[totalWrites].dstBinding = binding;
++totalWrites;
}
++binding;
} }
++binding;
} }
else
{
for (size_t i=0 ; i<BOO_GLSL_MAX_UNIFORM_COUNT ; ++i)
{
if (i<m_ubufCount)
{
writes[totalWrites].sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET;
writes[totalWrites].pNext = nullptr;
writes[totalWrites].dstSet = m_descSets[b];
writes[totalWrites].descriptorCount = 1;
writes[totalWrites].descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC;
writes[totalWrites].pBufferInfo = GetBufferGPUResource(m_ubufs[i], b);
writes[totalWrites].dstArrayElement = 0;
writes[totalWrites].dstBinding = binding;
++totalWrites;
}
++binding;
}
}
for (size_t i=0 ; i<BOO_GLSL_MAX_TEXTURE_COUNT ; ++i) for (size_t i=0 ; i<BOO_GLSL_MAX_TEXTURE_COUNT ; ++i)
{ {
if (i<m_texCount) if (i<m_texCount)
@ -2868,7 +2916,7 @@ VulkanDataFactory::VulkanDataFactory(IGraphicsContext* parent, VulkanContext* ct
ThrowIfFailed(vkCreateRenderPass(ctx->m_dev, &renderPass, nullptr, &ctx->m_pass)); ThrowIfFailed(vkCreateRenderPass(ctx->m_dev, &renderPass, nullptr, &ctx->m_pass));
} }
IShaderPipeline* VulkanDataFactory::newShaderPipeline IShaderPipeline* VulkanDataFactory::Context::newShaderPipeline
(const char* vertSource, const char* fragSource, (const char* vertSource, const char* fragSource,
std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut, std::vector<unsigned int>& vertBlobOut, std::vector<unsigned int>& fragBlobOut,
std::vector<unsigned char>& pipelineBlob, IVertexFormat* vtxFmt, std::vector<unsigned char>& pipelineBlob, IVertexFormat* vtxFmt,
@ -2918,12 +2966,12 @@ IShaderPipeline* VulkanDataFactory::newShaderPipeline
smCreateInfo.codeSize = vertBlobOut.size() * sizeof(unsigned int); smCreateInfo.codeSize = vertBlobOut.size() * sizeof(unsigned int);
smCreateInfo.pCode = vertBlobOut.data(); smCreateInfo.pCode = vertBlobOut.data();
VkShaderModule vertModule; VkShaderModule vertModule;
ThrowIfFailed(vkCreateShaderModule(m_ctx->m_dev, &smCreateInfo, nullptr, &vertModule)); ThrowIfFailed(vkCreateShaderModule(m_parent.m_ctx->m_dev, &smCreateInfo, nullptr, &vertModule));
smCreateInfo.codeSize = fragBlobOut.size() * sizeof(unsigned int); smCreateInfo.codeSize = fragBlobOut.size() * sizeof(unsigned int);
smCreateInfo.pCode = fragBlobOut.data(); smCreateInfo.pCode = fragBlobOut.data();
VkShaderModule fragModule; VkShaderModule fragModule;
ThrowIfFailed(vkCreateShaderModule(m_ctx->m_dev, &smCreateInfo, nullptr, &fragModule)); ThrowIfFailed(vkCreateShaderModule(m_parent.m_ctx->m_dev, &smCreateInfo, nullptr, &fragModule));
VkPipelineCacheCreateInfo cacheDataInfo = {}; VkPipelineCacheCreateInfo cacheDataInfo = {};
cacheDataInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO; cacheDataInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_CACHE_CREATE_INFO;
@ -2933,180 +2981,116 @@ IShaderPipeline* VulkanDataFactory::newShaderPipeline
cacheDataInfo.pInitialData = pipelineBlob.data(); cacheDataInfo.pInitialData = pipelineBlob.data();
VkPipelineCache pipelineCache; VkPipelineCache pipelineCache;
ThrowIfFailed(vkCreatePipelineCache(m_ctx->m_dev, &cacheDataInfo, nullptr, &pipelineCache)); ThrowIfFailed(vkCreatePipelineCache(m_parent.m_ctx->m_dev, &cacheDataInfo, nullptr, &pipelineCache));
VulkanShaderPipeline* retval = new VulkanShaderPipeline(m_ctx, vertModule, fragModule, pipelineCache, VulkanShaderPipeline* retval = new VulkanShaderPipeline(m_parent.m_ctx, vertModule, fragModule, pipelineCache,
static_cast<const VulkanVertexFormat*>(vtxFmt), static_cast<const VulkanVertexFormat*>(vtxFmt),
srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling); srcFac, dstFac, prim, depthTest, depthWrite, backfaceCulling);
if (pipelineBlob.empty()) if (pipelineBlob.empty())
{ {
size_t cacheSz = 0; size_t cacheSz = 0;
ThrowIfFailed(vkGetPipelineCacheData(m_ctx->m_dev, pipelineCache, &cacheSz, nullptr)); ThrowIfFailed(vkGetPipelineCacheData(m_parent.m_ctx->m_dev, pipelineCache, &cacheSz, nullptr));
if (cacheSz) if (cacheSz)
{ {
pipelineBlob.resize(cacheSz); pipelineBlob.resize(cacheSz);
ThrowIfFailed(vkGetPipelineCacheData(m_ctx->m_dev, pipelineCache, &cacheSz, pipelineBlob.data())); ThrowIfFailed(vkGetPipelineCacheData(m_parent.m_ctx->m_dev, pipelineCache, &cacheSz, pipelineBlob.data()));
pipelineBlob.resize(cacheSz); pipelineBlob.resize(cacheSz);
} }
} }
vkDestroyPipelineCache(m_ctx->m_dev, pipelineCache, nullptr); vkDestroyPipelineCache(m_parent.m_ctx->m_dev, pipelineCache, nullptr);
vkDestroyShaderModule(m_ctx->m_dev, fragModule, nullptr); vkDestroyShaderModule(m_parent.m_ctx->m_dev, fragModule, nullptr);
vkDestroyShaderModule(m_ctx->m_dev, vertModule, nullptr); vkDestroyShaderModule(m_parent.m_ctx->m_dev, vertModule, nullptr);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_SPs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_SPs.emplace_back(retval);
return retval; return retval;
} }
IGraphicsBufferS* VulkanDataFactory::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count) IGraphicsBufferS* VulkanDataFactory::Context::newStaticBuffer(BufferUse use, const void* data, size_t stride, size_t count)
{ {
VulkanGraphicsBufferS* retval = new VulkanGraphicsBufferS(use, m_ctx, data, stride, count); VulkanGraphicsBufferS* retval = new VulkanGraphicsBufferS(use, m_parent.m_ctx, data, stride, count);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_SBufs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_SBufs.emplace_back(retval);
return retval; return retval;
} }
IGraphicsBufferD* VulkanDataFactory::newDynamicBuffer(BufferUse use, size_t stride, size_t count) IGraphicsBufferD* VulkanDataFactory::Context::newDynamicBuffer(BufferUse use, size_t stride, size_t count)
{ {
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent->getCommandQueue()); VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent.m_parent->getCommandQueue());
VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, m_ctx, stride, count); VulkanGraphicsBufferD* retval = new VulkanGraphicsBufferD(q, use, m_parent.m_ctx, stride, count);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_DBufs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_DBufs.emplace_back(retval);
return retval; return retval;
} }
ITextureS* VulkanDataFactory::newStaticTexture(size_t width, size_t height, size_t mips, ITextureS* VulkanDataFactory::Context::newStaticTexture(size_t width, size_t height, size_t mips,
TextureFormat fmt, const void* data, size_t sz) TextureFormat fmt, const void* data, size_t sz)
{ {
VulkanTextureS* retval = new VulkanTextureS(m_ctx, width, height, mips, fmt, data, sz); VulkanTextureS* retval = new VulkanTextureS(m_parent.m_ctx, width, height, mips, fmt, data, sz);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_STexs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_STexs.emplace_back(retval);
return retval; return retval;
} }
GraphicsDataToken ITextureSA* VulkanDataFactory::Context::newStaticArrayTexture(size_t width, size_t height, size_t layers,
VulkanDataFactory::newStaticTextureNoContext(size_t width, size_t height, size_t mips, TextureFormat fmt, TextureFormat fmt, const void* data, size_t sz)
const void* data, size_t sz, ITextureS*& texOut)
{ {
VulkanTextureS* retval = new VulkanTextureS(m_ctx, width, height, mips, fmt, data, sz); VulkanTextureSA* retval = new VulkanTextureSA(m_parent.m_ctx, width, height, layers, fmt, data, sz);
VulkanData* tokData = new struct VulkanData(m_ctx);
tokData->m_STexs.emplace_back(retval);
texOut = retval;
uint32_t memTypeBits = ~0;
VkDeviceSize memSize = SizeTextureForGPU(retval, m_ctx, memTypeBits, 0);
/* allocate memory */
VkMemoryAllocateInfo memAlloc = {};
memAlloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
memAlloc.pNext = nullptr;
memAlloc.memoryTypeIndex = 0;
memAlloc.allocationSize = memSize;
ThrowIfFalse(MemoryTypeFromProperties(m_ctx, memTypeBits, 0, &memAlloc.memoryTypeIndex));
ThrowIfFailed(vkAllocateMemory(m_ctx->m_dev, &memAlloc, nullptr, &tokData->m_texMem));
/* Place texture */
PlaceTextureForGPU(retval, m_ctx, tokData->m_texMem);
/* Execute static uploads */
ThrowIfFailed(vkEndCommandBuffer(m_ctx->m_loadCmdBuf));
VkSubmitInfo submitInfo = {};
submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
submitInfo.commandBufferCount = 1;
submitInfo.pCommandBuffers = &m_ctx->m_loadCmdBuf;
ThrowIfFailed(vkQueueSubmit(m_ctx->m_queue, 1, &submitInfo, m_ctx->m_loadFence));
/* Block handle return until data is ready on GPU */
ThrowIfFailed(vkWaitForFences(m_ctx->m_dev, 1, &m_ctx->m_loadFence, VK_TRUE, -1));
/* Reset fence and command buffer */
ThrowIfFailed(vkResetFences(m_ctx->m_dev, 1, &m_ctx->m_loadFence));
ThrowIfFailed(vkResetCommandBuffer(m_ctx->m_loadCmdBuf, 0));
VkCommandBufferBeginInfo cmdBufBeginInfo = {};
cmdBufBeginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO;
cmdBufBeginInfo.flags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
ThrowIfFailed(vkBeginCommandBuffer(m_ctx->m_loadCmdBuf, &cmdBufBeginInfo));
/* Delete upload objects */
retval->deleteUploadObjects();
/* All set! */
std::unique_lock<std::mutex> lk(m_committedMutex);
m_committedData.insert(tokData);
return GraphicsDataToken(this, tokData);
}
ITextureSA* VulkanDataFactory::newStaticArrayTexture(size_t width, size_t height, size_t layers,
TextureFormat fmt, const void* data, size_t sz)
{
VulkanTextureSA* retval = new VulkanTextureSA(m_ctx, width, height, layers, fmt, data, sz);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_SATexs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_SATexs.emplace_back(retval);
return retval; return retval;
} }
ITextureD* VulkanDataFactory::newDynamicTexture(size_t width, size_t height, TextureFormat fmt) ITextureD* VulkanDataFactory::Context::newDynamicTexture(size_t width, size_t height, TextureFormat fmt)
{ {
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent->getCommandQueue()); VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent.m_parent->getCommandQueue());
VulkanTextureD* retval = new VulkanTextureD(q, m_ctx, width, height, fmt); VulkanTextureD* retval = new VulkanTextureD(q, m_parent.m_ctx, width, height, fmt);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_DTexs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_DTexs.emplace_back(retval);
return retval; return retval;
} }
ITextureR* VulkanDataFactory::newRenderTexture(size_t width, size_t height, ITextureR* VulkanDataFactory::Context::newRenderTexture(size_t width, size_t height,
bool enableShaderColorBinding, bool enableShaderDepthBinding) bool enableShaderColorBinding, bool enableShaderDepthBinding)
{ {
VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent->getCommandQueue()); VulkanCommandQueue* q = static_cast<VulkanCommandQueue*>(m_parent.m_parent->getCommandQueue());
VulkanTextureR* retval = new VulkanTextureR(m_ctx, q, width, height, m_drawSamples, VulkanTextureR* retval = new VulkanTextureR(m_parent.m_ctx, q, width, height, m_parent.m_drawSamples,
enableShaderColorBinding, enableShaderDepthBinding); enableShaderColorBinding, enableShaderDepthBinding);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_RTexs.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_RTexs.emplace_back(retval);
return retval; return retval;
} }
IVertexFormat* VulkanDataFactory::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements) IVertexFormat* VulkanDataFactory::Context::newVertexFormat(size_t elementCount, const VertexElementDescriptor* elements)
{ {
VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements); VulkanVertexFormat* retval = new struct VulkanVertexFormat(elementCount, elements);
if (!m_deferredData.get())
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_VFmts.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_VFmts.emplace_back(retval);
return retval; return retval;
} }
IShaderDataBinding* VulkanDataFactory::newShaderDataBinding(IShaderPipeline* pipeline, IShaderDataBinding* VulkanDataFactory::Context::newShaderDataBinding(IShaderPipeline* pipeline,
IVertexFormat* /*vtxFormat*/, IVertexFormat* /*vtxFormat*/,
IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf, IGraphicsBuffer* vbuf, IGraphicsBuffer* instVbuf, IGraphicsBuffer* ibuf,
size_t ubufCount, IGraphicsBuffer** ubufs, size_t ubufCount, IGraphicsBuffer** ubufs,
const size_t* ubufOffs, const size_t* ubufSizes,
size_t texCount, ITexture** texs) size_t texCount, ITexture** texs)
{ {
VulkanShaderDataBinding* retval = VulkanShaderDataBinding* retval =
new VulkanShaderDataBinding(m_ctx, pipeline, vbuf, instVbuf, ibuf, ubufCount, ubufs, texCount, texs); new VulkanShaderDataBinding(m_parent.m_ctx, pipeline, vbuf, instVbuf, ibuf,
if (!m_deferredData.get()) ubufCount, ubufs, ubufOffs, ubufSizes, texCount, texs);
m_deferredData.reset(new struct VulkanData(m_ctx));
static_cast<VulkanData*>(m_deferredData.get())->m_SBinds.emplace_back(retval); static_cast<VulkanData*>(m_deferredData.get())->m_SBinds.emplace_back(retval);
return retval; return retval;
} }
void VulkanDataFactory::reset() GraphicsDataToken VulkanDataFactory::commitTransaction
(const std::function<bool(IGraphicsDataFactory::Context&)>& trans)
{ {
delete static_cast<VulkanData*>(m_deferredData.get()); if (m_deferredData.get())
m_deferredData.reset(); Log.report(logvisor::Fatal, "nested commitTransaction usage detected");
} m_deferredData.reset(new VulkanData(m_ctx));
GraphicsDataToken VulkanDataFactory::commit() Context ctx(*this);
{ if (!trans(ctx))
if (!m_deferredData.get()) {
delete m_deferredData.get();
m_deferredData.reset();
return GraphicsDataToken(this, nullptr); return GraphicsDataToken(this, nullptr);
}
VulkanData* retval = static_cast<VulkanData*>(m_deferredData.get()); VulkanData* retval = static_cast<VulkanData*>(m_deferredData.get());

View File

@ -228,92 +228,128 @@ struct TestApplicationCallback : IApplicationCallback
IGraphicsDataFactory* factory = self->mainWindow->getLoadContextDataFactory(); IGraphicsDataFactory* factory = self->mainWindow->getLoadContextDataFactory();
/* Create render target */ GraphicsDataToken data = factory->commitTransaction([&](IGraphicsDataFactory::Context& ctx) -> bool
int x, y, w, h;
self->mainWindow->getWindowFrame(x, y, w, h);
self->m_renderTarget = factory->newRenderTexture(w, h, false, false);
/* Make Tri-strip VBO */
struct Vert
{ {
float pos[3]; /* Create render target */
float uv[2]; int x, y, w, h;
}; self->mainWindow->getWindowFrame(x, y, w, h);
static const Vert quad[4] = self->m_renderTarget = ctx.newRenderTexture(w, h, false, false);
{
{{0.5,0.5},{1.0,1.0}},
{{-0.5,0.5},{0.0,1.0}},
{{0.5,-0.5},{1.0,0.0}},
{{-0.5,-0.5},{0.0,0.0}}
};
IGraphicsBuffer* vbo =
factory->newStaticBuffer(BufferUse::Vertex, quad, sizeof(Vert), 4);
/* Make vertex format */ /* Make Tri-strip VBO */
VertexElementDescriptor descs[2] = struct Vert
{
{vbo, nullptr, VertexSemantic::Position3},
{vbo, nullptr, VertexSemantic::UV2}
};
IVertexFormat* vfmt = factory->newVertexFormat(2, descs);
/* Make ramp texture */
using Pixel = uint8_t[4];
static Pixel tex[256][256];
for (int i=0 ; i<256 ; ++i)
for (int j=0 ; j<256 ; ++j)
{ {
tex[i][j][0] = i; float pos[3];
tex[i][j][1] = j; float uv[2];
tex[i][j][2] = 0; };
tex[i][j][3] = 0xff; static const Vert quad[4] =
{
{{0.5,0.5},{1.0,1.0}},
{{-0.5,0.5},{0.0,1.0}},
{{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);
/* Make vertex format */
VertexElementDescriptor descs[2] =
{
{vbo, nullptr, VertexSemantic::Position3},
{vbo, nullptr, VertexSemantic::UV2}
};
IVertexFormat* vfmt = ctx.newVertexFormat(2, descs);
/* Make ramp texture */
using Pixel = uint8_t[4];
static Pixel tex[256][256];
for (int i=0 ; i<256 ; ++i)
for (int j=0 ; j<256 ; ++j)
{
tex[i][j][0] = i;
tex[i][j][1] = j;
tex[i][j][2] = 0;
tex[i][j][3] = 0xff;
}
ITexture* texture =
ctx.newStaticTexture(256, 256, 1, TextureFormat::RGBA8, tex, 256*256*4);
/* Make shader pipeline */
IShaderPipeline* pipeline = nullptr;
if (ctx.platform() == IGraphicsDataFactory::Platform::OGL)
{
GLDataFactory::Context& glF = dynamic_cast<GLDataFactory::Context&>(ctx);
static const char* VS =
"#version 330\n"
"layout(location=0) in vec3 in_pos;\n"
"layout(location=1) in vec2 in_uv;\n"
"out vec2 out_uv;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(in_pos, 1.0);\n"
" out_uv = in_uv;\n"
"}\n";
static const char* FS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"precision highp float;\n"
"TBINDING0 uniform sampler2D texs[1];\n"
"layout(location=0) out vec4 out_frag;\n"
"in vec2 out_uv;\n"
"void main()\n"
"{\n"
" out_frag = texture(texs[0], out_uv);\n"
"}\n";
pipeline = glF.newShaderPipeline(VS, FS, 1, "texs", 0, nullptr,
BlendFactor::One, BlendFactor::Zero,
Primitive::TriStrips, true, true, false);
} }
ITexture* texture =
factory->newStaticTexture(256, 256, 1, TextureFormat::RGBA8, tex, 256*256*4);
/* Make shader pipeline */
IShaderPipeline* pipeline = nullptr;
if (factory->platform() == IGraphicsDataFactory::Platform::OGL)
{
GLDataFactory* glF = dynamic_cast<GLDataFactory*>(factory);
static const char* VS =
"#version 330\n"
"layout(location=0) in vec3 in_pos;\n"
"layout(location=1) in vec2 in_uv;\n"
"out vec2 out_uv;\n"
"void main()\n"
"{\n"
" gl_Position = vec4(in_pos, 1.0);\n"
" out_uv = in_uv;\n"
"}\n";
static const char* FS =
"#version 330\n"
BOO_GLSL_BINDING_HEAD
"precision highp float;\n"
"TBINDING0 uniform sampler2D texs[1];\n"
"layout(location=0) out vec4 out_frag;\n"
"in vec2 out_uv;\n"
"void main()\n"
"{\n"
" out_frag = texture(texs[0], out_uv);\n"
"}\n";
pipeline = glF->newShaderPipeline(VS, FS, 1, "texs", 0, nullptr,
BlendFactor::One, BlendFactor::Zero,
Primitive::TriStrips, true, true, false);
}
#if _WIN32 #if _WIN32
else if (factory->platform() == IGraphicsDataFactory::Platform::D3D12 || else if (ctx.platform() == IGraphicsDataFactory::Platform::D3D12 ||
factory->platform() == IGraphicsDataFactory::Platform::D3D11) ctx.platform() == IGraphicsDataFactory::Platform::D3D11)
{ {
ID3DDataFactory* d3dF = dynamic_cast<ID3DDataFactory*>(factory); ID3DDataFactory* d3dF = dynamic_cast<ID3DDataFactory*>(factory);
static const char* VS = static const char* VS =
"struct VertData {float3 in_pos : POSITION; float2 in_uv : UV;};\n" "struct VertData {float3 in_pos : POSITION; float2 in_uv : UV;};\n"
"struct VertToFrag {float4 out_pos : SV_Position; float2 out_uv : UV;};\n" "struct VertToFrag {float4 out_pos : SV_Position; float2 out_uv : UV;};\n"
"VertToFrag main(in VertData v)\n" "VertToFrag main(in VertData v)\n"
"{\n"
" VertToFrag retval;\n"
" retval.out_pos = float4(v.in_pos, 1.0);\n"
" retval.out_uv = v.in_uv;\n"
" return retval;\n"
"}\n";
static const char* PS =
"SamplerState samp : register(s0);\n"
"Texture2D tex : register(t0);\n"
"struct VertToFrag {float4 out_pos : SV_Position; float2 out_uv : UV;};\n"
"float4 main(in VertToFrag d) : SV_Target0\n"
"{\n"
" return tex.Sample(samp, d.out_uv);\n"
"}\n";
ComPtr<ID3DBlob> vsCompile;
ComPtr<ID3DBlob> psCompile;
ComPtr<ID3DBlob> cachedPipeline;
pipeline = d3dF->newShaderPipeline(VS, PS, vsCompile, psCompile, cachedPipeline, vfmt,
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
true, true, false);
}
#elif BOO_HAS_METAL
else if (ctx.platform() == IGraphicsDataFactory::Platform::Metal)
{
MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory);
static const char* VS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertData {float3 in_pos [[ attribute(0) ]]; float2 in_uv [[ attribute(1) ]];};\n"
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"vertex VertToFrag vmain(VertData v [[ stage_in ]])\n"
"{\n" "{\n"
" VertToFrag retval;\n" " VertToFrag retval;\n"
" retval.out_pos = float4(v.in_pos, 1.0);\n" " retval.out_pos = float4(v.in_pos, 1.0);\n"
@ -321,62 +357,26 @@ struct TestApplicationCallback : IApplicationCallback
" return retval;\n" " return retval;\n"
"}\n"; "}\n";
static const char* PS = static const char* FS =
"SamplerState samp : register(s0);\n" "#include <metal_stdlib>\n"
"Texture2D tex : register(t0);\n" "using namespace metal;\n"
"struct VertToFrag {float4 out_pos : SV_Position; float2 out_uv : UV;};\n" "constexpr sampler samp(address::repeat);\n"
"float4 main(in VertToFrag d) : SV_Target0\n" "struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"fragment float4 fmain(VertToFrag d [[ stage_in ]], texture2d<float> tex [[ texture(0) ]])\n"
"{\n" "{\n"
" return tex.Sample(samp, d.out_uv);\n" " return tex.sample(samp, d.out_uv);\n"
"}\n"; "}\n";
ComPtr<ID3DBlob> vsCompile; pipeline = metalF->newShaderPipeline(VS, FS, vfmt, 1,
ComPtr<ID3DBlob> psCompile; BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
ComPtr<ID3DBlob> cachedPipeline; true, true, false);
pipeline = d3dF->newShaderPipeline(VS, PS, vsCompile, psCompile, cachedPipeline, vfmt, }
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
true, true, false);
}
#elif BOO_HAS_METAL
else if (factory->platform() == IGraphicsDataFactory::Platform::Metal)
{
MetalDataFactory* metalF = dynamic_cast<MetalDataFactory*>(factory);
static const char* VS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"struct VertData {float3 in_pos [[ attribute(0) ]]; float2 in_uv [[ attribute(1) ]];};\n"
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"vertex VertToFrag vmain(VertData v [[ stage_in ]])\n"
"{\n"
" VertToFrag retval;\n"
" retval.out_pos = float4(v.in_pos, 1.0);\n"
" retval.out_uv = v.in_uv;\n"
" return retval;\n"
"}\n";
static const char* FS =
"#include <metal_stdlib>\n"
"using namespace metal;\n"
"constexpr sampler samp(address::repeat);\n"
"struct VertToFrag {float4 out_pos [[ position ]]; float2 out_uv;};\n"
"fragment float4 fmain(VertToFrag d [[ stage_in ]], texture2d<float> tex [[ texture(0) ]])\n"
"{\n"
" return tex.sample(samp, d.out_uv);\n"
"}\n";
pipeline = metalF->newShaderPipeline(VS, FS, vfmt, 1,
BlendFactor::One, BlendFactor::Zero, Primitive::TriStrips,
true, true, false);
}
#endif #endif
/* Make shader data binding */ /* Make shader data binding */
self->m_binding = self->m_binding =
factory->newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, 1, &texture); ctx.newShaderDataBinding(pipeline, vfmt, vbo, nullptr, nullptr, 0, nullptr, 1, &texture);
});
/* Commit objects */
GraphicsDataToken data = factory->commit();
/* Return control to client */ /* Return control to client */
lk.unlock(); lk.unlock();