From 7d2fd004de5c0c33df6f0d8655572f19a531f0cc Mon Sep 17 00:00:00 2001 From: "r.kuznetsov" Date: Fri, 3 Jul 2015 09:55:36 +0300 Subject: [PATCH] Added cache for OGL states --- drape/drape_common.pri | 2 + drape/drape_tests/stipple_pen_tests.cpp | 1 + drape/drape_tests/texture_of_colors_tests.cpp | 1 + drape/drape_tests/uniform_value_tests.cpp | 25 ++--- drape/glfunctions.cpp | 62 ++++++++++--- drape/glfunctions.hpp | 12 +++ drape/glfunctions_cache.cpp | 80 ++++++++++++++++ drape/glfunctions_cache.hpp | 92 +++++++++++++++++++ drape/glstate.cpp | 33 +++---- drape/glstate.hpp | 14 ++- drape/texture.cpp | 3 + drape_frontend/frontend_renderer.cpp | 3 + 12 files changed, 276 insertions(+), 52 deletions(-) create mode 100644 drape/glfunctions_cache.cpp create mode 100644 drape/glfunctions_cache.hpp diff --git a/drape/drape_common.pri b/drape/drape_common.pri index 1f0d8c141d..3cf9253a91 100644 --- a/drape/drape_common.pri +++ b/drape/drape_common.pri @@ -17,6 +17,7 @@ SOURCES += \ $$DRAPE_DIR/fribidi.cpp \ $$DRAPE_DIR/glconstants.cpp \ $$DRAPE_DIR/glextensions_list.cpp \ + $$DRAPE_DIR/glfunctions_cache.cpp \ $$DRAPE_DIR/glstate.cpp \ $$DRAPE_DIR/glyph_manager.cpp \ $$DRAPE_DIR/gpu_buffer.cpp \ @@ -67,6 +68,7 @@ HEADERS += \ $$DRAPE_DIR/glconstants.hpp \ $$DRAPE_DIR/glextensions_list.hpp \ $$DRAPE_DIR/glfunctions.hpp \ + $$DRAPE_DIR/glfunctions_cache.hpp \ $$DRAPE_DIR/glIncludes.hpp \ $$DRAPE_DIR/glsl_func.hpp \ $$DRAPE_DIR/glsl_types.hpp \ diff --git a/drape/drape_tests/stipple_pen_tests.cpp b/drape/drape_tests/stipple_pen_tests.cpp index 2620bb6a7c..5c53735787 100644 --- a/drape/drape_tests/stipple_pen_tests.cpp +++ b/drape/drape_tests/stipple_pen_tests.cpp @@ -450,6 +450,7 @@ UNIT_TEST(StippleMappingTest) EXPECTGL(glTexParameter(gl_const::GLMagFilter, gl_const::GLLinear)); EXPECTGL(glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge)); EXPECTGL(glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge)); + EXPECTGL(glBindTexture(0)).WillOnce(Return()); MemoryComparer cmp(firstUploadEtalon, ARRAY_SIZE(firstUploadEtalon)); EXPECTGL(glTexSubImage2D(0, 0, 256, 6, AnyOf(gl_const::GLAlpha, gl_const::GLAlpha8), gl_const::GL8BitOnChannel, _)) .WillOnce(Invoke(&cmp, &MemoryComparer::cmpSubImage)); diff --git a/drape/drape_tests/texture_of_colors_tests.cpp b/drape/drape_tests/texture_of_colors_tests.cpp index 2c6cf2cc01..804ea474a8 100644 --- a/drape/drape_tests/texture_of_colors_tests.cpp +++ b/drape/drape_tests/texture_of_colors_tests.cpp @@ -41,6 +41,7 @@ void InitOpenGLTextures(int const w, int const h) EXPECTGL(glTexParameter(gl_const::GLMagFilter, gl_const::GLLinear)); EXPECTGL(glTexParameter(gl_const::GLWrapS, gl_const::GLClampToEdge)); EXPECTGL(glTexParameter(gl_const::GLWrapT, gl_const::GLClampToEdge)); + EXPECTGL(glBindTexture(0)).WillOnce(Return()); } class DummyColorPallete : public ColorPalette diff --git a/drape/drape_tests/uniform_value_tests.cpp b/drape/drape_tests/uniform_value_tests.cpp index 9aba3d4334..12d2994b9a 100644 --- a/drape/drape_tests/uniform_value_tests.cpp +++ b/drape/drape_tests/uniform_value_tests.cpp @@ -49,7 +49,6 @@ private: uint32_t m_size; }; -#ifdef DEBUG void mock_glGetActiveUniform(uint32_t programID, uint32_t index, int32_t * size, @@ -77,7 +76,6 @@ void mock_glGetActiveUniform(uint32_t programID, else ASSERT(false, ("Undefined index:", index)); } -#endif } // namespace @@ -85,7 +83,7 @@ UNIT_TEST(UniformValueTest) { uint32_t const VertexShaderID = 1; uint32_t const FragmentShaderID = 2; - uint32_t const ProgramID = 3; + uint32_t const ProgramID = 2; int32_t const positionLoc = 10; int32_t const modelViewLoc = 11; @@ -119,41 +117,34 @@ UNIT_TEST(UniformValueTest) EXPECTGL(glLinkProgram(ProgramID, _)).WillOnce(Return(true)); + EXPECTGL(glGetProgramiv(ProgramID, gl_const::GLActiveUniforms)).WillOnce(Return(9)); + for (int i = 0; i < 9; i++) + { + EXPECTGL(glGetActiveUniform(ProgramID, _, _, _, _)).WillOnce(Invoke(mock_glGetActiveUniform)); + EXPECTGL(glGetUniformLocation(ProgramID, _)).WillOnce(Return(i == 8 ? modelViewLoc : positionLoc)); + } + EXPECTGL(glDetachShader(ProgramID, VertexShaderID)); EXPECTGL(glDetachShader(ProgramID, FragmentShaderID)); -#ifdef DEBUG - EXPECTGL(glGetProgramiv(ProgramID, gl_const::GLActiveUniforms)).WillOnce(Return(9)); - EXPECTGL(glGetActiveUniform(ProgramID, _, _, _, _)).Times(9).WillRepeatedly(Invoke(mock_glGetActiveUniform)); -#endif - EXPECTGL(glUseProgram(ProgramID)); - EXPECTGL(glGetUniformLocation(ProgramID, "position0")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuei(positionLoc, 1)); - EXPECTGL(glGetUniformLocation(ProgramID, "position1")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuei(positionLoc, 1, 2)); - EXPECTGL(glGetUniformLocation(ProgramID, "position2")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuei(positionLoc, 1, 2, 3)); - EXPECTGL(glGetUniformLocation(ProgramID, "position3")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuei(positionLoc, 1, 2, 3, 4)); - EXPECTGL(glGetUniformLocation(ProgramID, "position4")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuef(positionLoc, 1.0f)); - EXPECTGL(glGetUniformLocation(ProgramID, "position5")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuef(positionLoc, 1.0f, 2.0f)); - EXPECTGL(glGetUniformLocation(ProgramID, "position6")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuef(positionLoc, 1.0f, 2.0f, 3.0f)); - EXPECTGL(glGetUniformLocation(ProgramID, "position7")).WillOnce(Return(positionLoc)); EXPECTGL(glUniformValuef(positionLoc, 1.0f, 2.0f, 3.0f, 4.0f)); - EXPECTGL(glGetUniformLocation(ProgramID, "viewModel")).WillOnce(Return(modelViewLoc)); EXPECTGL(glUniformMatrix4x4Value(modelViewLoc, _)) .WillOnce(Invoke(&comparer, &MemoryComparer::Compare)); diff --git a/drape/glfunctions.cpp b/drape/glfunctions.cpp index 517854aa93..1fc12e68b1 100644 --- a/drape/glfunctions.cpp +++ b/drape/glfunctions.cpp @@ -1,6 +1,7 @@ #include "drape/glfunctions.hpp" #include "drape/glIncludes.hpp" #include "drape/glextensions_list.hpp" +#include "drape/glfunctions_cache.hpp" #include "base/assert.hpp" #include "base/logging.hpp" @@ -377,12 +378,12 @@ int32_t GLFunctions::glGetBufferParameter(glConst target, glConst name) void GLFunctions::glEnable(glConst mode) { - GLCHECK(::glEnable(mode)); + GLFunctionsCache::glEnable(mode); } void GLFunctions::glDisable(glConst mode) { - GLCHECK(::glDisable(mode)); + GLFunctionsCache::glDisable(mode); } void GLFunctions::glClearDepthValue(double depth) @@ -588,8 +589,7 @@ void GLFunctions::glDeleteProgram(uint32_t programID) void GLFunctions::glUseProgram(uint32_t programID) { - ASSERT(glUseProgramFn != nullptr, ()); - GLCHECK(glUseProgramFn(programID)); + GLFunctionsCache::glUseProgram(programID); } int8_t GLFunctions::glGetAttribLocation(uint32_t programID, string const & name) @@ -649,9 +649,7 @@ int8_t GLFunctions::glGetUniformLocation(uint32_t programID, string const & name void GLFunctions::glUniformValuei(int8_t location, int32_t v) { - ASSERT(glUniform1iFn != nullptr, ()); - ASSERT(location != -1, ()); - GLCHECK(glUniform1iFn(location, v)); + GLFunctionsCache::glUniformValuei(location, v); } void GLFunctions::glUniformValuei(int8_t location, int32_t v1, int32_t v2) @@ -684,9 +682,7 @@ void GLFunctions::glUniformValueiv(int8_t location, int32_t * v, uint32_t size) void GLFunctions::glUniformValuef(int8_t location, float v) { - ASSERT(glUniform1fFn != nullptr, ()); - ASSERT(location != -1, ()); - GLCHECK(glUniform1fFn(location, v)); + GLFunctionsCache::glUniformValuef(location, v); } void GLFunctions::glUniformValuef(int8_t location, float v1, float v2) @@ -741,8 +737,7 @@ int32_t GLFunctions::glGetProgramiv(uint32_t program, glConst paramName) void GLFunctions::glActiveTexture(glConst texBlock) { - ASSERT(glActiveTextureFn != nullptr, ()); - GLCHECK(glActiveTextureFn(texBlock)); + GLFunctionsCache::glActiveTexture(texBlock); } uint32_t GLFunctions::glGenTexture() @@ -759,7 +754,7 @@ void GLFunctions::glDeleteTexture(uint32_t id) void GLFunctions::glBindTexture(uint32_t textureID) { - GLCHECK(::glBindTexture(GL_TEXTURE_2D, textureID)); + GLFunctionsCache::glBindTexture(textureID); } void GLFunctions::glTexImage2D(int width, int height, glConst layout, glConst pixelType, void const * data) @@ -783,6 +778,47 @@ void GLFunctions::glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint reinterpret_cast(startIndex * sizeOfIndex))); } +void GLFunctions::glActiveTextureImpl(glConst texBlock) +{ + ASSERT(glActiveTextureFn != nullptr, ()); + GLCHECK(glActiveTextureFn(texBlock)); +} + +void GLFunctions::glBindTextureImpl(uint32_t textureID) +{ + GLCHECK(::glBindTexture(GL_TEXTURE_2D, textureID)); +} + +void GLFunctions::glEnableImpl(glConst mode) +{ + GLCHECK(::glEnable(mode)); +} + +void GLFunctions::glDisableImpl(glConst mode) +{ + GLCHECK(::glDisable(mode)); +} + +void GLFunctions::glUseProgramImpl(uint32_t programID) +{ + ASSERT(glUseProgramFn != nullptr, ()); + GLCHECK(glUseProgramFn(programID)); +} + +void GLFunctions::glUniformValueiImpl(int8_t location, int32_t v) +{ + ASSERT(glUniform1iFn != nullptr, ()); + ASSERT(location != -1, ()); + GLCHECK(glUniform1iFn(location, v)); +} + +void GLFunctions::glUniformValuefImpl(int8_t location, float v) +{ + ASSERT(glUniform1fFn != nullptr, ()); + ASSERT(location != -1, ()); + GLCHECK(glUniform1fFn(location, v)); +} + namespace { diff --git a/drape/glfunctions.hpp b/drape/glfunctions.hpp index 605b6612ee..1926cef3e6 100644 --- a/drape/glfunctions.hpp +++ b/drape/glfunctions.hpp @@ -8,6 +8,8 @@ class GLFunctions { + friend class GLFunctionsCache; + public: static void Init(); @@ -122,6 +124,16 @@ public: // Draw support static void glDrawElements(uint32_t sizeOfIndex, uint32_t indexCount, uint32_t startIndex = 0); + +private: + static void glActiveTextureImpl(glConst texBlock); + static void glBindTextureImpl(uint32_t textureID); + static void glEnableImpl(glConst mode); + static void glDisableImpl(glConst mode); + static void glUseProgramImpl(uint32_t programID); + + static void glUniformValueiImpl(int8_t location, int32_t v); + static void glUniformValuefImpl(int8_t location, float v); }; void CheckGLError(my::SrcPoint const &src); diff --git a/drape/glfunctions_cache.cpp b/drape/glfunctions_cache.cpp new file mode 100644 index 0000000000..2f920b9b8c --- /dev/null +++ b/drape/glfunctions_cache.cpp @@ -0,0 +1,80 @@ +#include "drape/glfunctions_cache.hpp" +#include "drape/glfunctions.hpp" + +#include "base/assert.hpp" + +#define INST GLFunctionsCache::Instance() + +GLFunctionsCache & GLFunctionsCache::Instance() +{ + static GLFunctionsCache instance; + return instance; +} + +void GLFunctionsCache::glBindTexture(uint32_t textureID) +{ + if (INST.CheckAndSetValue(textureID, INST.m_glBindTextureCache)) + GLFunctions::glBindTextureImpl(textureID); +} + +void GLFunctionsCache::glActiveTexture(glConst texBlock) +{ + if (INST.CheckAndSetValue(texBlock, INST.m_glActiveTextureCache)) + GLFunctions::glActiveTextureImpl(texBlock); +} + +void GLFunctionsCache::glUseProgram(uint32_t programID) +{ + if (INST.CheckAndSetValue(programID, INST.m_glUseProgramCache)) + GLFunctions::glUseProgramImpl(programID); +} + +void GLFunctionsCache::glEnable(glConst mode) +{ + EnablableParam & param = INST.m_glEnableCache[mode]; + bool const initialized = param.m_initialized; + if (!initialized || (initialized && !param.m_isEnabled)) + { + param = true; + GLFunctions::glEnableImpl(mode); + } +} + +void GLFunctionsCache::glDisable(glConst mode) +{ + EnablableParam & param = INST.m_glEnableCache[mode]; + bool const initialized = param.m_initialized; + if (!initialized || (initialized && param.m_isEnabled)) + { + param = false; + GLFunctions::glDisableImpl(mode); + } +} + +void GLFunctionsCache::glUniformValuei(int8_t location, int32_t v) +{ + ASSERT(INST.m_glUseProgramCache.m_initialized, ()); + UniformsCache & cache = INST.m_uniformsCache[INST.m_glUseProgramCache.m_param]; + + CachedParam & param = cache.m_glUniform1iCache[location]; + bool const initialized = param.m_initialized; + if (!initialized || (initialized && param != v)) + { + param = v; + GLFunctions::glUniformValueiImpl(location, v); + } +} + +void GLFunctionsCache::glUniformValuef(int8_t location, float v) +{ + ASSERT(INST.m_glUseProgramCache.m_initialized, ()); + UniformsCache & cache = INST.m_uniformsCache[INST.m_glUseProgramCache.m_param]; + + CachedParam & param = cache.m_glUniform1fCache[location]; + bool const initialized = param.m_initialized; + if (!initialized || (initialized && param != v)) + { + param = v; + GLFunctions::glUniformValuefImpl(location, v); + } +} diff --git a/drape/glfunctions_cache.hpp b/drape/glfunctions_cache.hpp new file mode 100644 index 0000000000..a88fdd014c --- /dev/null +++ b/drape/glfunctions_cache.hpp @@ -0,0 +1,92 @@ +#pragma once + +#include "drape/glconstants.hpp" + +#include "std/map.hpp" +#include "std/string.hpp" + +class GLFunctionsCache +{ +public: + + static void glBindTexture(uint32_t textureID); + static void glActiveTexture(glConst texBlock); + static void glUseProgram(uint32_t programID); + static void glEnable(glConst mode); + static void glDisable(glConst mode); + + static void glUniformValuei(int8_t location, int32_t v); + static void glUniformValuef(int8_t location, float v); + +private: + static GLFunctionsCache & Instance(); + + template + struct CachedParam + { + TParam m_param; + bool m_initialized = false; + + CachedParam() : m_param(TParam()) {} + explicit CachedParam(TParam const & param) : m_param(param) {} + + bool operator!=(TParam const & param) + { + return m_param != param; + } + + CachedParam & operator=(TParam const & param) + { + m_param = param; + m_initialized = true; + return *this; + } + }; + + struct EnablableParam + { + bool m_isEnabled = false; + bool m_initialized = false; + + EnablableParam(){} + explicit EnablableParam(bool enabled) : m_isEnabled(enabled) {} + + bool operator!=(bool enabled) + { + return m_isEnabled != enabled; + } + + EnablableParam & operator=(bool enabled) + { + m_isEnabled = enabled; + m_initialized = true; + return *this; + } + }; + + template using UniformCache = map>; + + struct UniformsCache + { + UniformCache m_glUniform1iCache; + UniformCache m_glUniform1fCache; + }; + + template + bool CheckAndSetValue(TParamInternal const & newValue, TParam & cachedValue) + { + if (!cachedValue.m_initialized || cachedValue != newValue) + { + cachedValue = newValue; + return true; + } + return false; + } + + CachedParam m_glBindTextureCache; + CachedParam m_glActiveTextureCache; + CachedParam m_glUseProgramCache; + map m_glEnableCache; + + map m_uniformsCache; +}; diff --git a/drape/glstate.cpp b/drape/glstate.cpp index 895a079a4b..d0319c1966 100644 --- a/drape/glstate.cpp +++ b/drape/glstate.cpp @@ -9,44 +9,39 @@ namespace dp { -Blending::Blending(bool isEnabled) - : m_isEnabled(isEnabled) - , m_blendFunction(gl_const::GLAddBlend) +BlendingParams::BlendingParams() + : m_blendFunction(gl_const::GLAddBlend) , m_blendSrcFactor(gl_const::GLSrcAlfa) , m_blendDstFactor(gl_const::GLOneMinusSrcAlfa) { } +void BlendingParams::Apply() const +{ + GLFunctions::glBlendEquation(m_blendFunction); + GLFunctions::glBlendFunc(m_blendSrcFactor, m_blendDstFactor); +} + +Blending::Blending(bool isEnabled) + : m_isEnabled(isEnabled) +{} + void Blending::Apply() const { if (m_isEnabled) - { GLFunctions::glEnable(gl_const::GLBlending); - GLFunctions::glBlendEquation(m_blendFunction); - GLFunctions::glBlendFunc(m_blendSrcFactor, m_blendDstFactor); - } else GLFunctions::glDisable(gl_const::GLBlending); } bool Blending::operator < (Blending const & other) const { - if (m_isEnabled != other.m_isEnabled) - return m_isEnabled < other.m_isEnabled; - if (m_blendFunction != other.m_blendFunction) - return m_blendFunction < other.m_blendFunction; - if (m_blendSrcFactor != other.m_blendSrcFactor) - return m_blendSrcFactor < other.m_blendSrcFactor; - - return m_blendDstFactor < other.m_blendDstFactor; + return m_isEnabled < other.m_isEnabled; } bool Blending::operator == (Blending const & other) const { - return m_isEnabled == other.m_isEnabled && - m_blendFunction == other.m_blendFunction && - m_blendSrcFactor == other.m_blendSrcFactor && - m_blendDstFactor == other.m_blendDstFactor; + return m_isEnabled == other.m_isEnabled; } GLState::GLState(uint32_t gpuProgramIndex, DepthLayer depthLayer) diff --git a/drape/glstate.hpp b/drape/glstate.hpp index 231d56c48a..4d06a45855 100644 --- a/drape/glstate.hpp +++ b/drape/glstate.hpp @@ -8,6 +8,17 @@ namespace dp { +struct BlendingParams +{ + BlendingParams(); + + void Apply() const; + + glConst m_blendFunction; + glConst m_blendSrcFactor; + glConst m_blendDstFactor; +}; + struct Blending { Blending(bool isEnabled = true); @@ -18,9 +29,6 @@ struct Blending bool operator == (Blending const & other) const; bool m_isEnabled; - glConst m_blendFunction; - glConst m_blendSrcFactor; - glConst m_blendDstFactor; }; class GLState diff --git a/drape/texture.cpp b/drape/texture.cpp index 9d87854a52..db646439a3 100644 --- a/drape/texture.cpp +++ b/drape/texture.cpp @@ -67,6 +67,9 @@ void Texture::Create(uint32_t width, uint32_t height, TextureFormat format, ref_ SetFilterParams(gl_const::GLLinear, gl_const::GLLinear); SetWrapMode(gl_const::GLClampToEdge, gl_const::GLClampToEdge); + GLFunctions::glFlush(); + GLFunctions::glBindTexture(0); + #if defined(TRACK_GPU_MEM) uint32_t channelBitSize = 8; uint32_t channelCount = 4; diff --git a/drape_frontend/frontend_renderer.cpp b/drape_frontend/frontend_renderer.cpp index 8c5f4a359e..24aec69cf4 100755 --- a/drape_frontend/frontend_renderer.cpp +++ b/drape_frontend/frontend_renderer.cpp @@ -738,6 +738,9 @@ void FrontendRenderer::Routine::Do() GLFunctions::glCullFace(gl_const::GLBack); GLFunctions::glEnable(gl_const::GLCullFace); + dp::BlendingParams blendingParams; + blendingParams.Apply(); + my::HighResTimer timer; //double processingTime = InitAvarageTimePerMessage; // By init we think that one message processed by 1ms