diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index a5a7fe9df..4721081c7 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -30,7 +30,7 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable bool Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); - bool Fill(const void* data, unsigned int offset, unsigned int length); + bool Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard = false); NzBufferImpl* GetImpl() const; unsigned int GetLength() const; diff --git a/include/Nazara/Utility/BufferImpl.hpp b/include/Nazara/Utility/BufferImpl.hpp index f1015d75d..ddcc685e1 100644 --- a/include/Nazara/Utility/BufferImpl.hpp +++ b/include/Nazara/Utility/BufferImpl.hpp @@ -18,7 +18,7 @@ class NAZARA_API NzBufferImpl 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 size) = 0; + virtual bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard = false) = 0; virtual void* GetPointer() = 0; diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index 088d9d79d..f77322525 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -105,29 +106,32 @@ void NzHardwareBuffer::Destroy() glDeleteBuffers(1, &m_buffer); } -bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) +bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) { NzContext::EnsureContext(); + unsigned int totalSize = m_parent->GetSize(); + + if (!forceDiscard) + forceDiscard = (size == totalSize); + GLuint previous; glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast(&previous)); if (previous != m_buffer) glBindBuffer(NzOpenGL::BufferTarget[m_type], m_buffer); + // http://www.opengl.org/wiki/Vertex_Specification_Best_Practices + if (forceDiscard) + glBufferData(NzOpenGL::BufferTarget[m_type], totalSize, nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard + // Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil // http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/ if (size < 32*1024) - { - // http://www.opengl.org/wiki/Vertex_Specification_Best_Practices - if (size == m_parent->GetSize()) - glBufferData(NzOpenGL::BufferTarget[m_type], size, nullptr, NzOpenGL::BufferUsage[m_parent->GetUsage()]); // Discard - glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data); - } else { - nzUInt8* ptr = mapBuffer(m_type, (size == m_parent->GetSize()) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size); + nzUInt8* ptr = mapBuffer(m_type, (forceDiscard) ? nzBufferAccess_DiscardAndWrite : nzBufferAccess_WriteOnly, offset, size); if (!ptr) { NazaraError("Failed to map buffer"); @@ -141,7 +145,7 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int // 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()]); + glBufferData(NzOpenGL::BufferTarget[m_type], totalSize, nullptr, NzOpenGL::BufferUsage[m_parent->GetStorage()]); return false; } @@ -175,6 +179,9 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned if (previous != m_buffer) glBindBuffer(NzOpenGL::BufferTarget[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érrations chaînées) diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index d13d7ec1d..092b6f9bf 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -22,7 +22,7 @@ class NzHardwareBuffer : public NzBufferImpl bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); - bool Fill(const void* data, unsigned int offset, unsigned int size); + bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard); void* GetPointer(); diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index fd98e68be..56023342e 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -372,7 +372,7 @@ void NzRenderer::FillInstancingBuffer(const NzRenderer::InstancingData* instanci } #endif - if (!s_instancingBuffer->Fill(instancingData, 0, instanceCount)) + if (!s_instancingBuffer->Fill(instancingData, 0, instanceCount, true)) NazaraError("Failed to fill instancing buffer"); } diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index ee2c9a9f9..76bd601d7 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -117,7 +117,7 @@ void NzBuffer::Destroy() } } -bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length) +bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length, bool forceDiscard) { #if NAZARA_UTILITY_SAFE if (!m_impl) @@ -133,7 +133,7 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length) } #endif - return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); + return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize, forceDiscard); } NzBufferImpl* NzBuffer::GetImpl() const diff --git a/src/Nazara/Utility/SoftwareBuffer.cpp b/src/Nazara/Utility/SoftwareBuffer.cpp index f2a7e8b13..a77b2acba 100644 --- a/src/Nazara/Utility/SoftwareBuffer.cpp +++ b/src/Nazara/Utility/SoftwareBuffer.cpp @@ -44,8 +44,10 @@ void NzSoftwareBuffer::Destroy() delete[] m_buffer; } -bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size) +bool NzSoftwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard) { + NazaraUnused(forceDiscard); + #if NAZARA_UTILITY_SAFE if (m_mapped) { diff --git a/src/Nazara/Utility/SoftwareBuffer.hpp b/src/Nazara/Utility/SoftwareBuffer.hpp index 9c07b9e2d..5181ecc1b 100644 --- a/src/Nazara/Utility/SoftwareBuffer.hpp +++ b/src/Nazara/Utility/SoftwareBuffer.hpp @@ -19,7 +19,7 @@ class NzSoftwareBuffer : public NzBufferImpl bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static); void Destroy(); - bool Fill(const void* data, unsigned int offset, unsigned int size); + bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard); void* GetPointer();