Optimized Buffer locking/filling

Former-commit-id: 41cb66257f3eeef375086bf51f26230a06ca9eb8
This commit is contained in:
Lynix 2013-03-06 22:40:15 +01:00
parent aa67a52e9c
commit 9f780ef2bd
8 changed files with 26 additions and 17 deletions

View File

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

View File

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

View File

@ -4,6 +4,7 @@
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Renderer/HardwareBuffer.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <cstring>
@ -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<GLint*>(&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)

View File

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

View File

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

View File

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

View File

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

View File

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