Reworked (fixed and optimized) matrix handling

Former-commit-id: 6148748da07e228a746f51950231126b036b05eb
This commit is contained in:
Lynix 2013-06-27 19:04:22 +02:00
parent 30cb518c74
commit 7172ceaa6b
3 changed files with 133 additions and 128 deletions

View File

@ -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

View File

@ -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;
};

View File

@ -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<const NzContext*, const NzIndexBuffer*, const NzVertexBuffer*, bool>;
std::map<VAO_Key, unsigned int> 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<nzMatrixType>(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;