From 7172ceaa6b893caae2af1d1f000944c6ce0939fb Mon Sep 17 00:00:00 2001 From: Lynix Date: Thu, 27 Jun 2013 19:04:22 +0200 Subject: [PATCH] Reworked (fixed and optimized) matrix handling Former-commit-id: 6148748da07e228a746f51950231126b036b05eb --- include/Nazara/Renderer/Enums.hpp | 8 +- include/Nazara/Renderer/Renderer.hpp | 4 +- src/Nazara/Renderer/Renderer.cpp | 249 +++++++++++++-------------- 3 files changed, 133 insertions(+), 128 deletions(-) diff --git a/include/Nazara/Renderer/Enums.hpp b/include/Nazara/Renderer/Enums.hpp index 2422b6d4f..af4b71e8e 100644 --- a/include/Nazara/Renderer/Enums.hpp +++ b/include/Nazara/Renderer/Enums.hpp @@ -53,11 +53,17 @@ enum nzFaceFilling enum nzMatrixType { + // Matrices de base nzMatrixType_Projection, nzMatrixType_View, nzMatrixType_World, - nzMatrixType_Max = nzMatrixType_World + // Matrices combinées + nzMatrixType_ViewProj, + nzMatrixType_WorldView, + nzMatrixType_WorldViewProj, + + nzMatrixType_Max = nzMatrixType_WorldViewProj }; enum nzPixelBufferType diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 0f6c9bd9d..513926bf2 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -37,18 +37,17 @@ class NAZARA_API NzRenderer static void Clear(unsigned long flags = nzRendererClear_Color | nzRendererClear_Depth); + static void DrawFullscreenQuad(); static void DrawIndexedPrimitives(nzPrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); static void DrawIndexedPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount); static void DrawPrimitives(nzPrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); static void DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitiveMode mode, unsigned int firstVertex, unsigned int vertexCount); - static void DrawFullscreenQuad(); static void Enable(nzRendererParameter parameter, bool enable); static void Flush(); static float GetLineWidth(); - //static NzMatrix4f GetMatrix(nzMatrixCombination combination); static NzMatrix4f GetMatrix(nzMatrixType type); static nzUInt8 GetMaxAnisotropyLevel(); static unsigned int GetMaxRenderTargets(); @@ -100,6 +99,7 @@ class NAZARA_API NzRenderer private: static void EnableInstancing(bool instancing); static bool EnsureStateUpdate(); + static void UpdateMatrix(nzMatrixType type); static unsigned int s_moduleReferenceCounter; }; diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index f54d7a7a3..4e0d8eadc 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -32,16 +32,6 @@ namespace { - ///FIXME: Solution temporaire pour plus de facilité - enum nzMatrixCombination - { - nzMatrixCombination_ViewProj = nzMatrixType_Max+1, - nzMatrixCombination_WorldView, - nzMatrixCombination_WorldViewProj, - - nzMatrixCombination_Max = nzMatrixCombination_WorldViewProj - }; - enum UpdateFlags { Update_None = 0, @@ -52,6 +42,14 @@ namespace Update_VAO = 0x08, }; + struct MatrixUnit + { + NzMatrix4f matrix; + bool sent; + bool updated; + int location; + }; + struct TextureUnit { NzTextureSampler sampler; @@ -65,8 +63,6 @@ namespace return new NzHardwareBuffer(parent, type); } - constexpr unsigned int totalMatrixCount = nzMatrixCombination_Max+1; - using VAO_Key = std::tuple; std::map s_vaos; @@ -75,7 +71,7 @@ namespace GLuint s_currentVAO = 0; NzBuffer* s_instancingBuffer = nullptr; NzVertexBuffer* s_fullscreenQuadBuffer = nullptr; - NzMatrix4f s_matrix[totalMatrixCount]; + MatrixUnit s_matrices[nzMatrixType_Max+1]; NzRenderStates s_states; NzVector2ui s_targetSize; nzUInt8 s_maxAnisotropyLevel; @@ -86,10 +82,8 @@ namespace const NzVertexBuffer* s_vertexBuffer; bool s_capabilities[nzRendererCap_Max+1]; bool s_instancing; - bool s_matrixUpdated[totalMatrixCount]; bool s_useSamplerObjects; bool s_useVertexArrayObjects; - int s_matrixLocation[totalMatrixCount]; unsigned int s_maxRenderTarget; unsigned int s_maxTextureUnit; } @@ -124,6 +118,29 @@ void NzRenderer::Clear(unsigned long flags) } } +void NzRenderer::DrawFullscreenQuad() +{ + #ifdef NAZARA_DEBUG + if (NzContext::GetCurrent() == nullptr) + { + NazaraError("No active context"); + return; + } + #endif + + EnableInstancing(false); + SetIndexBuffer(nullptr); + SetVertexBuffer(s_fullscreenQuadBuffer); + + if (!EnsureStateUpdate()) + { + NazaraError("Failed to update states"); + return; + } + + glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); +} + void NzRenderer::DrawIndexedPrimitives(nzPrimitiveMode mode, unsigned int firstIndex, unsigned int indexCount) { #ifdef NAZARA_DEBUG @@ -329,20 +346,6 @@ void NzRenderer::DrawPrimitivesInstanced(unsigned int instanceCount, nzPrimitive glBindVertexArray(0); } -void NzRenderer::DrawFullscreenQuad() -{ - SetIndexBuffer(nullptr); - SetVertexBuffer(s_fullscreenQuadBuffer); - - if (!EnsureStateUpdate()) - { - NazaraError("Failed to update states"); - return; - } - - glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); -} - void NzRenderer::Enable(nzRendererParameter parameter, bool enable) { #ifdef NAZARA_DEBUG @@ -387,40 +390,7 @@ float NzRenderer::GetLineWidth() return s_states.lineWidth; } -/* -NzMatrix4f NzRenderer::GetMatrix(nzMatrixCombination combination) -{ - ///FIXME: Duplication - switch (combination) - { - case nzMatrixCombination_ViewProj: - if (!s_matrixUpdated[nzMatrixCombination_ViewProj]) - { - s_matrix[nzMatrixCombination_ViewProj] = s_matrix[nzMatrixType_View] * s_matrix[nzMatrixType_Projection]; - s_matrixUpdated[nzMatrixCombination_ViewProj] = true; - } - break; - case nzMatrixCombination_WorldView: - if (!s_matrixUpdated[nzMatrixCombination_WorldView]) - { - s_matrix[nzMatrixCombination_WorldView] = NzMatrix4f::ConcatenateAffine(s_matrix[nzMatrixType_World], s_matrix[nzMatrixType_View]); - s_matrixUpdated[nzMatrixCombination_WorldView] = true; - } - break; - - case nzMatrixCombination_WorldViewProj: - if (!s_matrixUpdated[nzMatrixCombination_WorldViewProj]) - { - s_matrix[nzMatrixCombination_WorldViewProj] = s_matrix[nzMatrixCombination_WorldView] * s_matrix[nzMatrixType_Projection]; - s_matrixUpdated[nzMatrixCombination_WorldViewProj] = true; - } - break; - } - - return m_matrix[combination]; -} -*/ NzMatrix4f NzRenderer::GetMatrix(nzMatrixType type) { #ifdef NAZARA_DEBUG @@ -431,7 +401,10 @@ NzMatrix4f NzRenderer::GetMatrix(nzMatrixType type) } #endif - return s_matrix[type]; + if (!s_matrices[type].updated) + UpdateMatrix(type); + + return s_matrices[type].matrix; } nzUInt8 NzRenderer::GetMaxAnisotropyLevel() @@ -545,11 +518,13 @@ bool NzRenderer::Initialize() NzBuffer::SetBufferFunction(nzBufferStorage_Hardware, HardwareBufferFunction); - for (unsigned int i = 0; i < totalMatrixCount; ++i) + for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) { - s_matrix[i].MakeIdentity(); - s_matrixLocation[i] = -1; - s_matrixUpdated[i] = false; + MatrixUnit& unit = s_matrices[i]; + unit.location = -1; + unit.matrix.MakeIdentity(); + unit.sent = false; + unit.updated = true; } // Récupération des capacités d'OpenGL @@ -901,21 +876,38 @@ void NzRenderer::SetMatrix(nzMatrixType type, const NzMatrix4f& matrix) } #endif - s_matrix[type] = matrix; - s_matrixUpdated[type] = false; + s_matrices[type].matrix = matrix; + s_matrices[type].updated = true; // Invalidation des combinaisons - if (type == nzMatrixType_View) + switch (type) { - s_matrixUpdated[nzMatrixCombination_ViewProj] = false; - s_matrixUpdated[nzMatrixCombination_WorldView] = false; - } - else if (type == nzMatrixType_Projection) - s_matrixUpdated[nzMatrixCombination_ViewProj] = false; - else if (type == nzMatrixType_World) - s_matrixUpdated[nzMatrixCombination_WorldView] = false; + case nzMatrixType_Projection: + s_matrices[nzMatrixType_ViewProj].updated = false; + s_matrices[nzMatrixType_WorldViewProj].updated = false; + break; - s_matrixUpdated[nzMatrixCombination_WorldViewProj] = false; // Toujours invalidée + case nzMatrixType_View: + s_matrices[nzMatrixType_ViewProj].updated = false; + s_matrices[nzMatrixType_World].updated = false; + s_matrices[nzMatrixType_WorldViewProj].updated = false; + break; + + case nzMatrixType_World: + s_matrices[nzMatrixType_WorldView].updated = false; + s_matrices[nzMatrixType_WorldViewProj].updated = false; + break; + + case nzMatrixType_ViewProj: + break; + + case nzMatrixType_WorldView: + s_matrices[nzMatrixType_WorldViewProj].updated = false; + break; + + case nzMatrixType_WorldViewProj: + break; + } s_updateFlags |= Update_Matrices; } @@ -1268,23 +1260,17 @@ bool NzRenderer::EnsureStateUpdate() if (s_updateFlags & Update_Shader) { // Récupération des indices des variables uniformes (-1 si la variable n'existe pas) - s_matrixLocation[nzMatrixType_Projection] = shaderImpl->GetUniformLocation(nzShaderUniform_ProjMatrix); - s_matrixLocation[nzMatrixType_View] = shaderImpl->GetUniformLocation(nzShaderUniform_ViewMatrix); - s_matrixLocation[nzMatrixType_World] = shaderImpl->GetUniformLocation(nzShaderUniform_WorldMatrix); + s_matrices[nzMatrixType_Projection].location = shaderImpl->GetUniformLocation(nzShaderUniform_ProjMatrix); + s_matrices[nzMatrixType_View].location = shaderImpl->GetUniformLocation(nzShaderUniform_ViewMatrix); + s_matrices[nzMatrixType_World].location = shaderImpl->GetUniformLocation(nzShaderUniform_WorldMatrix); - s_matrixLocation[nzMatrixCombination_ViewProj] = shaderImpl->GetUniformLocation(nzShaderUniform_ViewProjMatrix); - s_matrixLocation[nzMatrixCombination_WorldView] = shaderImpl->GetUniformLocation(nzShaderUniform_WorldViewMatrix); - s_matrixLocation[nzMatrixCombination_WorldViewProj] = shaderImpl->GetUniformLocation(nzShaderUniform_WorldViewProjMatrix); + s_matrices[nzMatrixType_ViewProj].location = shaderImpl->GetUniformLocation(nzShaderUniform_ViewProjMatrix); + s_matrices[nzMatrixType_WorldView].location = shaderImpl->GetUniformLocation(nzShaderUniform_WorldViewMatrix); + s_matrices[nzMatrixType_WorldViewProj].location = shaderImpl->GetUniformLocation(nzShaderUniform_WorldViewProjMatrix); s_updateFlags |= Update_Matrices; - for (unsigned int i = 0; i < totalMatrixCount; ++i) - { - ///TODO: Voir le FIXME au niveau de l'envoi des matrices - /*if (s_matrixLocation[i] != -1) - s_matrixUpdated[i] = false; - else*/ - s_matrixUpdated[i] = false; - } + for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) + s_matrices[i].sent = false; // Changement de shader, on renvoie toutes les matrices demandées s_updateFlags &= ~Update_Shader; } @@ -1340,43 +1326,17 @@ bool NzRenderer::EnsureStateUpdate() { for (unsigned int i = 0; i <= nzMatrixType_Max; ++i) { - if (!s_matrixUpdated[i]) + MatrixUnit& unit = s_matrices[i]; + if (unit.location != -1) // On ne traite que les matrices existant dans le shader { - shaderImpl->SendMatrix(s_matrixLocation[i], s_matrix[i]); - s_matrixUpdated[i] = true; + if (!unit.updated) + UpdateMatrix(static_cast(i)); + + shaderImpl->SendMatrix(unit.location, unit.matrix); + unit.sent = true; } } - ///FIXME: Optimiser les matrices - ///TODO: Prendre en compte les FIXME... - // 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; } @@ -1515,4 +1475,43 @@ bool NzRenderer::EnsureStateUpdate() return true; } +void NzRenderer::UpdateMatrix(nzMatrixType type) +{ + #ifdef NAZARA_DEBUG + if (type > nzMatrixType_Max) + { + NazaraError("Matrix type out of enum"); + return; + } + #endif + + switch (type) + { + case nzMatrixType_Projection: + case nzMatrixType_View: + case nzMatrixType_World: + break; + + case nzMatrixType_ViewProj: + s_matrices[nzMatrixType_ViewProj].matrix = s_matrices[nzMatrixType_View].matrix * s_matrices[nzMatrixType_Projection].matrix; + s_matrices[nzMatrixType_ViewProj].updated = true; + break; + + case nzMatrixType_WorldView: + s_matrices[nzMatrixType_WorldView].matrix = s_matrices[nzMatrixType_World].matrix; + s_matrices[nzMatrixType_WorldView].matrix.ConcatenateAffine(s_matrices[nzMatrixType_View].matrix); + s_matrices[nzMatrixType_WorldView].updated = true; + break; + + case nzMatrixType_WorldViewProj: + if (!s_matrices[nzMatrixType_WorldView].updated) + UpdateMatrix(nzMatrixType_WorldView); + + s_matrices[nzMatrixType_WorldViewProj].matrix = s_matrices[nzMatrixType_WorldView].matrix; + s_matrices[nzMatrixType_WorldViewProj].matrix.Concatenate(s_matrices[nzMatrixType_Projection].matrix); + s_matrices[nzMatrixType_WorldViewProj].updated = true; + break; + } +} + unsigned int NzRenderer::s_moduleReferenceCounter = 0;