From 7d117ce97cf1436cb86ff71a28f6607c0b102460 Mon Sep 17 00:00:00 2001 From: Lynix Date: Wed, 2 May 2012 16:45:44 +0200 Subject: [PATCH] Laid the basis for rendering --- .../Nazara/Core/Debug/MemoryLeakTracker.hpp | 1 - include/Nazara/Math/EulerAngles.hpp | 1 - include/Nazara/Renderer/Buffer.hpp | 5 +- include/Nazara/Renderer/IndexBuffer.hpp | 2 + include/Nazara/Renderer/Renderer.hpp | 27 +++- include/Nazara/Renderer/VertexBuffer.hpp | 2 + include/Nazara/Renderer/VertexDeclaration.hpp | 10 +- src/Nazara/Core/Debug/MemoryLeakTracker.cpp | 25 ++-- src/Nazara/Renderer/Buffer.cpp | 57 ++++++-- src/Nazara/Renderer/BufferImpl.cpp | 1 + src/Nazara/Renderer/BufferImpl.hpp | 8 +- src/Nazara/Renderer/GLSLShader.cpp | 79 ++++++++++- src/Nazara/Renderer/GLSLShader.hpp | 2 + src/Nazara/Renderer/HardwareBuffer.cpp | 49 ++++--- src/Nazara/Renderer/HardwareBuffer.hpp | 4 +- src/Nazara/Renderer/IndexBuffer.cpp | 49 +++++++ src/Nazara/Renderer/Renderer.cpp | 133 ++++++++++++++++-- src/Nazara/Renderer/Shader.cpp | 2 +- src/Nazara/Renderer/ShaderImpl.cpp | 1 + src/Nazara/Renderer/ShaderImpl.hpp | 9 ++ src/Nazara/Renderer/SoftwareBuffer.cpp | 21 +-- src/Nazara/Renderer/SoftwareBuffer.hpp | 6 +- src/Nazara/Renderer/VertexBuffer.cpp | 10 ++ src/Nazara/Renderer/Win32/ContextImpl.cpp | 1 + src/Nazara/Utility/Window.cpp | 2 +- 25 files changed, 412 insertions(+), 95 deletions(-) diff --git a/include/Nazara/Core/Debug/MemoryLeakTracker.hpp b/include/Nazara/Core/Debug/MemoryLeakTracker.hpp index 3acb16991..070a90040 100644 --- a/include/Nazara/Core/Debug/MemoryLeakTracker.hpp +++ b/include/Nazara/Core/Debug/MemoryLeakTracker.hpp @@ -24,7 +24,6 @@ class NAZARA_API NzMemoryManager static void NextFree(const char* file, unsigned int line); private: - static void EnsureInitialization(); static void Initialize(); static char* TimeInfo(); static void Uninitialize(); diff --git a/include/Nazara/Math/EulerAngles.hpp b/include/Nazara/Math/EulerAngles.hpp index a91a68cbd..be39258fd 100644 --- a/include/Nazara/Math/EulerAngles.hpp +++ b/include/Nazara/Math/EulerAngles.hpp @@ -39,7 +39,6 @@ template class NzEulerAngles template void Set(const NzEulerAngles& angles); void SetZero(); - //NzEulerAngles ToEulerAngles() const; //NzMatrix3 ToRotationMatrix() const; NzQuaternion ToQuaternion() const; NzString ToString() const; diff --git a/include/Nazara/Renderer/Buffer.hpp b/include/Nazara/Renderer/Buffer.hpp index 3e0a7a76d..7049a297d 100644 --- a/include/Nazara/Renderer/Buffer.hpp +++ b/include/Nazara/Renderer/Buffer.hpp @@ -55,6 +55,9 @@ class NAZARA_API NzBuffer : public NzResource bool Fill(const void* data, unsigned int offset, unsigned int length); + void* GetBufferPtr(); + const void* GetBufferPtr() const; + NzBufferImpl* GetImpl() const; unsigned int GetLength() const; unsigned int GetSize() const; nzBufferStorage GetStorage() const; @@ -67,7 +70,7 @@ class NAZARA_API NzBuffer : public NzResource void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); bool Unlock(); - static bool IsHardwareSupported(); + static bool IsSupported(nzBufferStorage storage); private: nzBufferStorage m_storage; diff --git a/include/Nazara/Renderer/IndexBuffer.hpp b/include/Nazara/Renderer/IndexBuffer.hpp index 45941743b..a7b4a9015 100644 --- a/include/Nazara/Renderer/IndexBuffer.hpp +++ b/include/Nazara/Renderer/IndexBuffer.hpp @@ -21,6 +21,8 @@ class NAZARA_API NzIndexBuffer bool Fill(const void* data, unsigned int offset, unsigned int length); NzBuffer* GetBuffer() const; + void* GetBufferPtr(); + const void* GetBufferPtr() const; nzUInt8 GetIndexSize() const; unsigned int GetIndexCount() const; unsigned int GetStartIndex() const; diff --git a/include/Nazara/Renderer/Renderer.hpp b/include/Nazara/Renderer/Renderer.hpp index 5d7aaab38..a82c51825 100644 --- a/include/Nazara/Renderer/Renderer.hpp +++ b/include/Nazara/Renderer/Renderer.hpp @@ -8,19 +8,26 @@ #define NAZARA_RENDERER_HPP #include -#include -#include -#include -#include #define NazaraRenderer NzRenderer::Instance() +enum nzPrimitiveType +{ + nzPrimitiveType_LineList, + nzPrimitiveType_LineStrip, + nzPrimitiveType_PointList, + nzPrimitiveType_TriangleList, + nzPrimitiveType_TriangleStrip, + nzPrimitiveType_TriangleFan +}; + enum nzRendererCap { nzRendererCap_AnisotropicFilter, nzRendererCap_FP64, nzRendererCap_HardwareBuffer, nzRendererCap_MultipleRenderTargets, + nzRendererCap_SoftwareBuffer, nzRendererCap_Texture3D, nzRendererCap_TextureCubemap, nzRendererCap_TextureMulti, @@ -36,6 +43,12 @@ enum nzRendererClear nzRendererClear_Stencil = 0x04 }; +class NzRenderTarget; +class NzIndexBuffer; +class NzShader; +class NzVertexBuffer; +class NzVertexDeclaration; + class NAZARA_API NzRenderer { public: @@ -44,6 +57,9 @@ class NAZARA_API NzRenderer void Clear(nzRendererClear flags); + void DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount); + void DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount); + NzShader* GetShader() const; NzRenderTarget* GetTarget() const; @@ -67,12 +83,15 @@ class NAZARA_API NzRenderer static NzRenderer* Instance(); private: + bool UpdateVertexBuffer(); + static NzRenderer* s_instance; const NzIndexBuffer* m_indexBuffer; NzRenderTarget* m_target; NzShader* m_shader; const NzVertexBuffer* m_vertexBuffer; + const NzVertexDeclaration* m_vertexDeclaration; bool m_capabilities[nzRendererCap_Count]; bool m_vertexBufferUpdated; }; diff --git a/include/Nazara/Renderer/VertexBuffer.hpp b/include/Nazara/Renderer/VertexBuffer.hpp index 5c221cd06..721b32ee4 100644 --- a/include/Nazara/Renderer/VertexBuffer.hpp +++ b/include/Nazara/Renderer/VertexBuffer.hpp @@ -21,6 +21,8 @@ class NAZARA_API NzVertexBuffer bool Fill(const void* data, unsigned int offset, unsigned int length); NzBuffer* GetBuffer() const; + void* GetBufferPtr(); + const void* GetBufferPtr() const; unsigned int GetStartVertex() const; nzUInt8 GetTypeSize() const; unsigned int GetVertexCount() const; diff --git a/include/Nazara/Renderer/VertexDeclaration.hpp b/include/Nazara/Renderer/VertexDeclaration.hpp index 94b1976fb..1a4fa6267 100644 --- a/include/Nazara/Renderer/VertexDeclaration.hpp +++ b/include/Nazara/Renderer/VertexDeclaration.hpp @@ -23,11 +23,11 @@ enum nzElementType enum nzElementUsage { - nzElementType_Diffuse, - nzElementType_Normal, - nzElementType_Position, - nzElementType_Tangent, - nzElementType_TexCoord + nzElementUsage_Diffuse, + nzElementUsage_Normal, + nzElementUsage_Position, + nzElementUsage_Tangent, + nzElementUsage_TexCoord }; struct NzVertexElement diff --git a/src/Nazara/Core/Debug/MemoryLeakTracker.cpp b/src/Nazara/Core/Debug/MemoryLeakTracker.cpp index ffb7a876c..3199195a9 100644 --- a/src/Nazara/Core/Debug/MemoryLeakTracker.cpp +++ b/src/Nazara/Core/Debug/MemoryLeakTracker.cpp @@ -50,7 +50,8 @@ NzMemoryManager::~NzMemoryManager() void* NzMemoryManager::Allocate(std::size_t size, bool multi, const char* file, unsigned int line) { - EnsureInitialization(); + if (!initialized) + Initialize(); Block* ptr = reinterpret_cast(std::malloc(size+sizeof(Block))); if (!ptr) @@ -121,21 +122,6 @@ void NzMemoryManager::NextFree(const char* file, unsigned int line) nextFreeLine = line; } -void NzMemoryManager::EnsureInitialization() -{ - if (!initialized) - { - Initialize(); - - if (std::atexit(Uninitialize) != 0) - { - static NzMemoryManager manager; - } - - initialized = true; - } -} - void NzMemoryManager::Initialize() { char* time = TimeInfo(); @@ -147,6 +133,13 @@ void NzMemoryManager::Initialize() std::fclose(file); std::free(time); + + if (std::atexit(Uninitialize) != 0) + { + static NzMemoryManager manager; + } + + initialized = true; } char* NzMemoryManager::TimeInfo() diff --git a/src/Nazara/Renderer/Buffer.cpp b/src/Nazara/Renderer/Buffer.cpp index b2e80ae96..f1fcac5fa 100644 --- a/src/Nazara/Renderer/Buffer.cpp +++ b/src/Nazara/Renderer/Buffer.cpp @@ -11,6 +11,14 @@ #include #include +namespace +{ + nzRendererCap storageToCapability[] = { + nzRendererCap_HardwareBuffer, // nzBufferStorage_Hardware + nzRendererCap_SoftwareBuffer, // nzBufferStorage_Software + }; +} + NzBuffer::NzBuffer(nzBufferType type) : m_type(type), m_typeSize(0), @@ -25,7 +33,7 @@ m_impl(nullptr) { Create(length, typeSize, usage); - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (!m_impl) { NazaraError("Failed to create buffer"); @@ -44,14 +52,14 @@ bool NzBuffer::CopyContent(NzBuffer& buffer) void* ptr = buffer.Lock(nzBufferLock_ReadOnly); if (!ptr) { - NazaraError("Unable to lock buffer"); + NazaraError("Unable to lock source buffer"); return false; } bool r = Fill(ptr, 0, m_length); if (!buffer.Unlock()) - NazaraWarning("Unable to unlock buffer"); + NazaraWarning("Unable to unlock source buffer"); return r; } @@ -64,7 +72,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage if (NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer)) { m_impl = new NzHardwareBuffer(this, m_type); - if (!m_impl->Create(length, typeSize, usage)) + if (!m_impl->Create(length*typeSize, usage)) { NazaraWarning("Failed to create hardware buffer, trying to create software buffer..."); @@ -76,7 +84,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage if (!m_impl) { m_impl = new NzSoftwareBuffer(this, m_type); - if (!m_impl->Create(length, typeSize, usage)) + if (!m_impl->Create(length*typeSize, usage)) { NazaraError("Failed to create software buffer"); delete m_impl; @@ -120,7 +128,38 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length) } #endif - return m_impl->Fill(data, offset, length); + return m_impl->Fill(data, offset*m_typeSize, length*m_typeSize); +} + +void* NzBuffer::GetBufferPtr() +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Buffer not created"); + return false; + } + #endif + + return m_impl->GetBufferPtr(); +} + +const void* NzBuffer::GetBufferPtr() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_impl) + { + NazaraError("Buffer not created"); + return false; + } + #endif + + return m_impl->GetBufferPtr(); +} + +NzBufferImpl* NzBuffer::GetImpl() const +{ + return m_impl; } unsigned int NzBuffer::GetLength() const @@ -174,7 +213,7 @@ void* NzBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length } #endif - return m_impl->Lock(lock, offset, length); + return m_impl->Lock(lock, offset*m_typeSize, length*m_typeSize); } bool NzBuffer::Unlock() @@ -190,7 +229,7 @@ bool NzBuffer::Unlock() return m_impl->Unlock(); } -bool NzBuffer::IsHardwareSupported() +bool NzBuffer::IsSupported(nzBufferStorage storage) { - return NazaraRenderer->HasCapability(nzRendererCap_HardwareBuffer); + return NazaraRenderer->HasCapability(storageToCapability[storage]); } diff --git a/src/Nazara/Renderer/BufferImpl.cpp b/src/Nazara/Renderer/BufferImpl.cpp index 7a204f7ae..99f034067 100644 --- a/src/Nazara/Renderer/BufferImpl.cpp +++ b/src/Nazara/Renderer/BufferImpl.cpp @@ -3,5 +3,6 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include NzBufferImpl::~NzBufferImpl() = default; diff --git a/src/Nazara/Renderer/BufferImpl.hpp b/src/Nazara/Renderer/BufferImpl.hpp index fe4d28eb8..74b8d835a 100644 --- a/src/Nazara/Renderer/BufferImpl.hpp +++ b/src/Nazara/Renderer/BufferImpl.hpp @@ -17,14 +17,16 @@ class NzBufferImpl virtual void Bind() = 0; - virtual bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static) = 0; + virtual bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static) = 0; virtual void Destroy() = 0; - virtual bool Fill(const void* data, unsigned int offset, unsigned int length) = 0; + virtual bool Fill(const void* data, unsigned int offset, unsigned int size) = 0; + + virtual void* GetBufferPtr() = 0; virtual bool IsHardware() const = 0; - virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0) = 0; + virtual void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int size = 0) = 0; virtual bool Unlock() = 0; }; diff --git a/src/Nazara/Renderer/GLSLShader.cpp b/src/Nazara/Renderer/GLSLShader.cpp index 7bf79d0c8..b9d4c3b3b 100644 --- a/src/Nazara/Renderer/GLSLShader.cpp +++ b/src/Nazara/Renderer/GLSLShader.cpp @@ -6,15 +6,53 @@ #include #include #include +#include +#include +#include #include namespace { - GLenum shaderType[nzShaderType_Count] = { + nzUInt8 attribIndex[] = + { + 2, // nzElementUsage_Diffuse + 1, // nzElementUsage_Normal + 0, // nzElementUsage_Position + 3, // nzElementUsage_Tangent + 4 // nzElementUsage_TexCoord + }; + + const GLenum shaderType[nzShaderType_Count] = { GL_FRAGMENT_SHADER, // nzShaderType_Fragment GL_GEOMETRY_SHADER, // nzShaderType_Geometry GL_VERTEX_SHADER // nzShaderType_Vertex }; + + const nzUInt8 size[] = + { + 4, // nzElementType_Color + 1, // nzElementType_Double1 + 2, // nzElementType_Double2 + 3, // nzElementType_Double3 + 4, // nzElementType_Double4 + 1, // nzElementType_Float1 + 2, // nzElementType_Float2 + 3, // nzElementType_Float3 + 4 // nzElementType_Float4 + }; + + const GLenum type[] = + { + GL_UNSIGNED_BYTE, // nzElementType_Color + GL_DOUBLE, // nzElementType_Double1 + GL_DOUBLE, // nzElementType_Double2 + GL_DOUBLE, // nzElementType_Double3 + GL_DOUBLE, // nzElementType_Double4 + GL_FLOAT, // nzElementType_Float1 + GL_FLOAT, // nzElementType_Float2 + GL_FLOAT, // nzElementType_Float3 + GL_FLOAT // nzElementType_Float4 + }; } NzGLSLShader::NzGLSLShader(NzShader* parent) : @@ -80,15 +118,16 @@ bool NzGLSLShader::Create() return false; } - glBindAttribLocation(m_program, 0, "Position"); - glBindAttribLocation(m_program, 1, "Normal"); - //glBindAttribLocation(m_program, 2, "Diffuse"); - glBindAttribLocation(m_program, 3, "Tangent"); + glBindAttribLocation(m_program, attribIndex[nzElementUsage_Position], "Position"); + glBindAttribLocation(m_program, attribIndex[nzElementUsage_Normal], "Normal"); + glBindAttribLocation(m_program, attribIndex[nzElementUsage_Diffuse], "Diffuse"); + glBindAttribLocation(m_program, attribIndex[nzElementUsage_Tangent], "Tangent"); + NzString uniformName = "TexCoord0"; for (unsigned int i = 0; i < 8; ++i) { - NzString uniformName = "TexCoord" + NzString::Number(i); - glBindAttribLocation(m_program, 4+i, uniformName.GetConstBuffer()); + uniformName[8] = '0'+i; + glBindAttribLocation(m_program, attribIndex[nzElementUsage_TexCoord]+i, uniformName.GetConstBuffer()); } for (int i = 0; i < nzShaderType_Count; ++i) @@ -252,3 +291,29 @@ void NzGLSLShader::Unbind() { glUseProgram(0); } + +bool NzGLSLShader::UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration) +{ + vertexBuffer->GetBuffer()->GetImpl()->Bind(); + const nzUInt8* buffer = reinterpret_cast(vertexBuffer->GetBufferPtr()); + + ///FIXME: Améliorer les déclarations pour permettre de faire ça plus simplement + for (int i = 0; i < 12; ++i) // Solution temporaire, à virer + glDisableVertexAttribArray(i); // Chaque itération tue un chaton :( + + unsigned int stride = vertexDeclaration->GetStride(); + unsigned int elementCount = vertexDeclaration->GetElementCount(); + for (unsigned int i = 0; i < elementCount; ++i) + { + const NzVertexDeclaration::Element* element = vertexDeclaration->GetElement(i); + glEnableVertexAttribArray(attribIndex[element->usage]+element->usageIndex); + glVertexAttribPointer(attribIndex[element->usage]+element->usageIndex, + size[element->type], + type[element->type], + (element->type == nzElementType_Color) ? GL_TRUE : GL_FALSE, + stride, + &buffer[element->offset]); + } + + return true; +} diff --git a/src/Nazara/Renderer/GLSLShader.hpp b/src/Nazara/Renderer/GLSLShader.hpp index 499c76aa4..176e34d76 100644 --- a/src/Nazara/Renderer/GLSLShader.hpp +++ b/src/Nazara/Renderer/GLSLShader.hpp @@ -45,6 +45,8 @@ class NzGLSLShader : public NzShaderImpl void Unbind(); private: + bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration); + mutable std::map m_idCache; GLuint m_program; GLuint m_shaders[nzShaderType_Count]; diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index d51284a07..7d15071fd 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -43,11 +43,11 @@ namespace GL_STATIC_DRAW // nzBufferUsage_Static }; - typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length); + typedef nzUInt8* (*LockRoutine)(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size); - nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length) + nzUInt8* LockBuffer(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size) { - NazaraUnused(length); + NazaraUnused(size); if (lock == nzBufferLock_DiscardAndWrite) { @@ -68,22 +68,24 @@ namespace return nullptr; } - nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length) + nzUInt8* LockBufferRange(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size) { - return reinterpret_cast(glMapBufferRange(bufferTarget[type], offset, length, bufferLockRange[lock])); + return reinterpret_cast(glMapBufferRange(bufferTarget[type], offset, size, bufferLockRange[lock])); } - nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int length) + nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size); + + LockRoutine lockBuffer = LockBufferFirstRun; + + nzUInt8* LockBufferFirstRun(nzBufferType type, nzBufferLock lock, unsigned int offset, unsigned int size) { if (glMapBufferRange) lockBuffer = LockBufferRange; else lockBuffer = LockBuffer; - return lockBuffer(type, lock, offset, length); + return lockBuffer(type, lock, offset, size); } - - LockRoutine lockBuffer = LockBufferFirstRun; } NzHardwareBuffer::NzHardwareBuffer(NzBuffer* parent, nzBufferType type) : @@ -101,7 +103,7 @@ void NzHardwareBuffer::Bind() glBindBuffer(bufferTarget[m_type], m_buffer); } -bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) +bool NzHardwareBuffer::Create(unsigned int size, nzBufferUsage usage) { m_buffer = 0; glGenBuffers(1, &m_buffer); @@ -116,7 +118,7 @@ bool NzHardwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsa glGetIntegerv(bufferTargetBinding[m_type], &previous); glBindBuffer(bufferTarget[m_type], m_buffer); - glBufferData(bufferTarget[m_type], length*typeSize, nullptr, bufferUsage[usage]); + glBufferData(bufferTarget[m_type], size, nullptr, bufferUsage[usage]); // Pour ne pas perturber le rendu, on interfère pas avec le binding déjà présent if (previous != 0) @@ -130,7 +132,7 @@ void NzHardwareBuffer::Destroy() glDeleteBuffers(1, &m_buffer); } -bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length) +bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) { GLuint previous; glGetIntegerv(bufferTargetBinding[m_type], reinterpret_cast(&previous)); @@ -139,26 +141,24 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int glBindBuffer(bufferTarget[m_type], m_buffer); // Il semblerait que glBufferSubData soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil - if (length < 32*1024) + /*if (size < 32*1024) { - if (length == m_parent->GetLength()) + if (size == m_parent->GetLength()) glBufferData(bufferTarget[m_type], m_parent->GetSize(), data, bufferUsage[m_parent->GetStorage()]); else - { - nzUInt8 typeSize = m_parent->GetTypeSize(); - glBufferSubData(bufferTarget[m_type], offset*typeSize, length*typeSize, data); - } + glBufferSubData(bufferTarget[m_type], offset, size, data); } - else + else*/ { - nzUInt8* ptr = lockBuffer(m_type, (length == m_parent->GetLength()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, length); - if (ptr) + // La longueur que nous recevons est en fait la taille + nzUInt8* ptr = lockBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferLock_DiscardAndWrite : nzBufferLock_WriteOnly, offset, size); + if (!ptr) { NazaraError("Failed to lock buffer"); return false; } - std::memcpy(ptr, data, length*m_parent->GetTypeSize()); + std::memcpy(ptr, data, size); if (glUnmapBuffer(bufferTarget[m_type]) != GL_TRUE) { @@ -178,6 +178,11 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int return true; } +void* NzHardwareBuffer::GetBufferPtr() +{ + return nullptr; +} + bool NzHardwareBuffer::IsHardware() const { return true; diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index 8b447eb46..044633634 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -19,11 +19,13 @@ class NzHardwareBuffer : public NzBufferImpl void Bind(); - bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); + bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); bool Fill(const void* data, unsigned int offset, unsigned int length); + void* GetBufferPtr(); + bool IsHardware() const; void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); diff --git a/src/Nazara/Renderer/IndexBuffer.cpp b/src/Nazara/Renderer/IndexBuffer.cpp index 96c5bd702..b13ddab9a 100644 --- a/src/Nazara/Renderer/IndexBuffer.cpp +++ b/src/Nazara/Renderer/IndexBuffer.cpp @@ -13,7 +13,20 @@ m_indexCount(indexCount), m_startIndex(startIndex) { if (m_buffer) + { + #ifdef NAZARA_DEBUG + nzUInt8 indexSize = m_buffer->GetSize(); + if (indexSize != 1 && indexSize != 2 && indexSize != 4) + { + NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')'); + m_buffer = nullptr; + + throw std::runtime_error("Constructor failed"); + } + #endif + m_buffer->AddResourceReference(); + } } NzIndexBuffer::NzIndexBuffer(unsigned int length, nzUInt8 indexSize, nzBufferUsage usage) : @@ -21,6 +34,16 @@ m_ownsBuffer(true), m_indexCount(length), m_startIndex(0) { + #ifdef NAZARA_DEBUG + if (indexSize != 1 && indexSize != 2 && indexSize != 4) + { + NazaraError("Invalid index size"); + m_buffer = nullptr; + + throw std::runtime_error("Constructor failed"); + } + #endif + m_buffer = new NzBuffer(nzBufferType_Index, length, indexSize, usage); m_buffer->AddResourceReference(); m_buffer->SetPersistent(false); @@ -80,6 +103,32 @@ NzBuffer* NzIndexBuffer::GetBuffer() const return m_buffer; } +void* NzIndexBuffer::GetBufferPtr() +{ + #if NAZARA_RENDERER_SAFE + if (!m_buffer) + { + NazaraError("Sequential index buffer: Buffer has no pointer"); + return nullptr; + } + #endif + + return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize(); +} + +const void* NzIndexBuffer::GetBufferPtr() const +{ + #if NAZARA_RENDERER_SAFE + if (!m_buffer) + { + NazaraError("Sequential index buffer: Buffer has no pointer"); + return nullptr; + } + #endif + + return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startIndex*m_buffer->GetTypeSize(); +} + nzUInt8 NzIndexBuffer::GetIndexSize() const { #if NAZARA_RENDERER_SAFE diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 710e1758c..c3460f72c 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -6,14 +6,33 @@ #include #include #include +#include +#include +#include #include +#include #include #include +namespace +{ + GLenum openglPrimitive[] = { + GL_LINES, // nzPrimitiveType_LineList, + GL_LINE_STRIP, // nzPrimitiveType_LineStrip, + GL_POINTS, // nzPrimitiveType_PointList, + GL_TRIANGLES, // nzPrimitiveType_TriangleList, + GL_TRIANGLE_STRIP, // nzPrimitiveType_TriangleStrip, + GL_TRIANGLE_FAN // nzPrimitiveType_TriangleFan + }; +} + NzRenderer::NzRenderer() : m_indexBuffer(nullptr), m_target(nullptr), -m_shader(nullptr) +m_shader(nullptr), +m_vertexBuffer(nullptr), +m_vertexDeclaration(nullptr), +m_vertexBufferUpdated(false) { #if NAZARA_RENDERER_SAFE if (s_instance) @@ -32,7 +51,7 @@ NzRenderer::~NzRenderer() void NzRenderer::Clear(nzRendererClear flags) { - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) { NazaraError("No active context"); @@ -57,6 +76,64 @@ void NzRenderer::Clear(nzRendererClear flags) } } +void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int firstIndex, unsigned int indexCount) +{ + #ifdef NAZARA_DEBUG + if (!m_indexBuffer) + { + UngineError("No index buffer"); + return; + } + #endif + + if (!m_vertexBufferUpdated) + { + if (!UpdateVertexBuffer()) + { + NazaraError("Failed to update vertex buffer"); + return; + } + } + + nzUInt8 indexSize = m_indexBuffer->GetIndexSize(); + + GLenum type; + switch (indexSize) + { + case 1: + type = GL_UNSIGNED_BYTE; + break; + + case 2: + type = GL_UNSIGNED_SHORT; + break; + + case 4: + type = GL_UNSIGNED_INT; + break; + + default: + NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')'); + return; + } + + glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast(m_indexBuffer->GetBufferPtr()) + firstIndex*indexSize); +} + +void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount) +{ + if (!m_vertexBufferUpdated) + { + if (!UpdateVertexBuffer()) + { + NazaraError("Failed to update vertex buffer"); + return; + } + } + + glDrawArrays(openglPrimitive[primitive], firstVertex, vertexCount); +} + NzShader* NzRenderer::GetShader() const { return m_shader; @@ -80,6 +157,7 @@ bool NzRenderer::Initialize() m_capabilities[nzRendererCap_FP64] = NzOpenGL::IsSupported(NzOpenGL::FP64); m_capabilities[nzRendererCap_HardwareBuffer] = true; // Natif depuis OpenGL 2.0 m_capabilities[nzRendererCap_MultipleRenderTargets] = true; // Natif depuis OpenGL 2.0 + m_capabilities[nzRendererCap_SoftwareBuffer] = NzOpenGL::GetVersion() <= 310; // Déprécié en OpenGL 3.1 m_capabilities[nzRendererCap_Texture3D] = NzOpenGL::IsSupported(NzOpenGL::Texture3D); m_capabilities[nzRendererCap_TextureCubemap] = true; // Natif depuis OpenGL 1.3 m_capabilities[nzRendererCap_TextureMulti] = true; // Natif depuis OpenGL 1.3 @@ -93,7 +171,7 @@ bool NzRenderer::Initialize() void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a) { - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) { NazaraError("No active context"); @@ -106,7 +184,7 @@ void NzRenderer::SetClearColor(nzUInt8 r, nzUInt8 g, nzUInt8 b, nzUInt8 a) void NzRenderer::SetClearDepth(double depth) { - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) { NazaraError("No active context"); @@ -119,7 +197,7 @@ void NzRenderer::SetClearDepth(double depth) void NzRenderer::SetClearStencil(unsigned int value) { - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (NzContext::GetCurrent() == nullptr) { NazaraError("No active context"); @@ -164,6 +242,7 @@ bool NzRenderer::SetShader(NzShader* shader) } m_shader = shader; + m_vertexBufferUpdated = false; } else if (m_shader) { @@ -213,18 +292,20 @@ bool NzRenderer::SetVertexBuffer(const NzVertexBuffer* vertexBuffer) if (m_vertexBuffer == vertexBuffer) return true; + if (m_vertexBuffer && vertexBuffer) + { + // Si l'ancien buffer et le nouveau sont hardware, pas besoin de mettre à jour la déclaration + if (!m_vertexBuffer->IsHardware() || !vertexBuffer->IsHardware()) + m_vertexBufferUpdated = false; + } m_vertexBuffer = vertexBuffer; - m_vertexBufferUpdated = false; return true; } -bool NzRenderer::SetVertexDeclaration(const NzVertexBuffer* vertexBuffer) +bool NzRenderer::SetVertexDeclaration(const NzVertexDeclaration* vertexDeclaration) { - if (m_vertexBuffer == vertexBuffer) - return true; - - m_vertexBuffer = vertexBuffer; + m_vertexDeclaration = vertexDeclaration; m_vertexBufferUpdated = false; return true; @@ -256,4 +337,34 @@ NzRenderer* NzRenderer::Instance() return s_instance; } +bool NzRenderer::UpdateVertexBuffer() +{ + #if NAZARA_RENDERER_SAFE + if (!m_shader) + { + NazaraError("No shader"); + return false; + } + + if (!m_vertexBuffer) + { + NazaraError("No vertex buffer"); + return false; + } + + if (!m_vertexDeclaration) + { + NazaraError("No vertex declaration"); + return false; + } + #endif + + if (!m_shader->m_impl->UpdateVertexBuffer(m_vertexBuffer, m_vertexDeclaration)) + return false; + + m_vertexBufferUpdated = true; + + return true; +} + NzRenderer* NzRenderer::s_instance = nullptr; diff --git a/src/Nazara/Renderer/Shader.cpp b/src/Nazara/Renderer/Shader.cpp index 208277f4e..4e5b5b4ee 100644 --- a/src/Nazara/Renderer/Shader.cpp +++ b/src/Nazara/Renderer/Shader.cpp @@ -25,7 +25,7 @@ m_compiled(false) { Create(language); - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (!m_impl) { NazaraError("Failed to create shader"); diff --git a/src/Nazara/Renderer/ShaderImpl.cpp b/src/Nazara/Renderer/ShaderImpl.cpp index 4dbe4f11e..5f2b2976b 100644 --- a/src/Nazara/Renderer/ShaderImpl.cpp +++ b/src/Nazara/Renderer/ShaderImpl.cpp @@ -3,5 +3,6 @@ // For conditions of distribution and use, see copyright notice in Config.hpp #include +#include NzShaderImpl::~NzShaderImpl() = default; diff --git a/src/Nazara/Renderer/ShaderImpl.hpp b/src/Nazara/Renderer/ShaderImpl.hpp index 7212583a5..2a650cfec 100644 --- a/src/Nazara/Renderer/ShaderImpl.hpp +++ b/src/Nazara/Renderer/ShaderImpl.hpp @@ -9,8 +9,14 @@ #include +class NzRenderer; +class NzVertexBuffer; +class NzVertexDeclaration; + class NzShaderImpl { + friend class NzRenderer; + public: NzShaderImpl() = default; virtual ~NzShaderImpl(); @@ -38,6 +44,9 @@ class NzShaderImpl virtual bool SendMatrix(const NzString& name, const NzMatrix4f& matrix) = 0; virtual void Unbind() = 0; + + protected: + virtual bool UpdateVertexBuffer(const NzVertexBuffer* vertexBuffer, const NzVertexDeclaration* vertexDeclaration) = 0; }; #endif // NAZARA_SHADERIMPL_HPP diff --git a/src/Nazara/Renderer/SoftwareBuffer.cpp b/src/Nazara/Renderer/SoftwareBuffer.cpp index 44ca1ec43..c0e99ce4a 100644 --- a/src/Nazara/Renderer/SoftwareBuffer.cpp +++ b/src/Nazara/Renderer/SoftwareBuffer.cpp @@ -32,14 +32,14 @@ void NzSoftwareBuffer::Bind() glBindBuffer(bufferTarget[m_type], 0); } -bool NzSoftwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage) +bool NzSoftwareBuffer::Create(unsigned int size, nzBufferUsage usage) { NazaraUnused(usage); // Cette allocation est protégée car sa taille dépend directement de paramètres utilisateurs try { - m_buffer = new nzUInt8[length*typeSize]; + m_buffer = new nzUInt8[size]; } catch (const std::exception& e) { @@ -47,9 +47,7 @@ bool NzSoftwareBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferUsa return false; } - m_length = length; m_locked = false; - m_typeSize = typeSize; return true; } @@ -59,7 +57,7 @@ void NzSoftwareBuffer::Destroy() delete[] m_buffer; } -bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int length) +bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) { #if NAZARA_RENDERER_SAFE if (m_locked) @@ -69,20 +67,25 @@ bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int } #endif - std::memcpy(&m_buffer[offset*m_typeSize], data, length*m_typeSize); + std::memcpy(&m_buffer[offset], data, size); return true; } +void* NzSoftwareBuffer::GetBufferPtr() +{ + return m_buffer; +} + bool NzSoftwareBuffer::IsHardware() const { return false; } -void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int length) +void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned int size) { - NazaraUnused(length); NazaraUnused(lock); + NazaraUnused(size); #if NAZARA_RENDERER_SAFE if (m_locked) @@ -94,7 +97,7 @@ void* NzSoftwareBuffer::Lock(nzBufferLock lock, unsigned int offset, unsigned in m_locked = true; - return &m_buffer[offset*m_typeSize]; + return &m_buffer[offset]; } bool NzSoftwareBuffer::Unlock() diff --git a/src/Nazara/Renderer/SoftwareBuffer.hpp b/src/Nazara/Renderer/SoftwareBuffer.hpp index 2f8fab6e0..865b7d6d2 100644 --- a/src/Nazara/Renderer/SoftwareBuffer.hpp +++ b/src/Nazara/Renderer/SoftwareBuffer.hpp @@ -18,11 +18,13 @@ class NzSoftwareBuffer : public NzBufferImpl void Bind(); - bool Create(unsigned int length, nzUInt8 typeSize, nzBufferUsage usage = nzBufferUsage_Static); + bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); bool Fill(const void* data, unsigned int offset, unsigned int length); + void* GetBufferPtr(); + bool IsHardware() const; void* Lock(nzBufferLock lock, unsigned int offset = 0, unsigned int length = 0); @@ -30,10 +32,8 @@ class NzSoftwareBuffer : public NzBufferImpl private: nzBufferType m_type; - nzUInt8 m_typeSize; nzUInt8* m_buffer; bool m_locked; - unsigned int m_length; }; #endif // NAZARA_SOFTWAREBUFFER_HPP diff --git a/src/Nazara/Renderer/VertexBuffer.cpp b/src/Nazara/Renderer/VertexBuffer.cpp index c5376f823..62bdac667 100644 --- a/src/Nazara/Renderer/VertexBuffer.cpp +++ b/src/Nazara/Renderer/VertexBuffer.cpp @@ -67,6 +67,16 @@ NzBuffer* NzVertexBuffer::GetBuffer() const return m_buffer; } +void* NzVertexBuffer::GetBufferPtr() +{ + return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize(); +} + +const void* NzVertexBuffer::GetBufferPtr() const +{ + return reinterpret_cast(m_buffer->GetBufferPtr()) + m_startVertex*m_buffer->GetTypeSize(); +} + unsigned int NzVertexBuffer::GetStartVertex() const { return m_startVertex; diff --git a/src/Nazara/Renderer/Win32/ContextImpl.cpp b/src/Nazara/Renderer/Win32/ContextImpl.cpp index 157a68261..64fbc4445 100644 --- a/src/Nazara/Renderer/Win32/ContextImpl.cpp +++ b/src/Nazara/Renderer/Win32/ContextImpl.cpp @@ -12,6 +12,7 @@ #include #include #include +#include NzContextImpl::NzContextImpl() { diff --git a/src/Nazara/Utility/Window.cpp b/src/Nazara/Utility/Window.cpp index acba77ddb..384549143 100644 --- a/src/Nazara/Utility/Window.cpp +++ b/src/Nazara/Utility/Window.cpp @@ -64,7 +64,7 @@ m_impl(nullptr) { Create(handle); - #if NAZARA_DEBUG + #ifdef NAZARA_DEBUG if (!m_impl) { NazaraError("Failed to create window");