From 4f3060a40dbe52e6c4e1f64e02253c95c0716627 Mon Sep 17 00:00:00 2001 From: Lynix Date: Fri, 3 May 2013 02:58:35 +0200 Subject: [PATCH] Greatly improved Renderer Separated Viewport from Scissor rect Improved performances Removed Lock/Unlock system from Shader/Texture class Former-commit-id: f54bca6de58fe9d495d9192dc0d761f92594ee86 --- include/Nazara/Renderer/Enums.hpp | 5 +- include/Nazara/Renderer/OpenGL.hpp | 20 +- include/Nazara/Renderer/Renderer.hpp | 11 +- include/Nazara/Renderer/Shader.hpp | 4 - include/Nazara/Renderer/Texture.hpp | 6 +- src/Nazara/Renderer/DebugDrawer.cpp | 36 +-- src/Nazara/Renderer/GLSLShader.cpp | 184 ++----------- src/Nazara/Renderer/GLSLShader.hpp | 4 - src/Nazara/Renderer/HardwareBuffer.cpp | 55 +--- src/Nazara/Renderer/OpenGL.cpp | 95 ++++++- src/Nazara/Renderer/RenderWindow.cpp | 4 +- src/Nazara/Renderer/Renderer.cpp | 365 +++++++++++++++---------- src/Nazara/Renderer/Shader.cpp | 26 -- src/Nazara/Renderer/ShaderImpl.hpp | 5 - src/Nazara/Renderer/Texture.cpp | 130 ++------- 15 files changed, 389 insertions(+), 561 deletions(-) diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 35d70bad2..705daf6a0 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -113,9 +113,10 @@ enum nzRendererParameter nzRendererParameter_DepthTest, nzRendererParameter_DepthWrite, nzRendererParameter_FaceCulling, - nzRendererParameter_Stencil, + nzRendererParameter_ScissorTest, + nzRendererParameter_StencilTest, - nzRendererParameter_Max = nzRendererParameter_Stencil + nzRendererParameter_Max = nzRendererParameter_StencilTest }; enum nzSamplerFilter diff --git a/include/Nazara/Renderer/OpenGL.hpp b/include/Nazara/Renderer/OpenGL.hpp index e3a361cb8..b0b7bc838 100644 --- a/include/Nazara/Renderer/OpenGL.hpp +++ b/include/Nazara/Renderer/OpenGL.hpp @@ -51,7 +51,7 @@ class NAZARA_API NzOpenGL enum FormatType { FormatType_RenderBuffer, - // FormatType_MultisampleTexture, +// FormatType_MultisampleTexture, FormatType_Texture }; @@ -65,15 +65,33 @@ class NAZARA_API NzOpenGL NzOpenGL() = delete; ~NzOpenGL() = delete; + static void BindBuffer(nzBufferType type, GLuint id); + static void BindProgram(GLuint id); + static void BindTexture(nzImageType type, GLuint id); + + static void DeleteBuffer(nzBufferType type, GLuint id); + static void DeleteProgram(GLuint id); + static void DeleteTexture(GLuint id); + + static GLuint GetCurrentBuffer(nzBufferType type); + static GLuint GetCurrentProgram(); + static GLuint GetCurrentTexture(); static NzOpenGLFunc GetEntry(const NzString& entryPoint); static NzString GetRendererName(); + static unsigned int GetTextureUnit(); static NzString GetVendorName(); static unsigned int GetVersion(); + static bool Initialize(); + static bool IsInitialized(); static bool IsSupported(nzOpenGLExtension extension); static bool IsSupported(const NzString& string); + + static void SetTextureUnit(unsigned int textureUnit); + static bool TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType target); + static void Uninitialize(); static GLenum Attachment[nzAttachmentPoint_Max+1]; diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 1d5d0246d..2fc4b0314 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -53,6 +53,7 @@ class NAZARA_API NzRenderer static unsigned int GetMaxRenderTargets(); static unsigned int GetMaxTextureUnits(); static float GetPointSize(); + static NzRectui GetScissorRect(); static const NzShader* GetShader(); static const NzRenderTarget* GetTarget(); static NzRectui GetViewport(); @@ -72,12 +73,13 @@ class NAZARA_API NzRenderer static void SetDepthFunc(nzRendererComparison compareFunc); static void SetFaceCulling(nzFaceCulling cullingMode); static void SetFaceFilling(nzFaceFilling fillingMode); - static bool SetIndexBuffer(const NzIndexBuffer* indexBuffer); + static void SetIndexBuffer(const NzIndexBuffer* indexBuffer); static void SetInstancingData(const InstancingData* instancingData, unsigned int instanceCount); static void SetLineWidth(float size); static void SetMatrix(nzMatrixType type, const NzMatrix4f& matrix); static void SetPointSize(float size); - static bool SetShader(const NzShader* shader); + static void SetScissorRect(const NzRectui& viewport); + static void SetShader(const NzShader* shader); static void SetStencilCompareFunction(nzRendererComparison compareFunc); static void SetStencilFailOperation(nzStencilOperation failOperation); static void SetStencilMask(nzUInt32 mask); @@ -87,13 +89,14 @@ class NAZARA_API NzRenderer static bool SetTarget(const NzRenderTarget* target); static void SetTexture(nzUInt8 unit, const NzTexture* texture); static void SetTextureSampler(nzUInt8 textureUnit, const NzTextureSampler& sampler); - static bool SetVertexBuffer(const NzVertexBuffer* vertexBuffer); + static void SetVertexBuffer(const NzVertexBuffer* vertexBuffer); static void SetViewport(const NzRectui& viewport); static void Uninitialize(); private: - static bool EnsureStateUpdate(bool instancing); + static void EnableInstancing(bool instancing); + static bool EnsureStateUpdate(); static unsigned int s_moduleReferenceCounter; }; diff --git a/include/Nazara/Renderer/Shader.hpp b/include/Nazara/Renderer/Shader.hpp index 9027b47ce..4e6aa45dc 100644 --- a/include/Nazara/Renderer/Shader.hpp +++ b/include/Nazara/Renderer/Shader.hpp @@ -57,8 +57,6 @@ class NAZARA_API NzShader : public NzResource, NzNonCopyable bool Load(nzShaderType type, const NzString& source); bool LoadFromFile(nzShaderType type, const NzString& source); - bool Lock(); - bool SendBoolean(int location, bool value) const; bool SendColor(int location, const NzColor& color) const; bool SendDouble(int location, double value) const; @@ -76,8 +74,6 @@ class NAZARA_API NzShader : public NzResource, NzNonCopyable void SetFlags(nzUInt32 flags); - void Unlock(); - NzShader& operator=(NzShader&& shader); static bool IsLanguageSupported(nzShaderLanguage language); diff --git a/include/Nazara/Renderer/Texture.hpp b/include/Nazara/Renderer/Texture.hpp index 55f2972f2..f716160f4 100644 --- a/include/Nazara/Renderer/Texture.hpp +++ b/include/Nazara/Renderer/Texture.hpp @@ -34,7 +34,7 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable explicit NzTexture(const NzImage& image); ~NzTexture(); - bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1, bool lock = false); + bool Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth = 1, nzUInt8 levelCount = 1); void Destroy(); bool Download(NzImage* image) const; @@ -72,8 +72,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable bool LoadFaceFromMemory(nzCubemapFace face, const void* data, std::size_t size, const NzImageParams& params = NzImageParams()); bool LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, const NzImageParams& params = NzImageParams()); - bool Lock(); - bool SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel); bool Update(const NzImage& image, nzUInt8 level = 0); @@ -87,8 +85,6 @@ class NAZARA_API NzTexture : public NzResource, NzNonCopyable bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); bool UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRectui& rect, unsigned int srcWidth = 0, unsigned int srcHeight = 0, nzUInt8 level = 0); - void Unlock(); - // Fonctions OpenGL bool Bind() const; unsigned int GetOpenGLID() const; diff --git a/src/Nazara/Renderer/DebugDrawer.cpp b/src/Nazara/Renderer/DebugDrawer.cpp index ee9203e62..9ca4a1f4a 100644 --- a/src/Nazara/Renderer/DebugDrawer.cpp +++ b/src/Nazara/Renderer/DebugDrawer.cpp @@ -130,11 +130,7 @@ void NzDebugDrawer::Draw(const NzCubef& cube) const NzShader* oldShader = NzRenderer::GetShader(); - if (!NzRenderer::SetShader(shader)) - { - NazaraError("Failed to set debug shader"); - return; - } + NzRenderer::SetShader(shader); bool depthTestActive = NzRenderer::IsEnabled(nzRendererParameter_DepthTest); if (depthTestActive != depthTest) @@ -154,8 +150,7 @@ void NzDebugDrawer::Draw(const NzCubef& cube) if (depthTestActive != depthTest) NzRenderer::Enable(nzRendererParameter_DepthTest, depthTestActive); - if (!NzRenderer::SetShader(oldShader)) - NazaraWarning("Failed to reset shader"); + NzRenderer::SetShader(oldShader); } void NzDebugDrawer::Draw(const NzCubeui& cube) @@ -238,11 +233,7 @@ void NzDebugDrawer::Draw(const NzFrustumf& frustum) const NzShader* oldShader = NzRenderer::GetShader(); - if (!NzRenderer::SetShader(shader)) - { - NazaraError("Failed to set debug shader"); - return; - } + NzRenderer::SetShader(shader); bool depthTestActive = NzRenderer::IsEnabled(nzRendererParameter_DepthTest); if (depthTestActive != depthTest) @@ -262,8 +253,7 @@ void NzDebugDrawer::Draw(const NzFrustumf& frustum) if (depthTestActive != depthTest) NzRenderer::Enable(nzRendererParameter_DepthTest, depthTestActive); - if (!NzRenderer::SetShader(oldShader)) - NazaraWarning("Failed to reset shader"); + NzRenderer::SetShader(oldShader); } void NzDebugDrawer::Draw(const NzOrientedCubef& orientedCube) @@ -341,11 +331,7 @@ void NzDebugDrawer::Draw(const NzOrientedCubef& orientedCube) const NzShader* oldShader = NzRenderer::GetShader(); - if (!NzRenderer::SetShader(shader)) - { - NazaraError("Failed to set debug shader"); - return; - } + NzRenderer::SetShader(shader); bool depthTestActive = NzRenderer::IsEnabled(nzRendererParameter_DepthTest); if (depthTestActive != depthTest) @@ -365,8 +351,7 @@ void NzDebugDrawer::Draw(const NzOrientedCubef& orientedCube) if (depthTestActive != depthTest) NzRenderer::Enable(nzRendererParameter_DepthTest, depthTestActive); - if (!NzRenderer::SetShader(oldShader)) - NazaraWarning("Failed to reset shader"); + NzRenderer::SetShader(oldShader); } void NzDebugDrawer::Draw(const NzSkeleton* skeleton) @@ -410,11 +395,7 @@ void NzDebugDrawer::Draw(const NzSkeleton* skeleton) { const NzShader* oldShader = NzRenderer::GetShader(); - if (!NzRenderer::SetShader(shader)) - { - NazaraError("Failed to set debug shader"); - return; - } + NzRenderer::SetShader(shader); bool depthTestActive = NzRenderer::IsEnabled(nzRendererParameter_DepthTest); if (depthTestActive != depthTest) @@ -440,8 +421,7 @@ void NzDebugDrawer::Draw(const NzSkeleton* skeleton) if (depthTestActive != depthTest) NzRenderer::Enable(nzRendererParameter_DepthTest, depthTestActive); - if (!NzRenderer::SetShader(oldShader)) - NazaraWarning("Failed to reset shader"); + NzRenderer::SetShader(oldShader); } } /* diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 23ea71c70..83ea6a22b 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -12,12 +12,6 @@ #include #include -namespace -{ - GLuint lockedPrevious = 0; - nzUInt8 lockedLevel = 0; -} - NzGLSLShader::NzGLSLShader(NzShader* parent) : m_parent(parent) { @@ -25,14 +19,6 @@ m_parent(parent) bool NzGLSLShader::Bind() { - #if NAZARA_RENDERER_SAFE - if (lockedLevel > 0) - { - NazaraError("Cannot bind shader while a shader is locked"); - return false; - } - #endif - #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) { @@ -41,7 +27,7 @@ bool NzGLSLShader::Bind() } #endif - glUseProgram(m_program); + NzOpenGL::BindProgram(m_program); return true; } @@ -160,8 +146,7 @@ void NzGLSLShader::Destroy() glDeleteShader(shader); } - if (m_program) - glDeleteProgram(m_program); + NzOpenGL::DeleteProgram(m_program); } NzString NzGLSLShader::GetLog() const @@ -270,38 +255,14 @@ bool NzGLSLShader::Load(nzShaderType type, const NzString& source) } } -bool NzGLSLShader::Lock() -{ - if (lockedLevel++ == 0) - { - NzContext::EnsureContext(); - - GLint previous; - glGetIntegerv(GL_CURRENT_PROGRAM, &previous); - - lockedPrevious = previous; - - if (lockedPrevious != m_program) - glUseProgram(m_program); - } - - return true; -} - bool NzGLSLShader::SendBoolean(int location, bool value) { if (glProgramUniform1i) glProgramUniform1i(m_program, location, value); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform1i(location, value); - Unlock(); } return true; @@ -315,14 +276,8 @@ bool NzGLSLShader::SendColor(int location, const NzColor& color) glProgramUniform4fv(m_program, location, 1, vecColor); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform4fv(location, 1, vecColor); - Unlock(); } return true; @@ -334,14 +289,8 @@ bool NzGLSLShader::SendDouble(int location, double value) glProgramUniform1d(m_program, location, value); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform1d(location, value); - Unlock(); } return true; @@ -353,14 +302,8 @@ bool NzGLSLShader::SendFloat(int location, float value) glProgramUniform1f(m_program, location, value); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform1f(location, value); - Unlock(); } return true; @@ -372,14 +315,8 @@ bool NzGLSLShader::SendInteger(int location, int value) glProgramUniform1i(m_program, location, value); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform1i(location, value); - Unlock(); } return true; @@ -391,14 +328,8 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4d& matrix) glProgramUniformMatrix4dv(m_program, location, 1, GL_FALSE, matrix); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniformMatrix4dv(location, 1, GL_FALSE, matrix); - Unlock(); } return true; @@ -410,14 +341,8 @@ bool NzGLSLShader::SendMatrix(int location, const NzMatrix4f& matrix) glProgramUniformMatrix4fv(m_program, location, 1, GL_FALSE, matrix); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniformMatrix4fv(location, 1, GL_FALSE, matrix); - Unlock(); } return true; @@ -495,14 +420,8 @@ bool NzGLSLShader::SendTexture(int location, const NzTexture* texture, nzUInt8* glProgramUniform1i(m_program, location, unit); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform1i(location, unit); - Unlock(); } } @@ -522,14 +441,8 @@ bool NzGLSLShader::SendVector(int location, const NzVector2d& vector) glProgramUniform2dv(m_program, location, 1, vector); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform2dv(location, 1, vector); - Unlock(); } return true; @@ -541,14 +454,8 @@ bool NzGLSLShader::SendVector(int location, const NzVector2f& vector) glProgramUniform2fv(m_program, location, 1, vector); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform2fv(location, 1, vector); - Unlock(); } return true; @@ -560,14 +467,8 @@ bool NzGLSLShader::SendVector(int location, const NzVector3d& vector) glProgramUniform3dv(m_program, location, 1, vector); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform3dv(location, 1, vector); - Unlock(); } return true; @@ -579,14 +480,8 @@ bool NzGLSLShader::SendVector(int location, const NzVector3f& vector) glProgramUniform3fv(m_program, location, 1, vector); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform3fv(location, 1, vector); - Unlock(); } return true; @@ -598,14 +493,8 @@ bool NzGLSLShader::SendVector(int location, const NzVector4d& vector) glProgramUniform4dv(m_program, location, 1, vector); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform4dv(location, 1, vector); - Unlock(); } return true; @@ -617,54 +506,13 @@ bool NzGLSLShader::SendVector(int location, const NzVector4f& vector) glProgramUniform4fv(m_program, location, 1, vector); else { - if (!Lock()) - { - NazaraError("Failed to lock shader"); - return false; - } - + NzOpenGL::BindProgram(m_program); glUniform4fv(location, 1, vector); - Unlock(); } return true; } -void NzGLSLShader::Unbind() -{ - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - glUseProgram(0); -} - -void NzGLSLShader::Unlock() -{ - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (lockedLevel == 0) - { - NazaraWarning("Unlock called on non-locked texture"); - return; - } - #endif - - if (--lockedLevel == 0 && lockedPrevious != m_program) - glUseProgram(lockedPrevious); -} - void NzGLSLShader::OnResourceCreated(const NzResource* resource, int index) { NazaraUnused(resource); diff --git a/src/Nazara/Renderer/GLSLShader.hpp b/src/Nazara/Renderer/GLSLShader.hpp index 915adec5a..f1797652f 100644 --- a/src/Nazara/Renderer/GLSLShader.hpp +++ b/src/Nazara/Renderer/GLSLShader.hpp @@ -38,7 +38,6 @@ class NzGLSLShader : public NzShaderImpl, NzResourceListener bool IsLoaded(nzShaderType type) const; bool Load(nzShaderType type, const NzString& source); - bool Lock(); bool SendBoolean(int location, bool value); bool SendColor(int location, const NzColor& color); @@ -55,9 +54,6 @@ class NzGLSLShader : public NzShaderImpl, NzResourceListener bool SendVector(int location, const NzVector4d& vector); bool SendVector(int location, const NzVector4f& vector); - void Unbind(); - void Unlock(); - private: void OnResourceCreated(const NzResource* resource, int index) override; void OnResourceDestroy(const NzResource* resource, int index) override; diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index 9c2181190..2b89848ce 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -86,16 +86,9 @@ bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage) m_buffer = 0; glGenBuffers(1, &m_buffer); - GLint previous; - glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], &previous); - - glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer); + NzOpenGL::BindBuffer(m_type, m_buffer); glBufferData(NzOpenGL::BufferTarget[m_type], size, nullptr, NzOpenGL::BufferUsage[usage]); - // Pour ne pas perturber le rendu, on n'interfère pas avec le binding déjà présent - if (previous != 0) - glBindBuffer(NzOpenGL::BufferTarget[m_type], previous); - return true; } @@ -103,7 +96,7 @@ void NzHardwareBuffer::Destroy() { NzContext::EnsureContext(); - glDeleteBuffers(1, &m_buffer); + NzOpenGL::DeleteBuffer(m_type, m_buffer); } bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) @@ -115,11 +108,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int if (!forceDiscard) forceDiscard = (size == totalSize); - GLuint previous; - glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast(&previous)); - - if (previous != m_buffer) - glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer); + NzOpenGL::BindBuffer(m_type, m_buffer); // http://www.opengl.org/wiki/Vertex_Specification_Best_Practices if (forceDiscard) @@ -151,10 +140,6 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int } } - // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) - if (previous != m_buffer && previous != 0) - glBindBuffer(NzOpenGL::BufferTarget[m_type], previous); - return true; } @@ -172,52 +157,28 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned { NzContext::EnsureContext(); - // Pour ne pas perturber le rendu, on n'interfère pas avec le binding déjà présent - GLuint previous; - glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast(&previous)); - - if (previous != m_buffer) - glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer); + NzOpenGL::BindBuffer(m_type, m_buffer); if (access == nzBufferAccess_DiscardAndWrite) glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard - void* ptr = mapBuffer(m_type, access, offset, size); - - // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) - if (previous != m_buffer && previous != 0) - glBindBuffer(NzOpenGL::BufferTarget[m_type], previous); - - return ptr; + return mapBuffer(m_type, access, offset, size); } bool NzHardwareBuffer::Unmap() { NzContext::EnsureContext(); - GLuint previous; - glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast(&previous)); - - if (previous != m_buffer) - glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer); + NzOpenGL::BindBuffer(m_type, m_buffer); if (glUnmapBuffer(NzOpenGL::BufferTarget[m_type]) != GL_TRUE) { - // Une erreur rare est survenue, nous devons réinitialiser le buffer - NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')'); - glBufferData(NzOpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]); - // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) - if (previous != m_buffer && previous != 0) - glBindBuffer(NzOpenGL::BufferTarget[m_type], previous); - + // Une erreur rare est survenue, nous devons réinitialiser le buffer + NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + NzString::Number(glGetError(), 16) + ')'); return false; } - // Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérations chaînées) - if (previous != m_buffer && previous != 0) - glBindBuffer(NzOpenGL::BufferTarget[m_type], previous); - return true; } diff --git a/src/Nazara/Renderer/OpenGL.cpp b/src/Nazara/Renderer/OpenGL.cpp index 57a27a641..8e3734268 100644 --- a/src/Nazara/Renderer/OpenGL.cpp +++ b/src/Nazara/Renderer/OpenGL.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include #include @@ -58,11 +59,15 @@ namespace } std::set s_openGLextensionSet; + GLuint s_buffersBinding[nzBufferType_Max+1]; + GLuint s_currentProgram; + GLuint s_texturesBinding[32]; // 32 est pour l'instant la plus haute limite (GL_TEXTURE31) const char* s_rendererName = nullptr; const char* s_vendorName = nullptr; bool s_initialized = false; bool s_openGLextensions[nzOpenGLExtension_Max+1] = {false}; unsigned int s_openglVersion = 0; + unsigned int s_textureUnit = 0; bool LoadExtensionsString(const NzString& extensionString) { @@ -109,6 +114,64 @@ namespace } } +void NzOpenGL::BindBuffer(nzBufferType type, GLuint id) +{ + if (s_buffersBinding[type] != id) + { + glBindBuffer(BufferTarget[type], id); + s_buffersBinding[type] = id; + } +} + +void NzOpenGL::BindProgram(GLuint id) +{ + if (s_currentProgram != id) + { + glUseProgram(id); + s_currentProgram = id; + } +} + +void NzOpenGL::BindTexture(nzImageType type, GLuint id) +{ + if (s_texturesBinding[s_textureUnit] != id) + { + glBindTexture(TextureTarget[type], id); + s_texturesBinding[s_textureUnit] = id; + } +} + +void NzOpenGL::DeleteBuffer(nzBufferType type, GLuint id) +{ + glDeleteBuffers(1, &id); + if (s_buffersBinding[type] == id) + s_buffersBinding[type] = 0; +} + +void NzOpenGL::DeleteProgram(GLuint id) +{ + glDeleteProgram(id); + if (s_currentProgram == id) + s_currentProgram = 0; +} + +void NzOpenGL::DeleteTexture(GLuint id) +{ + glDeleteTextures(1, &id); + if (s_texturesBinding[s_textureUnit] == id) + s_texturesBinding[s_textureUnit] = 0; +} + +GLuint NzOpenGL::GetCurrentBuffer(nzBufferType type) +{ + return s_buffersBinding[type]; +} + +GLuint NzOpenGL::GetCurrentProgram() +{ + return s_currentProgram; +} + NzOpenGLFunc NzOpenGL::GetEntry(const NzString& entryPoint) { return LoadEntry(entryPoint.GetConstBuffer(), false); @@ -119,6 +182,11 @@ NzString NzOpenGL::GetRendererName() return s_rendererName; } +unsigned int NzOpenGL::GetTextureUnit() +{ + return s_textureUnit; +} + NzString NzOpenGL::GetVendorName() { return s_vendorName; @@ -629,7 +697,12 @@ bool NzOpenGL::Initialize() return false; } + std::memset(s_buffersBinding, 0, (nzBufferType_Max+1)*sizeof(GLuint)); + std::memset(s_texturesBinding, 0, 32*sizeof(GLuint)); + + s_currentProgram = 0; s_rendererName = reinterpret_cast(glGetString(GL_RENDERER)); + s_textureUnit = 0; s_vendorName = reinterpret_cast(glGetString(GL_VENDOR)); return true; @@ -650,6 +723,15 @@ bool NzOpenGL::IsSupported(const NzString& string) return s_openGLextensionSet.find(string) != s_openGLextensionSet.end(); } +void NzOpenGL::SetTextureUnit(unsigned int textureUnit) +{ + if (s_textureUnit != textureUnit) + { + glActiveTexture(GL_TEXTURE0 + textureUnit); + s_textureUnit = textureUnit; + } +} + bool NzOpenGL::TranslateFormat(nzPixelFormat pixelFormat, Format* format, FormatType type) { switch (pixelFormat) @@ -936,12 +1018,13 @@ GLenum NzOpenGL::RendererComparison[nzRendererComparison_Max+1] = GLenum NzOpenGL::RendererParameter[nzRendererParameter_Max+1] = { - GL_BLEND, // nzRendererParameter_Blend - GL_NONE, // nzRendererParameter_ColorWrite - GL_DEPTH_TEST, // nzRendererParameter_DepthTest - GL_NONE, // nzRendererParameter_DepthWrite - GL_CULL_FACE, // nzRendererParameter_FaceCulling - GL_STENCIL_TEST // nzRendererParameter_Stencil + GL_BLEND, // nzRendererParameter_Blend + GL_NONE, // nzRendererParameter_ColorWrite + GL_DEPTH_TEST, // nzRendererParameter_DepthTest + GL_NONE, // nzRendererParameter_DepthWrite + GL_CULL_FACE, // nzRendererParameter_FaceCulling + GL_SCISSOR_TEST, // nzRendererParameter_ScissorTest + GL_STENCIL_TEST // nzRendererParameter_StencilTest }; GLenum NzOpenGL::SamplerWrapMode[nzSamplerWrap_Max+1] = diff --git a/src/Nazara/Renderer/RenderWindow.cpp b/src/Nazara/Renderer/RenderWindow.cpp index ad5015068..1e5e7a1fb 100644 --- a/src/Nazara/Renderer/RenderWindow.cpp +++ b/src/Nazara/Renderer/RenderWindow.cpp @@ -124,7 +124,7 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const NzVector2ui size = GetSize(); - if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1, true)) + if (!texture->Create(nzImageType_2D, nzPixelFormat_RGBA8, size.x, size.y, 1, 1)) { NazaraError("Failed to create texture"); return false; @@ -143,8 +143,6 @@ bool NzRenderWindow::CopyToTexture(NzTexture* texture) const m_context->SetActive(false); } - texture->Unlock(); - return true; } diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 2f9d52609..c744c7e2c 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -41,13 +41,24 @@ namespace nzMatrixCombination_Max = nzMatrixCombination_WorldViewProj }; + enum UpdateFlags + { + Update_None = 0, + + Update_Matrices = 0x01, + Update_Shader = 0x02, + Update_StencilFunc = 0x04, + Update_StencilOp = 0x08, + Update_Textures = 0x10, + Update_VAO = 0x20, + }; + struct TextureUnit { NzTextureSampler sampler; const NzTexture* texture = nullptr; bool samplerUpdated = false; bool textureUpdated = true; - bool updated = true; }; NzBufferImpl* HardwareBufferFunction(NzBuffer* parent, nzBufferType type) @@ -61,6 +72,7 @@ namespace std::map s_vaos; std::vector s_textureUnits; + std::vector s_dirtyTextureUnits; NzBuffer* s_instancingBuffer = nullptr; NzVertexBuffer* s_quadBuffer = nullptr; NzMatrix4f s_matrix[totalMatrixCount]; @@ -76,18 +88,17 @@ namespace nzStencilOperation s_stencilZFail; nzUInt8 s_maxAnisotropyLevel; nzUInt32 s_stencilMask; + nzUInt32 s_updateFlags; const NzIndexBuffer* s_indexBuffer; const NzRenderTarget* s_target; const NzShader* s_shader; const NzVertexBuffer* s_vertexBuffer; const NzVertexDeclaration* s_vertexDeclaration; bool s_capabilities[nzRendererCap_Max+1]; + bool s_instancing; bool s_matrixUpdated[totalMatrixCount]; - bool s_stencilFuncUpdated; - bool s_stencilOpUpdated; bool s_useSamplerObjects; bool s_useVertexArrayObjects; - bool s_vaoUpdated; int s_matrixLocation[totalMatrixCount]; unsigned int s_maxRenderTarget; unsigned int s_maxTextureUnit; @@ -145,7 +156,9 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f } #endif - if (!EnsureStateUpdate(false)) + EnableInstancing(false); + + if (!EnsureStateUpdate()) { NazaraError("Failed to update states"); return; @@ -214,7 +227,9 @@ void NzRenderer::DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPr } #endif - if (!EnsureStateUpdate(true)) + EnableInstancing(true); + + if (!EnsureStateUpdate()) { NazaraError("Failed to update states"); return; @@ -257,7 +272,9 @@ void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVer } #endif - if (!EnsureStateUpdate(false)) + EnableInstancing(false); + + if (!EnsureStateUpdate()) { NazaraError("Failed to update states"); return; @@ -302,7 +319,9 @@ void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitive } #endif - if (!EnsureStateUpdate(true)) + EnableInstancing(true); + + if (!EnsureStateUpdate()) { NazaraError("Failed to update states"); return; @@ -415,13 +434,13 @@ void NzRenderer::DrawTexture(unsigned int unit, const NzRectf& rect, const NzVec SetShader(shader); SetVertexBuffer(s_quadBuffer); - if (!EnsureStateUpdate(true)) + if (!EnsureStateUpdate()) { NazaraError("Failed to update states"); return; } - shader->SendMatrix(shader->GetUniformLocation("WorldViewProjMatrix"), NzMatrix4f::Ortho(0.f, s_targetSize.x, 0.f, s_targetSize.y, 0.f)); + shader->SendMatrix(s_matrixLocation[nzMatrixCombination_WorldViewProj], NzMatrix4f::Ortho(0.f, s_targetSize.x, 0.f, s_targetSize.y, 0.f)); glDrawArrays(NzOpenGL::PrimitiveType[nzPrimitiveType_TriangleStrip], 0, 4); @@ -429,9 +448,6 @@ void NzRenderer::DrawTexture(unsigned int unit, const NzRectf& rect, const NzVec Enable(nzRendererParameter_FaceCulling, faceCulling); SetShader(oldShader); SetVertexBuffer(oldBuffer); - - s_matrixUpdated[nzMatrixCombination_WorldViewProj] = false; - s_vaoUpdated = false; } } @@ -577,6 +593,22 @@ float NzRenderer::GetPointSize() return pointSize; } +NzRectui NzRenderer::GetScissorRect() +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return NzRectui(); + } + #endif + + GLint params[4]; + glGetIntegerv(GL_SCISSOR_BOX, ¶ms[0]); + + return NzRectui(params[0], params[1], params[2], params[3]); +} + const NzShader* NzRenderer::GetShader() { return s_shader; @@ -711,6 +743,7 @@ bool NzRenderer::Initialize() else s_maxTextureUnit = 1; + s_dirtyTextureUnits.reserve(s_maxTextureUnit); s_dstBlend = nzBlendFunc_Zero; s_faceCulling = nzFaceCulling_Back; s_faceFilling = nzFaceFilling_Fill; @@ -719,9 +752,7 @@ bool NzRenderer::Initialize() s_srcBlend = nzBlendFunc_One; s_stencilCompare = nzRendererComparison_Always; s_stencilFail = nzStencilOperation_Keep; - s_stencilFuncUpdated = true; s_stencilMask = 0xFFFFFFFF; - s_stencilOpUpdated = true; s_stencilPass = nzStencilOperation_Keep; s_stencilReference = 0; s_stencilZFail = nzStencilOperation_Keep; @@ -729,9 +760,9 @@ bool NzRenderer::Initialize() s_textureUnits.resize(s_maxTextureUnit); s_useSamplerObjects = NzOpenGL::IsSupported(nzOpenGLExtension_SamplerObjects); s_useVertexArrayObjects = NzOpenGL::IsSupported(nzOpenGLExtension_VertexArrayObjects); - s_vaoUpdated = false; s_vertexBuffer = nullptr; s_vertexDeclaration = nullptr; + s_updateFlags = (Update_Matrices | Update_Shader | Update_VAO); NzVertexElement elements[2]; elements[0].offset = 0; @@ -945,23 +976,21 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode) } } -bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) +void NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) { #if NAZARA_RENDERER_SAFE if (indexBuffer && !indexBuffer->IsHardware() && !indexBuffer->IsSequential()) { NazaraError("Buffer must be hardware"); - return false; + return; } #endif if (s_indexBuffer != indexBuffer) { s_indexBuffer = indexBuffer; - s_vaoUpdated = false; + s_updateFlags |= Update_VAO; } - - return true; } void NzRenderer::SetInstancingData(const NzRenderer::InstancingData* instancingData, unsigned int instanceCount) @@ -1042,6 +1071,8 @@ void NzRenderer::SetMatrix(nzMatrixType type, const NzMatrix4f& matrix) s_matrixUpdated[nzMatrixCombination_WorldView] = false; s_matrixUpdated[nzMatrixCombination_WorldViewProj] = false; // Toujours invalidée + + s_updateFlags |= Update_Matrices; } void NzRenderer::SetPointSize(float size) @@ -1065,51 +1096,51 @@ void NzRenderer::SetPointSize(float size) glPointSize(size); } -bool NzRenderer::SetShader(const NzShader* shader) +void NzRenderer::SetScissorRect(const NzRectui& rect) { - if (s_shader == shader) - return true; - - if (s_shader) - s_shader->m_impl->Unbind(); - - if (shader) + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) { - #if NAZARA_RENDERER_SAFE - if (!shader->IsCompiled()) - { - NazaraError("Shader is not compiled"); - shader = nullptr; + NazaraError("No active context"); + return; + } + #endif - return false; - } - #endif + unsigned int height = s_target->GetHeight(); - if (!shader->m_impl->Bind()) - { - NazaraError("Failed to bind shader"); - shader = nullptr; - - return false; - } - - // Récupération des indices des variables uniformes (-1 si la variable n'existe pas) - s_matrixLocation[nzMatrixType_Projection] = shader->GetUniformLocation("ProjMatrix"); - s_matrixLocation[nzMatrixType_View] = shader->GetUniformLocation("ViewMatrix"); - s_matrixLocation[nzMatrixType_World] = shader->GetUniformLocation("WorldMatrix"); - - s_matrixLocation[nzMatrixCombination_ViewProj] = shader->GetUniformLocation("ViewProjMatrix"); - s_matrixLocation[nzMatrixCombination_WorldView] = shader->GetUniformLocation("WorldViewMatrix"); - s_matrixLocation[nzMatrixCombination_WorldViewProj] = shader->GetUniformLocation("WorldViewProjMatrix"); - - ///FIXME: Peut être optimisé - for (unsigned int i = 0; i < totalMatrixCount; ++i) - s_matrixUpdated[i] = false; + #if NAZARA_RENDERER_SAFE + if (!s_target) + { + NazaraError("Renderer has no target"); + return; } - s_shader = shader; + unsigned int width = s_target->GetWidth(); + if (rect.x+rect.width > width || rect.y+rect.height > height) + { + NazaraError("Rectangle dimensions are out of bounds"); + return; + } + #endif - return true; + glScissor(rect.x, height-rect.height-rect.y, rect.width, rect.height); +} + +void NzRenderer::SetShader(const NzShader* shader) +{ + #if NAZARA_RENDERER_SAFE + if (shader && !shader->IsCompiled()) + { + NazaraError("Shader is not compiled"); + return; + } + #endif + + if (s_shader != shader) + { + s_shader = shader; + s_updateFlags |= Update_Shader; + } } void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc) @@ -1125,7 +1156,7 @@ void NzRenderer::SetStencilCompareFunction(nzRendererComparison compareFunc) if (compareFunc != s_stencilCompare) { s_stencilCompare = compareFunc; - s_stencilFuncUpdated = false; + s_updateFlags |= Update_StencilFunc; } } @@ -1142,7 +1173,7 @@ void NzRenderer::SetStencilFailOperation(nzStencilOperation failOperation) if (failOperation != s_stencilFail) { s_stencilFail = failOperation; - s_stencilOpUpdated = false; + s_updateFlags |= Update_StencilOp; } } @@ -1151,7 +1182,7 @@ void NzRenderer::SetStencilMask(nzUInt32 mask) if (mask != s_stencilMask) { s_stencilMask = mask; - s_stencilFuncUpdated = false; + s_updateFlags |= Update_StencilFunc; } } @@ -1168,7 +1199,7 @@ void NzRenderer::SetStencilPassOperation(nzStencilOperation passOperation) if (passOperation != s_stencilPass) { s_stencilPass = passOperation; - s_stencilOpUpdated = false; + s_updateFlags |= Update_StencilOp; } } @@ -1177,7 +1208,7 @@ void NzRenderer::SetStencilReferenceValue(unsigned int refValue) if (refValue != s_stencilReference) { s_stencilReference = refValue; - s_stencilFuncUpdated = false; + s_updateFlags |= Update_StencilFunc; } } @@ -1194,7 +1225,7 @@ void NzRenderer::SetStencilZFailOperation(nzStencilOperation zfailOperation) if (zfailOperation != s_stencilZFail) { s_stencilZFail = zfailOperation; - s_stencilOpUpdated = false; + s_updateFlags |= Update_StencilOp; } } @@ -1253,9 +1284,10 @@ void NzRenderer::SetTexture(nzUInt8 unit, const NzTexture* texture) { if (s_textureUnits[unit].sampler.UseMipmaps(texture->HasMipmaps())) s_textureUnits[unit].samplerUpdated = false; - - s_textureUnits[unit].updated = false; } + + s_dirtyTextureUnits.push_back(unit); + s_updateFlags |= Update_Textures; } } @@ -1271,19 +1303,21 @@ void NzRenderer::SetTextureSampler(nzUInt8 unit, const NzTextureSampler& sampler s_textureUnits[unit].sampler = sampler; s_textureUnits[unit].samplerUpdated = false; - s_textureUnits[unit].updated = false; if (s_textureUnits[unit].texture) s_textureUnits[unit].sampler.UseMipmaps(s_textureUnits[unit].texture->HasMipmaps()); + + s_dirtyTextureUnits.push_back(unit); + s_updateFlags |= Update_Textures; } -bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) +void NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) { #if NAZARA_RENDERER_SAFE if (vertexBuffer && !vertexBuffer->IsHardware()) { NazaraError("Buffer must be hardware"); - return false; + return; } #endif @@ -1295,10 +1329,8 @@ bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) if (s_vertexDeclaration != vertexDeclaration) s_vertexDeclaration = vertexDeclaration; - s_vaoUpdated = false; + s_updateFlags |= Update_VAO; } - - return true; } void NzRenderer::SetViewport(const NzRectui& viewport) @@ -1329,7 +1361,6 @@ void NzRenderer::SetViewport(const NzRectui& viewport) #endif glViewport(viewport.x, height-viewport.height-viewport.y, viewport.width, viewport.height); - glScissor(viewport.x, height-viewport.height-viewport.y, viewport.width, viewport.height); } void NzRenderer::Uninitialize() @@ -1381,8 +1412,20 @@ void NzRenderer::Uninitialize() NzUtility::Uninitialize(); } -bool NzRenderer::EnsureStateUpdate(bool instancing) +void NzRenderer::EnableInstancing(bool instancing) { + if (s_instancing != instancing) + { + s_updateFlags |= Update_VAO; + s_instancing = instancing; + } +} + +bool NzRenderer::EnsureStateUpdate() +{ + if (s_updateFlags == Update_None) + return true; + #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) { @@ -1391,30 +1434,57 @@ bool NzRenderer::EnsureStateUpdate(bool instancing) } #endif - #if NAZARA_RENDERER_SAFE - if (!s_shader) - { - NazaraError("No shader"); - return false; - } - #endif + NzShaderImpl* shaderImpl; - // Il est plus rapide d'opérer sur l'implémentation du shader directement - NzShaderImpl* shaderImpl = s_shader->m_impl; - shaderImpl->BindTextures(); - - if (s_useSamplerObjects) + if (s_updateFlags & Update_Shader) { - ///FIXME: Itère sur toutes les unités (Dont beaucoup inutilisées) - for (unsigned int i = 0; i < s_textureUnits.size(); ++i) + #if NAZARA_RENDERER_SAFE + if (!s_shader) { - TextureUnit& unit = s_textureUnits[i]; + NazaraError("No shader"); + return false; + } + #endif - if (!unit.updated) + // Il est plus rapide d'opérer sur l'implémentation du shader directement + shaderImpl = s_shader->m_impl; + shaderImpl->Bind(); + shaderImpl->BindTextures(); + + // Récupération des indices des variables uniformes (-1 si la variable n'existe pas) + s_matrixLocation[nzMatrixType_Projection] = shaderImpl->GetUniformLocation("ProjMatrix"); + s_matrixLocation[nzMatrixType_View] = shaderImpl->GetUniformLocation("ViewMatrix"); + s_matrixLocation[nzMatrixType_World] = shaderImpl->GetUniformLocation("WorldMatrix"); + + s_matrixLocation[nzMatrixCombination_ViewProj] = shaderImpl->GetUniformLocation("ViewProjMatrix"); + s_matrixLocation[nzMatrixCombination_WorldView] = shaderImpl->GetUniformLocation("WorldViewMatrix"); + s_matrixLocation[nzMatrixCombination_WorldViewProj] = shaderImpl->GetUniformLocation("WorldViewProjMatrix"); + + s_updateFlags |= Update_Matrices; + for (unsigned int i = 0; i < totalMatrixCount; ++i) + { + if (s_matrixLocation[i] != -1) + s_matrixUpdated[i] = false; + else + s_matrixUpdated[i] = false; + } + + s_updateFlags &= ~Update_Shader; + } + else + shaderImpl = s_shader->m_impl; + + if (s_updateFlags & Update_Textures) + { + if (s_useSamplerObjects) + { + for (unsigned int i : s_dirtyTextureUnits) { + TextureUnit& unit = s_textureUnits[i]; + if (!unit.textureUpdated) { - glActiveTexture(GL_TEXTURE0 + i); + NzOpenGL::SetTextureUnit(i); unit.texture->Bind(); unit.textureUpdated = true; @@ -1425,83 +1495,83 @@ bool NzRenderer::EnsureStateUpdate(bool instancing) unit.sampler.Bind(i); unit.samplerUpdated = true; } - - unit.updated = true; } } - } - else - { - ///FIXME: Itère sur toutes les unités (Dont beaucoup inutilisées) - for (unsigned int i = 0; i < s_textureUnits.size(); ++i) + else { - TextureUnit& unit = s_textureUnits[i]; - - if (!unit.updated) + for (unsigned int i : s_dirtyTextureUnits) { - glActiveTexture(GL_TEXTURE0 + i); + TextureUnit& unit = s_textureUnits[i]; + + NzOpenGL::SetTextureUnit(i); unit.texture->Bind(); unit.textureUpdated = true; unit.sampler.Apply(unit.texture); unit.samplerUpdated = true; - - unit.updated = true; } } + + s_dirtyTextureUnits.clear(); // Ne change pas la capacité + s_updateFlags &= ~Update_Textures; } - for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) + if (s_updateFlags & Update_Matrices) { - if (!s_matrixUpdated[i]) + for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) { - shaderImpl->SendMatrix(s_matrixLocation[i], s_matrix[i]); - s_matrixUpdated[i] = true; + if (!s_matrixUpdated[i]) + { + shaderImpl->SendMatrix(s_matrixLocation[i], s_matrix[i]); + s_matrixUpdated[i] = true; + } } + + // Cas spéciaux car il faut recalculer la matrice + if (!s_matrixUpdated[nzMatrixCombination_ViewProj]) + { + s_matrix[nzMatrixCombination_ViewProj] = s_matrix[nzMatrixType_View]; + s_matrix[nzMatrixCombination_ViewProj].Concatenate(s_matrix[nzMatrixType_Projection]); + + shaderImpl->SendMatrix(s_matrixLocation[nzMatrixCombination_ViewProj], s_matrix[nzMatrixCombination_ViewProj]); + s_matrixUpdated[nzMatrixCombination_ViewProj] = true; + } + + if (!s_matrixUpdated[nzMatrixCombination_WorldView]) + { + s_matrix[nzMatrixCombination_WorldView] = s_matrix[nzMatrixType_World]; + s_matrix[nzMatrixCombination_WorldView].ConcatenateAffine(s_matrix[nzMatrixType_View]); + + shaderImpl->SendMatrix(s_matrixLocation[nzMatrixCombination_WorldView], s_matrix[nzMatrixCombination_WorldView]); + s_matrixUpdated[nzMatrixCombination_WorldView] = true; + } + + if (!s_matrixUpdated[nzMatrixCombination_WorldViewProj]) + { + s_matrix[nzMatrixCombination_WorldViewProj] = s_matrix[nzMatrixCombination_WorldView]; + s_matrix[nzMatrixCombination_WorldViewProj].Concatenate(s_matrix[nzMatrixType_Projection]); + + shaderImpl->SendMatrix(s_matrixLocation[nzMatrixCombination_WorldViewProj], s_matrix[nzMatrixCombination_WorldViewProj]); + s_matrixUpdated[nzMatrixCombination_WorldViewProj] = true; + } + + s_updateFlags &= ~Update_Matrices; } - // Cas spéciaux car il faut recalculer la matrice - if (!s_matrixUpdated[nzMatrixCombination_ViewProj]) - { - s_matrix[nzMatrixCombination_ViewProj] = s_matrix[nzMatrixType_View]; - s_matrix[nzMatrixCombination_ViewProj].Concatenate(s_matrix[nzMatrixType_Projection]); - - shaderImpl->SendMatrix(s_matrixLocation[nzMatrixCombination_ViewProj], s_matrix[nzMatrixCombination_ViewProj]); - s_matrixUpdated[nzMatrixCombination_ViewProj] = true; - } - - if (!s_matrixUpdated[nzMatrixCombination_WorldView]) - { - s_matrix[nzMatrixCombination_WorldView] = s_matrix[nzMatrixType_World]; - s_matrix[nzMatrixCombination_WorldView].ConcatenateAffine(s_matrix[nzMatrixType_View]); - - shaderImpl->SendMatrix(s_matrixLocation[nzMatrixCombination_WorldView], s_matrix[nzMatrixCombination_WorldView]); - s_matrixUpdated[nzMatrixCombination_WorldView] = true; - } - - if (!s_matrixUpdated[nzMatrixCombination_WorldViewProj]) - { - s_matrix[nzMatrixCombination_WorldViewProj] = s_matrix[nzMatrixCombination_WorldView]; - s_matrix[nzMatrixCombination_WorldViewProj].Concatenate(s_matrix[nzMatrixType_Projection]); - - shaderImpl->SendMatrix(s_matrixLocation[nzMatrixCombination_WorldViewProj], s_matrix[nzMatrixCombination_WorldViewProj]); - s_matrixUpdated[nzMatrixCombination_WorldViewProj] = true; - } - - if (!s_stencilFuncUpdated) + if (s_updateFlags & Update_StencilFunc) { glStencilFunc(NzOpenGL::RendererComparison[s_stencilCompare], s_stencilReference, s_stencilMask); - s_stencilFuncUpdated = true; + s_updateFlags &= ~Update_StencilFunc; } - if (!s_stencilOpUpdated) + if (s_updateFlags & Update_StencilOp) { glStencilOp(NzOpenGL::StencilOperation[s_stencilFail], NzOpenGL::StencilOperation[s_stencilZFail], NzOpenGL::StencilOperation[s_stencilPass]); - s_stencilOpUpdated = true; + s_updateFlags &= ~Update_StencilOp; } - if (!s_vaoUpdated) + if (s_updateFlags & Update_VAO) { #if NAZARA_RENDERER_SAFE if (!s_vertexBuffer) @@ -1526,7 +1596,7 @@ bool NzRenderer::EnsureStateUpdate(bool instancing) // On recherche si un VAO existe déjà avec notre configuration // Note: Les VAOs ne sont pas partagés entre les contextes, ces derniers font donc partie de notre configuration - auto key = std::make_tuple(NzContext::GetCurrent(), s_indexBuffer, s_vertexBuffer, s_vertexDeclaration, instancing); + auto key = std::make_tuple(NzContext::GetCurrent(), s_indexBuffer, s_vertexBuffer, s_vertexDeclaration, s_instancing); auto it = s_vaos.find(key); if (it == s_vaos.end()) { @@ -1577,7 +1647,7 @@ bool NzRenderer::EnsureStateUpdate(bool instancing) glDisableVertexAttribArray(NzOpenGL::AttributeIndex[i]); } - if (instancing) + if (s_instancing) { static_cast(s_instancingBuffer->GetImpl())->Bind(); @@ -1611,9 +1681,14 @@ bool NzRenderer::EnsureStateUpdate(bool instancing) glBindVertexArray(vao); } - s_vaoUpdated = true; + s_updateFlags &= ~Update_VAO; } + #ifdef NAZARA_DEBUG + if (s_updateFlags != Update_None) + NazaraWarning("Update flags not fully cleared"); + #endif + return true; } diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 9e681d795..4c4e637dc 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -298,19 +298,6 @@ 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(int location, bool value) const { #if NAZARA_RENDERER_SAFE @@ -612,19 +599,6 @@ void NzShader::SetFlags(nzUInt32 flags) m_flags = flags; } -void NzShader::Unlock() -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Shader not created"); - return; - } - #endif - - return m_impl->Unlock(); -} - NzShader& NzShader::operator=(NzShader&& shader) { Destroy(); diff --git a/src/Nazara/Renderer/ShaderImpl.hpp b/src/Nazara/Renderer/ShaderImpl.hpp index 964a085ea..dc4a96cf0 100644 --- a/src/Nazara/Renderer/ShaderImpl.hpp +++ b/src/Nazara/Renderer/ShaderImpl.hpp @@ -34,8 +34,6 @@ class NzShaderImpl virtual bool Load(nzShaderType type, const NzString& source) = 0; - virtual bool Lock() = 0; - virtual bool SendBoolean(int location, bool value) = 0; virtual bool SendColor(int location, const NzColor& color) = 0; virtual bool SendDouble(int location, double value) = 0; @@ -50,9 +48,6 @@ class NzShaderImpl virtual bool SendVector(int location, const NzVector3f& vector) = 0; virtual bool SendVector(int location, const NzVector4d& vector) = 0; virtual bool SendVector(int location, const NzVector4f& vector) = 0; - - virtual void Unbind() = 0; - virtual void Unlock() = 0; }; #endif // NAZARA_SHADERIMPL_HPP diff --git a/src/Nazara/Renderer/Texture.cpp b/src/Nazara/Renderer/Texture.cpp index 1e32a5178..0a4abf459 100644 --- a/src/Nazara/Renderer/Texture.cpp +++ b/src/Nazara/Renderer/Texture.cpp @@ -37,8 +37,6 @@ namespace } GLenum target = (proxy) ? NzOpenGL::TextureTargetProxy[impl->type] : NzOpenGL::TextureTarget[impl->type]; - GLint previous; - glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous); switch (impl->type) { case nzImageType_1D: @@ -137,25 +135,6 @@ namespace return true; } - static unsigned short lockedLevel[nzImageType_Max+1] = {0}; - static GLuint lockedPrevious[nzImageType_Max+1] = {0}; - - void LockTexture(NzTextureImpl* impl) - { - if (lockedLevel[impl->type]++ == 0) - { - NzContext::EnsureContext(); - - GLint previous; - glGetIntegerv(NzOpenGL::TextureTargetBinding[impl->type], &previous); - - lockedPrevious[impl->type] = static_cast(previous); - - if (lockedPrevious[impl->type] != impl->id) - glBindTexture(NzOpenGL::TextureTarget[impl->type], impl->id); - } - } - inline void SetUnpackAlignement(nzUInt8 bpp) { if (bpp % 8 == 0) @@ -167,28 +146,6 @@ namespace else glPixelStorei(GL_UNPACK_ALIGNMENT, 1); } - - void UnlockTexture(NzTextureImpl* impl) - { - #ifdef NAZARA_DEBUG - if (NzContext::GetCurrent() == nullptr) - { - NazaraError("No active context"); - return; - } - #endif - - #if NAZARA_RENDERER_SAFE - if (lockedLevel[impl->type] == 0) - { - NazaraError("Unlock called on non-locked texture"); - return; - } - #endif - - if (--lockedLevel[impl->type] == 0 && lockedPrevious[impl->type] != impl->id) - glBindTexture(NzOpenGL::TextureTarget[impl->type], lockedPrevious[impl->type]); - } } NzTexture::NzTexture(const NzImage& image) @@ -209,7 +166,7 @@ NzTexture::~NzTexture() Destroy(); } -bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount, bool lock) +bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int width, unsigned int height, unsigned int depth, nzUInt8 levelCount) { Destroy(); @@ -305,7 +262,7 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt levelCount = 1; } - NzTextureImpl* impl = new NzTextureImpl; + std::unique_ptr impl(new NzTextureImpl); glGenTextures(1, &impl->id); impl->depth = GetValidSize(depth); @@ -315,38 +272,31 @@ bool NzTexture::Create(nzImageType type, nzPixelFormat format, unsigned int widt impl->type = type; impl->width = GetValidSize(width); - LockTexture(impl); + NzOpenGL::BindTexture(impl->type, impl->id); // Vérification du support par la carte graphique /*if (!CreateTexture(impl, true)) { - NazaraError("Texture's parameters not supported by driver"); - UnlockTexture(impl); - glDeleteTextures(1, &impl->id); - delete impl; + NzOpenGL::DeleteTexture(m_impl->id); + NazaraError("Texture's parameters not supported by driver"); return false; }*/ // Création de la texture - if (!CreateTexture(impl, false)) + if (!CreateTexture(impl.get(), false)) { - NazaraError("Failed to create texture"); - UnlockTexture(impl); - glDeleteTextures(1, &impl->id); - delete impl; + NzOpenGL::DeleteTexture(m_impl->id); + NazaraError("Failed to create texture"); return false; } - m_impl = impl; + m_impl = impl.release(); if (m_impl->levelCount > 1U) EnableMipmapping(true); - if (!lock) - UnlockTexture(impl); - NotifyCreated(); return true; } @@ -358,8 +308,8 @@ void NzTexture::Destroy() NotifyDestroy(); NzContext::EnsureContext(); + NzOpenGL::DeleteTexture(m_impl->id); - glDeleteTextures(1, &m_impl->id); delete m_impl; m_impl = nullptr; } @@ -394,13 +344,12 @@ bool NzTexture::Download(NzImage* image) const return false; } - LockTexture(m_impl); - unsigned int width = m_impl->width; unsigned int height = m_impl->height; unsigned int depth = m_impl->depth; // Téléchargement... + NzOpenGL::BindTexture(m_impl->type, m_impl->id); for (nzUInt8 level = 0; level < m_impl->levelCount; ++level) { glGetTexImage(NzOpenGL::TextureTarget[m_impl->type], level, format.dataFormat, format.dataType, image->GetPixels(level)); @@ -415,8 +364,6 @@ bool NzTexture::Download(NzImage* image) const depth >>= 1; } - UnlockTexture(m_impl); - // Inversion de la texture pour le repère d'OpenGL if (!image->FlipVertically()) NazaraWarning("Failed to flip image"); @@ -639,7 +586,7 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps) nzImageType type = newImage.GetType(); nzUInt8 levelCount = newImage.GetLevelCount(); - if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), (generateMipmaps) ? 0xFF : levelCount, true)) + if (!Create(type, format, newImage.GetWidth(), newImage.GetHeight(), newImage.GetDepth(), (generateMipmaps) ? 0xFF : levelCount)) { NazaraError("Failed to create texture"); return false; @@ -675,8 +622,6 @@ bool NzTexture::LoadFromImage(const NzImage& image, bool generateMipmaps) } } - UnlockTexture(m_impl); - return true; } @@ -784,7 +729,7 @@ bool NzTexture::LoadCubemapFromImage(const NzImage& image, bool generateMipmaps, return false; } - if (!Create(nzImageType_Cubemap, image.GetFormat(), faceSize, faceSize, 1, (generateMipmaps) ? 0xFF : 1, true)) + if (!Create(nzImageType_Cubemap, image.GetFormat(), faceSize, faceSize, 1, (generateMipmaps) ? 0xFF : 1)) { NazaraError("Failed to create texture"); return false; @@ -797,8 +742,6 @@ bool NzTexture::LoadCubemapFromImage(const NzImage& image, bool generateMipmaps, UpdateFace(nzCubemapFace_PositiveY, image.GetConstPixels(upPos.x, upPos.y), width, height); UpdateFace(nzCubemapFace_PositiveZ, image.GetConstPixels(forwardPos.x, forwardPos.y), width, height); - UnlockTexture(m_impl); - return true; } @@ -946,21 +889,6 @@ bool NzTexture::LoadFaceFromStream(nzCubemapFace face, NzInputStream& stream, co return UpdateFace(face, image); } -bool NzTexture::Lock() -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return false; - } - #endif - - LockTexture(m_impl); - - return true; -} - bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel) { #if NAZARA_RENDERER_SAFE @@ -983,10 +911,9 @@ bool NzTexture::SetMipmapRange(nzUInt8 minLevel, nzUInt8 maxLevel) } #endif - LockTexture(m_impl); + NzOpenGL::BindTexture(m_impl->type, m_impl->id); glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_BASE_LEVEL, minLevel); glTexParameteri(NzOpenGL::TextureTarget[m_impl->type], GL_TEXTURE_MAX_LEVEL, maxLevel); - UnlockTexture(m_impl); return true; } @@ -1158,7 +1085,7 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, unsigned int SetUnpackAlignement(bpp); - LockTexture(m_impl); + NzOpenGL::BindTexture(m_impl->type, m_impl->id); switch (m_impl->type) { case nzImageType_1D: @@ -1179,7 +1106,6 @@ bool NzTexture::Update(const nzUInt8* pixels, const NzCubeui& cube, unsigned int NazaraError("Update used on a cubemap texture, please enable safe mode"); break; } - UnlockTexture(m_impl); return true; } @@ -1304,37 +1230,15 @@ bool NzTexture::UpdateFace(nzCubemapFace face, const nzUInt8* pixels, const NzRe SetUnpackAlignement(bpp); - LockTexture(m_impl); + NzOpenGL::BindTexture(m_impl->type, m_impl->id); glTexSubImage2D(NzOpenGL::CubemapFace[face], level, rect.x, height-rect.height-rect.y, rect.width, rect.height, format.dataFormat, format.dataType, flipped.get()); - UnlockTexture(m_impl); return true; } -void NzTexture::Unlock() -{ - #if NAZARA_RENDERER_SAFE - if (!m_impl) - { - NazaraError("Texture must be valid"); - return; - } - #endif - - UnlockTexture(m_impl); -} - bool NzTexture::Bind() const { - #if NAZARA_RENDERER_SAFE - if (lockedLevel[m_impl->type] > 0) - { - NazaraError("Cannot bind texture while a texture is locked"); - return false; - } - #endif - - glBindTexture(NzOpenGL::TextureTarget[m_impl->type], m_impl->id); + NzOpenGL::BindTexture(m_impl->type, m_impl->id); if (m_impl->mipmapping && !m_impl->mipmapsUpdated) {