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); @@ -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; @@ -168,26 +168,18 @@ // 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 (Iter 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); } @@ -232,8 +224,12 @@ pglBindBufferARB(m_Target, m_Handle); + if (UseStreaming(m_Usage)) { + if (!m_HasNeededChunks) + return static_cast(0); + // 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 +290,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;