From d751718a1692e6f3641281bae7c73dc4ef98f69a Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 1 Aug 2013 23:22:48 +0200 Subject: [PATCH] Added methods to retrieve shader binary Added support for GL_ARB_get_program_binary Former-commit-id: 3c23cfd237680f7832d15279af9e4248f9fa4678 --- include/Nazara/Renderer/OpenGL.hpp | 4 +++ include/Nazara/Renderer/Shader.hpp | 3 ++ src/Nazara/Renderer/AbstractShader.hpp | 2 ++ src/Nazara/Renderer/GLSLShader.cpp | 34 +++++++++++++++++++++++ src/Nazara/Renderer/GLSLShader.hpp | 2 ++ src/Nazara/Renderer/OpenGL.cpp | 20 ++++++++++++++ src/Nazara/Renderer/Shader.cpp | 38 ++++++++++++++++++++++++++ 7 files changed, 103 insertions(+) diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index 9cc198576..b2e179117 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -32,6 +32,7 @@ enum nzOpenGLExtension nzOpenGLExtension_DrawInstanced, nzOpenGLExtension_FP64, nzOpenGLExtension_FrameBufferObject, + nzOpenGLExtension_GetProgramBinary, nzOpenGLExtension_InstancedArray, nzOpenGLExtension_PixelBufferObject, nzOpenGLExtension_SamplerObjects, @@ -202,6 +203,7 @@ NAZARA_API extern PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog; NAZARA_API extern PFNGLGETERRORPROC glGetError; NAZARA_API extern PFNGLGETFLOATVPROC glGetFloatv; NAZARA_API extern PFNGLGETINTEGERVPROC glGetIntegerv; +NAZARA_API extern PFNGLGETPROGRAMBINARYPROC glGetProgramBinary; NAZARA_API extern PFNGLGETPROGRAMIVPROC glGetProgramiv; NAZARA_API extern PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog; NAZARA_API extern PFNGLGETQUERYIVPROC glGetQueryiv; @@ -227,6 +229,8 @@ NAZARA_API extern PFNGLMAPBUFFERRANGEPROC glMapBufferRange; NAZARA_API extern PFNGLPIXELSTOREIPROC glPixelStorei; NAZARA_API extern PFNGLPOINTSIZEPROC glPointSize; NAZARA_API extern PFNGLPOLYGONMODEPROC glPolygonMode; +NAZARA_API extern PFNGLPROGRAMBINARYPROC glProgramBinary; +NAZARA_API extern PFNGLPROGRAMPARAMETERIPROC glProgramParameteri; NAZARA_API extern PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d; NAZARA_API extern PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f; NAZARA_API extern PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i; diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index d79b314d5..5ade91d74 100644 --- a/include/Nazara/Renderer/Shader.hpp +++ b/include/Nazara/Renderer/Shader.hpp @@ -8,6 +8,7 @@ #define NAZARA_SHADER_HPP #include +#include #include #include #include @@ -42,6 +43,7 @@ class NAZARA_API NzShader : public NzResource, NzNonCopyable void Destroy(); + NzByteArray GetBinary() const; nzUInt32 GetFlags() const; NzString GetLog() const; nzShaderLanguage GetLanguage() const; @@ -51,6 +53,7 @@ class NAZARA_API NzShader : public NzResource, NzNonCopyable bool HasUniform(const NzString& name) const; + bool IsBinaryRetrievable() const; bool IsCompiled() const; bool IsLoaded(nzShaderType type) const; bool IsValid() const; diff --git a/src/Nazara/Renderer/AbstractShader.hpp b/src/Nazara/Renderer/AbstractShader.hpp index 9d6ad582b..6867e476c 100644 --- a/src/Nazara/Renderer/AbstractShader.hpp +++ b/src/Nazara/Renderer/AbstractShader.hpp @@ -25,12 +25,14 @@ class NzAbstractShader virtual void Destroy() = 0; + virtual NzByteArray GetBinary() const = 0; virtual NzString GetLog() const = 0; virtual nzShaderLanguage GetLanguage() const = 0; virtual NzString GetSourceCode(nzShaderType type) const = 0; virtual int GetUniformLocation(const NzString& name) const = 0; virtual int GetUniformLocation(nzShaderUniform uniform) const = 0; + virtual bool IsBinaryRetrievable() const = 0; virtual bool IsLoaded(nzShaderType type) const = 0; virtual bool Load(nzShaderType type, const NzString& source) = 0; diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index e7608e0d7..37c1a58e6 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -51,6 +51,9 @@ bool NzGLSLShader::Compile() m_idCache.clear(); m_textures.clear(); + if (NzOpenGL::IsSupported(nzOpenGLExtension_GetProgramBinary)) + glProgramParameteri(m_program, GL_PROGRAM_BINARY_RETRIEVABLE_HINT, GL_TRUE); + glLinkProgram(m_program); GLint success; @@ -170,6 +173,32 @@ void NzGLSLShader::Destroy() NzOpenGL::DeleteProgram(m_program); } +NzByteArray NzGLSLShader::GetBinary() const +{ + NzByteArray byteArray; + + NzContext::EnsureContext(); + + GLint binaryLength; + glGetProgramiv(m_program, GL_PROGRAM_BINARY_LENGTH, &binaryLength); + + if (binaryLength > 0) + { + byteArray.Resize(sizeof(nzUInt64) + binaryLength); + + nzUInt8* ptr = byteArray.GetBuffer(); + + GLenum binaryFormat; + glGetProgramBinary(m_program, binaryLength, nullptr, &binaryFormat, &ptr[sizeof(nzUInt64)]); + + // On stocke le format au début du binaire + nzUInt64* format = reinterpret_cast(&ptr[0]); + *format = binaryFormat; + } + + return byteArray; +} + NzString NzGLSLShader::GetLog() const { return m_log; @@ -219,6 +248,11 @@ int NzGLSLShader::GetUniformLocation(nzShaderUniform uniform) const return m_uniformLocations[uniform]; } +bool NzGLSLShader::IsBinaryRetrievable() const +{ + return NzOpenGL::IsSupported(nzOpenGLExtension_GetProgramBinary); +} + bool NzGLSLShader::IsLoaded(nzShaderType type) const { return m_shaders[type] != 0; diff --git a/src/Nazara/Renderer/GLSLShader.hpp b/src/Nazara/Renderer/GLSLShader.hpp index 53aee3ea6..e8a1fee9d 100644 --- a/src/Nazara/Renderer/GLSLShader.hpp +++ b/src/Nazara/Renderer/GLSLShader.hpp @@ -31,12 +31,14 @@ class NzGLSLShader : public NzAbstractShader, NzResourceListener bool Create(); void Destroy(); + NzByteArray GetBinary() const; NzString GetLog() const; nzShaderLanguage GetLanguage() const; NzString GetSourceCode(nzShaderType type) const; int GetUniformLocation(const NzString& name) const; int GetUniformLocation(nzShaderUniform uniform) const; + bool IsBinaryRetrievable() const; bool IsLoaded(nzShaderType type) const; bool Load(nzShaderType type, const NzString& source); diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index d90c1e273..b2eaff115 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -866,6 +866,23 @@ bool NzOpenGL::Initialize() } } + // GetProgramBinary + if (s_openglVersion >= 410 || IsSupported("GL_ARB_get_program_binary")) + { + try + { + glGetProgramBinary = reinterpret_cast(LoadEntry("glGetProgramBinary")); + glProgramBinary = reinterpret_cast(LoadEntry("glProgramBinary")); + glProgramParameteri = reinterpret_cast(LoadEntry("glProgramParameteri")); + + s_openGLextensions[nzOpenGLExtension_GetProgramBinary] = true; + } + catch (const std::exception& e) + { + NazaraWarning("Failed to load ARB_get_program_binary: (" + NzString(e.what()) + ")"); + } + } + // InstancedArray if (s_openglVersion >= 330) { @@ -1480,6 +1497,7 @@ PFNGLGETDEBUGMESSAGELOGPROC glGetDebugMessageLog = nullptr; PFNGLGETERRORPROC glGetError = nullptr; PFNGLGETFLOATVPROC glGetFloatv = nullptr; PFNGLGETINTEGERVPROC glGetIntegerv = nullptr; +PFNGLGETPROGRAMBINARYPROC glGetProgramBinary = nullptr; PFNGLGETPROGRAMIVPROC glGetProgramiv = nullptr; PFNGLGETPROGRAMINFOLOGPROC glGetProgramInfoLog = nullptr; PFNGLGETQUERYIVPROC glGetQueryiv = nullptr; @@ -1505,6 +1523,8 @@ PFNGLMAPBUFFERRANGEPROC glMapBufferRange = nullptr; PFNGLPIXELSTOREIPROC glPixelStorei = nullptr; PFNGLPOINTSIZEPROC glPointSize = nullptr; PFNGLPOLYGONMODEPROC glPolygonMode = nullptr; +PFNGLPROGRAMBINARYPROC glProgramBinary = nullptr; +PFNGLPROGRAMPARAMETERIPROC glProgramParameteri = nullptr; PFNGLPROGRAMUNIFORM1DPROC glProgramUniform1d = nullptr; PFNGLPROGRAMUNIFORM1FPROC glProgramUniform1f = nullptr; PFNGLPROGRAMUNIFORM1IPROC glProgramUniform1i = nullptr; diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 271d1ecf6..45533af9d 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -106,6 +106,31 @@ void NzShader::Destroy() } } +NzByteArray NzShader::GetBinary() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return NzByteArray(); + } + + if (!m_compiled) + { + NazaraError("Shader is not compiled"); + return NzByteArray(); + } + + if (!m_impl->IsBinaryRetrievable()) + { + NazaraError("Shader binary is not retrievable"); + return NzByteArray(); + } + #endif + + return m_impl->GetBinary(); +} + nzUInt32 NzShader::GetFlags() const { return m_flags; @@ -211,6 +236,19 @@ bool NzShader::HasUniform(const NzString& name) const return m_impl->GetUniformLocation(name) != -1; } +bool NzShader::IsBinaryRetrievable() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + #endif + + return m_impl->IsBinaryRetrievable(); +} + bool NzShader::IsCompiled() const { #if NAZARA_RENDERER_SAFE