Index: binaries/data/mods/public/gui/credits/texts/programming.json =================================================================== --- binaries/data/mods/public/gui/credits/texts/programming.json +++ binaries/data/mods/public/gui/credits/texts/programming.json @@ -64,6 +64,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" }, Index: source/renderer/VertexBuffer.h =================================================================== --- source/renderer/VertexBuffer.h +++ source/renderer/VertexBuffer.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -102,7 +102,11 @@ 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) + { + chunk->m_Needed = true; + m_HasNeededChunks = true; + } /// Update vertex data for given chunk. Transfers the provided data to the actual OpenGL vertex buffer. void UpdateChunkVertices(VBChunk* chunk, void* data); @@ -145,9 +149,9 @@ /// 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::deque m_FreeList; /// List of allocated chunks - std::list m_AllocList; + std::deque 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 +162,7 @@ GLenum m_Usage; /// Buffer target (GL_ARRAY_BUFFER, GL_ELEMENT_ARRAY_BUFFER) GLenum m_Target; + bool m_HasNeededChunks; }; #endif Index: source/renderer/VertexBuffer.cpp =================================================================== --- source/renderer/VertexBuffer.cpp +++ source/renderer/VertexBuffer.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2016 Wildfire Games. +/* Copyright (C) 2020 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -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; @@ -81,8 +81,7 @@ delete[] m_SysMem; - typedef std::list::iterator Iter; - for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) + for (std::deque::iterator iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) delete *iter; } @@ -113,24 +112,27 @@ 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::deque::iterator best_iter = m_FreeList.end(); + for (std::deque::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) { + if (best_iter == m_FreeList.end() || (*best_iter)->m_Count < (*iter)->m_Count) + best_iter = iter; + } } - if (!chunk) { + if (best_iter == m_FreeList.end()) { // no big enough spare chunk available return 0; } + VBChunk* chunk = *best_iter; + m_FreeList.erase(best_iter); + m_FreeVertices -= chunk->m_Count; + chunk->m_BackingStore = backingStore; chunk->m_Dirty = false; chunk->m_Needed = false; @@ -162,32 +164,22 @@ // Update total free count before potentially modifying this chunk's count m_FreeVertices += chunk->m_Count; - m_AllocList.remove(chunk); - - typedef std::list::iterator Iter; + m_AllocList.erase(std::find(m_AllocList.begin(), m_AllocList.end(), chunk)); // 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 - // from the list, and repeat until no more are found - bool coalesced; - do + // from the list + for (std::deque::iterator iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) { - coalesced = false; - for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) + if ((*iter)->m_Index == chunk->m_Index + chunk->m_Count + || (*iter)->m_Index + (*iter)->m_Count == chunk->m_Index) { - if ((*iter)->m_Index == chunk->m_Index + chunk->m_Count - || (*iter)->m_Index + (*iter)->m_Count == chunk->m_Index) - { - chunk->m_Index = std::min(chunk->m_Index, (*iter)->m_Index); - chunk->m_Count += (*iter)->m_Count; - delete *iter; - m_FreeList.erase(iter); - coalesced = true; - break; - } + chunk->m_Index = std::min(chunk->m_Index, (*iter)->m_Index); + chunk->m_Count += (*iter)->m_Count; + delete *iter; + iter = std::prev(m_FreeList.erase(iter)); } } - while (coalesced); m_FreeList.push_front(chunk); } @@ -234,6 +226,9 @@ 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 +289,20 @@ 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; @@ -340,8 +340,7 @@ debug_printf("freeverts = %d\n", (int)m_FreeVertices); size_t maxSize = 0; - typedef std::list::iterator Iter; - for (Iter iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) + for (std::deque::iterator iter = m_FreeList.begin(); iter != m_FreeList.end(); ++iter) { debug_printf("free chunk %p: size=%d\n", (void *)*iter, (int)((*iter)->m_Count)); maxSize = std::max((*iter)->m_Count, maxSize);