Utility/Buffer: Refactor Buffer classes

This commit is contained in:
Lynix
2016-12-09 08:56:46 +01:00
parent e66e0dfdce
commit d62720d610
29 changed files with 461 additions and 677 deletions

View File

@@ -7,6 +7,7 @@
#include <Nazara/Core/Error.hpp>
#include <Nazara/Renderer/Context.hpp>
#include <Nazara/Renderer/OpenGL.hpp>
#include <Nazara/Utility/Buffer.hpp>
#include <cstring>
#include <stdexcept>
#include <Nazara/Renderer/Debug.hpp>
@@ -14,14 +15,23 @@
namespace Nz
{
HardwareBuffer::HardwareBuffer(Buffer* parent, BufferType type) :
m_buffer(0),
m_type(type),
m_parent(parent)
{
}
HardwareBuffer::~HardwareBuffer() = default;
HardwareBuffer::~HardwareBuffer()
{
if (m_buffer)
{
Context::EnsureContext();
bool HardwareBuffer::Create(unsigned int size, BufferUsage usage)
OpenGL::DeleteBuffer(m_type, m_buffer);
}
}
bool HardwareBuffer::Initialize(UInt32 size, BufferUsageFlags usage)
{
Context::EnsureContext();
@@ -29,37 +39,28 @@ namespace Nz
glGenBuffers(1, &m_buffer);
OpenGL::BindBuffer(m_type, m_buffer);
glBufferData(OpenGL::BufferTarget[m_type], size, nullptr, OpenGL::BufferUsage[usage]);
glBufferData(OpenGL::BufferTarget[m_type], size, nullptr, (usage & BufferUsage_Dynamic) ? GL_STREAM_DRAW : GL_STATIC_DRAW);
return true;
}
void HardwareBuffer::Destroy()
bool HardwareBuffer::Fill(const void* data, UInt32 offset, UInt32 size)
{
Context::EnsureContext();
OpenGL::DeleteBuffer(m_type, m_buffer);
}
UInt32 totalSize = m_parent->GetSize();
bool HardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard)
{
Context::EnsureContext();
unsigned int totalSize = m_parent->GetSize();
if (!forceDiscard)
forceDiscard = (size == totalSize);
bool forceDiscard = (size == totalSize);
OpenGL::BindBuffer(m_type, m_buffer);
// Il semblerait que glBuffer(Sub)Data soit plus performant que glMapBuffer(Range) en dessous d'un certain seuil
// It seems glBuffer(Sub)Data performs faster than glMapBuffer under a specific range
// http://www.stevestreeting.com/2007/03/17/glmapbuffer-vs-glbuffersubdata-the-return/
if (size < 32*1024)
{
// http://www.opengl.org/wiki/Buffer_Object_Streaming
if (forceDiscard)
glBufferData(OpenGL::BufferTarget[m_type], totalSize, nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
glBufferData(OpenGL::BufferTarget[m_type], totalSize, nullptr, (m_parent->GetUsage() & BufferUsage_Dynamic) ? GL_STREAM_DRAW : GL_STATIC_DRAW); // Discard
glBufferSubData(OpenGL::BufferTarget[m_type], offset, size, data);
}
@@ -80,12 +81,12 @@ namespace Nz
return true;
}
bool HardwareBuffer::IsHardware() const
DataStorage HardwareBuffer::GetStorage() const
{
return true;
return DataStorage_Hardware;
}
void* HardwareBuffer::Map(BufferAccess access, unsigned int offset, unsigned int size)
void* HardwareBuffer::Map(BufferAccess access, UInt32 offset, UInt32 size)
{
Context::EnsureContext();
@@ -97,7 +98,7 @@ namespace Nz
{
// http://www.opengl.org/wiki/Buffer_Object_Streaming
if (access == BufferAccess_DiscardAndWrite)
glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]); // Discard
glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, (m_parent->GetUsage() & BufferUsage_Dynamic) ? GL_STREAM_DRAW : GL_STATIC_DRAW); // Discard
UInt8* ptr = static_cast<UInt8*>(glMapBuffer(OpenGL::BufferTarget[m_type], OpenGL::BufferLock[access]));
if (ptr)
@@ -115,10 +116,10 @@ namespace Nz
if (glUnmapBuffer(OpenGL::BufferTarget[m_type]) != GL_TRUE)
{
glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, OpenGL::BufferUsage[m_parent->GetUsage()]);
// An error occured, we have to reset the buffer
glBufferData(OpenGL::BufferTarget[m_type], m_parent->GetSize(), nullptr, (m_parent->GetUsage() & BufferUsage_Dynamic) ? GL_STREAM_DRAW : GL_STATIC_DRAW);
// Une erreur rare est survenue, nous devons réinitialiser le buffer
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error : 0x" + String::Number(glGetError(), 16) + ')');
NazaraError("Failed to unmap buffer, reinitialising content... (OpenGL error: 0x" + String::Number(glGetError(), 16) + ')');
return false;
}
@@ -130,8 +131,8 @@ namespace Nz
OpenGL::BindBuffer(m_type, m_buffer);
}
unsigned int HardwareBuffer::GetOpenGLID() const
GLuint HardwareBuffer::GetOpenGLID() const
{
return m_buffer;
}
}
}

View File

@@ -13,25 +13,26 @@
namespace Nz
{
class Buffer;
class HardwareBuffer : public AbstractBuffer
{
public:
HardwareBuffer(Buffer* parent, BufferType type);
~HardwareBuffer();
bool Create(unsigned int size, BufferUsage usage = BufferUsage_Static);
void Destroy();
bool Fill(const void* data, UInt32 offset, UInt32 size) override;
bool Fill(const void* data, unsigned int offset, unsigned int size, bool forceDiscard);
bool Initialize(unsigned int size, BufferUsageFlags usage) override;
bool IsHardware() const;
DataStorage GetStorage() const override;
void* Map(BufferAccess access, unsigned int offset = 0, unsigned int size = 0);
bool Unmap();
void* Map(BufferAccess access, UInt32 offset = 0, UInt32 size = 0) override;
bool Unmap() override;
// Fonctions OpenGL
void Bind() const;
unsigned int GetOpenGLID() const;
GLuint GetOpenGLID() const;
private:
GLuint m_buffer;

View File

@@ -1906,16 +1906,6 @@ namespace Nz
static_assert(BufferType_Max + 1 == 2, "Buffer target binding array is incomplete");
GLenum OpenGL::BufferUsage[] =
{
// D'après la documentation, GL_STREAM_DRAW semble être plus adapté à notre cas (ratio modification/rendu 1:2-3)
// Source: http://www.opengl.org/sdk/docs/man/html/glBufferData.xhtml
GL_STREAM_DRAW, // BufferUsage_Dynamic
GL_STATIC_DRAW // BufferUsage_Static
};
static_assert(BufferUsage_Max + 1 == 2, "Buffer usage array is incomplete");
GLenum OpenGL::ComponentType[] =
{
GL_UNSIGNED_BYTE, // ComponentType_Color

View File

@@ -656,7 +656,7 @@ namespace Nz
s_updateFlags = Update_Matrices | Update_Shader | Update_VAO;
s_vertexBuffer = nullptr;
s_fullscreenQuadBuffer.Reset(VertexDeclaration::Get(VertexLayout_XY_UV), 4, DataStorage_Hardware, BufferUsage_Static);
s_fullscreenQuadBuffer.Reset(VertexDeclaration::Get(VertexLayout_XY_UV), 4, DataStorage_Hardware, 0);
float vertices[4 * 2 * 2] =
{
@@ -939,14 +939,6 @@ namespace Nz
void Renderer::SetIndexBuffer(const IndexBuffer* indexBuffer)
{
#if NAZARA_RENDERER_SAFE
if (indexBuffer && !indexBuffer->IsHardware())
{
NazaraError("Buffer must be hardware");
return;
}
#endif
if (s_indexBuffer != indexBuffer)
{
s_indexBuffer = indexBuffer;
@@ -1349,15 +1341,7 @@ namespace Nz
void Renderer::SetVertexBuffer(const VertexBuffer* vertexBuffer)
{
#if NAZARA_RENDERER_SAFE
if (vertexBuffer && !vertexBuffer->IsHardware())
{
NazaraError("Buffer must be hardware");
return;
}
#endif
if (vertexBuffer && s_vertexBuffer != vertexBuffer)
if (s_vertexBuffer != vertexBuffer)
{
s_vertexBuffer = vertexBuffer;
s_updateFlags |= Update_VAO;
@@ -1540,13 +1524,17 @@ namespace Nz
if (s_updateFlags & Update_VAO)
{
#if NAZARA_RENDERER_SAFE
if (!s_vertexBuffer)
if (!s_vertexBuffer || !s_vertexBuffer->IsValid())
{
NazaraError("No vertex buffer");
NazaraError("Invalid vertex buffer");
return false;
}
if (s_vertexBuffer->GetBuffer()->GetStorage() != DataStorage_Hardware)
{
NazaraError("Vertex buffer storage is not hardware");
return false;
}
#endif
// Note: Les VAOs ne sont pas partagés entre les contextes, nous avons donc un tableau de VAOs par contexte
const Context* context = Context::GetCurrent();
@@ -1712,6 +1700,18 @@ namespace Nz
// Et on active l'index buffer (Un seul index buffer par VAO)
if (s_indexBuffer)
{
if (!s_indexBuffer->IsValid())
{
NazaraError("Invalid index buffer");
return false;
}
if (s_vertexBuffer->GetBuffer()->GetStorage() != DataStorage_Hardware)
{
NazaraError("Index buffer storage is not hardware");
return false;
}
HardwareBuffer* indexBufferImpl = static_cast<HardwareBuffer*>(s_indexBuffer->GetBuffer()->GetImpl());
glBindBuffer(OpenGL::BufferTarget[BufferType_Index], indexBufferImpl->GetOpenGLID());
}