diff --git a/drape/batcher.cpp b/drape/batcher.cpp index 4cb6f9db63..c38cc5c45e 100644 --- a/drape/batcher.cpp +++ b/drape/batcher.cpp @@ -177,15 +177,20 @@ RefPointer Batcher::GetBucket(GLState const & state) void Batcher::FinalizeBucket(GLState const & state) { ASSERT(m_buckets.find(state) != m_buckets.end(), ("Have no bucket for finalize with given state")); - m_flushInterface(state, m_buckets[state].Move()); + MasterPointer bucket = m_buckets[state]; m_buckets.erase(state); + bucket->GetBuffer()->Preflush(); + m_flushInterface(state, bucket.Move()); } void Batcher::Flush() { ASSERT(m_flushInterface != NULL, ()); for (buckets_t::iterator it = m_buckets.begin(); it != m_buckets.end(); ++it) + { + it->second->GetBuffer()->Preflush(); m_flushInterface(it->first, it->second.Move()); + } m_buckets.clear(); } diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index 9d8a2729c2..6f58c24ea9 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -4,6 +4,12 @@ #include "../base/assert.hpp" #include "../base/logging.hpp" +#ifdef DEBUG +#include "../base/thread.hpp" +#include "../base/mutex.hpp" +#include "../std/map.hpp" +#endif + #include "../std/cstring.hpp" #ifndef OMIM_OS_WINDOWS @@ -12,6 +18,14 @@ namespace { +#ifdef DEBUG + typedef pair TKey; + typedef pair TNode; + typedef map TBoundMap; + TBoundMap g_boundBuffers; + threads::Mutex g_mutex; +#endif + inline GLboolean convert(bool v) { return (v == true) ? GL_TRUE : GL_FALSE; @@ -294,12 +308,26 @@ uint32_t GLFunctions::glGenBuffer() void GLFunctions::glBindBuffer(uint32_t vbo, uint32_t target) { ASSERT(glBindBufferFn != NULL, ()); +#ifdef DEBUG + threads::MutexGuard guard(g_mutex); + TKey key = make_pair(threads::GetCurrentThreadID(), target); + auto iter = g_boundBuffers.find(key); + if (iter != g_boundBuffers.end()) + g_boundBuffers.erase(iter); + g_boundBuffers.emplace(key, vbo); +#endif GLCHECK(glBindBufferFn(target, vbo)); } void GLFunctions::glDeleteBuffer(uint32_t vbo) { ASSERT(glDeleteBuffersFn != NULL, ()); +#ifdef DEBUG + threads::MutexGuard guard(g_mutex); + threads::ThreadID id = threads::GetCurrentThreadID(); + for (TNode const & n : g_boundBuffers) + ASSERT(n.second != vbo, ()); +#endif GLCHECK(glDeleteBuffersFn(1, &vbo)); } @@ -615,6 +643,9 @@ void GLFunctions::glDrawElements(uint16_t indexCount) void CheckGLError() { GLenum result = glGetError(); - if (result != GL_NO_ERROR) + while (result != GL_NO_ERROR) + { LOG(LERROR, ("GLError:", result)); + result = glGetError(); + } } diff --git a/drape/gpu_buffer.cpp b/drape/gpu_buffer.cpp index 6c76f52d4d..8a9e2674e3 100644 --- a/drape/gpu_buffer.cpp +++ b/drape/gpu_buffer.cpp @@ -39,6 +39,7 @@ GPUBuffer::GPUBuffer(Target t, uint8_t elementSize, uint16_t capacity) GPUBuffer::~GPUBuffer() { + GLFunctions::glBindBuffer(0, glTarget(m_t)); GLFunctions::glDeleteBuffer(m_bufferID); } @@ -56,7 +57,7 @@ void GPUBuffer::UploadData(void const * data, uint16_t elementCount) void GPUBuffer::Bind() { - GLFunctions::glBindBuffer(m_bufferID, glTarget((m_t))); + GLFunctions::glBindBuffer(m_bufferID, glTarget(m_t)); } void * GPUBuffer::Map() diff --git a/drape/vertex_array_buffer.cpp b/drape/vertex_array_buffer.cpp index b041a216a4..baa3b0d5fc 100644 --- a/drape/vertex_array_buffer.cpp +++ b/drape/vertex_array_buffer.cpp @@ -32,6 +32,12 @@ VertexArrayBuffer::~VertexArrayBuffer() } } +void VertexArrayBuffer::Preflush() +{ + GLFunctions::glBindBuffer(0, gl_const::GLElementArrayBuffer); + GLFunctions::glBindBuffer(0, gl_const::GLArrayBuffer); +} + void VertexArrayBuffer::Render() { if (!(m_staticBuffers.empty() && m_dynamicBuffers.empty())) diff --git a/drape/vertex_array_buffer.hpp b/drape/vertex_array_buffer.hpp index 855ff32d56..0b2d80b101 100644 --- a/drape/vertex_array_buffer.hpp +++ b/drape/vertex_array_buffer.hpp @@ -20,6 +20,9 @@ public: VertexArrayBuffer(uint32_t indexBufferSize, uint32_t dataBufferSize); ~VertexArrayBuffer(); + /// This method must be call on reading thread, before VAO will be transfer on render thread + void Preflush(); + ///{@ /// On devices where implemented OES_vertex_array_object extensions we use it for build VertexArrayBuffer /// OES_vertex_array_object create OpenGL resource that belong only one GL context (which was created by)