2025-06-22 21:05:09 +02:00
|
|
|
#pragma once
|
|
|
|
|
|
2026-03-16 06:37:51 +01:00
|
|
|
#include <pd/core/mat.hpp>
|
|
|
|
|
#include <pd/drivers/interface.hpp>
|
2025-06-22 21:05:09 +02:00
|
|
|
#include <pd/lithium/command.hpp>
|
2026-03-18 09:31:47 +01:00
|
|
|
#include <pd/lithium/texture.hpp>
|
2025-06-22 21:05:09 +02:00
|
|
|
|
|
|
|
|
using LiBackendFlags = PD::u32;
|
|
|
|
|
enum LiBackendFlags_ {
|
|
|
|
|
LiBackendFlags_None = 0,
|
2026-03-16 06:37:51 +01:00
|
|
|
LiBackendFlags_FlipUV_Y = 1 << 0, // Essential for font loading
|
2025-06-22 21:05:09 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
namespace PD {
|
2026-03-16 06:37:51 +01:00
|
|
|
|
2026-03-16 15:19:12 +01:00
|
|
|
// Pre interface class
|
2026-03-16 06:37:51 +01:00
|
|
|
class PD_API GfxDriver : public DriverInterface {
|
2026-01-25 00:04:40 +01:00
|
|
|
public:
|
2026-03-16 15:19:12 +01:00
|
|
|
GfxDriver(std::string_view name);
|
2026-03-18 09:31:47 +01:00
|
|
|
virtual ~GfxDriver();
|
2026-01-25 00:04:40 +01:00
|
|
|
|
|
|
|
|
virtual void Init() {}
|
2026-03-16 17:33:46 +01:00
|
|
|
virtual void Deinit() { SysDeinit(); }
|
2026-03-16 15:19:12 +01:00
|
|
|
|
|
|
|
|
void SetViewPort(const ivec2& size);
|
|
|
|
|
void SetViewPort(int x, int y);
|
2026-03-16 06:37:51 +01:00
|
|
|
virtual void BindTexture(TextureID id) {}
|
2026-03-16 15:19:12 +01:00
|
|
|
void Reset();
|
2026-03-18 09:31:47 +01:00
|
|
|
virtual Li::Texture LoadTexture(
|
|
|
|
|
const std::vector<PD::u8>& pixels, int w, int h,
|
|
|
|
|
TextureFormat type = TextureFormat::RGBA32,
|
|
|
|
|
TextureFilter filter = TextureFilter::Linear) {
|
|
|
|
|
return Li::Texture();
|
2026-03-16 15:19:12 +01:00
|
|
|
}
|
2026-03-18 09:31:47 +01:00
|
|
|
virtual void DeleteTexture(const Li::Texture& tex) {}
|
2026-03-16 15:19:12 +01:00
|
|
|
virtual void Draw(const Pool<Li::Command>& commands) {}
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
virtual void SysDeinit() {}
|
|
|
|
|
virtual void SysInit() {}
|
|
|
|
|
virtual void SysReset() {}
|
|
|
|
|
virtual void Submit(size_t count, size_t start) {}
|
|
|
|
|
virtual void ResetPools() = 0;
|
2026-03-18 09:31:47 +01:00
|
|
|
void RegisterTexture(const Li::Texture& tex);
|
|
|
|
|
void UnregisterTexture(const Li::Texture& tex);
|
2026-03-16 15:19:12 +01:00
|
|
|
|
|
|
|
|
// Counters
|
|
|
|
|
size_t CountDrawcalls = 0;
|
|
|
|
|
size_t CountCommands = 0;
|
|
|
|
|
size_t CountVertices = 0;
|
|
|
|
|
size_t CountIndices = 0;
|
|
|
|
|
size_t CurrentIndex = 0;
|
|
|
|
|
size_t CurrentVertex = 0;
|
|
|
|
|
TextureID CurrentTex = 0;
|
|
|
|
|
Mat4 Projection;
|
|
|
|
|
ivec2 ViewPort;
|
2026-03-18 09:31:47 +01:00
|
|
|
std::unordered_map<TextureID, Li::Texture> pTextureRegestry;
|
2026-03-16 15:19:12 +01:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
struct DefaultGfxConfig {
|
|
|
|
|
// Vertex Allocator
|
|
|
|
|
template <typename T>
|
|
|
|
|
using VertexAlloc = std::allocator<T>;
|
|
|
|
|
// Index Allocator
|
|
|
|
|
template <typename T>
|
|
|
|
|
using IndexAlloc = std::allocator<T>;
|
|
|
|
|
|
|
|
|
|
static constexpr size_t NumVertices = 32768; // 8192*4
|
|
|
|
|
static constexpr size_t NumIndices = 49152; // 8192*6
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
template <typename Config = DefaultGfxConfig>
|
2026-03-17 16:47:19 +01:00
|
|
|
class GfxDriverBase : public GfxDriver {
|
2026-03-16 15:19:12 +01:00
|
|
|
public:
|
|
|
|
|
using VtxPool =
|
|
|
|
|
Pool<Li::Vertex, typename Config::template VertexAlloc<Li::Vertex>>;
|
2026-03-17 16:47:19 +01:00
|
|
|
using IdxPool = Pool<u16, typename Config::template VertexAlloc<u16>>;
|
2026-03-16 15:19:12 +01:00
|
|
|
GfxDriverBase(std::string_view name = "Default") : GfxDriver(name) {}
|
|
|
|
|
virtual ~GfxDriverBase() {}
|
|
|
|
|
|
|
|
|
|
void Init() override {
|
|
|
|
|
pVtxPool.Init(Config::NumVertices);
|
|
|
|
|
pIdxPool.Init(Config::NumIndices);
|
|
|
|
|
SysInit();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void Draw(const Pool<Li::Command>& commands) override {
|
2026-03-16 06:37:51 +01:00
|
|
|
CountCommands += commands.size();
|
|
|
|
|
size_t index = 0;
|
|
|
|
|
while (index < commands.size()) {
|
|
|
|
|
CurrentTex = commands[index].Tex;
|
|
|
|
|
if (!CurrentTex) {
|
|
|
|
|
index++;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2026-03-16 15:19:12 +01:00
|
|
|
size_t startidx = CurrentIndex;
|
|
|
|
|
while (index < commands.size() && CurrentTex == commands[index].Tex) {
|
|
|
|
|
const auto& c = commands[index];
|
|
|
|
|
CountVertices += c.VertexCount;
|
|
|
|
|
CountIndices += c.IndexCount;
|
|
|
|
|
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];
|
|
|
|
|
}
|
2026-03-17 16:47:19 +01:00
|
|
|
CurrentIndex += c.IndexCount;
|
|
|
|
|
CurrentVertex += c.VertexCount;
|
2026-03-16 15:19:12 +01:00
|
|
|
for (size_t i = 0; i < c.VertexCount; i++) {
|
|
|
|
|
pVtx[i] = c.FirstVertex[i];
|
|
|
|
|
}
|
|
|
|
|
index++;
|
|
|
|
|
}
|
2026-03-17 16:47:19 +01:00
|
|
|
Submit(CurrentIndex - startidx, startidx);
|
2026-03-16 06:37:51 +01:00
|
|
|
}
|
2026-01-25 00:04:40 +01:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 15:19:12 +01:00
|
|
|
protected:
|
2026-03-17 16:47:19 +01:00
|
|
|
u16* GetIndexBufPtr(size_t start) { return &pIdxPool[start]; }
|
2026-03-16 15:19:12 +01:00
|
|
|
Li::Vertex* GetVertexBufPtr(size_t start) { return &pVtxPool[start]; }
|
|
|
|
|
void ResetPools() override {
|
|
|
|
|
pVtxPool.Reset();
|
|
|
|
|
pIdxPool.Reset();
|
|
|
|
|
}
|
2025-06-22 21:05:09 +02:00
|
|
|
|
2026-03-16 15:19:12 +01:00
|
|
|
private:
|
|
|
|
|
VtxPool pVtxPool;
|
|
|
|
|
IdxPool pIdxPool;
|
2026-03-16 06:37:51 +01:00
|
|
|
};
|
2025-06-22 21:05:09 +02:00
|
|
|
|
2026-03-16 06:37:51 +01:00
|
|
|
class PD_API Gfx {
|
|
|
|
|
public:
|
|
|
|
|
Gfx() = default;
|
|
|
|
|
~Gfx() = default;
|
2025-07-23 23:21:34 +02:00
|
|
|
|
2026-03-16 06:37:51 +01:00
|
|
|
template <typename T, typename... Args>
|
|
|
|
|
static void UseDriver(Args&&... args) {
|
|
|
|
|
// assert(driver == nullptr && "OS Driver already set");
|
|
|
|
|
driver = std::make_unique<T>(std::forward<Args>(args)...);
|
2025-06-22 21:05:09 +02:00
|
|
|
}
|
|
|
|
|
|
2026-03-16 17:33:46 +01:00
|
|
|
static void Init() { driver->Init(); }
|
|
|
|
|
static void Deinit() { driver->Deinit(); }
|
|
|
|
|
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<Li::Command>& commands) {
|
|
|
|
|
driver->Draw(commands);
|
|
|
|
|
}
|
2026-03-18 09:31:47 +01:00
|
|
|
static Li::Texture LoadTexture(const std::vector<PD::u8>& pixels, int w,
|
|
|
|
|
int h,
|
|
|
|
|
TextureFormat type = TextureFormat::RGBA32,
|
|
|
|
|
TextureFilter filter = TextureFilter::Linear) {
|
2026-03-16 17:33:46 +01:00
|
|
|
return driver->LoadTexture(pixels, w, h, type, filter);
|
|
|
|
|
}
|
2026-03-18 09:31:47 +01:00
|
|
|
static void DeleteTexture(const Li::Texture& tex) {
|
|
|
|
|
driver->DeleteTexture(tex);
|
|
|
|
|
}
|
2026-03-16 17:33:46 +01:00
|
|
|
|
|
|
|
|
static const char* GetDriverName() { return driver->GetName(); }
|
|
|
|
|
|
2026-03-16 06:37:51 +01:00
|
|
|
private:
|
|
|
|
|
static std::unique_ptr<GfxDriver> driver;
|
2025-06-22 21:05:09 +02:00
|
|
|
};
|
|
|
|
|
} // namespace PD
|