From 77ae38e452c04fa20ad98d57af6797c0d1a4d04f Mon Sep 17 00:00:00 2001 From: dfighter1985 Date: Mon, 9 Sep 2013 04:16:24 +0200 Subject: [PATCH] Added a very primitive shader caching scheme. --HG-- branch : gsoc2013-dfighter --- .../src/3d/driver/OpenGL3/driver_opengl.cpp | 6 +- .../nel/src/3d/driver/OpenGL3/driver_opengl.h | 4 + .../driver/OpenGL3/driver_opengl_program.cpp | 131 ++++++++++++------ .../OpenGL3/driver_opengl_shader_cache.cpp | 60 ++++++++ .../OpenGL3/driver_opengl_shader_cache.h | 44 ++++++ .../OpenGL3/driver_opengl_shader_desc.h | 72 ++++++++++ 6 files changed, 267 insertions(+), 50 deletions(-) create mode 100644 code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.cpp create mode 100644 code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.h create mode 100644 code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp b/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp index 73375b2e1..7a45d7fb1 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl.cpp @@ -342,11 +342,7 @@ CDriverGL3::~CDriverGL3() { H_AUTO_OGL(CDriverGL3_CDriverGLDtor) - if( currentProgram != NULL ) - { - delete currentProgram; - currentProgram = NULL; - } + currentProgram = NULL; release(); diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl.h b/code/nel/src/3d/driver/OpenGL3/driver_opengl.h index 1aa68d6a1..1363b96cf 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl.h +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl.h @@ -63,6 +63,7 @@ #include "driver_opengl_states.h" #include "driver_opengl_extension.h" +#include "driver_opengl_shader_cache.h" #ifdef NL_OS_WINDOWS @@ -1450,6 +1451,9 @@ private: */ inline void setupTextureBasicParameters(ITexture &tex); + +private: + CShaderCache shaderCache; }; // *************************************************************************** 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 51e75a975..b8bc77534 100644 --- a/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_program.cpp @@ -1,3 +1,20 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + #include "driver_opengl.h" #include "driver_glsl_program.h" #include "driver_glsl_vertex_program.h" @@ -121,56 +138,84 @@ namespace NL3D bool CDriverGL3::setupProgram( CMaterial &mat ) { - std::string vs; - std::string ps; - - shaderGenerator->reset(); - shaderGenerator->setMaterial( &mat ); - shaderGenerator->setVBFormat( _CurrentVertexBufferHard->VB->getVertexFormat() ); - shaderGenerator->generateVS( vs ); - shaderGenerator->generatePS( ps ); #ifdef GLSL - vp = createVertexProgram(); - std::string log; + CShaderDesc desc; + desc.setShaderType( mat.getShader() ); + desc.setVBFlags( _CurrentVertexBufferHard->VB->getVertexFormat() ); + + int i = 0; - vp->shaderSource( vs.c_str() ); - if( !vp->compile( log ) ) + if( mat.getShader() == CMaterial::Normal ) { - delete vp; - vp = NULL; - nlinfo( "%s", log.c_str() ); - return false; + for( i = 0; i < MAX_TEXTURES; i++ ) + { + desc.setTexEnvMode( i, mat.getTexEnvMode( i ) ); + } } - - pp = createPixelProgram(); - pp->shaderSource( ps.c_str() ); - if( !pp->compile( log ) ) + + p = shaderCache.findShader( desc ); + + if( p != NULL ) { - delete vp; - vp = NULL; - delete pp; - pp = NULL; - nlinfo( "%s", log.c_str() ); - return false; + if( !activeProgramObject( p ) ) + return false; } - - p = createProgramObject(); - p->attachVertexProgram( vp ); - p->attachPixelProgram( pp ); - if( !p->link( log ) ) + else { - vp = NULL; - pp = NULL; - delete p; - p = NULL; - nlinfo( "%s", log.c_str() ); - return false; + std::string vs; + std::string ps; + + shaderGenerator->reset(); + shaderGenerator->setMaterial( &mat ); + shaderGenerator->setVBFormat( _CurrentVertexBufferHard->VB->getVertexFormat() ); + shaderGenerator->generateVS( vs ); + shaderGenerator->generatePS( ps ); + + vp = createVertexProgram(); + std::string log; + + vp->shaderSource( vs.c_str() ); + if( !vp->compile( log ) ) + { + delete vp; + vp = NULL; + nlinfo( "%s", log.c_str() ); + return false; + } + + pp = createPixelProgram(); + pp->shaderSource( ps.c_str() ); + if( !pp->compile( log ) ) + { + delete vp; + vp = NULL; + delete pp; + pp = NULL; + nlinfo( "%s", log.c_str() ); + return false; + } + + p = createProgramObject(); + p->attachVertexProgram( vp ); + p->attachPixelProgram( pp ); + if( !p->link( log ) ) + { + vp = NULL; + pp = NULL; + delete p; + p = NULL; + nlinfo( "%s", log.c_str() ); + return false; + } + + if( !activeProgramObject( p ) ) + return false; + + desc.setProgram( p ); + shaderCache.cacheShader( desc ); } - - if( !activeProgramObject( p ) ) - return false; - + int mvpIndex = getUniformLocation( "mvpMatrix" ); if( mvpIndex != -1 ) { @@ -185,10 +230,6 @@ namespace NL3D void CDriverGL3::releaseProgram() { - if( currentProgram == NULL ) - return; - - delete currentProgram; currentProgram = NULL; #ifndef GLSL diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.cpp b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.cpp new file mode 100644 index 000000000..ecdd1d4e8 --- /dev/null +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.cpp @@ -0,0 +1,60 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#include "driver_opengl_shader_cache.h" + +namespace NL3D +{ + CShaderCache::CShaderCache() + { + } + + CShaderCache::~CShaderCache() + { + clearCache(); + } + + IProgramObject* CShaderCache::findShader( const CShaderDesc &desc ) const + { + for( int i = 0; i < shaders.size(); i++ ) + { + if( shaders[ i ] == desc ) + return shaders[ i ].getProgram(); + } + + return NULL; + } + + void CShaderCache::cacheShader( CShaderDesc &desc ) + { + shaders.push_back( desc ); + } + + void CShaderCache::clearCache() + { + std::vector< CShaderDesc >::iterator itr = shaders.begin(); + while( itr != shaders.end() ) + { + IProgramObject *p = itr->getProgram(); + delete p; + ++itr; + } + + shaders.clear(); + } +} + diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.h b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.h new file mode 100644 index 000000000..2e687654c --- /dev/null +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_cache.h @@ -0,0 +1,44 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + + +#ifndef OPENGL_SHADER_CACHE +#define OPENGL_SHADER_CACHE + +#include "driver_opengl_shader_desc.h" +#include + +namespace NL3D +{ + class CShaderCache + { + public: + CShaderCache(); + ~CShaderCache(); + + IProgramObject* findShader( const CShaderDesc &desc ) const; + void cacheShader( CShaderDesc &desc ); + void clearCache(); + + private: + std::vector< CShaderDesc > shaders; + + }; +} + + +#endif + diff --git a/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h new file mode 100644 index 000000000..ced7d724b --- /dev/null +++ b/code/nel/src/3d/driver/OpenGL3/driver_opengl_shader_desc.h @@ -0,0 +1,72 @@ +// NeL - MMORPG Framework +// Copyright (C) 2010 Winch Gate Property Limited +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . + +#ifndef SHADER_DESC +#define SHADER_DESC + +#include "nel/misc/types_nl.h" + +#define MAX_TEXTURES 4 + +namespace NL3D +{ + class IProgramObject; + + class CShaderDesc + { + public: + CShaderDesc(){ + for( int i = 0; i < MAX_TEXTURES; i++ ) + texEnvMode[ i ] = 0; + shaderType = 0; + program = NULL; + vbFlags = 0; + } + + ~CShaderDesc(){ + } + + bool operator==( const CShaderDesc &o ) const + { + if( shaderType != o.shaderType ) + return false; + + if( vbFlags != o.vbFlags ) + return false; + + for( int i = 0; i < MAX_TEXTURES; i++ ) + if( texEnvMode[ i ] != o.texEnvMode[ i ] ) + return false; + + return true; + } + + void setTexEnvMode( uint32 index, uint32 mode ){ texEnvMode[ index ] = mode; } + void setVBFlags( uint32 flags ){ vbFlags = flags; } + void setShaderType( uint32 type ){ shaderType = type; } + void setProgram( IProgramObject *p ){ program = p; } + IProgramObject* getProgram() const{ return program; } + + private: + uint32 texEnvMode[ MAX_TEXTURES ]; + uint32 vbFlags; + uint32 shaderType; + IProgramObject *program; + }; +} + +#endif +