diff --git a/binaries/data/mods/public/gui/credits/texts/programming.json b/binaries/data/mods/public/gui/credits/texts/programming.json
index a5a02106b0..b3e101c038 100644
--- a/binaries/data/mods/public/gui/credits/texts/programming.json
+++ b/binaries/data/mods/public/gui/credits/texts/programming.json
@@ -66,6 +66,7 @@
{ "name": "Daniel Trevitz" },
{ "nick": "Dariost", "name": "Dario Ostuni" },
{ "nick": "Dave", "name": "David Protasowski" },
+ { "name": "David Marshall" },
{ "nick": "dax", "name": "Dacian Fiordean" },
{ "nick": "deebee", "name": "Deepak Anthony" },
{ "nick": "Deiz" },
diff --git a/source/renderer/VertexBuffer.cpp b/source/renderer/VertexBuffer.cpp
index 2d190e0bb6..a44e7740a1 100644
--- a/source/renderer/VertexBuffer.cpp
+++ b/source/renderer/VertexBuffer.cpp
@@ -1,4 +1,4 @@
-/* Copyright (C) 2016 Wildfire Games.
+/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -15,18 +15,18 @@
* along with 0 A.D. If not, see .
*/
-/*
- * encapsulation of VBOs with sharing
- */
-
#include "precompiled.h"
-#include "ps/Errors.h"
+
+#include "VertexBuffer.h"
+
#include "lib/ogl.h"
#include "lib/sysdep/cpu.h"
#include "Renderer.h"
-#include "VertexBuffer.h"
-#include "VertexBufferManager.h"
#include "ps/CLogger.h"
+#include "ps/Errors.h"
+
+#include
+#include
// Absolute maximum (bytewise) size of each GL vertex buffer object.
// Make it large enough for the maximum feasible mesh size (64K vertexes,
@@ -35,7 +35,7 @@
#define MAX_VB_SIZE_BYTES (4*1024*1024)
CVertexBuffer::CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target)
- : m_VertexSize(vertexSize), m_Handle(0), m_SysMem(0), m_Usage(usage), m_Target(target)
+ : m_VertexSize(vertexSize), m_Handle(0), m_SysMem(0), m_Usage(usage), m_Target(target), m_HasNeededChunks(false)
{
size_t size = MAX_VB_SIZE_BYTES;
@@ -68,7 +68,7 @@ CVertexBuffer::CVertexBuffer(size_t vertexSize, GLenum usage, GLenum target)
chunk->m_Owner = this;
chunk->m_Count = m_FreeVertices;
chunk->m_Index = 0;
- m_FreeList.push_front(chunk);
+ m_FreeList.emplace_back(chunk);
}
CVertexBuffer::~CVertexBuffer()
@@ -79,20 +79,16 @@ CVertexBuffer::~CVertexBuffer()
if (m_Handle)
pglDeleteBuffersARB(1, &m_Handle);
- delete[] m_SysMem;
+ SAFE_ARRAY_DELETE(m_SysMem);
- typedef std::list::iterator Iter;
- for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter)
- delete *iter;
+ for (VBChunk* const& chunk : m_FreeList)
+ delete chunk;
}
bool CVertexBuffer::CompatibleVertexType(size_t vertexSize, GLenum usage, GLenum target)
{
- if (usage != m_Usage || target != m_Target || vertexSize != m_VertexSize)
- return false;
-
- return true;
+ return usage == m_Usage && target == m_Target && vertexSize == m_VertexSize;
}
///////////////////////////////////////////////////////////////////////////////
@@ -113,23 +109,25 @@ CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize, size_t numVer
return 0;
// trawl free list looking for first free chunk with enough space
- VBChunk* chunk = 0;
- typedef std::list::iterator Iter;
- for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) {
- if (numVertices <= (*iter)->m_Count) {
- chunk = *iter;
- // remove this chunk from the free list
- m_FreeList.erase(iter);
- m_FreeVertices -= chunk->m_Count;
- // no need to search further ..
+ std::vector::iterator best_iter = m_FreeList.end();
+ for (std::vector::iterator iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter)
+ {
+ if (numVertices == (*iter)->m_Count)
+ {
+ best_iter = iter;
break;
}
+ else if (numVertices < (*iter)->m_Count && (best_iter == m_FreeList.end() || (*best_iter)->m_Count < (*iter)->m_Count))
+ best_iter = iter;
}
- if (!chunk) {
- // no big enough spare chunk available
- return 0;
- }
+ // We could not find a large enough chunk.
+ if (best_iter == m_FreeList.end())
+ return nullptr;
+
+ VBChunk* chunk = *best_iter;
+ m_FreeList.erase(best_iter);
+ m_FreeVertices -= chunk->m_Count;
chunk->m_BackingStore = backingStore;
chunk->m_Dirty = false;
@@ -143,7 +141,7 @@ CVertexBuffer::VBChunk* CVertexBuffer::Allocate(size_t vertexSize, size_t numVer
newchunk->m_Owner = this;
newchunk->m_Count = chunk->m_Count - numVertices;
newchunk->m_Index = chunk->m_Index + numVertices;
- m_FreeList.push_front(newchunk);
+ m_FreeList.emplace_back(newchunk);
m_FreeVertices += newchunk->m_Count;
// resize given chunk
@@ -162,9 +160,9 @@ void CVertexBuffer::Release(VBChunk* chunk)
// Update total free count before potentially modifying this chunk's count
m_FreeVertices += chunk->m_Count;
- m_AllocList.remove(chunk);
+ m_AllocList.erase(std::find(m_AllocList.begin(), m_AllocList.end(), chunk));
- typedef std::list::iterator Iter;
+ typedef std::vector::iterator Iter;
// Coalesce with any free-list items that are adjacent to this chunk;
// merge the found chunk with the new one, and remove the old one
@@ -189,7 +187,7 @@ void CVertexBuffer::Release(VBChunk* chunk)
}
while (coalesced);
- m_FreeList.push_front(chunk);
+ m_FreeList.emplace_back(chunk);
}
///////////////////////////////////////////////////////////////////////////////
@@ -234,6 +232,9 @@ u8* CVertexBuffer::Bind()
if (UseStreaming(m_Usage))
{
+ if (!m_HasNeededChunks)
+ return nullptr;
+
// If any chunks are out of sync with the current VBO, and are
// needed for rendering this frame, we'll need to re-upload the VBO
bool needUpload = false;
@@ -294,15 +295,22 @@ u8* CVertexBuffer::Bind()
for (VBChunk* const& chunk : m_AllocList)
{
if (chunk->m_Needed)
+ {
chunk->m_Dirty = false;
+ chunk->m_Needed = false;
+ }
else
chunk->m_Dirty = true;
}
}
+ else
+ {
+ // Reset the flags for the next phase.
+ for (VBChunk* const& chunk : m_AllocList)
+ chunk->m_Needed = false;
+ }
- // Reset the flags for the next phase
- for (VBChunk* const& chunk : m_AllocList)
- chunk->m_Needed = false;
+ m_HasNeededChunks = false;
}
return (u8*)0;
@@ -337,19 +345,24 @@ size_t CVertexBuffer::GetBytesAllocated() const
void CVertexBuffer::DumpStatus()
{
- debug_printf("freeverts = %d\n", (int)m_FreeVertices);
+ debug_printf("freeverts = %d\n", static_cast(m_FreeVertices));
size_t maxSize = 0;
- typedef std::list::iterator Iter;
- for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter)
+ for (VBChunk* const& chunk : m_FreeList)
{
- debug_printf("free chunk %p: size=%d\n", (void *)*iter, (int)((*iter)->m_Count));
- maxSize = std::max((*iter)->m_Count, maxSize);
+ debug_printf("free chunk %p: size=%d\n", static_cast(chunk), static_cast(chunk->m_Count));
+ maxSize = std::max(chunk->m_Count, maxSize);
}
- debug_printf("max size = %d\n", (int)maxSize);
+ debug_printf("max size = %d\n", static_cast(maxSize));
}
bool CVertexBuffer::UseStreaming(GLenum usage)
{
return (usage == GL_DYNAMIC_DRAW || usage == GL_STREAM_DRAW);
}
+
+void CVertexBuffer::PrepareForRendering(VBChunk* chunk)
+{
+ chunk->m_Needed = true;
+ m_HasNeededChunks = true;
+}
diff --git a/source/renderer/VertexBuffer.h b/source/renderer/VertexBuffer.h
index 54d107bfe6..3c7990b434 100644
--- a/source/renderer/VertexBuffer.h
+++ b/source/renderer/VertexBuffer.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2015 Wildfire Games.
+/* Copyright (C) 2021 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -24,7 +24,6 @@
#include "lib/res/graphics/ogl_tex.h"
-#include
#include
/**
@@ -102,7 +101,7 @@ public:
static void Unbind();
/// Make the vertex data available for the next call to Bind()
- void PrepareForRendering(VBChunk* chunk) { chunk->m_Needed = true; }
+ void PrepareForRendering(VBChunk* chunk);
/// Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer.
void UpdateChunkVertices(VBChunk* chunk, void* data);
@@ -145,9 +144,9 @@ private:
/// Number of vertices of above size in this buffer
size_t m_MaxVertices;
/// List of free chunks in this buffer
- std::list m_FreeList;
+ std::vector m_FreeList;
/// List of allocated chunks
- std::list m_AllocList;
+ std::vector m_AllocList;
/// Available free vertices - total of all free vertices in the free list
size_t m_FreeVertices;
/// Handle to the actual GL vertex buffer object
@@ -158,6 +157,7 @@ private:
GLenum m_Usage;
/// Buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER)
GLenum m_Target;
+ bool m_HasNeededChunks;
};
#endif