mirror of
https://github.com/scratchfoundation/bgfx.git
synced 2024-11-28 18:45:54 -05:00
GL: Added draw indirect support.
This commit is contained in:
parent
5c6854c684
commit
b04af680ad
4 changed files with 147 additions and 58 deletions
|
@ -1409,6 +1409,9 @@ namespace bgfx
|
|||
///
|
||||
void setBuffer(uint8_t _stage, DynamicVertexBufferHandle _handle, Access::Enum _access);
|
||||
|
||||
///
|
||||
void setBuffer(uint8_t _stage, DrawIndirectBufferHandle _handle, Access::Enum _access);
|
||||
|
||||
///
|
||||
void setImage(uint8_t _stage, UniformHandle _sampler, TextureHandle _handle, uint8_t _mip, Access::Enum _access, TextureFormat::Enum _format = TextureFormat::Count);
|
||||
|
||||
|
|
|
@ -146,6 +146,8 @@ typedef GLint (GL_APIENTRYP PFNGLGETUNIFORMLOCATIONPROC) (GLuint progra
|
|||
typedef void (GL_APIENTRYP PFNGLINVALIDATEFRAMEBUFFERPROC) (GLenum target, GLsizei numAttachments, const GLenum *attachments);
|
||||
typedef void (GL_APIENTRYP PFNGLLINKPROGRAMPROC) (GLuint program);
|
||||
typedef void (GL_APIENTRYP PFNGLMEMORYBARRIERPROC) (GLbitfield barriers);
|
||||
typedef void (GL_APIENTRYP PFNGLMULTIDRAWARRAYSINDIRECTPROC) (GLenum mode, const void *indirect, GLsizei drawcount, GLsizei stride);
|
||||
typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSINDIRECTPROC) (GLenum mode, GLenum type, const void *indirect, GLsizei drawcount, GLsizei stride);
|
||||
typedef void (GL_APIENTRYP PFNGLOBJECTLABELPROC) (GLenum identifier, GLuint name, GLsizei length, const GLchar *label);
|
||||
typedef void (GL_APIENTRYP PFNGLOBJECTPTRLABELPROC) (const void *ptr, GLsizei length, const GLchar *label);
|
||||
typedef void (GL_APIENTRYP PFNGLPIXELSTOREIPROC) (GLenum pname, GLint param);
|
||||
|
@ -266,7 +268,7 @@ GL_IMPORT______(false, PFNGLDISABLEVERTEXATTRIBARRAYPROC, glDisableVert
|
|||
GL_IMPORT______(true, PFNGLDISPATCHCOMPUTEPROC, glDispatchCompute);
|
||||
GL_IMPORT______(true, PFNGLDISPATCHCOMPUTEINDIRECTPROC, glDispatchComputeIndirect);
|
||||
GL_IMPORT______(false, PFNGLDRAWARRAYSPROC, glDrawArrays);
|
||||
GL_IMPORT______(true, PFNGLDRAWARRAYSINDIRECTPROC, glDrawArraysInderect);
|
||||
GL_IMPORT______(true, PFNGLDRAWARRAYSINDIRECTPROC, glDrawArraysIndirect);
|
||||
GL_IMPORT______(true, PFNGLDRAWARRAYSINSTANCEDPROC, glDrawArraysInstanced);
|
||||
GL_IMPORT______(true, PFNGLDRAWBUFFERPROC, glDrawBuffer);
|
||||
GL_IMPORT______(true, PFNGLDRAWBUFFERSPROC, glDrawBuffers);
|
||||
|
@ -317,6 +319,8 @@ GL_IMPORT______(false, PFNGLGETUNIFORMLOCATIONPROC, glGetUniformL
|
|||
GL_IMPORT______(true, PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer);
|
||||
GL_IMPORT______(false, PFNGLLINKPROGRAMPROC, glLinkProgram);
|
||||
GL_IMPORT______(true, PFNGLMEMORYBARRIERPROC, glMemoryBarrier);
|
||||
GL_IMPORT______(true, PFNGLMULTIDRAWARRAYSINDIRECTPROC, glMultiDrawArraysIndirect);
|
||||
GL_IMPORT______(true, PFNGLMULTIDRAWELEMENTSINDIRECTPROC, glMultiDrawElementsIndirect);
|
||||
GL_IMPORT______(true, PFNGLOBJECTLABELPROC, glObjectLabel);
|
||||
GL_IMPORT______(true, PFNGLOBJECTPTRLABELPROC, glObjectPtrLabel);
|
||||
GL_IMPORT______(false, PFNGLPIXELSTOREIPROC, glPixelStorei);
|
||||
|
@ -395,6 +399,9 @@ GL_IMPORT_ARB__(true, PFNGLDRAWBUFFERSPROC, glDrawBuffers
|
|||
|
||||
GL_IMPORT_ARB__(true, PFNGLINVALIDATEFRAMEBUFFERPROC, glInvalidateFramebuffer);
|
||||
|
||||
GL_IMPORT_ARB__(true, PFNGLMULTIDRAWARRAYSINDIRECTPROC, glMultiDrawArraysIndirect);
|
||||
GL_IMPORT_ARB__(true, PFNGLMULTIDRAWELEMENTSINDIRECTPROC, glMultiDrawElementsIndirect);
|
||||
|
||||
GL_IMPORT_EXT__(true, PFNGLBINDFRAMEBUFFERPROC, glBindFramebuffer);
|
||||
GL_IMPORT_EXT__(true, PFNGLGENFRAMEBUFFERSPROC, glGenFramebuffers);
|
||||
GL_IMPORT_EXT__(true, PFNGLDELETEFRAMEBUFFERSPROC, glDeleteFramebuffers);
|
||||
|
@ -443,8 +450,10 @@ GL_IMPORT_EXT__(true, PFNGLPUSHGROUPMARKEREXTPROC, glPushGroupMa
|
|||
GL_IMPORT_EXT__(true, PFNGLPOPGROUPMARKEREXTPROC, glPopGroupMarker);
|
||||
GL_IMPORT_EXT__(true, PFNGLOBJECTLABELPROC, glObjectLabel);
|
||||
|
||||
GL_IMPORT_EXT__(true, PFNGLDRAWARRAYSINDIRECTPROC, glDrawArraysInderect);
|
||||
GL_IMPORT_EXT__(true, PFNGLDRAWARRAYSINDIRECTPROC, glDrawArraysIndirect);
|
||||
GL_IMPORT_EXT__(true, PFNGLDRAWELEMENTSINDIRECTPROC, glDrawElementsIndirect);
|
||||
GL_IMPORT_EXT__(true, PFNGLMULTIDRAWARRAYSINDIRECTPROC, glMultiDrawArraysIndirect);
|
||||
GL_IMPORT_EXT__(true, PFNGLMULTIDRAWELEMENTSINDIRECTPROC, glMultiDrawElementsIndirect);
|
||||
|
||||
GL_IMPORT_OES__(true, PFNGLGETPROGRAMBINARYPROC, glGetProgramBinary);
|
||||
GL_IMPORT_OES__(true, PFNGLPROGRAMBINARYPROC, glProgramBinary);
|
||||
|
|
|
@ -813,6 +813,26 @@ namespace bgfx { namespace gl
|
|||
{
|
||||
}
|
||||
|
||||
static void GL_APIENTRY stubMultiDrawArraysIndirect(GLenum _mode, const void* _indirect, GLsizei _drawcount, GLsizei _stride)
|
||||
{
|
||||
const uint8_t* args = (const uint8_t*)_indirect;
|
||||
for (GLsizei ii = 0; ii < _drawcount; ++ii)
|
||||
{
|
||||
GL_CHECK(glDrawArraysIndirect(_mode, (void*)args) );
|
||||
args += _stride;
|
||||
}
|
||||
}
|
||||
|
||||
static void GL_APIENTRY stubMultiDrawElementsIndirect(GLenum _mode, GLenum _type, const void* _indirect, GLsizei _drawcount, GLsizei _stride)
|
||||
{
|
||||
const uint8_t* args = (const uint8_t*)_indirect;
|
||||
for (GLsizei ii = 0; ii < _drawcount; ++ii)
|
||||
{
|
||||
GL_CHECK(glDrawElementsIndirect(_mode, _type, (void*)args) );
|
||||
args += _stride;
|
||||
}
|
||||
}
|
||||
|
||||
typedef void (*PostSwapBuffersFn)(uint32_t _width, uint32_t _height);
|
||||
|
||||
static const char* getGLString(GLenum _name)
|
||||
|
@ -1401,8 +1421,18 @@ namespace bgfx { namespace gl
|
|||
|| s_extension[Extension::EXT_multi_draw_indirect].m_supported
|
||||
;
|
||||
|
||||
if (drawIndirectSupported)
|
||||
{
|
||||
if (NULL == glMultiDrawArraysIndirect
|
||||
|| NULL == glMultiDrawElementsIndirect)
|
||||
{
|
||||
glMultiDrawArraysIndirect = stubMultiDrawArraysIndirect;
|
||||
glMultiDrawElementsIndirect = stubMultiDrawElementsIndirect;
|
||||
}
|
||||
}
|
||||
|
||||
g_caps.supported |= drawIndirectSupported
|
||||
? 0 //BGFX_CAPS_DRAW_INDIRECT
|
||||
? BGFX_CAPS_DRAW_INDIRECT
|
||||
: 0
|
||||
;
|
||||
|
||||
|
@ -1688,9 +1718,9 @@ namespace bgfx { namespace gl
|
|||
{
|
||||
}
|
||||
|
||||
void createVertexBuffer(VertexBufferHandle _handle, Memory* _mem, VertexDeclHandle _declHandle, uint8_t /*_flags*/) BX_OVERRIDE
|
||||
void createVertexBuffer(VertexBufferHandle _handle, Memory* _mem, VertexDeclHandle _declHandle, uint8_t _flags) BX_OVERRIDE
|
||||
{
|
||||
m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle);
|
||||
m_vertexBuffers[_handle.idx].create(_mem->size, _mem->data, _declHandle, _flags);
|
||||
}
|
||||
|
||||
void destroyVertexBuffer(VertexBufferHandle _handle) BX_OVERRIDE
|
||||
|
@ -1713,10 +1743,10 @@ namespace bgfx { namespace gl
|
|||
m_indexBuffers[_handle.idx].destroy();
|
||||
}
|
||||
|
||||
void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint8_t /*_flags*/) BX_OVERRIDE
|
||||
void createDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _size, uint8_t _flags) BX_OVERRIDE
|
||||
{
|
||||
VertexDeclHandle decl = BGFX_INVALID_HANDLE;
|
||||
m_vertexBuffers[_handle.idx].create(_size, NULL, decl);
|
||||
m_vertexBuffers[_handle.idx].create(_size, NULL, decl, _flags);
|
||||
}
|
||||
|
||||
void updateDynamicVertexBuffer(VertexBufferHandle _handle, uint32_t _offset, uint32_t _size, Memory* _mem) BX_OVERRIDE
|
||||
|
@ -5376,61 +5406,104 @@ namespace bgfx { namespace gl
|
|||
numVertices = vb.m_size/vertexDecl.m_stride;
|
||||
}
|
||||
|
||||
uint32_t numIndices = 0;
|
||||
uint32_t numIndices = 0;
|
||||
uint32_t numPrimsSubmitted = 0;
|
||||
uint32_t numInstances = 0;
|
||||
uint32_t numPrimsRendered = 0;
|
||||
uint32_t numInstances = 0;
|
||||
uint32_t numPrimsRendered = 0;
|
||||
uint32_t numDrawIndirect = 0;
|
||||
|
||||
if (isValid(draw.m_indexBuffer) )
|
||||
if (isValid(draw.m_drawIndirectBuffer) )
|
||||
{
|
||||
const IndexBufferGL& ib = m_indexBuffers[draw.m_indexBuffer.idx];
|
||||
const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32);
|
||||
const GLenum indexFormat = hasIndex16
|
||||
? GL_UNSIGNED_SHORT
|
||||
: GL_UNSIGNED_INT
|
||||
;
|
||||
|
||||
if (UINT32_MAX == draw.m_numIndices)
|
||||
const VertexBufferGL& vb = m_vertexBuffers[draw.m_drawIndirectBuffer.idx];
|
||||
if (currentState.m_drawIndirectBuffer.idx != draw.m_drawIndirectBuffer.idx)
|
||||
{
|
||||
const uint32_t indexSize = hasIndex16 ? 2 : 4;
|
||||
numIndices = ib.m_size/indexSize;
|
||||
numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub;
|
||||
numInstances = draw.m_numInstances;
|
||||
numPrimsRendered = numPrimsSubmitted*draw.m_numInstances;
|
||||
|
||||
GL_CHECK(glDrawElementsInstanced(prim.m_type
|
||||
, numIndices
|
||||
, indexFormat
|
||||
, (void*)0
|
||||
, draw.m_numInstances
|
||||
) );
|
||||
currentState.m_drawIndirectBuffer = draw.m_drawIndirectBuffer;
|
||||
GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, vb.m_id) );
|
||||
}
|
||||
else if (prim.m_min <= draw.m_numIndices)
|
||||
{
|
||||
numIndices = draw.m_numIndices;
|
||||
numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub;
|
||||
numInstances = draw.m_numInstances;
|
||||
numPrimsRendered = numPrimsSubmitted*draw.m_numInstances;
|
||||
|
||||
GL_CHECK(glDrawElementsInstanced(prim.m_type
|
||||
, numIndices
|
||||
, indexFormat
|
||||
, (void*)(uintptr_t)(draw.m_startIndex*2)
|
||||
, draw.m_numInstances
|
||||
) );
|
||||
if (isValid(draw.m_indexBuffer) )
|
||||
{
|
||||
const IndexBufferGL& ib = m_indexBuffers[draw.m_indexBuffer.idx];
|
||||
const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32);
|
||||
const GLenum indexFormat = hasIndex16
|
||||
? GL_UNSIGNED_SHORT
|
||||
: GL_UNSIGNED_INT
|
||||
;
|
||||
|
||||
const uint32_t commandSize = 5 * sizeof(uint32_t);
|
||||
numDrawIndirect = UINT16_MAX == draw.m_numDrawIndirect ? vb.m_size/commandSize : draw.m_numDrawIndirect;
|
||||
|
||||
uint32_t args = draw.m_startDrawIndirect * commandSize;
|
||||
GL_CHECK(glMultiDrawElementsIndirect(prim.m_type, indexFormat, (void*)args, numDrawIndirect, commandSize) );
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t commandSize = 4 * sizeof(uint32_t);
|
||||
numDrawIndirect = UINT16_MAX == draw.m_numDrawIndirect ? vb.m_size/commandSize : draw.m_numDrawIndirect;
|
||||
|
||||
uint32_t args = draw.m_startDrawIndirect * commandSize;
|
||||
GL_CHECK(glMultiDrawArraysIndirect(prim.m_type, (void*)args, numDrawIndirect, commandSize) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numPrimsSubmitted = numVertices/prim.m_div - prim.m_sub;
|
||||
numInstances = draw.m_numInstances;
|
||||
numPrimsRendered = numPrimsSubmitted*draw.m_numInstances;
|
||||
if (isValid(currentState.m_drawIndirectBuffer) )
|
||||
{
|
||||
currentState.m_drawIndirectBuffer.idx = invalidHandle;
|
||||
GL_CHECK(glBindBuffer(GL_DRAW_INDIRECT_BUFFER, 0) );
|
||||
}
|
||||
|
||||
GL_CHECK(glDrawArraysInstanced(prim.m_type
|
||||
, 0
|
||||
, numVertices
|
||||
, draw.m_numInstances
|
||||
) );
|
||||
if (isValid(draw.m_indexBuffer) )
|
||||
{
|
||||
const IndexBufferGL& ib = m_indexBuffers[draw.m_indexBuffer.idx];
|
||||
const bool hasIndex16 = 0 == (ib.m_flags & BGFX_BUFFER_INDEX32);
|
||||
const GLenum indexFormat = hasIndex16
|
||||
? GL_UNSIGNED_SHORT
|
||||
: GL_UNSIGNED_INT
|
||||
;
|
||||
|
||||
if (UINT32_MAX == draw.m_numIndices)
|
||||
{
|
||||
const uint32_t indexSize = hasIndex16 ? 2 : 4;
|
||||
numIndices = ib.m_size/indexSize;
|
||||
numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub;
|
||||
numInstances = draw.m_numInstances;
|
||||
numPrimsRendered = numPrimsSubmitted*draw.m_numInstances;
|
||||
|
||||
GL_CHECK(glDrawElementsInstanced(prim.m_type
|
||||
, numIndices
|
||||
, indexFormat
|
||||
, (void*)0
|
||||
, draw.m_numInstances
|
||||
) );
|
||||
}
|
||||
else if (prim.m_min <= draw.m_numIndices)
|
||||
{
|
||||
numIndices = draw.m_numIndices;
|
||||
numPrimsSubmitted = numIndices/prim.m_div - prim.m_sub;
|
||||
numInstances = draw.m_numInstances;
|
||||
numPrimsRendered = numPrimsSubmitted*draw.m_numInstances;
|
||||
|
||||
GL_CHECK(glDrawElementsInstanced(prim.m_type
|
||||
, numIndices
|
||||
, indexFormat
|
||||
, (void*)(uintptr_t)(draw.m_startIndex*2)
|
||||
, draw.m_numInstances
|
||||
) );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
numPrimsSubmitted = numVertices/prim.m_div - prim.m_sub;
|
||||
numInstances = draw.m_numInstances;
|
||||
numPrimsRendered = numPrimsSubmitted*draw.m_numInstances;
|
||||
|
||||
GL_CHECK(glDrawArraysInstanced(prim.m_type
|
||||
, 0
|
||||
, numVertices
|
||||
, draw.m_numInstances
|
||||
) );
|
||||
}
|
||||
}
|
||||
|
||||
statsNumPrimsSubmitted[primIndex] += numPrimsSubmitted;
|
||||
|
|
|
@ -868,32 +868,35 @@ namespace bgfx { namespace gl
|
|||
|
||||
struct VertexBufferGL
|
||||
{
|
||||
void create(uint32_t _size, void* _data, VertexDeclHandle _declHandle)
|
||||
void create(uint32_t _size, void* _data, VertexDeclHandle _declHandle, uint8_t _flags)
|
||||
{
|
||||
m_size = _size;
|
||||
m_decl = _declHandle;
|
||||
const bool drawIndirect = 0 != (_flags & BGFX_BUFFER_DRAW_INDIRECT);
|
||||
|
||||
m_target = drawIndirect ? GL_DRAW_INDIRECT_BUFFER : GL_ARRAY_BUFFER;
|
||||
|
||||
GL_CHECK(glGenBuffers(1, &m_id) );
|
||||
BX_CHECK(0 != m_id, "Failed to generate buffer id.");
|
||||
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id) );
|
||||
GL_CHECK(glBufferData(GL_ARRAY_BUFFER
|
||||
GL_CHECK(glBindBuffer(m_target, m_id) );
|
||||
GL_CHECK(glBufferData(m_target
|
||||
, _size
|
||||
, _data
|
||||
, (NULL==_data) ? GL_DYNAMIC_DRAW : GL_STATIC_DRAW
|
||||
) );
|
||||
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
|
||||
GL_CHECK(glBindBuffer(m_target, 0) );
|
||||
}
|
||||
|
||||
void update(uint32_t _offset, uint32_t _size, void* _data)
|
||||
{
|
||||
BX_CHECK(0 != m_id, "Updating invalid vertex buffer.");
|
||||
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, m_id) );
|
||||
GL_CHECK(glBufferSubData(GL_ARRAY_BUFFER
|
||||
GL_CHECK(glBindBuffer(m_target, m_id) );
|
||||
GL_CHECK(glBufferSubData(m_target
|
||||
, _offset
|
||||
, _size
|
||||
, _data
|
||||
) );
|
||||
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
|
||||
GL_CHECK(glBindBuffer(m_target, 0) );
|
||||
}
|
||||
|
||||
void destroy();
|
||||
|
@ -904,6 +907,7 @@ namespace bgfx { namespace gl
|
|||
}
|
||||
|
||||
GLuint m_id;
|
||||
GLenum m_target;
|
||||
uint32_t m_size;
|
||||
VertexDeclHandle m_decl;
|
||||
VaoCacheRef m_vcref;
|
||||
|
|
Loading…
Reference in a new issue