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); }