diff --git a/backends/source/gfx_citro3d.cpp b/backends/source/gfx_citro3d.cpp index f4d19f7..0d16260 100644 --- a/backends/source/gfx_citro3d.cpp +++ b/backends/source/gfx_citro3d.cpp @@ -236,7 +236,7 @@ void GfxCitro3D::DeleteTexture(const Li::Texture& tex) { #else namespace PD { void GfxCitro3D::SysInit() { - PDLOG( + PDERR( "GfxCitro3D::SysInit: Citro3D Driver is not included in " "palladium-system"); } diff --git a/backends/source/gfx_directx9.cpp b/backends/source/gfx_directx9.cpp index 9e20de8..260ea29 100644 --- a/backends/source/gfx_directx9.cpp +++ b/backends/source/gfx_directx9.cpp @@ -86,7 +86,7 @@ void GfxDirectX9::SysInit() { HRESULT hr = D3DCompile(g_vsCode, strlen(g_vsCode), nullptr, nullptr, nullptr, "main", "vs_2_0", 0, 0, &vsBlob, &errBlob); if (FAILED(hr)) { - PDLOG("Vertex Shader compile error: {}", + PDERR("Vertex Shader compile error: {}", errBlob ? (char*)errBlob->GetBufferPointer() : ""); } else { impl->Device->CreateVertexShader((DWORD*)vsBlob->GetBufferPointer(), @@ -109,7 +109,7 @@ void GfxDirectX9::SysInit() { if (psBlob) psBlob->Release(); if (errBlob) errBlob->Release(); } else { - PDLOG( + PDERR( "GfxDirectX9::SysInit Error: pDevice is not set!\nYOu need to include " "your D3D9 Device as " "folowing:\nPD::Gfx::UseDriver(D3D9Device);"); @@ -276,7 +276,7 @@ void GfxDirectX9::DeleteTexture(const Li::Texture& tex) { #else namespace PD { void GfxDirectX9::SysInit() { - PDLOG( + PDERR( "GfxDirectX9::SysInit: DirectX9 Driver is not included in " "palladium-system"); } diff --git a/backends/source/gfx_opengl2.cpp b/backends/source/gfx_opengl2.cpp index 91291b8..630d5b1 100644 --- a/backends/source/gfx_opengl2.cpp +++ b/backends/source/gfx_opengl2.cpp @@ -82,10 +82,6 @@ void GfxOpenGL2::SysInit() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - PDLOG( - "GfxOpenGL2::SysInit():\n pShader = {}\n pLocTex = {}\n pLocAlfa = " - "{}\n pLocProjection = {}\n VBO = {}\n IBO = {}", - pShader, pLocTex, pLocAlfa, pLocProjection, VBO, IBO); } void GfxOpenGL2::SysDeinit() { @@ -172,7 +168,7 @@ void GfxOpenGL2::DeleteTexture(const Li::Texture& tex) { #else namespace PD { void GfxOpenGL2::SysInit() { - PDLOG( + PDERR( "GfxOpenGL2::SysInit: OpenGL2 Driver is not included in " "palladium-system"); } diff --git a/backends/source/gfx_opengl3.cpp b/backends/source/gfx_opengl3.cpp index 227956e..48e1b96 100644 --- a/backends/source/gfx_opengl3.cpp +++ b/backends/source/gfx_opengl3.cpp @@ -52,10 +52,6 @@ void GfxOpenGL3::SysInit() { glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindVertexArray(0); - PDLOG( - "GfxOpenGL3::SysInit():\n pShader = {}\n pLocTex = {}\n pLocAlfa = " - "{}\n pLocProjection = {}\n VBO = {}\n IBO = {}, VAO = {}", - pShader, pLocTex, pLocAlfa, pLocProjection, VBO, IBO, VAO); } void GfxOpenGL3::SysDeinit() { @@ -142,7 +138,7 @@ void GfxOpenGL3::DeleteTexture(const Li::Texture& tex) { #else namespace PD { void GfxOpenGL3::SysInit() { - PDLOG( + PDERR( "GfxOpenGL3::SysInit: OpenGL3 Driver is not included in " "palladium-system"); } diff --git a/include/pd/common.hpp b/include/pd/common.hpp index 01405d8..1afbc13 100644 --- a/include/pd/common.hpp +++ b/include/pd/common.hpp @@ -23,6 +23,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ +#if defined(__GNUG__) && !defined(_MSC_VER) +#include +#endif + #include #include #include @@ -39,6 +43,11 @@ SOFTWARE. #include namespace PD { +enum class LogLevel { + Info, + Warning, + Error, +}; [[noreturn]] inline void Throw(const std::string& msg) { throw std::runtime_error(msg); } @@ -47,17 +56,48 @@ using u16 = unsigned short; using u32 = unsigned int; using u64 = unsigned long long; using ptr = uintptr_t; -PD_API void Log(const std::string& txt); +PD_API void Log(const std::string& txt, LogLevel lvl = LogLevel::Info); template void Log(std::format_string fmt, Args&&... args) { std::string msg = std::format(fmt, std::forward(args)...); - Log(msg); + Log(msg, LogLevel::Info); +} +template +void Log(LogLevel lvl, std::format_string fmt, Args&&... args) { + std::string msg = std::format(fmt, std::forward(args)...); + Log(msg, lvl); +} +template +std::string TypeName() { +#if defined(__GNUG__) && !defined(_MSC_VER) + int res = 0; + std::unique_ptr up{ + abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, &res), std::free}; + return (res == 0) ? up.get() : typeid(T).name(); +#else + return typeid(T).name(); // no demangler available :/ +#endif } } // namespace PD +#if defined(__GNUC__) || defined(__clang__) +#define PDPRETTYFUNC __PRETTY_FUNCTION__ +#elif defined(_MSC_VER) +#define PDPRETTYFUNC __FUNCSIG__ +#else +#define PDPRETTYFUNC __FUNCTION__ +#endif #ifdef PD_DEBUG #define PDLOG(fmt, ...) \ PD::Log("[{}:{}]: " fmt, __FILE__, __LINE__, ##__VA_ARGS__) +#define PDWARN(fmt, ...) \ + PD::Log(PD::LogLevel::Warning, "[{}:{}]: " fmt, __FILE__, __LINE__, \ + ##__VA_ARGS__) +#define PDERR(fmt, ...) \ + PD::Log(PD::LogLevel::Error, "[{}:{}]: " fmt, __FILE__, __LINE__, \ + ##__VA_ARGS__) #else #define PDLOG(fmt, ...) +#define PDWARN(fmt, ...) +#define PDERR(fmt, ...) #endif \ No newline at end of file diff --git a/include/pd/core/pool.hpp b/include/pd/core/pool.hpp index 968106c..6ce6101 100644 --- a/include/pd/core/pool.hpp +++ b/include/pd/core/pool.hpp @@ -3,6 +3,11 @@ #include #include namespace PD { +// lets take use of c++ 20 concepts +// https://en.cppreference.com/w/cpp/language/constraints.html +template +concept Resettable = requires(T& v) { v.Reset(); }; + template > class Pool { public: @@ -13,6 +18,9 @@ class Pool { Pool() = default; ~Pool() { if (pData) { + for (size_t i = 0; i < pCap; i++) { + std::allocator_traits::destroy(pAlloc, &pData[i]); + } pAlloc.deallocate(pData, pCap); pData = nullptr; } @@ -47,6 +55,11 @@ class Pool { *e = elem; } + void Put(size_t idx, const T& elem) { + if (idx >= pCap) ExpandIf(idx); + pData[idx] = elem; + } + void ExpandIf(size_t req) { if ((pPos + req) <= pCap) return; size_t ncap = std::max(pCap * 2, pPos + req); @@ -56,11 +69,14 @@ class Pool { std::allocator_traits::construct( pAlloc, &nu[i], std::move_if_noexcept(pData[i])); } + for (size_t i = 0; i < pCap; i++) { + std::allocator_traits::destroy(pAlloc, &pData[i]); + } pAlloc.deallocate(pData, pCap); } for (size_t i = pPos; i < ncap; i++) { - std::allocator_traits::construct(pAlloc, &nu[i]); - } + std::allocator_traits::construct(pAlloc, &nu[i]); + } PDLOG("Pool::ExpandIf({}): {} -> {}", req, pCap, ncap); pData = nu; pCap = ncap; @@ -76,6 +92,21 @@ class Pool { } } + void ResetFast() { + if constexpr (Resettable) { + for (size_t i = 0; i < pPos; i++) { + pData[i].Reset(); + } + } else if constexpr (!std::is_trivially_destructible_v) { + PDWARN( + "ResetFast should only be executed with a non destructible type or a " + "class/struct that has a Reset func! {} is not " + "trivially_destructible and has no reset func.", + TypeName()); + } + pPos = 0; + } + size_t size() const { return pPos; } size_t capacity() const { return pCap; } T& at(size_t idx) { return pData[idx]; } @@ -89,7 +120,16 @@ class Pool { const T& operator[](size_t idx) const { return at(idx); } private: - Pool(size_t size) : pCap(size), pPos(0) { pData = pAlloc.allocate(size); } + Pool(size_t size) : pCap(size), pPos(0) { + pPos = 0; + pCap = size; + pData = pAlloc.allocate(size); + for (size_t i = 0; i < pCap; i++) { + std::allocator_traits::construct(pAlloc, &pData[i]); + } + PDLOG("Pool::Init({})", size); + } + size_t pCap = 0; size_t pPos = 0; Alloc pAlloc; diff --git a/include/pd/drivers/gfx.hpp b/include/pd/drivers/gfx.hpp index 9252543..49c5a59 100755 --- a/include/pd/drivers/gfx.hpp +++ b/include/pd/drivers/gfx.hpp @@ -3,6 +3,7 @@ #include #include #include +#include #include using PDBackendFlags = PD::u32; @@ -105,12 +106,12 @@ class GfxDriverBase : public GfxDriver { auto pIdx = pIdxPool.Allocate(c.IndexCount); auto pVtx = pVtxPool.Allocate(c.VertexCount); for (size_t i = 0; i < c.IndexCount; i++) { - pIdx[i] = CurrentVertex + c.FirstIndex[i]; + pIdx[i] = CurrentVertex + Li::GetIndex(c.FirstIndex + i); } CurrentIndex += c.IndexCount; CurrentVertex += c.VertexCount; for (size_t i = 0; i < c.VertexCount; i++) { - pVtx[i] = c.FirstVertex[i]; + pVtx[i] = Li::GetVertex(c.FirstVertex + i); } index++; } @@ -124,8 +125,8 @@ class GfxDriverBase : public GfxDriver { size_t GetVertexPoolSize() const { return pVtxPool.size(); } size_t GetIndexPoolSize() const { return pIdxPool.size(); } void ResetPools() override { - pVtxPool.Reset(); - pIdxPool.Reset(); + pVtxPool.ResetFast(); + pIdxPool.ResetFast(); } private: diff --git a/include/pd/lithium/command.hpp b/include/pd/lithium/command.hpp index 825bd88..f3b96d3 100644 --- a/include/pd/lithium/command.hpp +++ b/include/pd/lithium/command.hpp @@ -13,44 +13,58 @@ class Command { ~Command() {} void Reserve(size_t vtx, size_t idx) { - if (!FirstVertex) - FirstVertex = AllocateVertices(vtx); - else - AllocateVertices(vtx); - if (!FirstIndex) - FirstIndex = AllocateIndices(idx); - else - AllocateIndices(idx); + if (!FirstVertex) { + FirstVertex = AllocateVertices(vtx, (PD::ptr)this); + VertexCountMax = vtx; + } else { + ExpandVertices(vtx, (PD::ptr)this); + VertexCountMax += vtx; + } + if (!FirstIndex) { + FirstIndex = AllocateIndices(idx, (PD::ptr)this); + IndexCountMax = idx; + } else { + ExpandVertices(idx, (PD::ptr)this); + IndexCountMax += idx; + } } void Reset() { Layer = 0; Tex = 0; - FirstIndex = nullptr; - FirstVertex = nullptr; + FirstIndex = 0; + FirstVertex = 0; IndexCount = 0; VertexCount = 0; + VertexCountMax = 0; + IndexCountMax = 0; } Command& Add(const Vertex& vtx) { - FirstVertex[VertexCount++] = vtx; + if (VertexCount <= VertexCountMax) + PutVertex(FirstVertex + VertexCount++, vtx, (PD::ptr)this); return *this; } Command& Add(u16 idx) { - FirstIndex[IndexCount++] = VertexCount + idx; + if (IndexCount <= IndexCountMax) + PutIndex(FirstIndex + IndexCount++, VertexCount + idx, (PD::ptr)this); return *this; } Command& Add(u16 a, u16 b, u16 c) { - FirstIndex[IndexCount++] = VertexCount + a; - FirstIndex[IndexCount++] = VertexCount + b; - FirstIndex[IndexCount++] = VertexCount + c; + if (IndexCount + 3 <= IndexCountMax) { + size_t idx = FirstIndex + IndexCount; + PutIndex(idx + 0, VertexCount + a, (PD::ptr)this); + PutIndex(idx + 1, VertexCount + b, (PD::ptr)this); + PutIndex(idx + 2, VertexCount + c, (PD::ptr)this); + IndexCount += 3; + } return *this; } int Layer = 0; ptr Tex = 0; - Vertex* FirstVertex = nullptr; - u16* FirstIndex = nullptr; + size_t FirstVertex = 0; + size_t FirstIndex = 0; size_t VertexCount = 0; size_t IndexCount = 0; // Todo: implement diff --git a/include/pd/lithium/formatters.hpp b/include/pd/lithium/formatters.hpp index 8e51c6a..c3f1874 100644 --- a/include/pd/lithium/formatters.hpp +++ b/include/pd/lithium/formatters.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include #include #include #include @@ -106,4 +107,16 @@ struct std::formatter : std::formatter { } return std::format_to(ctx.out(), "{}", ret); } -}; \ No newline at end of file +}; + +template <> +struct std::formatter : std::formatter { + constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); } + + template + auto format(const PD::Li::Command& value, FormatContext& ctx) const { + return std::format_to(ctx.out(), "[0x{:X}, 0x{:X}] [{}, {}] 0x{:X}", + (PD::ptr)value.FirstVertex, (PD::ptr)value.FirstIndex, + value.VertexCount, value.IndexCount, value.Tex); + } +}; diff --git a/include/pd/lithium/pools.hpp b/include/pd/lithium/pools.hpp index 0664382..dd19f0e 100644 --- a/include/pd/lithium/pools.hpp +++ b/include/pd/lithium/pools.hpp @@ -5,8 +5,22 @@ namespace PD { namespace Li { -PD_API Vertex* AllocateVertices(size_t count); -PD_API u16* AllocateIndices(size_t count); +/** + * Allocate an amount of vertices + * returns the index of the first vertex + */ +PD_API size_t AllocateVertices(size_t count, PD::ptr accessor); +/** + * Allocate an amount of indices + * returns the index of the first elem + */ +PD_API size_t AllocateIndices(size_t count, PD::ptr accessor); +PD_API bool ExpandVertices(size_t count, PD::ptr accessor); +PD_API bool EcpandIndices(size_t count, PD::ptr accessor); +PD_API void PutVertex(size_t loc, const Vertex& vtx, PD::ptr accessor); +PD_API void PutIndex(size_t loc, u16 idx, PD::ptr accessor); +PD_API const Vertex& GetVertex(size_t loc); +PD_API const u16& GetIndex(size_t loc); PD_API void ResetPools(); } // namespace Li } // namespace PD \ No newline at end of file diff --git a/include/pd/lithium/vertex.hpp b/include/pd/lithium/vertex.hpp index cdb8f52..ab888b5 100755 --- a/include/pd/lithium/vertex.hpp +++ b/include/pd/lithium/vertex.hpp @@ -11,6 +11,12 @@ class Vertex { : pos(pos), uv(uv), color(color) {} ~Vertex() {} + void Reset() { + pos = fvec2(0.f); + uv = fvec2(0.f); + color = 0x00000000; + } + fvec2 pos; fvec2 uv; u32 color = 0x00000000; diff --git a/source/common.cpp b/source/common.cpp index 5d5615c..84a5fdb 100644 --- a/source/common.cpp +++ b/source/common.cpp @@ -1,6 +1,30 @@ #include #include -PD_API void PD::Log(const std::string& txt) { - std::cout << "[PD] " << txt << std::endl; -} \ No newline at end of file +namespace PD { +constexpr const char* pColorNo = "\033[0m"; +constexpr const char* pColorYellow = "\033[33m"; +constexpr const char* pColorRed = "\033[31m"; +static LogLevel pFilter = LogLevel::Info; +PD_API void Log(const std::string& txt, LogLevel lvl) { + if ((int)lvl < (int)pFilter) return; + const char* clr = pColorNo; + const char* plvl = "INFO"; + switch (lvl) { + case PD::LogLevel::Info: + clr = pColorNo; + plvl = "INFO"; + break; + case PD::LogLevel::Warning: + clr = pColorYellow; + plvl = "WARNING"; + break; + case PD::LogLevel::Error: + clr = pColorRed; + plvl = "ERROR"; + break; + } + + std::cout << clr << "[PD][" << plvl << "] " << txt << pColorNo << std::endl; +} +} // namespace PD \ No newline at end of file diff --git a/source/drivers/gfx.cpp b/source/drivers/gfx.cpp index bf1558b..86b11c0 100644 --- a/source/drivers/gfx.cpp +++ b/source/drivers/gfx.cpp @@ -8,7 +8,7 @@ PD_API GfxDriver::GfxDriver(std::string_view name) : DriverInterface(name) {} PD_API GfxDriver::~GfxDriver() { if (pTextureRegestry.size()) { - PDLOG("GfxDriver: {} is still holding {} texture{}!", GetName(), + PDERR("GfxDriver: {} is still holding {} texture{}!", GetName(), pTextureRegestry.size(), (pTextureRegestry.size() == 1 ? "" : "s")); } } @@ -40,7 +40,7 @@ PD_API void GfxDriver::UnregisterTexture(const Li::Texture& tex) { pTextureRegestry.erase(pTextureRegestry.find(tex.GetID())); PDLOG("GfxDriver: Texture {{ {} }} has been deleted!", tex); } else { - PDLOG("GfxDriver: WARNING Texture {{ {} }} does not exist in regestry!", + PDWARN("GfxDriver: WARNING Texture {{ {} }} does not exist in regestry!", tex); } } diff --git a/source/lithium/drawlist.cpp b/source/lithium/drawlist.cpp index 5f6f925..84f7ae4 100644 --- a/source/lithium/drawlist.cpp +++ b/source/lithium/drawlist.cpp @@ -1,5 +1,7 @@ +#include #include #include +#include #include namespace PD { @@ -16,9 +18,10 @@ PD_API void Drawlist::Optimize() {} PD_API void Drawlist::Clear() { UnbindTexture(); - pPath.Reset(); - pVertices.Reset(); - pIndices.Reset(); + pPath.ResetFast(); + pVertices.ResetFast(); + pIndices.ResetFast(); + pCommands.ResetFast(); } /** Command Allocation */ @@ -262,6 +265,7 @@ PD_API void Drawlist::DrawConvexPolyFilled(const Pool& points, uv_tl.y + ((points[i].y - minY) / (maxY - minY)) * (uv_bl.y - uv_tl.y); cmd.Add(Vertex(points[i], fvec2(u, v), color)); } + std::cout << std::format("{}: {}", __PRETTY_FUNCTION__, cmd); } PD_API void Drawlist::PrimQuad(Command& cmd, const Rect& quad, const Rect& uv, diff --git a/source/lithium/pools.cpp b/source/lithium/pools.cpp index d3722e3..80ad5d0 100644 --- a/source/lithium/pools.cpp +++ b/source/lithium/pools.cpp @@ -5,12 +5,56 @@ namespace PD { namespace Li { PD::Pool pVtxPool; PD::Pool pIdxPool; +PD::ptr pVertexAccessor = 0; +PD::ptr pIndexAccessor = 0; -PD_API Vertex* AllocateVertices(size_t count) { - return pVtxPool.Allocate(count); +PD_API size_t AllocateVertices(size_t count, PD::ptr accessor) { + pVertexAccessor = accessor; + int loc = pVtxPool.size(); + pVtxPool.Allocate(count); + return loc; } -PD_API u16* AllocateIndices(size_t count) { return pIdxPool.Allocate(count); } +PD_API size_t AllocateIndices(size_t count, PD::ptr accessor) { + pIndexAccessor = accessor; + int loc = pIdxPool.size(); + pIdxPool.Allocate(count); + return loc; +} + +PD_API bool ExpandVertices(size_t count, PD::ptr accessor) { + if (pVertexAccessor != accessor) return false; + pVtxPool.Allocate(count); + return true; +} + +PD_API bool EcpandIndices(size_t count, PD::ptr accessor) { + if (pIndexAccessor != accessor) return false; + pVtxPool.Allocate(count); + return true; +} + +PD_API void PutVertex(size_t loc, const Vertex& vtx, PD::ptr accessor) { + if (pVertexAccessor != accessor) return; + pVtxPool.Put(loc, vtx); +} + +PD_API void PutIndex(size_t loc, u16 idx, PD::ptr accessor) { + if (pIndexAccessor != accessor) return; + pIdxPool.Put(loc, idx); +} + +PD_API const Vertex& GetVertex(size_t loc) { + if (loc < pVtxPool.size()) return pVtxPool[loc]; + static Vertex pErrVtx; + return pErrVtx; +} + +PD_API const u16& GetIndex(size_t loc) { + if (loc < pIdxPool.size()) return pIdxPool[loc]; + static u16 pErrIdx = 0; + return pErrIdx; +} PD_API void ResetPools() { pVtxPool.Reset(); diff --git a/tests/gfx/source/main.cpp b/tests/gfx/source/main.cpp index 453ff06..c4bdeb1 100644 --- a/tests/gfx/source/main.cpp +++ b/tests/gfx/source/main.cpp @@ -145,7 +145,7 @@ class App { pList.DrawRectFilled(0, 50, 0xff00ffff); pList.BindTexture(pTex); pList.DrawRectFilled(50, pTex.GetSize(), 0xffffffff); - pList.DrawCircleFilled(500, 100, 0xffffffff, 50); + pList.DrawCircleFilled(PD::fvec2(700, 500), 100, 0xffffffff, 50); // pList.PathRect(300, 700, 40.f); // pList.PathFill(0xffffffff); std::cout << "GfxDriver: " << PD::Gfx::GetDriverName() << std::endl;