From e866a7b2e30434d53c704b3889d861559fee88f7 Mon Sep 17 00:00:00 2001 From: bkaradzic Date: Mon, 21 Jan 2013 23:36:47 -0800 Subject: [PATCH] Fixed VAO cache. --- src/renderer_gl.cpp | 73 ++++++++++++++++----- src/renderer_gl.h | 150 +++++++++++++++++++++++++++----------------- 2 files changed, 153 insertions(+), 70 deletions(-) diff --git a/src/renderer_gl.cpp b/src/renderer_gl.cpp index 2df08870b..51daf2602 100644 --- a/src/renderer_gl.cpp +++ b/src/renderer_gl.cpp @@ -720,6 +720,8 @@ namespace bgfx { GL_CHECK(glUseProgram(0) ); GL_CHECK(glDeleteProgram(m_id) ); + + m_vcref.invalidate(s_renderCtx.m_vaoCache); } 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) { #if BGFX_CONFIG_RENDERER_OPENGL|BGFX_CONFIG_RENDERER_OPENGLES3 @@ -1829,7 +1847,7 @@ namespace bgfx } #if !BGFX_CONFIG_RENDERER_OPENGLES3 - if (NULL != glVertexAttribDivisor + if (false && NULL != glVertexAttribDivisor && NULL != glDrawArraysInstanced && NULL != glDrawElementsInstanced) { @@ -1995,6 +2013,13 @@ namespace bgfx 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); int64_t elapsed = -bx::getHPCounter(); @@ -2041,8 +2066,7 @@ namespace bgfx GLenum primType = m_render->m_debug&BGFX_DEBUG_WIREFRAME ? GL_LINES : GL_TRIANGLES; uint32_t primNumVerts = 3; uint32_t baseVertex = 0; - - GL_CHECK(glBindFramebuffer(GL_FRAMEBUFFER, 0) ); + GLuint currentVao = 0; uint32_t statsNumPrimsSubmitted = 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 || 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) - | (uint64_t(state.m_indexBuffer.idx)<<32) - | (uint64_t(state.m_instanceDataBuffer.idx)<<16) - | programIdx - ; - hash ^= state.m_startVertex; + bx::HashMurmur2A murmur; + murmur.begin(); + murmur.add(state.m_vertexBuffer.idx); + murmur.add(state.m_indexBuffer.idx); + murmur.add(state.m_instanceDataBuffer.idx); + murmur.add(programIdx); + uint32_t hash = murmur.end(); currentState.m_vertexBuffer = state.m_vertexBuffer; currentState.m_indexBuffer = state.m_indexBuffer; @@ -2525,25 +2552,32 @@ namespace bgfx GLuint id = s_renderCtx.m_vaoCache.find(hash); if (UINT32_MAX != id) { + currentVao = id; GL_CHECK(glBindVertexArray(id) ); } else { id = s_renderCtx.m_vaoCache.add(hash); + currentVao = id; GL_CHECK(glBindVertexArray(id) ); + Program& program = s_renderCtx.m_program[programIdx]; + program.add(hash); + if (invalidHandle != 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) ); 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); 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); } } @@ -2555,6 +2589,7 @@ namespace bgfx if (invalidHandle != 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) ); } else @@ -2566,6 +2601,16 @@ namespace bgfx } 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 || currentState.m_vertexBuffer.idx != state.m_vertexBuffer.idx) { diff --git a/src/renderer_gl.h b/src/renderer_gl.h index 57021ba13..31e212158 100755 --- a/src/renderer_gl.h +++ b/src/renderer_gl.h @@ -178,6 +178,8 @@ typedef void (*PFNGLGETTRANSLATEDSHADERSOURCEANGLEPROC)(GLuint shader, GLsizei b # define glClearDepth glClearDepthf #endif // !BGFX_CONFIG_RENDERER_OPENGL +#include + namespace bgfx { typedef void (GL_APIENTRYP PFNGLVERTEXATTRIBDIVISORBGFXPROC)(GLuint _index, GLuint _divisor); @@ -229,6 +231,82 @@ namespace bgfx 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 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 VaoSet; + VaoSet m_vaoSet; + }; + struct IndexBuffer { void create(uint32_t _size, void* _data) @@ -257,14 +335,16 @@ namespace bgfx GL_CHECK(glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) ); } - void destroy() + void destroy(); + + void add(uint32_t _hash) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glDeleteBuffers(1, &m_id); + m_vcref.add(_hash); } GLuint m_id; uint32_t m_size; + VaoCacheRef m_vcref; }; struct VertexBuffer @@ -296,65 +376,17 @@ namespace bgfx GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); } - void destroy() + void destroy(); + + void add(uint32_t _hash) { - GL_CHECK(glBindBuffer(GL_ARRAY_BUFFER, 0) ); - GL_CHECK(glDeleteBuffers(1, &m_id) ); + m_vcref.add(_hash); } GLuint m_id; uint32_t m_size; VertexDeclHandle m_decl; - }; - - 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 HashMap; - HashMap m_hashMap; + VaoCacheRef m_vcref; }; struct Texture @@ -456,6 +488,11 @@ namespace bgfx m_constantBuffer->commit(); } + void add(uint32_t _hash) + { + m_vcref.add(_hash); + } + GLuint m_id; uint8_t m_used[Attrib::Count+1]; // dense @@ -468,6 +505,7 @@ namespace bgfx ConstantBuffer* m_constantBuffer; PredefinedUniform m_predefined[PredefinedUniform::Count]; uint8_t m_numPredefined; + VaoCacheRef m_vcref; }; #if BGFX_CONFIG_RENDERER_OPENGL