From e02aece40ad55a16bb9c7024ef736af0fcdf09a1 Mon Sep 17 00:00:00 2001 From: Magnus Norddahl Date: Sun, 15 Jan 2017 21:45:21 +0100 Subject: [PATCH] Added a generic memory allocator for memory needed for a frame --- src/swrenderer/plane/r_visibleplane.cpp | 5 +-- src/swrenderer/r_memory.cpp | 48 +++++++++++++++++-------- src/swrenderer/r_memory.h | 44 +++++++++++++++++++++-- src/swrenderer/scene/r_scene.cpp | 3 +- 4 files changed, 78 insertions(+), 22 deletions(-) diff --git a/src/swrenderer/plane/r_visibleplane.cpp b/src/swrenderer/plane/r_visibleplane.cpp index fbb1e37a0..a1928bbb8 100644 --- a/src/swrenderer/plane/r_visibleplane.cpp +++ b/src/swrenderer/plane/r_visibleplane.cpp @@ -65,10 +65,7 @@ namespace swrenderer } if (!found) { - visplane_light *newlight = R_NewPlaneLight(); - if (!newlight) - return; - + visplane_light *newlight = RenderMemory::NewObject(); newlight->next = lights; newlight->lightsource = node->lightsource; lights = newlight; diff --git a/src/swrenderer/r_memory.cpp b/src/swrenderer/r_memory.cpp index 0893f6936..b4faa44cd 100644 --- a/src/swrenderer/r_memory.cpp +++ b/src/swrenderer/r_memory.cpp @@ -72,23 +72,43 @@ namespace swrenderer } ///////////////////////////////////////////////////////////////////////// - - namespace + + void *RenderMemory::AllocBytes(int size) { - enum { max_plane_lights = 32 * 1024 }; - visplane_light plane_lights[max_plane_lights]; - int next_plane_light = 0; - } + size = (size + 15) / 16 * 16; // 16-byte align + + if (UsedBlocks.empty() || UsedBlocks.back()->Position + size > BlockSize) + { + if (!FreeBlocks.empty()) + { + auto block = std::move(FreeBlocks.back()); + block->Position = 0; + FreeBlocks.pop_back(); + UsedBlocks.push_back(std::move(block)); + } + else + { + UsedBlocks.push_back(std::make_unique()); + } + } + + auto &block = UsedBlocks.back(); + void *data = block->Data + block->Position; + block->Position += size; - visplane_light *R_NewPlaneLight() - { - if (next_plane_light == max_plane_lights) - return nullptr; - return &plane_lights[next_plane_light++]; + return data; } - - void R_FreePlaneLights() + + void RenderMemory::Clear() { - next_plane_light = 0; + while (!UsedBlocks.empty()) + { + auto block = std::move(UsedBlocks.back()); + UsedBlocks.pop_back(); + FreeBlocks.push_back(std::move(block)); + } } + + std::vector> RenderMemory::UsedBlocks; + std::vector> RenderMemory::FreeBlocks; } diff --git a/src/swrenderer/r_memory.h b/src/swrenderer/r_memory.h index 7914cdfcf..0bf86f2cd 100644 --- a/src/swrenderer/r_memory.h +++ b/src/swrenderer/r_memory.h @@ -13,6 +13,8 @@ #pragma once +#include + namespace swrenderer { struct visplane_light; @@ -22,7 +24,43 @@ namespace swrenderer ptrdiff_t R_NewOpening(ptrdiff_t len); void R_FreeOpenings(); void R_DeinitOpenings(); - - visplane_light *R_NewPlaneLight(); - void R_FreePlaneLights(); + + // Memory needed for the duration of a frame rendering + class RenderMemory + { + public: + static void Clear(); + + template + static T *AllocMemory(int size = 1) + { + return (T*)AllocBytes(sizeof(T) * size); + } + + template + static T *NewObject(Types &&... args) + { + void *ptr = AllocBytes(sizeof(T)); + return new (ptr)T(std::forward(args)...); + } + + private: + static void *AllocBytes(int size); + + enum { BlockSize = 1024 * 1024 }; + + struct MemoryBlock + { + MemoryBlock() : Data(new uint8_t[BlockSize]), Position(0) { } + ~MemoryBlock() { delete[] Data; } + + MemoryBlock(const MemoryBlock &) = delete; + MemoryBlock &operator=(const MemoryBlock &) = delete; + + uint8_t *Data; + uint32_t Position; + }; + static std::vector> UsedBlocks; + static std::vector> FreeBlocks; + }; } diff --git a/src/swrenderer/scene/r_scene.cpp b/src/swrenderer/scene/r_scene.cpp index f2f56b833..71740aefc 100644 --- a/src/swrenderer/scene/r_scene.cpp +++ b/src/swrenderer/scene/r_scene.cpp @@ -117,6 +117,8 @@ namespace swrenderer PlaneCycles.Reset(); MaskedCycles.Reset(); WallScanCycles.Reset(); + + RenderMemory::Clear(); Clip3DFloors *clip3d = Clip3DFloors::Instance(); clip3d->Cleanup(); @@ -132,7 +134,6 @@ namespace swrenderer R_ClearClipSegs(0, viewwidth); R_ClearDrawSegs(); VisiblePlaneList::Instance()->Clear(true); - R_FreePlaneLights(); RenderTranslucentPass::Clear(); // opening / clipping determination