Optimized Buffer locking/filling
Former-commit-id: 41cb66257f3eeef375086bf51f26230a06ca9eb8
This commit is contained in:
parent
aa67a52e9c
commit
9f780ef2bd
|
|
@ -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);
|
bool Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage storage = nzBufferStorage_Software, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
void Destroy();
|
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;
|
NzBufferImpl* GetImpl() const;
|
||||||
unsigned int GetLength() const;
|
unsigned int GetLength() const;
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,7 @@ class NAZARA_API NzBufferImpl
|
||||||
virtual bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static) = 0;
|
virtual bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static) = 0;
|
||||||
virtual void Destroy() = 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;
|
virtual void* GetPointer() = 0;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#include <Nazara/Renderer/OpenGL.hpp>
|
#include <Nazara/Renderer/OpenGL.hpp>
|
||||||
#include <Nazara/Renderer/HardwareBuffer.hpp>
|
#include <Nazara/Renderer/HardwareBuffer.hpp>
|
||||||
|
#include <Nazara/Core/Clock.hpp>
|
||||||
#include <Nazara/Core/Error.hpp>
|
#include <Nazara/Core/Error.hpp>
|
||||||
#include <Nazara/Renderer/Context.hpp>
|
#include <Nazara/Renderer/Context.hpp>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
@ -105,29 +106,32 @@ void NzHardwareBuffer::Destroy()
|
||||||
glDeleteBuffers(1, &m_buffer);
|
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();
|
NzContext::EnsureContext();
|
||||||
|
|
||||||
|
unsigned int totalSize = m_parent->GetSize();
|
||||||
|
|
||||||
|
if (!forceDiscard)
|
||||||
|
forceDiscard = (size == totalSize);
|
||||||
|
|
||||||
GLuint previous;
|
GLuint previous;
|
||||||
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
glGetIntegerv(NzOpenGL::BufferTargetBinding[m_type], reinterpret_cast<GLint*>(&previous));
|
||||||
|
|
||||||
if (previous != m_buffer)
|
if (previous != m_buffer)
|
||||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], 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
|
// 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/
|
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
|
||||||
if (size < 32*1024)
|
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);
|
glBufferSubData(NzOpenGL::BufferTarget[m_type], offset, size, data);
|
||||||
}
|
|
||||||
else
|
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)
|
if (!ptr)
|
||||||
{
|
{
|
||||||
NazaraError("Failed to map buffer");
|
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
|
// 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) + ')');
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
@ -175,6 +179,9 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned
|
||||||
if (previous != m_buffer)
|
if (previous != m_buffer)
|
||||||
glBindBuffer(NzOpenGL::BufferTarget[m_type], 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);
|
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)
|
// Inutile de rebinder s'il n'y avait aucun buffer (Optimise les opérrations chaînées)
|
||||||
|
|
|
||||||
|
|
@ -22,7 +22,7 @@ class NzHardwareBuffer : public NzBufferImpl
|
||||||
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
|
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
void Destroy();
|
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();
|
void* GetPointer();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -372,7 +372,7 @@ void NzRenderer::FillInstancingBuffer(const NzRenderer::InstancingData* instanci
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!s_instancingBuffer->Fill(instancingData, 0, instanceCount))
|
if (!s_instancingBuffer->Fill(instancingData, 0, instanceCount, true))
|
||||||
NazaraError("Failed to fill instancing buffer");
|
NazaraError("Failed to fill instancing buffer");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 NAZARA_UTILITY_SAFE
|
||||||
if (!m_impl)
|
if (!m_impl)
|
||||||
|
|
@ -133,7 +133,7 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length)
|
||||||
}
|
}
|
||||||
#endif
|
#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
|
NzBufferImpl* NzBuffer::GetImpl() const
|
||||||
|
|
|
||||||
|
|
@ -44,8 +44,10 @@ void NzSoftwareBuffer::Destroy()
|
||||||
delete[] m_buffer;
|
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 NAZARA_UTILITY_SAFE
|
||||||
if (m_mapped)
|
if (m_mapped)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -19,7 +19,7 @@ class NzSoftwareBuffer : public NzBufferImpl
|
||||||
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
|
bool Create(unsigned int size, nzBufferUsage usage = nzBufferUsage_Static);
|
||||||
void Destroy();
|
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();
|
void* GetPointer();
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue