diff --git a/include/Nazara/Utility/Buffer.hpp b/include/Nazara/Utility/Buffer.hpp index b07d022a9..8cdc0b5ac 100644 --- a/include/Nazara/Utility/Buffer.hpp +++ b/include/Nazara/Utility/Buffer.hpp @@ -76,6 +76,9 @@ class NAZARA_API NzBuffer : public NzResource, NzNonCopyable bool IsValid() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + + bool SetStorage(nzBufferStorage storage); + bool Unmap(); static bool IsSupported(nzBufferStorage storage); diff --git a/include/Nazara/Utility/IndexBuffer.hpp b/include/Nazara/Utility/IndexBuffer.hpp index bfcfe0133..80d6eeb23 100644 --- a/include/Nazara/Utility/IndexBuffer.hpp +++ b/include/Nazara/Utility/IndexBuffer.hpp @@ -31,6 +31,9 @@ class NAZARA_API NzIndexBuffer bool IsSequential() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + + bool SetStorage(nzBufferStorage storage); + bool Unmap(); private: diff --git a/include/Nazara/Utility/VertexBuffer.hpp b/include/Nazara/Utility/VertexBuffer.hpp index 30deaf5a7..d5f1acc68 100644 --- a/include/Nazara/Utility/VertexBuffer.hpp +++ b/include/Nazara/Utility/VertexBuffer.hpp @@ -30,6 +30,9 @@ class NAZARA_API NzVertexBuffer bool IsHardware() const; void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + + bool SetStorage(nzBufferStorage storage); + bool Unmap(); private: diff --git a/src/Nazara/Renderer/HardwareBuffer.cpp b/src/Nazara/Renderer/HardwareBuffer.cpp index ddb98776b..03cf4ae11 100644 --- a/src/Nazara/Renderer/HardwareBuffer.cpp +++ b/src/Nazara/Renderer/HardwareBuffer.cpp @@ -52,14 +52,14 @@ namespace if (access == nzBufferAccess_DiscardAndWrite) { - GLint size; - glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &size); + GLint bufferSize; + glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_SIZE, &bufferSize); - GLint usage; - glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &usage); + GLint bufferUsage; + glGetBufferParameteriv(bufferTargetBinding[type], GL_BUFFER_USAGE, &bufferUsage); // On discard le buffer - glBufferData(bufferTargetBinding[type], size, nullptr, usage); + glBufferData(bufferTargetBinding[type], bufferSize, nullptr, bufferUsage); } void* ptr = glMapBuffer(bufferTarget[type], bufferLock[access]); @@ -154,8 +154,8 @@ bool NzHardwareBuffer::Fill(const void* data, unsigned int offset, unsigned int if (size < 32*1024) { // http://www.opengl.org/wiki/Vertex_Specification_Best_Practices - if (size == m_parent->GetLength()) - glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetStorage()]); // Discard + if (size == m_parent->GetSize()) + glBufferData(bufferTarget[m_type], m_parent->GetSize(), nullptr, bufferUsage[m_parent->GetUsage()]); // Discard glBufferSubData(bufferTarget[m_type], offset, size, data); } @@ -198,7 +198,7 @@ bool NzHardwareBuffer::IsHardware() const return true; } -void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int length) +void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int size) { NzContext::EnsureContext(); @@ -209,7 +209,7 @@ void* NzHardwareBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned if (previous != m_buffer) glBindBuffer(bufferTarget[m_type], m_buffer); - void* ptr = mapBuffer(m_type, access, offset, length); + 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) if (previous != m_buffer && previous != 0) diff --git a/src/Nazara/Renderer/HardwareBuffer.hpp b/src/Nazara/Renderer/HardwareBuffer.hpp index 7834fe9fe..c2451adc2 100644 --- a/src/Nazara/Renderer/HardwareBuffer.hpp +++ b/src/Nazara/Renderer/HardwareBuffer.hpp @@ -22,13 +22,13 @@ 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 length); + bool Fill(const void* data, unsigned int offset, unsigned int size); void* GetPointer(); bool IsHardware() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); bool Unmap(); private: diff --git a/src/Nazara/Renderer/Renderer.cpp b/src/Nazara/Renderer/Renderer.cpp index 5bfcf65f5..6f764ed1e 100644 --- a/src/Nazara/Renderer/Renderer.cpp +++ b/src/Nazara/Renderer/Renderer.cpp @@ -203,29 +203,34 @@ void NzRenderer::DrawIndexedPrimitives(nzPrimitiveType primitive, unsigned int f return; } - nzUInt8 indexSize = m_indexBuffer->GetIndexSize(); - - GLenum type; - switch (indexSize) + if (m_indexBuffer->IsSequential()) + glDrawArrays(openglPrimitive[primitive], m_indexBuffer->GetStartIndex(), m_indexBuffer->GetIndexCount()); + else { - case 1: - type = GL_UNSIGNED_BYTE; - break; + nzUInt8 indexSize = m_indexBuffer->GetIndexSize(); - case 2: - type = GL_UNSIGNED_SHORT; - break; + GLenum type; + switch (indexSize) + { + case 1: + type = GL_UNSIGNED_BYTE; + break; - case 4: - type = GL_UNSIGNED_INT; - break; + case 2: + type = GL_UNSIGNED_SHORT; + break; - default: - NazaraError("Invalid index size (" + NzString::Number(indexSize) + ')'); - return; + 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->GetPointer()) + firstIndex*indexSize); } - - glDrawElements(openglPrimitive[primitive], indexCount, type, reinterpret_cast(m_indexBuffer->GetPointer()) + firstIndex*indexSize); } void NzRenderer::DrawPrimitives(nzPrimitiveType primitive, unsigned int firstVertex, unsigned int vertexCount) @@ -507,7 +512,7 @@ void NzRenderer::SetFaceFilling(nzFaceFilling fillingMode) bool NzRenderer::SetIndexBuffer(const NzIndexBuffer* indexBuffer) { #if NAZARA_RENDERER_SAFE - if (indexBuffer && !indexBuffer->IsHardware()) + if (indexBuffer && !indexBuffer->IsHardware() && !indexBuffer->IsSequential()) { NazaraError("Buffer must be hardware"); return false; @@ -551,8 +556,6 @@ bool NzRenderer::SetShader(NzShader* shader) return false; } } - else - m_shader = nullptr; m_shader = shader; diff --git a/src/Nazara/Utility/Buffer.cpp b/src/Nazara/Utility/Buffer.cpp index 54d16bada..0f35946aa 100644 --- a/src/Nazara/Utility/Buffer.cpp +++ b/src/Nazara/Utility/Buffer.cpp @@ -110,6 +110,7 @@ bool NzBuffer::Create(unsigned int length, nzUInt8 typeSize, nzBufferStorage sto m_length = length; m_typeSize = typeSize; + m_storage = storage; m_usage = usage; // Si on arrive ici c'est que tout s'est bien passé. @@ -142,7 +143,7 @@ bool NzBuffer::Fill(const void* data, unsigned int offset, unsigned int length) } #endif - return m_impl->Fill(data, offset*m_typeSize, length*m_typeSize); + return m_impl->Fill(data, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); } NzBufferImpl* NzBuffer::GetImpl() const @@ -232,7 +233,69 @@ void* NzBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned int len } #endif - return m_impl->Map(access, offset*m_typeSize, length*m_typeSize); + return m_impl->Map(access, offset*m_typeSize, ((length == 0) ? m_length-offset : length)*m_typeSize); +} + +bool NzBuffer::SetStorage(nzBufferStorage storage) +{ + #if NAZARA_UTILITY_SAFE + if (!m_impl) + { + NazaraError("Buffer not valid"); + return false; + } + #endif + + if (m_storage == storage) + return true; + + #if NAZARA_UTILITY_SAFE + if (!IsSupported(storage)) + { + NazaraError("Storage not supported"); + return false; + } + #endif + + void* ptr = m_impl->Map(nzBufferAccess_ReadOnly, 0, m_length*m_typeSize); + if (!ptr) + { + NazaraError("Failed to map buffer"); + return false; + } + + NzBufferImpl* impl = s_bufferFunctions[storage](this, m_type); + if (!impl->Create(m_length*m_typeSize, m_usage)) + { + NazaraError("Failed to create buffer"); + delete impl; + + if (!m_impl->Unmap()) + NazaraWarning("Failed to unmap buffer"); + + return false; + } + + if (!impl->Fill(ptr, 0, m_length*m_typeSize)) + { + NazaraError("Failed to fill buffer"); + impl->Destroy(); + delete impl; + + if (!m_impl->Unmap()) + NazaraWarning("Failed to unmap buffer"); + + return false; + } + + m_impl->Unmap(); + m_impl->Destroy(); + delete m_impl; + + m_impl = impl; + m_storage = storage; + + return true; } bool NzBuffer::Unmap() diff --git a/src/Nazara/Utility/IndexBuffer.cpp b/src/Nazara/Utility/IndexBuffer.cpp index 9ed69c525..b4792b096 100644 --- a/src/Nazara/Utility/IndexBuffer.cpp +++ b/src/Nazara/Utility/IndexBuffer.cpp @@ -87,7 +87,7 @@ bool NzIndexBuffer::Fill(const void* data, unsigned int offset, unsigned int len #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Impossible to fill sequential buffer"); + NazaraError("Impossible to fill sequential buffers"); return false; } @@ -111,7 +111,7 @@ nzUInt8 NzIndexBuffer::GetIndexSize() const #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Sequential index buffer has no index size"); + NazaraError("Sequential buffers have no index size"); return 0; } #endif @@ -124,7 +124,7 @@ void* NzIndexBuffer::GetPointer() #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Sequential index buffer: Buffer has no pointer"); + NazaraError("Sequential buffers have no pointer"); return nullptr; } #endif @@ -137,7 +137,7 @@ const void* NzIndexBuffer::GetPointer() const #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Sequential index buffer has no pointer"); + NazaraError("Sequential buffers have no pointer"); return nullptr; } #endif @@ -178,7 +178,7 @@ void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned in #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Impossible to map sequential index buffer"); + NazaraError("Impossible to map sequential buffers"); return nullptr; } @@ -192,12 +192,25 @@ void* NzIndexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned in return m_buffer->Map(access, m_startIndex+offset, (length) ? length : m_indexCount-offset); } +bool NzIndexBuffer::SetStorage(nzBufferStorage storage) +{ + #if NAZARA_UTILITY_SAFE + if (!m_buffer) + { + NazaraWarning("Sequential buffers have no storage"); + return true; + } + #endif + + return m_buffer->SetStorage(storage); +} + bool NzIndexBuffer::Unmap() { #if NAZARA_UTILITY_SAFE if (!m_buffer) { - NazaraError("Impossible to unlock sequential index buffer"); + NazaraError("Impossible to unlock sequential buffers"); return false; } #endif diff --git a/src/Nazara/Utility/SoftwareBuffer.hpp b/src/Nazara/Utility/SoftwareBuffer.hpp index 56f5be074..8df91b919 100644 --- a/src/Nazara/Utility/SoftwareBuffer.hpp +++ b/src/Nazara/Utility/SoftwareBuffer.hpp @@ -19,13 +19,13 @@ 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 length); + bool Fill(const void* data, unsigned int offset, unsigned int size); void* GetPointer(); bool IsHardware() const; - void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int length = 0); + void* Map(nzBufferAccess access, unsigned int offset = 0, unsigned int size = 0); bool Unmap(); private: diff --git a/src/Nazara/Utility/VertexBuffer.cpp b/src/Nazara/Utility/VertexBuffer.cpp index 46758303e..5242afe14 100644 --- a/src/Nazara/Utility/VertexBuffer.cpp +++ b/src/Nazara/Utility/VertexBuffer.cpp @@ -120,6 +120,11 @@ void* NzVertexBuffer::Map(nzBufferAccess access, unsigned int offset, unsigned i return m_buffer->Map(access, m_startVertex+offset, (length) ? length : m_vertexCount-offset); } +bool NzVertexBuffer::SetStorage(nzBufferStorage storage) +{ + return m_buffer->SetStorage(storage); +} + bool NzVertexBuffer::Unmap() { return m_buffer->Unmap();