From b25747b2ef19a96519275380b8b153fd696b8143 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 30 Mar 2014 19:49:34 +0200 Subject: [PATCH] GL3: Optimize VP switching --HG-- branch : opengl3 --- .../src/3d/driver/opengl3/driver_opengl.cpp | 7 +- .../nel/src/3d/driver/opengl3/driver_opengl.h | 8 ++- .../3d/driver/opengl3/driver_opengl_light.cpp | 8 ++- .../driver/opengl3/driver_opengl_material.cpp | 8 +-- .../driver/opengl3/driver_opengl_program.cpp | 17 ++++- .../driver/opengl3/driver_opengl_states.cpp | 25 ------- .../3d/driver/opengl3/driver_opengl_states.h | 7 -- .../opengl3/driver_opengl_vertex_program.cpp | 66 ++++++++++++++----- 8 files changed, 85 insertions(+), 61 deletions(-) diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl.cpp index d51122a01..1e52d5d47 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl.cpp @@ -387,7 +387,10 @@ bool CDriverGL3::setupDisplay() // All User Light are disabled by Default for (uint i = 0; i < MaxLight; ++i) + { _UserLightEnable[i] = false; + touchLightVP(i); + } // init _DriverGLStates _DriverGLStates.init(); @@ -1029,8 +1032,8 @@ bool CDriverGL3::fogEnabled() void CDriverGL3::enableFog(bool enable) { H_AUTO_OGL(CDriverGL3_enableFog) - _DriverGLStates.enableFog(enable); - _FogEnabled= enable; + _FogEnabled = enable; + enableFogVP(enable); } // *************************************************************************** diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl.h b/code/nel/src/3d/driver/opengl3/driver_opengl.h index b9b176ed9..606a6b167 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl3/driver_opengl.h @@ -398,7 +398,11 @@ public: bool setupUniforms(); void setupUniforms(TProgram program); - CVertexProgram *generateBuiltinVertexProgram(); + void generateBuiltinVertexProgram(); + void enableFogVP(bool enable); + void enableLightingVP(bool enable); + void touchLightVP(int i); + void touchVertexFormatVP(); virtual void startSpecularBatch(); virtual void endSpecularBatch(); @@ -1356,6 +1360,8 @@ private: CPixelProgram *m_DriverPixelProgram; std::set m_VPBuiltinCache; + CVPBuiltin m_VPBuiltinCurrent; + bool m_VPBuiltinTouched; // init EMBM settings (set each stage to modify the next) void initEMBM(); diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_light.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_light.cpp index 6713f0ea6..949cc651b 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_light.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_light.cpp @@ -74,8 +74,8 @@ void CDriverGL3::setLightInternal(uint8 num, const CLight& light) // Copy the mode _LightMode[num] = mode; - _UserLight[num] = light; + touchLightVP(num); // Set the position if ((mode == CLight::DirectionalLight) || (mode == CLight::SpotLight)) @@ -136,6 +136,7 @@ void CDriverGL3::enableLightInternal(uint8 num, bool enable) { // _DriverGLStates.enableLight(num, enable); // FIXME GL3 VERTEX PROGRAM _UserLightEnable[num] = enable; + touchLightVP(num); } } @@ -201,9 +202,10 @@ void CDriverGL3::setupLightMapDynamicLighting(bool enable) void CDriverGL3::disableAllLights() { - for (int i = 0; i < MaxLight; i++) + for (int i = 0; i < MaxLight; ++i) { - _UserLightEnable[ i ] = false; + _UserLightEnable[i] = false; + touchLightVP(i); } } diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp index 83ad2387d..cf96c6d23 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_material.cpp @@ -437,7 +437,7 @@ bool CDriverGL3::setupMaterial(CMaterial& mat) // Light Part. - _DriverGLStates.enableLighting(mat.getFlags() & IDRV_MAT_LIGHTING); + enableLightingVP(mat.getFlags() & IDRV_MAT_LIGHTING); if ((mat.getFlags() & IDRV_MAT_LIGHTING) == 0) disableAllLights(); @@ -463,12 +463,12 @@ bool CDriverGL3::setupMaterial(CMaterial& mat) // Disable fog if dest blend is ONE if (blend && (pShader->DstBlend == GL_ONE)) { - _DriverGLStates.enableFog(false); + enableFogVP(false); } else { // Restaure fog state to its current value - _DriverGLStates.enableFog(_FogEnabled); + enableFogVP(_FogEnabled); } @@ -781,7 +781,7 @@ sint CDriverGL3::beginLightMapMultiPass () computeLightMapInfos (mat); // always enable lighting for lightmap (because of dynamic light) - _DriverGLStates.enableLighting(true); + enableLightingVP(true); // if the dynamic lightmap light has changed since the last render (should not happen), resetup // normal way is that setupLightMapDynamicLighting() is called in setupMaterial() if shader different from prec diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp index 6ee0ff24e..071f69869 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_program.cpp @@ -151,6 +151,9 @@ namespace NL3D { if (driver) nlassert(m_UserVertexProgram == NULL); + if (m_DriverVertexProgram == program) + return true; + if (program == NULL) { nglUseProgramStages(ppoId, GL_VERTEX_SHADER_BIT, 0); @@ -249,6 +252,9 @@ namespace NL3D { if (driver) nlassert(m_UserPixelProgram == NULL); + if (m_DriverPixelProgram == program) + return true; + if (program == NULL) { nglUseProgramStages(ppoId, GL_FRAGMENT_SHADER_BIT, 0); @@ -601,10 +607,15 @@ namespace NL3D { if (m_UserVertexProgram) return true; - CVertexProgram *vertexProgram = generateBuiltinVertexProgram(); - nlassert(vertexProgram); + touchVertexFormatVP(); // TODO + + if (m_VPBuiltinTouched) + { + generateBuiltinVertexProgram(); + nlassert(m_VPBuiltinCurrent.VertexProgram); + } - if (!activeVertexProgram(vertexProgram, true)) + if (!activeVertexProgram(m_VPBuiltinCurrent.VertexProgram, true)) return false; // GL3 TODO: Here we set the uniforms of the vertex program! diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_states.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_states.cpp index 5ac3caa80..447d824e8 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_states.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_states.cpp @@ -72,11 +72,9 @@ void CDriverGLStates3::forceDefaults(uint nbStages) H_AUTO_OGL(CDriverGLStates3_forceDefaults); // Enable / disable. - _CurFog = false; _CurBlend = false; _CurCullFace = true; _CurAlphaTest = false; - _CurLighting = false; _CurZWrite = true; _CurStencilTest =false; @@ -229,14 +227,6 @@ void CDriverGLStates3::enableAlphaTest(uint enable) } } -// *************************************************************************** -void CDriverGLStates3::enableLighting(uint enable) -{ - H_AUTO_OGL(CDriverGLStates3_enableLighting) - - _CurLighting = (enable != 0); -} - // *************************************************************************** void CDriverGLStates3::enableZWrite(uint enable) { @@ -583,21 +573,6 @@ void CDriverGLStates3::enableVertexAttribArrayARB(uint glIndex,bool enable) } -// *************************************************************************** -void CDriverGLStates3::enableFog(uint enable) -{ - H_AUTO_OGL(CDriverGLStates3_enableFog) - // If different from current setup, update. - bool enabled= (enable!=0); -#ifndef NL3D_GLSTATE_DISABLE_CACHE - if (enabled != _CurFog) -#endif - { - // new state. - _CurFog= enabled; - } -} - // *************************************************************************** void CDriverGLStates3::forceBindARBVertexBuffer(uint objectID) { diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_states.h b/code/nel/src/3d/driver/opengl3/driver_opengl_states.h index b608ece31..4f20acacd 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_states.h +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_states.h @@ -84,15 +84,10 @@ public: /// \name enable if !0 // @{ void enableBlend(uint enable); - void enableFog(uint enable); - bool isFogEnabled() const { return _CurFog; } void enableCullFace(uint enable); /// enable and set good AlphaFunc. void enableAlphaTest(uint enable); void enableZWrite(uint enable); - // overall lighting enabled - void enableLighting(uint enable); - bool isLightingEnabled() const { return _CurLighting; } /// enable/disable stencil test void enableStencilTest(bool enable); bool isStencilTestEnabled() const { return _CurStencilTest; } @@ -165,10 +160,8 @@ public: private: bool _CurBlend; - bool _CurFog; bool _CurCullFace; bool _CurAlphaTest; - bool _CurLighting; bool _CurZWrite; bool _CurStencilTest; diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_vertex_program.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_vertex_program.cpp index b5bd738d6..153a59692 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_vertex_program.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_vertex_program.cpp @@ -355,23 +355,17 @@ namespace } } -CVertexProgram *CDriverGL3::generateBuiltinVertexProgram() +void CDriverGL3::generateBuiltinVertexProgram() { - CVPBuiltin desc; - desc.VertexFormat = _CurrentVertexBufferHard->VB->getVertexFormat(); - desc.Fog = _DriverGLStates.isFogEnabled(); - desc.Lighting = _DriverGLStates.isLightingEnabled(); - if (desc.Lighting) - for (sint i = 0; i < MaxLight; ++i) - desc.LightMode[i] = _UserLightEnable[i] ? _LightMode[i] : -1; - desc.VertexColorLighted = false; // _DriverGLStates._VertexColorLighted; - - std::set::iterator it = m_VPBuiltinCache.find(desc); + std::set::iterator it = m_VPBuiltinCache.find(m_VPBuiltinCurrent); if (it != m_VPBuiltinCache.end()) - return it->VertexProgram; + { + m_VPBuiltinCurrent.VertexProgram = it->VertexProgram; + return; + } std::string result; - vpGenerate(result, desc); + vpGenerate(result, m_VPBuiltinCurrent); CVertexProgram *vertexProgram = new CVertexProgram(); IProgram::CSource *src = new IProgram::CSource(); @@ -387,10 +381,50 @@ CVertexProgram *CDriverGL3::generateBuiltinVertexProgram() delete vertexProgram; vertexProgram = NULL; } - desc.VertexProgram = vertexProgram; - m_VPBuiltinCache.insert(desc); + m_VPBuiltinCurrent.VertexProgram = vertexProgram; + m_VPBuiltinCache.insert(m_VPBuiltinCurrent); +} - return desc.VertexProgram; +void CDriverGL3::enableFogVP(bool enable) +{ + H_AUTO_OGL(CDriverGL3_enableFogInternal) + if (m_VPBuiltinCurrent.Fog != enable) + { + m_VPBuiltinCurrent.Fog = enable; + m_VPBuiltinTouched = true; + } +} + +void CDriverGL3::enableLightingVP(bool enable) +{ + H_AUTO_OGL(CDriverGL3_enableLightingVP) + if (m_VPBuiltinCurrent.Lighting != enable) + { + m_VPBuiltinCurrent.Lighting = enable; + m_VPBuiltinTouched = true; + } +} + +void CDriverGL3::touchLightVP(int i) +{ + H_AUTO_OGL(CDriverGL3_touchLightVP) + sint mode = _UserLightEnable[i] ? _LightMode[i] : -1; + if (m_VPBuiltinCurrent.LightMode[i] != mode) + { + m_VPBuiltinCurrent.LightMode[i] = mode; + m_VPBuiltinTouched = true; + } +} + +void CDriverGL3::touchVertexFormatVP() +{ + H_AUTO_OGL(CDriverGL3_touchLightVP) + uint16 format = _CurrentVertexBufferHard->VB->getVertexFormat(); + if (m_VPBuiltinCurrent.VertexFormat != format) + { + m_VPBuiltinCurrent.VertexFormat = format; + m_VPBuiltinTouched = true; + } } #ifdef NL_STATIC