diff --git a/external/imgui/imgui_user.inl b/external/imgui/imgui_user.inl index 4e495de70..5f95d8a96 100644 --- a/external/imgui/imgui_user.inl +++ b/external/imgui/imgui_user.inl @@ -905,7 +905,7 @@ namespace ImGuiEx { } // copy-pasted from imgui with alwaysautoresize flag removed - bool ImGuiEx::BeginResizableMenu(const char* label, const char* icon, bool enabled) + bool BeginResizableMenu(const char* label, const char* icon, bool enabled) { ImGuiWindow* window = GetCurrentWindow(); if (window->SkipItems) diff --git a/src/engine/allocators.cpp b/src/engine/allocators.cpp index 51a44952e..c1d5eefc0 100644 --- a/src/engine/allocators.cpp +++ b/src/engine/allocators.cpp @@ -316,14 +316,23 @@ static u32 roundUp(u32 val, u32 align) { void* LinearAllocator::allocate_aligned(size_t size, size_t align) { ASSERT(size < 0xffFFffFF); - const u32 start = roundUp(m_end, (u32)align); - if (start + size > m_commited) { - const u32 commited = roundUp(start + (u32)size, 4096); - ASSERT(commited < m_reserved); - os::memCommit(m_mem + m_commited, commited - m_commited); - m_commited = commited; + u32 start; + for (;;) { + const u32 end = m_end; + start = roundUp(end, (u32)align); + if (compareAndExchange(&m_end, u32(start + size), end)) break; } - m_end = start + (u32)size; + + if (start + size <= m_commited) return m_mem + start; + + MutexGuard guard(m_mutex); + if (start + size <= m_commited) return m_mem + start; + + const u32 commited = roundUp(start + (u32)size, 4096); + ASSERT(commited < m_reserved); + os::memCommit(m_mem + m_commited, commited - m_commited); + m_commited = commited; + return m_mem + start; } @@ -337,14 +346,18 @@ void* LinearAllocator::reallocate_aligned(void* ptr, size_t size, size_t align) void* LinearAllocator::allocate(size_t size) { ASSERT(size < 0xffFFffFF); - const u32 start = m_end; - if (start + size > m_commited) { - const u32 commited = roundUp(start + (u32)size, 4096); - ASSERT(commited < m_reserved); - os::memCommit(m_mem + m_commited, commited - m_commited); - m_commited = commited; - } - m_end = start + (u32)size; + const u32 start = atomicAdd(&m_end, (u32)size); + + if (start + size <= m_commited) return m_mem + start; + + MutexGuard guard(m_mutex); + if (start + size <= m_commited) return m_mem + start; + + const u32 commited = roundUp(start + (u32)size, 4096); + ASSERT(commited < m_reserved); + os::memCommit(m_mem + m_commited, commited - m_commited); + m_commited = commited; + return m_mem + start; } diff --git a/src/engine/allocators.h b/src/engine/allocators.h index 6962ff6d6..8a1d14ebe 100644 --- a/src/engine/allocators.h +++ b/src/engine/allocators.h @@ -41,7 +41,7 @@ private: volatile i32 m_allocation_count; }; -struct LinearAllocator : IAllocator { +struct LUMIX_ENGINE_API LinearAllocator : IAllocator { LinearAllocator(u32 reserved); ~LinearAllocator(); @@ -56,8 +56,9 @@ struct LinearAllocator : IAllocator { private: u32 m_commited; u32 m_reserved; - u32 m_end; + volatile i32 m_end; u8* m_mem; + Mutex m_mutex; }; // only single allocation, can be used by Array to allocate on stack diff --git a/src/renderer/pipeline.cpp b/src/renderer/pipeline.cpp index e8d83b4da..5a5537cbf 100644 --- a/src/renderer/pipeline.cpp +++ b/src/renderer/pipeline.cpp @@ -682,7 +682,7 @@ struct PipelineImpl final : Pipeline static_assert(sizeof(Page) == PageAllocator::PAGE_SIZE); - AutoInstancer(IAllocator& allocator, PageAllocator& page_allocator) + AutoInstancer(LinearAllocator& allocator, PageAllocator& page_allocator) : instances(allocator) , page_allocator(page_allocator) { @@ -806,7 +806,7 @@ struct PipelineImpl final : Pipeline }; struct View { - View(IAllocator& allocator, PageAllocator& page_allocator) + View(LinearAllocator& allocator, PageAllocator& page_allocator) : sorter(allocator, page_allocator) , instancers(allocator) , buckets(allocator) @@ -1459,8 +1459,8 @@ struct PipelineImpl final : Pipeline pipeline->m_renderer.endProfileBlock(); while (instanced_meshes) { InstancedMeshes* i = instanced_meshes; + i->~InstancedMeshes(); instanced_meshes = instanced_meshes->next; - LUMIX_DELETE(*allocator, i); } } @@ -2696,12 +2696,12 @@ struct PipelineImpl final : Pipeline // TODO optimize struct FillClustersJob : Renderer::RenderJob { - FillClustersJob(IAllocator& allocator) - : m_clusters(allocator) - , m_map(allocator) + FillClustersJob(LinearAllocator& current_frame_allocator, IAllocator& allocator) + : m_clusters(current_frame_allocator) + , m_map(current_frame_allocator) , m_point_lights(allocator) - , m_env_probes(allocator) - , m_refl_probes(allocator) + , m_env_probes(current_frame_allocator) + , m_refl_probes(current_frame_allocator) {} void setup() override { @@ -2772,6 +2772,7 @@ struct PipelineImpl final : Pipeline const Span scene_refl_probes = scene->getReflectionProbes(); const Span refl_probe_entities = scene->getReflectionProbesEntities(); + refl_probes.reserve(scene_refl_probes.length()); for (u32 i = 0, c = scene_refl_probes.length(); i < c; ++i) { const ReflectionProbe& refl_probe = scene_refl_probes[i]; if (!refl_probe.flags.isSet(ReflectionProbe::ENABLED)) continue; @@ -2795,6 +2796,7 @@ struct PipelineImpl final : Pipeline const Span scene_env_probes = scene->getEnvironmentProbes(); const Span env_probe_entities = scene->getEnvironmentProbesEntities(); + env_probes.reserve(scene_env_probes.length()); for (u32 i = 0, c = scene_env_probes.length(); i < c; ++i) { const EnvironmentProbe& env_probe = scene_env_probes[i]; if (!env_probe.flags.isSet(EnvironmentProbe::ENABLED)) continue; @@ -3347,7 +3349,10 @@ struct PipelineImpl final : Pipeline PROFILE_FUNCTION(); Array>& views = pipeline->m_views; UniquePtr& view = views.emplace(); - view = UniquePtr::create(pipeline->m_allocator, pipeline->m_allocator, pipeline->m_renderer.getEngine().getPageAllocator()); + LinearAllocator& allocator = pipeline->m_renderer.getCurrentFrameAllocator(); + view = UniquePtr::create(allocator + , allocator + , pipeline->m_renderer.getEngine().getPageAllocator()); view->cp = cp; if (views.size() > 1) { views[views.size() - 2]->instanced_meshes->next = view->instanced_meshes; @@ -3383,13 +3388,7 @@ struct PipelineImpl final : Pipeline view->layer_to_bucket[bucket.layer] = i; } - struct JobData { - PipelineImpl* pipeline; - u32 view_id; - IAllocator* allocator; - }; - - PrepareViewJob& job = pipeline->m_renderer.createJob(pipeline->m_allocator); + PrepareViewJob& job = pipeline->m_renderer.createJob(allocator); job.m_pipeline = pipeline; job.m_camera_params = cp; job.m_view = view.get(); @@ -4110,7 +4109,8 @@ struct PipelineImpl final : Pipeline void fillClusters(LuaWrapper::Optional cp) { PROFILE_FUNCTION(); - FillClustersJob& job = m_renderer.createJob(m_allocator); + LinearAllocator& current_frame_allocator = m_renderer.getCurrentFrameAllocator(); + FillClustersJob& job = m_renderer.createJob(current_frame_allocator, m_allocator); job.m_pipeline = this; if (cp.valid) { @@ -4641,8 +4641,9 @@ struct PipelineImpl final : Pipeline PagedListIterator iterator(view.renderables); view.instancers.reserve(jobs::getWorkersCount()); + LinearAllocator& allocator = m_renderer.getCurrentFrameAllocator(); for (u8 i = 0; i < jobs::getWorkersCount(); ++i) { - view.instancers.emplace(m_allocator, m_renderer.getEngine().getPageAllocator()); + view.instancers.emplace(allocator, m_renderer.getEngine().getPageAllocator()); } const float time_delta = m_renderer.getEngine().getLastTimeDelta(); diff --git a/src/renderer/renderer.cpp b/src/renderer/renderer.cpp index e2db094f0..521b4b377 100644 --- a/src/renderer/renderer.cpp +++ b/src/renderer/renderer.cpp @@ -1287,6 +1287,8 @@ struct RendererImpl final : Renderer jobs::setGreen(&m_gpu_frame->can_setup); } } + + LinearAllocator& getCurrentFrameAllocator() { return m_cpu_frame->job_allocator; } void waitForCommandSetup() override { diff --git a/src/renderer/renderer.h b/src/renderer/renderer.h index b52ca045b..5617bf46f 100644 --- a/src/renderer/renderer.h +++ b/src/renderer/renderer.h @@ -109,6 +109,8 @@ struct LUMIX_RENDERER_API Renderer : IPlugin { deallocJob(&job); } + virtual struct LinearAllocator& getCurrentFrameAllocator() = 0; + protected: virtual void* allocJob(u32 size, u32 align) = 0; virtual void deallocJob(void* ptr) = 0;