From 4488425a9450a5a5d07306a2a705a8337863cda1 Mon Sep 17 00:00:00 2001 From: tobid7 Date: Sat, 5 Sep 2026 22:52:59 +0200 Subject: [PATCH] Bring back global lithium pools why? cause sorting around the global driver pool would basically use more cpu power then just copy data sequences into the right order And sorting data references costs 0 performance at all --- CMakeLists.txt | 1 + include/pd/drivers/gfx.hpp | 62 +++++++++++++++++++++++------ include/pd/lithium/lithium.hpp | 3 +- include/pd/lithium/pools.hpp | 12 ++++++ source/lithium/command.cpp | 56 +++++++++++++++++++------- source/lithium/drawlist.cpp | 16 ++++++-- source/lithium/pools.cpp | 16 ++++++++ tests/gfx/source/main.cpp | 5 +-- tests/gfx/source/os/horizon-ctr.cpp | 4 +- 9 files changed, 139 insertions(+), 36 deletions(-) create mode 100644 include/pd/lithium/pools.hpp create mode 100644 source/lithium/pools.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index 88976d2..46437e5 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -52,6 +52,7 @@ set(PD_SOURCES source/lithium/drawlist.cpp source/lithium/font.cpp source/lithium/math.cpp + source/lithium/pools.cpp # UI7 source/ui7/io.cpp diff --git a/include/pd/drivers/gfx.hpp b/include/pd/drivers/gfx.hpp index 6134f16..06cb6cd 100755 --- a/include/pd/drivers/gfx.hpp +++ b/include/pd/drivers/gfx.hpp @@ -2,7 +2,8 @@ #include #include -#include +#include +#include #include using PDGfxBackendFlags = PD::u32; @@ -37,7 +38,7 @@ class PD_API GfxDriver : public DriverInterface { return Li::Texture(); } virtual void DeleteTexture(const Li::Texture& tex) {} - virtual void Draw(const Pool& commands) {} + virtual void Draw(const Li::Drawlist& commands) {} Li::Texture::Ptr GetWhiteTexture() { return &pWhite; } PDGfxBackendFlags GetFlags() { return Flags; } @@ -110,28 +111,67 @@ class GfxDriverBase : public GfxDriver { pWhite = LoadTexture(img, 16, 16); } - void Draw(const Pool& commands) override { + void Draw(const Li::Drawlist& dl) override { + const auto& commands = dl.Data(); + if (commands.size() == 0) return; pCountCommands += commands.size(); - size_t index = 0; + + size_t vtotal = dl.GetNumVertices(); + size_t itotal = dl.GetNumIndices(); + + size_t start_vtx = pVtxPool.size(); + pVtxPool.Allocate(vtotal); + CurrentVertex += vtotal; + + size_t start_idx = pIdxPool.size(); + pIdxPool.Allocate(itotal); + CurrentIndex += itotal; + + size_t current_vtx = start_vtx; + size_t current_idx = start_idx; + + const auto& vpool = Li::GetVertexPool(); + const auto& ipool = Li::GetIndexPool(); + /** Build Pools */ + for (size_t i = 0; i < commands.size(); i++) { + const auto& cmd = commands[i]; + if (cmd.VertexCount > 0) { + std::memcpy(pVtxPool.begin() + current_vtx, + vpool.begin() + cmd.FirstVertex, + cmd.VertexCount * sizeof(Li::Vertex)); + } + for (size_t idx = 0; idx < cmd.IndexCount; idx++) { + u16 local_idx = ipool[cmd.FirstIndex + idx]; + pIdxPool[current_idx + idx] = static_cast(current_vtx + local_idx); + } + current_vtx += cmd.VertexCount; + current_idx += cmd.IndexCount; + } + UploadPools(); + + size_t index = 0; + size_t ioff = start_idx; + while (index < commands.size()) { CurrentTex = commands[index].Tex; CurrentTexIsSDF = commands[index].SDF; if (!CurrentTex) { CurrentTex = pWhite.GetID(); } - size_t startidx = commands[index].FirstIndex; size_t num_indices = 0; while (index < commands.size() && CurrentTexIsSDF == commands[index].SDF && (CurrentTex == commands[index].Tex || - (CurrentTex == pWhite.GetID() && commands[index].Tex == 0)) && - commands[index].FirstIndex == startidx + num_indices) { + (CurrentTex == pWhite.GetID() && commands[index].Tex == 0))) { num_indices += commands[index].IndexCount; index++; } - Submit(num_indices, startidx); - pCountDrawcalls++; + if (num_indices > 0) { + Submit(num_indices, ioff); + ioff += num_indices; + pCountDrawcalls++; + } } } @@ -211,9 +251,7 @@ class PD_API Gfx { static void SetViewPort(const ivec2& vp) { driver->SetViewPort(vp); } static void SetViewPort(int w, int h) { driver->SetViewPort(w, h); } static void Reset() { driver->Reset(); } - static void Draw(const Pool& commands) { - driver->Draw(commands); - } + static void Draw(const Li::Drawlist& dl) { driver->Draw(dl); } static Li::Texture LoadTexture(const std::vector& pixels, int w, int h, TextureFormat type = TextureFormat::RGBA32, diff --git a/include/pd/lithium/lithium.hpp b/include/pd/lithium/lithium.hpp index e1165ce..1ccc5e5 100644 --- a/include/pd/lithium/lithium.hpp +++ b/include/pd/lithium/lithium.hpp @@ -4,4 +4,5 @@ #include #include #include -#include +#include +#include \ No newline at end of file diff --git a/include/pd/lithium/pools.hpp b/include/pd/lithium/pools.hpp new file mode 100644 index 0000000..d047972 --- /dev/null +++ b/include/pd/lithium/pools.hpp @@ -0,0 +1,12 @@ +#pragma once + +#include +#include + +namespace PD { +namespace Li { +PD_API PD::Pool& GetVertexPool(); +PD_API PD::Pool& GetIndexPool(); +PD_API void ResetPools(); +} // namespace Li +} // namespace PD \ No newline at end of file diff --git a/source/lithium/command.cpp b/source/lithium/command.cpp index 07299d0..9b67b19 100644 --- a/source/lithium/command.cpp +++ b/source/lithium/command.cpp @@ -1,23 +1,48 @@ #include #include +#include namespace PD { namespace Li { void Command::Reserve(size_t vtx, size_t idx) { + auto& vpool = GetVertexPool(); + auto& ipool = GetIndexPool(); if (VertexCountMax == 0) { - FirstVertex = Gfx::AllocateVertices(vtx, (PD::ptr)this); + FirstVertex = vpool.size(); + vpool.Allocate(vtx); VertexCountMax = vtx; } else { - Gfx::ExpandVertices(vtx, (PD::ptr)this); - VertexCountMax += vtx; + if (vpool.size() == FirstVertex + VertexCountMax) { + vpool.Allocate(vtx); + VertexCountMax += vtx; + } else { + size_t tmp = FirstVertex; + FirstVertex = vpool.size(); + vpool.Allocate(VertexCountMax + vtx); + for (size_t i = 0; i < VertexCount; i++) { + vpool[FirstVertex + i] = vpool[tmp + i]; + } + VertexCountMax += vtx; + } } if (IndexCountMax == 0) { - FirstIndex = Gfx::AllocateIndices(idx, (PD::ptr)this); + FirstIndex = ipool.size(); + ipool.Allocate(idx); IndexCountMax = idx; } else { - Gfx::ExpandIndices(idx, (PD::ptr)this); - IndexCountMax += idx; + if (ipool.size() == FirstIndex + IndexCountMax) { + ipool.Allocate(idx); + IndexCountMax += idx; + } else { + size_t tmp = FirstIndex; + FirstIndex = ipool.size(); + ipool.Allocate(IndexCountMax + idx); + for (size_t i = 0; i < IndexCount; i++) { + ipool[FirstIndex + i] = ipool[tmp + i]; + } + IndexCountMax += idx; + } } } @@ -34,22 +59,25 @@ void Command::Reset() { } Command& Command::Add(const Vertex& vtx) { - if (VertexCount <= VertexCountMax) - Gfx::PutVertex(FirstVertex + VertexCount++, vtx, (PD::ptr)this); + if (VertexCount < VertexCountMax) { + GetVertexPool()[FirstVertex + VertexCount++] = vtx; + } return *this; } Command& Command::Add(u16 idx) { - if (IndexCount <= IndexCountMax) - Gfx::PutIndex(FirstIndex + IndexCount++, FirstVertex + VertexCount + idx, - (PD::ptr)this); + if (IndexCount < IndexCountMax) { + GetIndexPool()[FirstIndex + IndexCount++] = + static_cast(VertexCount + idx); + } return *this; } Command& Command::Add(u16 a, u16 b, u16 c) { if (IndexCount + 3 <= IndexCountMax) { + auto& ip = GetIndexPool(); size_t idx = FirstIndex + IndexCount; - Gfx::PutIndex(idx + 0, FirstVertex + VertexCount + a, (PD::ptr)this); - Gfx::PutIndex(idx + 1, FirstVertex + VertexCount + b, (PD::ptr)this); - Gfx::PutIndex(idx + 2, FirstVertex + VertexCount + c, (PD::ptr)this); + ip[idx + 0] = static_cast(VertexCount + a); + ip[idx + 1] = static_cast(VertexCount + b); + ip[idx + 2] = static_cast(VertexCount + c); IndexCount += 3; } return *this; diff --git a/source/lithium/drawlist.cpp b/source/lithium/drawlist.cpp index 7075042..d067430 100644 --- a/source/lithium/drawlist.cpp +++ b/source/lithium/drawlist.cpp @@ -1,3 +1,4 @@ +#include #include #include #include @@ -19,19 +20,26 @@ PD_API void Drawlist::Copy(Drawlist& other) { pCommands.AppendCopy(other.pCommands); } -PD_API void Drawlist::Optimize() {} +PD_API void Drawlist::Optimize() { + if (pCommands.size() <= 1) return; + std::stable_sort(pCommands.begin(), pCommands.end(), + [](const Command& a, const Command& b) { + if (a.Layer != b.Layer) return a.Layer < b.Layer; + if (a.SDF != b.SDF) return a.SDF < b.SDF; + return a.Tex < b.Tex; + }); +} PD_API void Drawlist::Clear() { UnbindTexture(); pPath.ResetFast(); - pVertices.ResetFast(); - pIndices.ResetFast(); - pCommands.ResetFast(); + pCommands.NoReset(); } /** Command Allocation */ PD_API Command& Drawlist::NewCommand() { auto cmd = pCommands.Allocate(1); + cmd->Reset(); cmd->Tex = pCurrentTexture.GetID(); return *cmd; } diff --git a/source/lithium/pools.cpp b/source/lithium/pools.cpp new file mode 100644 index 0000000..4f5e209 --- /dev/null +++ b/source/lithium/pools.cpp @@ -0,0 +1,16 @@ +#include + +namespace PD { +namespace Li { +static PD::Pool gVertexPool; +static PD::Pool gIndexPool; + +PD_API PD::Pool& GetVertexPool() { return gVertexPool; } +PD_API PD::Pool& GetIndexPool() { return gIndexPool; } + +PD_API void ResetPools() { + gVertexPool.NoReset(); + gIndexPool.NoReset(); +} +} // namespace Li +} // namespace PD \ No newline at end of file diff --git a/tests/gfx/source/main.cpp b/tests/gfx/source/main.cpp index 013a5fa..8223666 100644 --- a/tests/gfx/source/main.cpp +++ b/tests/gfx/source/main.cpp @@ -217,6 +217,7 @@ int main(int argc, char** argv) { PD::TT::Beg("MainRaw"); PD::Hid::Update(); PD::Gfx::NewFrame(); + PD::Li::ResetPools(); // app.Update(pOs->GetViewport(), pList); pList.SetFontscale(0.7); if (PD::Hid::IsEvent(PD::Hid::Event::Down, PD::Hid::Gamepad::CPLeft | @@ -297,7 +298,6 @@ int main(int argc, char** argv) { "#ff00ff"); } pList.SetFont(&font); -#ifndef __3DS__ PD::TT::Beg("BuildUI7Menus"); if (auto m = ui7.BeginMenu("Test")) { m->Label("Hello World!"); @@ -318,11 +318,10 @@ int main(int argc, char** argv) { PD::TT::Beg("UI7::Context::Update"); ui7.Update(); PD::TT::End("UI7::Context::Update"); -#endif PD::Gfx::Reset(); PD::TT::Beg("PD::Gfx::Draw"); - PD::Gfx::Draw(pList); PD::Gfx::Draw(ui7.GetDrawData()); + PD::Gfx::Draw(pList); PD::TT::End("PD::Gfx::Draw"); pList.Clear(); PD::TT::End("MainRaw"); diff --git a/tests/gfx/source/os/horizon-ctr.cpp b/tests/gfx/source/os/horizon-ctr.cpp index 1e2de4b..e869d7f 100644 --- a/tests/gfx/source/os/horizon-ctr.cpp +++ b/tests/gfx/source/os/horizon-ctr.cpp @@ -33,7 +33,7 @@ void HorizonCtr::Init() { romfsInit(); osSetSpeedupEnable(true); gfxInitDefault(); - consoleInit(GFX_BOTTOM, nullptr); + // consoleInit(GFX_BOTTOM, nullptr); C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); impl->Top = C3D_RenderTargetCreate(240, 400, GPU_RB_RGBA8, GPU_RB_DEPTH24_STENCIL8); @@ -63,12 +63,12 @@ bool HorizonCtr::Mainloop() { pViewPort = ivec2(400, 240); hidScanInput(); bool _kill = hidKeysUp() & KEY_START; + C3D_FrameBegin(C3D_FRAME_SYNCDRAW); return aptMainLoop() && !_kill; } void HorizonCtr::ClearViewPort() { PD::Gfx::SetViewPort(pViewPort); - C3D_FrameBegin(C3D_FRAME_SYNCDRAW); C3D_FrameDrawOn(impl->Top); C3D_RenderTargetClear(impl->Top, C3D_CLEAR_ALL, PD::Color(25, 25, 25, 25), 0); }