Fixed VAO cache.

This commit is contained in:
bkaradzic 2013-01-21 23:36:47 -08:00
parent b1cb4de638
commit e866a7b2e3
2 changed files with 153 additions and 70 deletions

View file

@ -720,6 +720,8 @@ namespace bgfx
{ {
GL_CHECK(glUseProgram(0) ); GL_CHECK(glUseProgram(0) );
GL_CHECK(glDeleteProgram(m_id) ); GL_CHECK(glDeleteProgram(m_id) );
m_vcref.invalidate(s_renderCtx.m_vaoCache);
} }
void Program::init() void Program::init()
@ -917,6 +919,22 @@ namespace bgfx
} }
} }
void IndexBuffer::destroy()
{
GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
GL_CHECK(glDeleteBuffers(1, &m_id) );
m_vcref.invalidate(s_renderCtx.m_vaoCache);
}
void VertexBuffer::destroy()
{
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
GL_CHECK(glDeleteBuffers(1, &m_id) );
m_vcref.invalidate(s_renderCtx.m_vaoCache);
}
static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _pixels) static void texImage(GLenum _target, GLint _level, GLint _internalFormat, GLsizei _width, GLsizei _height, GLsizei _depth, GLint _border, GLenum _format, GLenum _type, const GLvoid* _pixels)
{ {
#if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3
@ -1829,7 +1847,7 @@ namespace bgfx
} }
#if !BGFX_CONFIG_RENDERER_OPENGLES3 #if !BGFX_CONFIG_RENDERER_OPENGLES3
if (NULL != glVertexAttribDivisor if (false && NULL != glVertexAttribDivisor
&& NULL != glDrawArraysInstanced && NULL != glDrawArraysInstanced
&& NULL != glDrawElementsInstanced) && NULL != glDrawElementsInstanced)
{ {
@ -1995,6 +2013,13 @@ namespace bgfx
void Context::rendererSubmit() void Context::rendererSubmit()
{ {
if (s_renderCtx.m_vaoSupport)
{
GL_CHECK(glBindVertexArray(0) );
}
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
s_renderCtx.updateResolution(m_render->m_resolution); s_renderCtx.updateResolution(m_render->m_resolution);
int64_t elapsed = -bx::getHPCounter(); int64_t elapsed = -bx::getHPCounter();
@ -2041,8 +2066,7 @@ namespace bgfx
GLenum primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : GL_TRIANGLES; GLenum primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : GL_TRIANGLES;
uint32_t primNumVerts = 3; uint32_t primNumVerts = 3;
uint32_t baseVertex = 0; uint32_t baseVertex = 0;
GLuint currentVao = 0;
GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) );
uint32_t statsNumPrimsSubmitted = 0; uint32_t statsNumPrimsSubmitted = 0;
uint32_t statsNumIndices = 0; uint32_t statsNumIndices = 0;
@ -2504,19 +2528,22 @@ namespace bgfx
} }
} }
if (s_renderCtx.m_vaoSupport) if (s_renderCtx.m_vaoSupport
&& 0 == state.m_startVertex
&& 0 == state.m_instanceDataOffset)
{ {
if (programChanged if (programChanged
|| currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx || currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx
|| baseVertex != state.m_startVertex || currentState.m_indexBuffer.idx != state.m_indexBuffer.idx
|| currentState.m_indexBuffer.idx != state.m_indexBuffer.idx) || currentState.m_instanceDataBuffer.idx != state.m_instanceDataBuffer.idx)
{ {
uint64_t hash = (uint64_t(state.m_vertexBuffer.idx)<<48) bx::HashMurmur2A murmur;
| (uint64_t(state.m_indexBuffer.idx)<<32) murmur.begin();
| (uint64_t(state.m_instanceDataBuffer.idx)<<16) murmur.add(state.m_vertexBuffer.idx);
| programIdx murmur.add(state.m_indexBuffer.idx);
; murmur.add(state.m_instanceDataBuffer.idx);
hash ^= state.m_startVertex; murmur.add(programIdx);
uint32_t hash = murmur.end();
currentState.m_vertexBuffer = state.m_vertexBuffer; currentState.m_vertexBuffer = state.m_vertexBuffer;
currentState.m_indexBuffer = state.m_indexBuffer; currentState.m_indexBuffer = state.m_indexBuffer;
@ -2525,25 +2552,32 @@ namespace bgfx
GLuint id = s_renderCtx.m_vaoCache.find(hash); GLuint id = s_renderCtx.m_vaoCache.find(hash);
if (UINT32_MAX != id) if (UINT32_MAX != id)
{ {
currentVao = id;
GL_CHECK(glBindVertexArray(id) ); GL_CHECK(glBindVertexArray(id) );
} }
else else
{ {
id = s_renderCtx.m_vaoCache.add(hash); id = s_renderCtx.m_vaoCache.add(hash);
currentVao = id;
GL_CHECK(glBindVertexArray(id) ); GL_CHECK(glBindVertexArray(id) );
Program& program = s_renderCtx.m_program[programIdx];
program.add(hash);
if (invalidHandle != state.m_vertexBuffer.idx) if (invalidHandle != state.m_vertexBuffer.idx)
{ {
VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx]; VertexBuffer& vb = s_renderCtx.m_vertexBuffers[state.m_vertexBuffer.idx];
vb.add(hash);
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) ); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, vb.m_id) );
uint16_t decl = vb.m_decl.idx == invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx; uint16_t decl = vb.m_decl.idx == invalidHandle ? state.m_vertexDecl.idx : vb.m_decl.idx;
const Program& program = s_renderCtx.m_program[programIdx];
program.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex); program.bindAttributes(s_renderCtx.m_vertexDecls[decl], state.m_startVertex);
if (invalidHandle != state.m_instanceDataBuffer.idx) if (invalidHandle != state.m_instanceDataBuffer.idx)
{ {
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx].m_id) ); VertexBuffer& instanceVb = s_renderCtx.m_vertexBuffers[state.m_instanceDataBuffer.idx];
instanceVb.add(hash);
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, instanceVb.m_id) );
program.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset); program.bindInstanceData(state.m_instanceDataStride, state.m_instanceDataOffset);
} }
} }
@ -2555,6 +2589,7 @@ namespace bgfx
if (invalidHandle != state.m_indexBuffer.idx) if (invalidHandle != state.m_indexBuffer.idx)
{ {
IndexBuffer& ib = s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx]; IndexBuffer& ib = s_renderCtx.m_indexBuffers[state.m_indexBuffer.idx];
ib.add(hash);
GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) ); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib.m_id) );
} }
else else
@ -2566,6 +2601,16 @@ namespace bgfx
} }
else else
{ {
if (s_renderCtx.m_vaoSupport
&& 0 != currentVao)
{
GL_CHECK(glBindVertexArray(0) );
currentState.m_vertexBuffer.idx = invalidHandle;
currentState.m_indexBuffer.idx = invalidHandle;
bindAttribs = true;
currentVao = 0;
}
if (programChanged if (programChanged
|| currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx) || currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx)
{ {

View file

@ -178,6 +178,8 @@ typedef void (*PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GLuint shader, GLsizei b
# define glClearDepth glClearDepthf # define glClearDepth glClearDepthf
#endif // !BGFX_CONFIG_RENDERER_OPENGL #endif // !BGFX_CONFIG_RENDERER_OPENGL
#include <set>
namespace bgfx namespace bgfx
{ {
typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORBGFXPROC)(GLuint _index, GLuint _divisor); typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORBGFXPROC)(GLuint _index, GLuint _divisor);
@ -229,6 +231,82 @@ namespace bgfx
class ConstantBuffer; class ConstantBuffer;
class VaoCache
{
public:
GLuint add(uint32_t _hash)
{
invalidate(_hash);
GLuint arrayId;
GL_CHECK(glGenVertexArrays(1, &arrayId) );
m_hashMap.insert(stl::make_pair(_hash, arrayId) );
return arrayId;
}
GLuint find(uint32_t _hash)
{
HashMap::iterator it = m_hashMap.find(_hash);
if (it != m_hashMap.end() )
{
return it->second;
}
return UINT32_MAX;
}
void invalidate(uint32_t _hash)
{
GL_CHECK(glBindVertexArray(0) );
HashMap::iterator it = m_hashMap.find(_hash);
if (it != m_hashMap.end() )
{
GL_CHECK(glDeleteVertexArrays(1, &it->second) );
m_hashMap.erase(it);
}
}
void invalidate()
{
GL_CHECK(glBindVertexArray(0) );
for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
{
GL_CHECK(glDeleteVertexArrays(1, &it->second) );
}
m_hashMap.clear();
}
private:
typedef stl::unordered_map<uint32_t, GLuint> HashMap;
HashMap m_hashMap;
};
class VaoCacheRef
{
public:
void add(uint32_t _hash)
{
m_vaoSet.insert(_hash);
}
void invalidate(VaoCache& _vaoCache)
{
for (VaoSet::iterator it = m_vaoSet.begin(), itEnd = m_vaoSet.end(); it != itEnd; ++it)
{
_vaoCache.invalidate(*it);
}
m_vaoSet.clear();
}
typedef stl::set<uint32_t> VaoSet;
VaoSet m_vaoSet;
};
struct IndexBuffer struct IndexBuffer
{ {
void create(uint32_t _size, void* _data) void create(uint32_t _size, void* _data)
@ -257,14 +335,16 @@ namespace bgfx
GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) );
} }
void destroy() void destroy();
void add(uint32_t _hash)
{ {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); m_vcref.add(_hash);
glDeleteBuffers(1, &m_id);
} }
GLuint m_id; GLuint m_id;
uint32_t m_size; uint32_t m_size;
VaoCacheRef m_vcref;
}; };
struct VertexBuffer struct VertexBuffer
@ -296,65 +376,17 @@ namespace bgfx
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) );
} }
void destroy() void destroy();
void add(uint32_t _hash)
{ {
GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); m_vcref.add(_hash);
GL_CHECK(glDeleteBuffers(1, &m_id) );
} }
GLuint m_id; GLuint m_id;
uint32_t m_size; uint32_t m_size;
VertexDeclHandle m_decl; VertexDeclHandle m_decl;
}; VaoCacheRef m_vcref;
class VaoCache
{
public:
GLuint add(uint64_t _hash)
{
invalidate(_hash);
GLuint arrayId;
GL_CHECK(glGenVertexArrays(1, &arrayId) );
m_hashMap.insert(stl::make_pair(_hash, arrayId) );
return arrayId;
}
GLuint find(uint64_t _hash)
{
HashMap::iterator it = m_hashMap.find(_hash);
if (it != m_hashMap.end() )
{
return it->second;
}
return UINT32_MAX;
}
void invalidate(uint64_t _hash)
{
HashMap::iterator it = m_hashMap.find(_hash);
if (it != m_hashMap.end() )
{
GL_CHECK(glDeleteVertexArrays(1, &it->second) );
m_hashMap.erase(it);
}
}
void invalidate()
{
for (HashMap::iterator it = m_hashMap.begin(), itEnd = m_hashMap.end(); it != itEnd; ++it)
{
GL_CHECK(glDeleteVertexArrays(1, &it->second) );
}
m_hashMap.clear();
}
private:
typedef stl::unordered_map<uint64_t, GLuint> HashMap;
HashMap m_hashMap;
}; };
struct Texture struct Texture
@ -456,6 +488,11 @@ namespace bgfx
m_constantBuffer->commit(); m_constantBuffer->commit();
} }
void add(uint32_t _hash)
{
m_vcref.add(_hash);
}
GLuint m_id; GLuint m_id;
uint8_t m_used[Attrib::Count+1]; // dense uint8_t m_used[Attrib::Count+1]; // dense
@ -468,6 +505,7 @@ namespace bgfx
ConstantBuffer* m_constantBuffer; ConstantBuffer* m_constantBuffer;
PredefinedUniform m_predefined[PredefinedUniform::Count]; PredefinedUniform m_predefined[PredefinedUniform::Count];
uint8_t m_numPredefined; uint8_t m_numPredefined;
VaoCacheRef m_vcref;
}; };
#if BGFX_CONFIG_RENDERER_OPENGL #if BGFX_CONFIG_RENDERER_OPENGL