From 0299519116c35b06187edd74fef4c91d97d1d917 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 29 Mar 2015 03:14:36 +0200 Subject: [PATCH] Use hashes for shader program lookup --HG-- branch : opengl3 --- .../src/3d/driver/opengl3/driver_opengl.cpp | 4 +- .../nel/src/3d/driver/opengl3/driver_opengl.h | 6 +- .../opengl3/driver_opengl_pixel_program.cpp | 68 ++++++++++++++++++- .../3d/driver/opengl3/driver_opengl_program.h | 18 +++++ .../opengl3/driver_opengl_vertex_program.cpp | 58 +++++++++++++++- 5 files changed, 148 insertions(+), 6 deletions(-) diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl.cpp index 998d75f1e..bf863ce1f 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl.cpp @@ -663,10 +663,10 @@ bool CDriverGL3::release() m_UserPixelProgram = NULL; // Delete all cached programs - for (std::set::iterator it(m_VPBuiltinCache.begin()), end(m_VPBuiltinCache.end()); it != end; ++it) + for (std::unordered_set::iterator it(m_VPBuiltinCache.begin()), end(m_VPBuiltinCache.end()); it != end; ++it) delete it->VertexProgram; m_VPBuiltinCache.clear(); - for (std::set::iterator it(m_PPBuiltinCache.begin()), end(m_PPBuiltinCache.end()); it != end; ++it) + for (std::unordered_set::iterator it(m_PPBuiltinCache.begin()), end(m_PPBuiltinCache.end()); it != end; ++it) delete it->PixelProgram; m_PPBuiltinCache.clear(); diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl.h b/code/nel/src/3d/driver/opengl3/driver_opengl.h index bce97289f..da124f50f 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl.h +++ b/code/nel/src/3d/driver/opengl3/driver_opengl.h @@ -35,6 +35,8 @@ # endif //XF86VIDMODE #endif // NL_OS_UNIX +#include + #include "nel/misc/matrix.h" #include "nel/misc/smart_ptr.h" #include "nel/misc/rgba.h" @@ -1302,9 +1304,9 @@ private: NLMISC::CRefPtr m_DriverPixelProgram; friend class CPPBuiltin; - std::set m_PPBuiltinCache; + std::unordered_set m_PPBuiltinCache; - std::set m_VPBuiltinCache; + std::unordered_set m_VPBuiltinCache; CVPBuiltin m_VPBuiltinCurrent; bool m_VPBuiltinTouched; diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp b/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp index 37875ac46..b1980e56c 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_pixel_program.cpp @@ -18,6 +18,8 @@ #include +#include "nel/misc/wang_hash.h" + #include "nel/3d/vertex_program.h" #include "nel/3d/light.h" @@ -95,6 +97,70 @@ bool operator<(const CPPBuiltin &left, const CPPBuiltin &right) return false; } +bool operator==(const CPPBuiltin &left, const CPPBuiltin &right) +{ + // Material state + if (left.Shader != right.Shader) + return false; + if (left.Flags != right.Flags) + return false; + if (left.TextureActive != right.TextureActive) + return false; + if (left.TexSamplerMode != right.TexSamplerMode) + return false; + uint maxTex = maxTextures(left.Shader); + if (useTexEnv(left.Shader)) + for (uint stage = 0; stage < maxTex; ++stage) + if (left.TexEnvMode[stage] != right.TexEnvMode[stage]) + return false; + + // Driver state + if (left.VertexFormat != right.VertexFormat) + return false; + if (left.Fog != right.Fog) + return false; + + return true; +} + +#ifdef NL_STATIC +} // NLDRIVERGL3 +#endif + +} // NL3D + +namespace std { + +size_t hash::operator()(const NL3D::CPPBuiltin & v) const +{ + uint32_t h; + + // Material state + h = NLMISC::wangHash((uint32)v.Shader); + h = NLMISC::wangHash(h ^ (uint32)v.Flags); + h = NLMISC::wangHash(h ^ (uint32)v.TextureActive); + h = NLMISC::wangHash(h ^ (uint32)v.TexSamplerMode); + uint maxTex = NL3D::maxTextures(v.Shader); + if (NL3D::useTexEnv(v.Shader)) + for (uint stage = 0; stage < maxTex; ++stage) + h = NLMISC::wangHash(h ^ (uint32)v.TexEnvMode[stage]); + + // Driver state + h = NLMISC::wangHash(h ^ (uint32)v.VertexFormat); + h = NLMISC::wangHash(h ^ (uint32)v.Fog); + + nlctassert(sizeof(size_t) > sizeof(uint32)); + return (size_t)h; +} + +} + +namespace NL3D { + +#ifdef NL_STATIC +namespace NLDRIVERGL3 { +#endif + namespace /* anonymous */ { const char *s_ShaderNames[] = @@ -568,7 +634,7 @@ void CDriverGL3::generateBuiltinPixelProgram(CMaterial &mat) CMaterialDrvInfosGL3 *matDrv = static_cast((IMaterialDrvInfos *)(mat._MatDrvInfo)); nlassert(matDrv); - std::set::iterator it = m_PPBuiltinCache.find(matDrv->PPBuiltin); + std::unordered_set::iterator it = m_PPBuiltinCache.find(matDrv->PPBuiltin); if (it != m_PPBuiltinCache.end()) { matDrv->PPBuiltin.PixelProgram = it->PixelProgram; diff --git a/code/nel/src/3d/driver/opengl3/driver_opengl_program.h b/code/nel/src/3d/driver/opengl3/driver_opengl_program.h index 139a57916..0173c0595 100644 --- a/code/nel/src/3d/driver/opengl3/driver_opengl_program.h +++ b/code/nel/src/3d/driver/opengl3/driver_opengl_program.h @@ -50,6 +50,7 @@ struct CVPBuiltin }; bool operator<(const CVPBuiltin &left, const CVPBuiltin &right); +bool operator==(const CVPBuiltin &left, const CVPBuiltin &right); static const uint64 Sampler2D = 0; static const uint64 SamplerCube = 1; @@ -78,6 +79,7 @@ struct CPPBuiltin }; bool operator<(const CPPBuiltin &left, const CPPBuiltin &right); +bool operator==(const CPPBuiltin &left, const CPPBuiltin &right); enum TAttribOffset { @@ -123,6 +125,22 @@ inline bool hasFlag(uint32 data, uint32 flag) } // NL3D +namespace std { + +template <> +struct hash +{ + size_t operator()(const NL3D::CVPBuiltin & v) const; +}; + +template <> +struct hash +{ + size_t operator()(const NL3D::CPPBuiltin & v) const; +}; + +} + #endif // NL_DRIVER_OPENGL_PROGRAM_H /* end of file */ 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 d14800204..fc5258e2e 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 @@ -18,6 +18,8 @@ #include +#include "nel/misc/wang_hash.h" + #include "nel/3d/vertex_program.h" #include "nel/3d/light.h" @@ -54,6 +56,60 @@ bool operator<(const CVPBuiltin &left, const CVPBuiltin &right) return false; } +bool operator==(const CVPBuiltin &left, const CVPBuiltin &right) +{ + if (left.VertexFormat != right.VertexFormat) + return false; + if (left.Lighting != right.Lighting) + return false; + if (left.Lighting) + for (sint i = 0; i < NL_OPENGL3_MAX_LIGHT; ++i) + if (left.LightMode[i] != right.LightMode[i]) + return false; + for (sint i = 0; i < IDRV_MAT_MAXTEXTURES; ++i) + if (left.TexGenMode[i] != right.TexGenMode[i]) + return false; + if (left.Specular != right.Specular) + return false; + if (left.Fog != right.Fog) + return false; + // if (left.VertexColorLighted != right.VertexColorLighted) + // return false; + + return true; +} + +#ifdef NL_STATIC +} // NLDRIVERGL3 +#endif + +} // NL3D + +namespace std { + +size_t hash::operator()(const NL3D::CVPBuiltin & v) const +{ + uint32_t h; + + h = NLMISC::wangHash(((uint32)v.VertexFormat) | (v.Lighting ? (1 << 16) : 0) | (v.Specular ? (1 << 17) : 0) | (v.Fog ? (1 << 18) : 0)); + if (v.Lighting) + for (sint i = 0; i < NL_OPENGL3_MAX_LIGHT; ++i) + h = NLMISC::wangHash(h ^ v.LightMode[i]); + for (sint i = 0; i < NL3D::IDRV_MAT_MAXTEXTURES; ++i) + h = NLMISC::wangHash(h ^ v.TexGenMode[i]); + + nlctassert(sizeof(size_t) > sizeof(uint32)); + return (size_t)h; +} + +} + +namespace NL3D { + +#ifdef NL_STATIC + namespace NLDRIVERGL3 { +#endif + namespace /* anonymous */ { void vpLightUniforms(std::stringstream &ss, const CVPBuiltin &desc, int i) @@ -316,7 +372,7 @@ void vpGenerate(std::string &result, const CVPBuiltin &desc) void CDriverGL3::generateBuiltinVertexProgram() { - std::set::iterator it = m_VPBuiltinCache.find(m_VPBuiltinCurrent); + std::unordered_set::iterator it = m_VPBuiltinCache.find(m_VPBuiltinCurrent); if (it != m_VPBuiltinCache.end()) { m_VPBuiltinCurrent.VertexProgram = it->VertexProgram;