From 3f394aa5df7a66e3d7cd14a1ba2d24cac6c9cdd2 Mon Sep 17 00:00:00 2001 From: baldurk Date: Wed, 25 Nov 2020 16:56:16 +0000 Subject: [PATCH] Handle multiple pages in a row being too full * When resetting pagesets in a granular fashion from the chunk allocator, it's possible to almost (or completely) exhaust a page but not have it be bumped out of the free list, then one more new full free pages is pushed. When that free page is exhausted we'll retire it then assume the next one is usable - but it is still not valid. We need to loop until we find a page with enough space. --- renderdoc/serialise/serialiser.cpp | 21 +++++++++++---------- renderdoc/serialise/serialiser.h | 8 ++++++-- 2 files changed, 17 insertions(+), 12 deletions(-) diff --git a/renderdoc/serialise/serialiser.cpp b/renderdoc/serialise/serialiser.cpp index c541a5e92..a89eaecaf 100644 --- a/renderdoc/serialise/serialiser.cpp +++ b/renderdoc/serialise/serialiser.cpp @@ -1142,18 +1142,19 @@ byte *ChunkAllocator::AllocateFromPages(bool chunkAlloc, size_t size) if(size > BufferPageSize) return NULL; - if(!freePages.empty()) + while(!freePages.empty()) { - // if the last free page can't satisfy this allocation, retire it to the full list - if((chunkAlloc && GetRemainingChunkBytes(freePages.back()) < size) || - (!chunkAlloc && GetRemainingBufferBytes(freePages.back()) < size)) - { - // mark this page as used in the current set - usedPages.push_back(freePages.back().ID); + // if the last free page can satisfy this allocation, stop iterating as we'll use it. + if(GetRemainingBytes(chunkAlloc, freePages.back()) >= size) + break; - fullPages.push_back(freePages.back()); - freePages.pop_back(); - } + // otherwise the last page doesn't have enough free, so remove it from the free list + + // mark this page as used in the current set + usedPages.push_back(freePages.back().ID); + + fullPages.push_back(freePages.back()); + freePages.pop_back(); } // if there are no free pages, allocate a new one diff --git a/renderdoc/serialise/serialiser.h b/renderdoc/serialise/serialiser.h index 3776eb47c..a64bb95d0 100644 --- a/renderdoc/serialise/serialiser.h +++ b/renderdoc/serialise/serialiser.h @@ -1585,14 +1585,18 @@ private: // includes it there rdcarray usedPages; - size_t GetRemainingBufferBytes(const Page &p) + inline size_t GetRemainingBufferBytes(const Page &p) { return BufferPageSize - (p.bufferHead - p.bufferBase); } - size_t GetRemainingChunkBytes(const Page &p) + inline size_t GetRemainingChunkBytes(const Page &p) { return ChunkPageSize - (p.chunkHead - p.chunkBase); } + inline size_t GetRemainingBytes(bool chunkAlloc, const Page &p) + { + return chunkAlloc ? GetRemainingChunkBytes(p) : GetRemainingBufferBytes(p); + } byte *AllocateFromPages(bool chunkAlloc, size_t size); };