diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index 44be24c26..be6c83132 100644 --- a/include/Nazara/Renderer/Shader.hpp +++ b/include/Nazara/Renderer/Shader.hpp @@ -55,6 +55,8 @@ class NAZARA_API NzShader bool Load(nzShaderType type, const NzString& source); bool LoadFromFile(nzShaderType type, const NzString& source); + bool Lock(); + bool SendBoolean(const NzString& name, bool value); bool SendDouble(const NzString& name, double value); bool SendFloat(const NzString& name, float value); @@ -62,12 +64,12 @@ class NAZARA_API NzShader bool SendMatrix(const NzString& name, const NzMatrix4d& matrix); bool SendMatrix(const NzString& name, const NzMatrix4f& matrix); + void Unlock(); + static bool IsLanguageSupported(nzShaderLanguage language); static bool IsTypeSupported(nzShaderType type); private: - bool CommitUniforms(); - NzShaderImpl* m_impl; bool m_compiled; }; diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index b9d4c3b3b..624c33fc9 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -245,44 +245,72 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source) } } +bool NzGLSLShader::Lock() const +{ + if (m_lockedLevel++ == 0) + { + GLint previous; + glGetIntegerv(GL_CURRENT_PROGRAM, &previous); + + m_lockedPrevious = previous; + + if (m_lockedPrevious != m_program) + glUseProgram(m_program); + } + + return true; +} + bool NzGLSLShader::SendBoolean(const NzString& name, bool value) { + Lock(); glUniform1i(GetUniformLocation(name), value); + Unlock(); return true; } bool NzGLSLShader::SendDouble(const NzString& name, double value) { + Lock(); glUniform1d(GetUniformLocation(name), value); + Unlock(); return true; } bool NzGLSLShader::SendFloat(const NzString& name, float value) { + Lock(); glUniform1f(GetUniformLocation(name), value); + Unlock(); return true; } bool NzGLSLShader::SendInteger(const NzString& name, int value) { + Lock(); glUniform1i(GetUniformLocation(name), value); + Unlock(); return true; } bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4d& matrix) { + Lock(); glUniformMatrix4dv(GetUniformLocation(name), 1, GL_FALSE, matrix); + Unlock(); return true; } bool NzGLSLShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix) { + Lock(); glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, matrix); + Unlock(); return true; } @@ -292,6 +320,18 @@ void NzGLSLShader::Unbind() glUseProgram(0); } +void NzGLSLShader::Unlock() const +{ + if (m_lockedLevel == 0) + { + NazaraWarning("Unlock called on non-locked texture"); + return; + } + + if (--m_lockedLevel == 0 && m_lockedPrevious != m_program) + glUseProgram(m_lockedPrevious); +} + bool NzGLSLShader::UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration) { vertexBuffer->GetBuffer()->GetImpl()->Bind(); diff --git a/src/Nazara/Renderer/GLSLShader.hpp b/src/Nazara/Renderer/GLSLShader.hpp index 176e34d76..86efaabaf 100644 --- a/src/Nazara/Renderer/GLSLShader.hpp +++ b/src/Nazara/Renderer/GLSLShader.hpp @@ -34,6 +34,7 @@ class NzGLSLShader : public NzShaderImpl bool IsLoaded(nzShaderType type) const; bool Load(nzShaderType type, const NzString& source); + bool Lock() const; bool SendBoolean(const NzString& name, bool value); bool SendDouble(const NzString& name, double value); @@ -43,13 +44,16 @@ class NzGLSLShader : public NzShaderImpl bool SendMatrix(const NzString& name, const NzMatrix4f& matrix); void Unbind(); + void Unlock() const; private: bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration); mutable std::map m_idCache; + mutable GLuint m_lockedPrevious; GLuint m_program; GLuint m_shaders[nzShaderType_Count]; + mutable nzUInt8 m_lockedLevel; NzShader* m_parent; NzString m_log; }; diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 4e5b5b4ee..f9f375b64 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -267,6 +267,19 @@ bool NzShader::LoadFromFile(nzShaderType type, const NzString& filePath) return m_impl->Load(type, source); } +bool NzShader::Lock() +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return false; + } + #endif + + return m_impl->Lock(); +} + bool NzShader::SendBoolean(const NzString& name, bool value) { #if NAZARA_RENDERER_SAFE @@ -357,6 +370,19 @@ bool NzShader::SendMatrix(const NzString& name, const NzMatrix4f& matrix) return m_impl->SendMatrix(name, matrix); } +void NzShader::Unlock() +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Shader not created"); + return; + } + #endif + + return m_impl->Unlock(); +} + bool NzShader::IsLanguageSupported(nzShaderLanguage language) { switch (language) diff --git a/src/Nazara/Renderer/ShaderImpl.hpp b/src/Nazara/Renderer/ShaderImpl.hpp index 2a650cfec..9d30cedbc 100644 --- a/src/Nazara/Renderer/ShaderImpl.hpp +++ b/src/Nazara/Renderer/ShaderImpl.hpp @@ -36,6 +36,8 @@ class NzShaderImpl virtual bool Load(nzShaderType type, const NzString& source) = 0; + virtual bool Lock() const = 0; + virtual bool SendBoolean(const NzString& name, bool value) = 0; virtual bool SendDouble(const NzString& name, double value) = 0; virtual bool SendFloat(const NzString& name, float value) = 0; @@ -44,6 +46,7 @@ class NzShaderImpl virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0; virtual void Unbind() = 0; + virtual void Unlock() const = 0; protected: virtual bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration) = 0;