Greatly improved Renderer

Separated Viewport from Scissor rect
Improved performances
Removed Lock/Unlock system from Shader/Texture class


Former-commit-id: f54bca6de58fe9d495d9192dc0d761f92594ee86
This commit is contained in:
Lynix 2013-05-03 02:58:35 +02:00
parent 76c19624d8
commit 4f3060a40d
15 changed files with 389 additions and 561 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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);
}
}
/*

View File

@ -12,12 +12,6 @@
#include <Nazara/Utility/VertexDeclaration.hpp>
#include <Nazara/Renderer/Debug.hpp>
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);

View File

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

View File

@ -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<GLint*>(&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<GLint*>(&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<GLint*>(&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;
}

View File

@ -5,6 +5,7 @@
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
#include <set>
#include <sstream>
#include <stdexcept>
@ -58,11 +59,15 @@ namespace
}
std::set<NzString> 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<const char*>(glGetString(GL_RENDERER));
s_textureUnit = 0;
s_vendorName = reinterpret_cast<const char*>(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] =

View File

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

View File

@ -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<VAO_Key, unsigned int> s_vaos;
std::vector<TextureUnit> s_textureUnits;
std::vector<unsigned int> 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, &params[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<NzHardwareBuffer*>(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;
}

View File

@ -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();

View File

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

View File

@ -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<GLuint>(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<NzTextureImpl> 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)
{