Add backends

- Renamed GfxOpenGL to GfxOPenGL2
- Added GfxOpenGL3 backend for OpenGL 3.3+
- Added WIP DirectX9 backend
- Added structure for Citro3D
- Added linear Allocator
This commit is contained in:
2026-03-17 16:47:19 +01:00
parent fe9194b907
commit d4c59e5b61
25 changed files with 1109 additions and 188 deletions

View File

@@ -14,110 +14,115 @@ option(PD_BUILD_SHARED "Build Shared Library" OFF)
option(PD_BUILD_TOOLS "Build Palladium Tools" OFF) option(PD_BUILD_TOOLS "Build Palladium Tools" OFF)
if(${PD_BUILD_TOOLS}) if(${PD_BUILD_TOOLS})
add_subdirectory(tools) add_subdirectory(tools)
endif() endif()
add_subdirectory(vendor) add_subdirectory(vendor)
# # Include Library Source # # Include Library Source
set(PD_SOURCES set(PD_SOURCES
# Common # Common
source/common.cpp source/common.cpp
# Core # Core
source/core/bits.cpp source/core/bits.cpp
source/core/color.cpp source/core/color.cpp
source/core/mat.cpp source/core/mat.cpp
source/core/strings.cpp source/core/strings.cpp
# Drivers # Drivers
source/drivers/os.cpp source/drivers/os.cpp
source/drivers/gfx.cpp source/drivers/gfx.cpp
# Lithium # Lithium
source/lithium/pools.cpp source/lithium/pools.cpp
) )
if(${PD_BUILD_SHARED}) if(${PD_BUILD_SHARED})
add_library(palladium SHARED ${PD_SOURCES}) add_library(palladium SHARED ${PD_SOURCES})
target_compile_definitions(palladium PRIVATE -DPD_BUILD_SHARED) target_compile_definitions(palladium PRIVATE PD_BUILD_SHARED)
else() else()
add_library(palladium STATIC ${PD_SOURCES}) add_library(palladium STATIC ${PD_SOURCES})
target_compile_definitions(palladium PUBLIC -DPD_BUILD_STATIC) target_compile_definitions(palladium PUBLIC PD_BUILD_STATIC)
endif() endif()
target_compile_definitions(palladium PUBLIC -DPD_DEBUG=1) target_compile_definitions(palladium PUBLIC PD_DEBUG)
target_compile_options(palladium target_compile_options(palladium
PUBLIC PUBLIC
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/source=source $<$<CXX_COMPILER_ID:GNU,Clang>:
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/include=include -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/source=source
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/include=include
>
) )
add_library(palladium::palladium ALIAS palladium) add_library(palladium::palladium ALIAS palladium)
target_include_directories(palladium target_include_directories(palladium
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
target_compile_options(palladium target_compile_options(palladium
PRIVATE PRIVATE
$<$<CONFIG:Debug>:-O0 -g> $<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:GNU,Clang>>:-O0 -g>
$<$<CONFIG:Release>:-O3> $<$<AND:$<CONFIG:Release>,$<CXX_COMPILER_ID:GNU,Clang>>:-O3>
$<$<AND:$<CONFIG:Debug>,$<CXX_COMPILER_ID:MSVC>>:/Od /Zi>
$<$<AND:$<CONFIG:Release>,$<CXX_COMPILER_ID:MSVC>>:/O2>
) )
install( install(
TARGETS palladium TARGETS palladium
EXPORT palladiumTargets EXPORT palladiumTargets
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
) )
install( install(
DIRECTORY include/ DIRECTORY include/
DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}
) )
install(EXPORT palladiumTargets install(EXPORT palladiumTargets
FILE palladiumTargets.cmake FILE palladiumTargets.cmake
NAMESPACE palladium:: NAMESPACE palladium::
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/palladium DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/palladium
) )
include(CMakePackageConfigHelpers) include(CMakePackageConfigHelpers)
configure_package_config_file( configure_package_config_file(
cmake/palladiumConfig.cmake.in cmake/palladiumConfig.cmake.in
${CMAKE_CURRENT_BINARY_DIR}/palladiumConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/palladiumConfig.cmake
INSTALL_DESTINATION INSTALL_DESTINATION
${CMAKE_INSTALL_LIBDIR}/cmake/palladium ${CMAKE_INSTALL_LIBDIR}/cmake/palladium
) )
write_basic_package_version_file( write_basic_package_version_file(
${CMAKE_CURRENT_BINARY_DIR}/palladiumConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/palladiumConfigVersion.cmake
VERSION VERSION
${PROJECT_VERSION} ${PROJECT_VERSION}
COMPATIBILITY COMPATIBILITY
SameMajorVersion SameMajorVersion
) )
install( install(
FILES FILES
${CMAKE_CURRENT_BINARY_DIR}/palladiumConfig.cmake ${CMAKE_CURRENT_BINARY_DIR}/palladiumConfig.cmake
${CMAKE_CURRENT_BINARY_DIR}/palladiumConfigVersion.cmake ${CMAKE_CURRENT_BINARY_DIR}/palladiumConfigVersion.cmake
DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/palladium DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/palladium
) )
find_program(CLANG_FORMAT clang-format) find_program(CLANG_FORMAT clang-format)
file(GLOB_RECURSE PD_FMTFILES file(GLOB_RECURSE PD_FMTFILES
CONFIGURE_DEPENDS CONFIGURE_DEPENDS
${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/*.cpp
${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp ${CMAKE_CURRENT_SOURCE_DIR}/include/*.hpp
) )
add_custom_target(pd-clang-format add_custom_target(pd-clang-format
COMMAND ${CLANG_FORMAT} --style=file -i ${PD_FMTFILES} COMMAND ${CLANG_FORMAT} --style=file -i ${PD_FMTFILES}
COMMENT "Formatting Project Sources" COMMENT "Formatting Project Sources"
) )
add_subdirectory(backends) add_subdirectory(backends)

View File

@@ -4,26 +4,60 @@ project(pd-system)
option(PD_ENABLE_OPENGL2 "Enable OpenGL 2.1 (On Supported Hardware)" ON) option(PD_ENABLE_OPENGL2 "Enable OpenGL 2.1 (On Supported Hardware)" ON)
option(PD_ENABLE_OPENGL3 "Enable OpenGL 3.3 (On Supported Hardware)" ON) option(PD_ENABLE_OPENGL3 "Enable OpenGL 3.3 (On Supported Hardware)" ON)
option(PD_ENABLE_DIRECTX9 "Enable DirectX9 Support" ON)
option(PD_ENABLE_CITRO3D "Enable Citro3D Support (3DS)" OFF)
option(PD_ENABLE_VULKAN "Not implemented yet" OFF) option(PD_ENABLE_VULKAN "Not implemented yet" OFF)
if(NOT WIN32) # cause we are not on windows...
set(PD_ENABLE_DIRECTX9 OFF)
endif()
add_library(pd-system STATIC add_library(pd-system STATIC
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl.cpp ${CMAKE_CURRENT_SOURCE_DIR}/source/gl-helper.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl2.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_opengl3.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_directx9.cpp
${CMAKE_CURRENT_SOURCE_DIR}/source/gfx_citro3d.cpp
) )
target_include_directories(pd-system target_include_directories(pd-system
PUBLIC PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include> $<INSTALL_INTERFACE:include>
) )
target_compile_options(pd-system target_compile_options(palladium
PUBLIC PUBLIC
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/source=source $<$<CXX_COMPILER_ID:GNU,Clang>:
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/include=include -fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/source=source
-fmacro-prefix-map=${CMAKE_CURRENT_SOURCE_DIR}/include=include
>
) )
target_link_libraries(pd-system target_compile_definitions(pd-system
PUBLIC PUBLIC
palladium::palladium $<$<BOOL:${PD_ENABLE_OPENGL2}>:PD_ENABLE_OPENGL2>
glad $<$<BOOL:${PD_ENABLE_OPENGL3}>:PD_ENABLE_OPENGL3>
) $<$<BOOL:${PD_ENABLE_VULKAN}>:PD_ENABLE_VULKAN>
$<$<BOOL:${PD_ENABLE_DIRECTX9}>:PD_ENABLE_DIRECTX9>
)
# Palladium
target_link_libraries(pd-system PUBLIC palladium::palladium)
# glad (if we have any OpenGL version included)
if(PD_ENABLE_OPENGL2 OR PD_ENABLE_OPENGL3)
target_link_libraries(pd-system
PUBLIC
glad
)
endif()
# DirectX9
if(PD_ENABLE_DIRECTX9)
target_link_libraries(pd-system
PUBLIC
d3d9
d3dcompiler
)
endif()

View File

@@ -0,0 +1,67 @@
#pragma once
#ifdef __3DS__
#include <3ds.h>
#endif
#include <limits>
#include <memory>
#include <stdexcept>
// Custom C++ Allocator class to interface with libctru linear heap memory
// based on this guide:
// https://johnfarrier.com/custom-allocators-in-c-high-performance-memory-management/
namespace PD {
template <typename T>
class LinearAllocator {
public:
using value_type = T;
LinearAllocator() noexcept = default;
template <typename U>
constexpr LinearAllocator(const LinearAllocator<U>&) noexcept {}
T* allocate(std::size_t n) {
if (n > max_size()) {
throw std::runtime_error("[PD] LinearAllocator: Bad alloc!");
}
#ifdef __3DS__
return static_cast<T*>(linearAlloc(n * sizeof(T)));
#else
return static_cast<T*>(malloc(n * sizeof(T)));
#endif
}
#ifdef __3DS__
void deallocate(T* p, std::size_t) noexcept { linearFree(p); }
#else
void deallocate(T* p, std::size_t) noexcept { free(p); }
#endif
template <class U, class... Args>
void construct(U* p, Args&&... args) {
::new ((void*)p) U(std::forward<Args>(args)...);
}
template <class U>
void destroy(U* p) {
p->~U();
}
friend bool operator==(const LinearAllocator, const LinearAllocator) {
return true;
}
friend bool operator!=(const LinearAllocator, const LinearAllocator) {
return false;
}
#ifdef __3DS__
// Use linearSpace free as max_size to not allocate out of bounds
// or to b eable to see a crash report screen.
size_t max_size() const noexcept { return linearSpaceFree(); }
#else
size_t max_size() const noexcept {
return std::numeric_limits<size_t>::max();
}
#endif
};
} // namespace PD

View File

@@ -0,0 +1,38 @@
#pragma once
#include <pd/drivers/gfx.hpp>
#include <pd_system/ctr-linear-allocator.hpp>
namespace PD {
struct GfxCitro3DConfig {
// Vertex Allocator
template <typename T>
using VertexAlloc = LinearAllocator<T>;
// Index Allocator
template <typename T>
using IndexAlloc = LinearAllocator<T>;
static constexpr size_t NumVertices = 32768; // 8192*4
static constexpr size_t NumIndices = 49152; // 8192*6
};
class GfxCitro3D : public GfxDriverBase<GfxCitro3DConfig> {
public:
GfxCitro3D() : GfxDriverBase("Citro3D") {}
~GfxCitro3D() {}
void SysInit() override;
void SysDeinit() override;
void Submit(size_t count, size_t start) override;
void BindTexture(TextureID id) override;
void SysReset() override;
TextureID LoadTexture(const std::vector<PD::u8>& pixels, int w, int h,
TextureFormat type = TextureFormat::RGBA32,
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const TextureID& tex) override;
private:
struct Impl;
Impl* impl = nullptr;
};
} // namespace PD

View File

@@ -0,0 +1,39 @@
#pragma once
#include <pd/drivers/gfx.hpp>
namespace PD {
struct GfxDirectX9Config {
// 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
};
class GfxDirectX9 : public GfxDriverBase<GfxDirectX9Config> {
public:
GfxDirectX9(void* device = nullptr)
: GfxDriverBase("DirectX9"), pDevice(device) {}
~GfxDirectX9() {}
void SysInit() override;
void SysDeinit() override;
void Submit(size_t count, size_t start) override;
void BindTexture(TextureID id) override;
void SysReset() override;
TextureID LoadTexture(const std::vector<PD::u8>& pixels, int w, int h,
TextureFormat type = TextureFormat::RGBA32,
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const TextureID& tex) override;
private:
struct Impl;
Impl* impl = nullptr;
void* pDevice = nullptr;
};
} // namespace PD

View File

@@ -3,22 +3,22 @@
#include <pd/drivers/gfx.hpp> #include <pd/drivers/gfx.hpp>
namespace PD { namespace PD {
struct GfxOpenGLConfig { struct GfxOpenGL2Config {
// Vertex Allocator // Vertex Allocator
template <typename T> template <typename T>
using VertexAlloc = std::allocator<T>; using VertexAlloc = std::allocator<T>;
// Index Allocator // Index Allocator
template <typename T> template <typename T>
using IndexAlloc = std::allocator<T>; using IndexAlloc = std::allocator<T>;
using IndexType = u32; // Index Type
static constexpr size_t NumVertices = 32768; // 8192*4 static constexpr size_t NumVertices = 32768; // 8192*4
static constexpr size_t NumIndices = 49152; // 8192*6 static constexpr size_t NumIndices = 49152; // 8192*6
}; };
class GfxOpenGL : public GfxDriverBase<GfxOpenGLConfig> {
class GfxOpenGL2 : public GfxDriverBase<GfxOpenGL2Config> {
public: public:
GfxOpenGL(): GfxDriverBase("OpenGL2") {} GfxOpenGL2() : GfxDriverBase("OpenGL2") {}
~GfxOpenGL() {} ~GfxOpenGL2() {}
void SysInit() override; void SysInit() override;
void SysDeinit() override; void SysDeinit() override;
@@ -38,5 +38,7 @@ class GfxOpenGL : public GfxDriverBase<GfxOpenGLConfig> {
int pLocTex = 0; int pLocTex = 0;
int pLocAlfa = 0; int pLocAlfa = 0;
int pLocProjection = 0; int pLocProjection = 0;
static const char* pVertCode;
static const char* pFragCode;
}; };
} // namespace PD } // namespace PD

View File

@@ -0,0 +1,44 @@
#pragma once
#include <pd/drivers/gfx.hpp>
namespace PD {
struct GfxOpenGL3Config {
// 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
};
class GfxOpenGL3 : public GfxDriverBase<GfxOpenGL3Config> {
public:
GfxOpenGL3() : GfxDriverBase("OpenGL3") {}
~GfxOpenGL3() {}
void SysInit() override;
void SysDeinit() override;
void Submit(size_t count, size_t start) override;
void BindTexture(TextureID id) override;
void SysReset() override;
TextureID LoadTexture(const std::vector<PD::u8>& pixels, int w, int h,
TextureFormat type = TextureFormat::RGBA32,
TextureFilter filter = TextureFilter::Linear) override;
void DeleteTexture(const TextureID& tex) override;
private:
u32 pShader = 0;
u32 VBO = 0;
u32 IBO = 0;
u32 VAO = 0;
int pLocTex = 0;
int pLocAlfa = 0;
int pLocProjection = 0;
static const char* pVertCode;
static const char* pFragCode;
};
} // namespace PD

View File

@@ -0,0 +1,7 @@
#pragma once
#include <pd/common.hpp>
namespace PD {
u32 CreateShaderProgram(const char* vert, const char* frag);
}

View File

@@ -0,0 +1,6 @@
#pragma once
#include <pd_system/gfx_citro3d.hpp>
#include <pd_system/gfx_directx9.hpp>
#include <pd_system/gfx_opengl2.hpp>
#include <pd_system/gfx_opengl3.hpp>

View File

@@ -0,0 +1,69 @@
// Well yes, i finally try it
#include <pd_system/gfx_citro3d.hpp>
#if defined(PD_ENABLE_CITRO3D) // && defined(__3DS__)
#include <3ds.h>
#include <citro3d.h>
#include <pd/drivers/drivers.hpp>
namespace PD {
struct GfxCitro3D::Impl {};
void GfxCitro3D::SysInit() {
if (impl) return;
PDLOG("GfxCitro3D::SysInit();");
impl = new Impl();
}
void GfxCitro3D::SysDeinit() {
if (!impl) return;
delete impl;
impl = nullptr;
PDLOG("GfxCitro3D::SysDeinit()");
}
void GfxCitro3D::Submit(size_t count, size_t start) {
if (!impl) return;
}
void GfxCitro3D::BindTexture(TextureID id) {
if (!impl) return;
}
void GfxCitro3D::SysReset() {
if (!impl) return;
}
TextureID GfxCitro3D::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
if (!impl) return 0;
return 0;
}
void GfxCitro3D::DeleteTexture(const TextureID& tex) {
if (!tex) return;
}
} // namespace PD
#else
namespace PD {
void GfxCitro3D::SysInit() {
PDLOG(
"GfxCitro3D::SysInit: Citro3D Driver is not included in "
"palladium-system");
}
void GfxCitro3D::SysDeinit() {}
void GfxCitro3D::Submit(size_t count, size_t start) {}
void GfxCitro3D::BindTexture(TextureID id) {}
void GfxCitro3D::SysReset() {}
TextureID GfxCitro3D::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
return 0;
}
void GfxCitro3D::DeleteTexture(const TextureID& tex) {}
} // namespace PD
#endif

View File

@@ -0,0 +1,267 @@
// Well yes, i finally try it
#include <pd_system/gfx_directx9.hpp>
// Sicher ist sicher
#if defined(PD_ENABLE_DIRECTX9) && defined(_WIN32)
#include <d3d9.h>
#include <d3dcompiler.h>
#include <pd/drivers/drivers.hpp>
namespace PD {
static const char* g_vsCode = R"(
float4x4 projection;
struct VS_IN {
float2 pos : POSITION0;
float2 uv : TEXCOORD0;
float4 col : COLOR0;
};
struct VS_OUT {
float4 pos : POSITION0;
float2 uv : TEXCOORD0;
float4 col : COLOR0;
};
VS_OUT main(VS_IN input) {
VS_OUT o;
o.pos = mul(projection, float4(input.pos, 0.0, 1.0));
o.uv = input.uv;
o.col = input.col;
return o;
}
)";
static const char* g_psCode = R"(
sampler2D tex : register(s0);
bool alfa;
struct PS_IN {
float2 uv : TEXCOORD0;
float4 col : COLOR0;
};
float4 main(PS_IN input) : COLOR0 {
float4 tc = tex2D(tex, input.uv);
if (alfa)
return float4(input.col.rgb, tc.a * input.col.a);
else
return tc * input.col;
}
)";
struct GfxDirectX9::Impl {
IDirect3DDevice9* Device = nullptr;
IDirect3DVertexBuffer9* VBO = nullptr;
IDirect3DIndexBuffer9* IBO = nullptr;
IDirect3DVertexDeclaration9* Decl = nullptr;
IDirect3DVertexShader9* VS = nullptr;
IDirect3DPixelShader9* FS = nullptr;
IDirect3DTexture9* CurrentTex = nullptr;
};
void GfxDirectX9::SysInit() {
if (impl) return;
PDLOG("GfxDirectX9::SysInit();");
impl = new Impl();
impl->Device = (IDirect3DDevice9*)pDevice;
if (impl->Device) {
D3DVERTEXELEMENT9 elements[]{
{0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION,
0},
{0, 8, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD,
0},
{0, 16, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR,
0},
D3DDECL_END()};
impl->Device->CreateVertexDeclaration(elements, &impl->Decl);
impl->Device->CreateVertexBuffer(
GfxDirectX9Config::NumVertices * sizeof(PD::Li::Vertex),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY, 0, D3DPOOL_DEFAULT, &impl->VBO,
nullptr);
impl->Device->CreateIndexBuffer(GfxDirectX9Config::NumIndices * sizeof(u16),
D3DUSAGE_DYNAMIC | D3DUSAGE_WRITEONLY,
D3DFMT_INDEX16, D3DPOOL_DEFAULT, &impl->IBO,
nullptr);
ID3DBlob* vsBlob = nullptr;
ID3DBlob* errBlob = nullptr;
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: {}",
errBlob ? (char*)errBlob->GetBufferPointer() : "");
} else {
impl->Device->CreateVertexShader((DWORD*)vsBlob->GetBufferPointer(),
&impl->VS);
}
if (vsBlob) vsBlob->Release();
if (errBlob) errBlob->Release();
ID3DBlob* psBlob = nullptr;
errBlob = nullptr;
hr = D3DCompile(g_psCode, strlen(g_psCode), nullptr, nullptr, nullptr,
"main", "ps_2_0", 0, 0, &psBlob, &errBlob);
if (FAILED(hr)) {
PDLOG("Pixel Shader compile error: {}",
errBlob ? (char*)errBlob->GetBufferPointer() : "");
} else {
impl->Device->CreatePixelShader((DWORD*)psBlob->GetBufferPointer(),
&impl->FS);
}
if (psBlob) psBlob->Release();
if (errBlob) errBlob->Release();
} else {
PDLOG(
"GfxDirectX9::SysInit Error: pDevice is not set!\nYOu need to include "
"your D3D9 Device as "
"folowing:\nPD::Gfx::UseDriver<PD::GfxDirectX9>(D3D9Device);");
}
}
void GfxDirectX9::SysDeinit() {
if (!impl || !impl->Device) return;
if (impl->VBO) impl->VBO->Release();
if (impl->IBO) impl->IBO->Release();
if (impl->Decl) impl->Decl->Release();
if (impl->VS) impl->VS->Release();
if (impl->FS) impl->FS->Release();
delete impl;
impl = nullptr;
PDLOG("GfxDirectX9::SysDeinit()");
}
void GfxDirectX9::Submit(size_t count, size_t start) {
if (!impl || !impl->Device || !impl->VBO || !impl->IBO) return;
impl->Device->SetVertexShaderConstantF(
0, reinterpret_cast<const float*>(&Projection), 4);
void* vptr;
impl->VBO->Lock(0, 0, &vptr, D3DLOCK_DISCARD);
memcpy(vptr, GetVertexBufPtr(0), CurrentVertex * sizeof(PD::Li::Vertex));
impl->VBO->Unlock();
void* iptr;
impl->IBO->Lock(0, 0, &iptr, D3DLOCK_DISCARD);
memcpy(iptr, GetIndexBufPtr(0), CurrentIndex * sizeof(u16));
impl->IBO->Unlock();
impl->Device->SetStreamSource(0, impl->VBO, 0, sizeof(PD::Li::Vertex));
impl->Device->SetIndices(impl->IBO);
impl->Device->SetVertexDeclaration(impl->Decl);
impl->Device->SetVertexShader(impl->VS);
impl->Device->SetPixelShader(impl->FS);
impl->Device->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, CurrentVertex,
start, count / 3);
}
void GfxDirectX9::BindTexture(TextureID id) {
if (!impl || !impl->Device) return;
impl->CurrentTex = (IDirect3DTexture9*)id;
impl->Device->SetTexture(0, impl->CurrentTex);
bool a8 = false;
if (impl->CurrentTex) {
D3DSURFACE_DESC desc;
impl->CurrentTex->GetLevelDesc(0, &desc);
a8 = (desc.Format == D3DFMT_A8);
}
float v = a8 ? 1.0f : 0.0f;
impl->Device->SetPixelShaderConstantF(0, &v, 1);
}
void GfxDirectX9::SysReset() {
if (!impl || !impl->Device) return;
impl->Device->SetRenderState(D3DRS_ALPHABLENDENABLE, TRUE);
impl->Device->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA);
impl->Device->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA);
}
TextureID GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
if (!impl || !impl->Device) return 0;
IDirect3DTexture9* tex = nullptr;
D3DFORMAT fmt = D3DFMT_A8R8G8B8;
if (type == TextureFormat::RGB24)
fmt = D3DFMT_X8R8G8B8;
else if (type == TextureFormat::A8)
fmt = D3DFMT_A8;
HRESULT hr = impl->Device->CreateTexture(w, h, 1, 0, fmt, D3DPOOL_MANAGED,
&tex, nullptr);
if (FAILED(hr) || !tex) return 0;
D3DLOCKED_RECT rect;
tex->LockRect(0, &rect, nullptr, 0);
if (type == TextureFormat::RGB24) {
u8* dstRow = reinterpret_cast<u8*>(rect.pBits);
for (int y = 0; y < h; ++y) {
u32* dst = reinterpret_cast<u32*>(dstRow);
for (int x = 0; x < w; ++x) {
u8 r = pixels[(y * w + x) * 3 + 0];
u8 g = pixels[(y * w + x) * 3 + 1];
u8 b = pixels[(y * w + x) * 3 + 2];
dst[x] = (0xFF << 24) | (r << 16) | (g << 8) | b; // X8R8G8B8
}
dstRow += rect.Pitch;
}
} else if (type == TextureFormat::RGBA32) {
u8* dstRow = reinterpret_cast<u8*>(rect.pBits);
for (int y = 0; y < h; ++y) {
u32* dst = reinterpret_cast<u32*>(dstRow);
for (int x = 0; x < w; ++x) {
u8 r = pixels[(y * w + x) * 4 + 0];
u8 g = pixels[(y * w + x) * 4 + 1];
u8 b = pixels[(y * w + x) * 4 + 2];
u8 a = pixels[(y * w + x) * 4 + 3];
dst[x] = (a << 24) | (r << 16) | (g << 8) | b; // A8R8G8B8
}
dstRow += rect.Pitch;
}
} else if (type == TextureFormat::A8) {
u8* dstRow = reinterpret_cast<u8*>(rect.pBits);
for (int y = 0; y < h; ++y) {
memcpy(dstRow, &pixels[y * w], w);
dstRow += rect.Pitch;
}
}
tex->UnlockRect(0);
PDLOG("GfxDirectX9::LoadTexture -> [{}] 0x{:X}, [{}, {}]", PD::ivec2(w, h),
(TextureID)tex, type, filter);
return (TextureID)tex;
}
void GfxDirectX9::DeleteTexture(const TextureID& tex) {
if (!tex) return;
IDirect3DTexture9* t = (IDirect3DTexture9*)tex;
t->Release();
}
} // namespace PD
#else
namespace PD {
void GfxDirectX9::SysInit() {
PDLOG(
"GfxDirectX9::SysInit: DirectX9 Driver is not included in "
"palladium-system");
}
void GfxDirectX9::SysDeinit() {}
void GfxDirectX9::Submit(size_t count, size_t start) {}
void GfxDirectX9::BindTexture(TextureID id) {}
void GfxDirectX9::SysReset() {}
TextureID GfxDirectX9::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
return 0;
}
void GfxDirectX9::DeleteTexture(const TextureID& tex) {}
} // namespace PD
#endif

View File

@@ -1,56 +1,13 @@
#include <pd_system/gfx_opengl2.hpp>
#if defined(PD_ENABLE_OPENGL2)
#include <glad/glad.h> #include <glad/glad.h>
#include <gfx_opengl.hpp> #include <pd/drivers/drivers.hpp>
#include <pd_system/gl-helper.hpp>
#include "pd/common.hpp"
#include "pd/drivers/gfx.hpp"
namespace PD { namespace PD {
GLuint compileShader(const std::string& source, GLenum type) { const char* GfxOpenGL2::pVertCode = R"(
GLuint shader = glCreateShader(type);
const char* src = source.c_str();
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "Shader Compilation Error: " << infoLog << std::endl;
}
return shader;
}
GLuint createShaderProgram(const std::string& vertexShaderSource,
const std::string& fragmentShaderSource) {
GLuint vertexShader = compileShader(vertexShaderSource, GL_VERTEX_SHADER);
GLuint fragmentShader =
compileShader(fragmentShaderSource, GL_FRAGMENT_SHADER);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
GLint success;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cerr << "Shader Program Linking Error: " << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
if (success) PDLOG("Shader [{}] compiled sucessfully", shaderProgram);
return shaderProgram;
}
const char* vertex_shader = R"(
#version 120 #version 120
attribute vec2 pos; attribute vec2 pos;
@@ -71,7 +28,7 @@ const char* vertex_shader = R"(
} }
)"; )";
const char* frag_shader = R"( const char* GfxOpenGL2::pFragCode = R"(
#version 120 #version 120
varying vec2 oUV; varying vec2 oUV;
@@ -90,7 +47,7 @@ const char* frag_shader = R"(
} }
)"; )";
void GfxOpenGL::pSetupShaderAttribs(u32 shader) { void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {
GLint _pos = glGetAttribLocation(shader, "pos"); GLint _pos = glGetAttribLocation(shader, "pos");
GLint _uv = glGetAttribLocation(shader, "uv"); GLint _uv = glGetAttribLocation(shader, "uv");
GLint _color = glGetAttribLocation(shader, "color"); GLint _color = glGetAttribLocation(shader, "color");
@@ -108,15 +65,15 @@ void GfxOpenGL::pSetupShaderAttribs(u32 shader) {
glEnableVertexAttribArray(_color); glEnableVertexAttribArray(_color);
} }
void GfxOpenGL::SysInit() { void GfxOpenGL2::SysInit() {
pShader = createShaderProgram(vertex_shader, frag_shader); pShader = CreateShaderProgram(pVertCode, pFragCode);
glUseProgram(pShader); glUseProgram(pShader);
glGenBuffers(1, &VBO); glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO);
pSetupShaderAttribs(pShader);
glGenBuffers(1, &IBO); glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
pSetupShaderAttribs(pShader);
pLocTex = glGetUniformLocation(pShader, "tex"); pLocTex = glGetUniformLocation(pShader, "tex");
pLocAlfa = glGetUniformLocation(pShader, "alfa"); pLocAlfa = glGetUniformLocation(pShader, "alfa");
pLocProjection = glGetUniformLocation(pShader, "projection"); pLocProjection = glGetUniformLocation(pShader, "projection");
@@ -124,21 +81,20 @@ void GfxOpenGL::SysInit() {
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
PDLOG( PDLOG(
"GfxOpenGL::SysInit():\n pShader = {}\n pLocTex = {}\n pLocAlfa = " "GfxOpenGL2::SysInit():\n pShader = {}\n pLocTex = {}\n pLocAlfa = "
"{}\n pLocProjection = {}\n VBO = {}\n IBO = {}", "{}\n pLocProjection = {}\n VBO = {}\n IBO = {}",
pShader, pLocTex, pLocAlfa, pLocProjection, VBO, IBO); pShader, pLocTex, pLocAlfa, pLocProjection, VBO, IBO);
} }
void GfxOpenGL::SysDeinit() { void GfxOpenGL2::SysDeinit() {
glDeleteBuffers(1, &VBO); glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &IBO); glDeleteBuffers(1, &IBO);
PDLOG("GfxOpenGL::SysDeinit()"); PDLOG("GfxOpenGL2::SysDeinit()");
} }
void GfxOpenGL::Submit(size_t count, size_t start) { void GfxOpenGL2::Submit(size_t count, size_t start) {
BindTexture(CurrentTex); BindTexture(CurrentTex);
glUseProgram(pShader); glUseProgram(pShader);
pSetupShaderAttribs(pShader);
glUniformMatrix4fv(pLocProjection, 1, GL_FALSE, Projection.m.data()); glUniformMatrix4fv(pLocProjection, 1, GL_FALSE, Projection.m.data());
glBindBuffer(GL_ARRAY_BUFFER, VBO); glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::Li::Vertex), glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::Li::Vertex),
@@ -148,14 +104,17 @@ void GfxOpenGL::Submit(size_t count, size_t start) {
glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(PD::u16), glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(PD::u16),
GetIndexBufPtr(0), GL_DYNAMIC_DRAW); GetIndexBufPtr(0), GL_DYNAMIC_DRAW);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, pSetupShaderAttribs(pShader);
GLint ibo = 0;
glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &ibo);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT,
reinterpret_cast<void*>(start * sizeof(u16))); reinterpret_cast<void*>(start * sizeof(u16)));
glBindBuffer(GL_ARRAY_BUFFER, 0); glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
BindTexture(0); BindTexture(0);
} }
void GfxOpenGL::BindTexture(TextureID id) { void GfxOpenGL2::BindTexture(TextureID id) {
glActiveTexture(GL_TEXTURE0); glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, (GLuint)id); glBindTexture(GL_TEXTURE_2D, (GLuint)id);
glUniform1i(pLocTex, 0); glUniform1i(pLocTex, 0);
@@ -164,25 +123,25 @@ void GfxOpenGL::BindTexture(TextureID id) {
glUniform1i(pLocAlfa, fmt == GL_ALPHA); glUniform1i(pLocAlfa, fmt == GL_ALPHA);
} }
void GfxOpenGL::SysReset() { void GfxOpenGL2::SysReset() {
glEnable(GL_BLEND); glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
} }
TextureID GfxOpenGL::LoadTexture(const std::vector<PD::u8>& pixels, int w, TextureID GfxOpenGL2::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type, int h, TextureFormat type,
TextureFilter filter) { TextureFilter filter) {
GLuint texID; GLuint texID;
glGenTextures(1, &texID); glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID); glBindTexture(GL_TEXTURE_2D, texID);
// Set base format (Always using RGBA as base) // Set base format (Always using RGBA as base)
GLenum fmt = GL_RGBA; GLenum fmt = GL_RGBA;
/*if (type == PD::Li::Texture::Type::RGB24) { if (type == TextureFormat::RGB24) {
fmt = GL_RGB; fmt = GL_RGB;
} else if (type == PD::Li::Texture::Type::A8) { } else if (type == TextureFormat::A8) {
fmt = GL_ALPHA; fmt = GL_ALPHA;
}*/ }
glTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE, glTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE,
pixels.data()); pixels.data());
if (filter == TextureFilter::Linear) { if (filter == TextureFilter::Linear) {
@@ -193,12 +152,33 @@ TextureID GfxOpenGL::LoadTexture(const std::vector<PD::u8>& pixels, int w,
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
} }
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
PDLOG("GfxOpenGL::LoadTexture -> [{}] {}", PD::ivec2(w, h), texID); PDLOG("GfxOpenGL2::LoadTexture -> [{}] {}, [{}, {}]", PD::ivec2(w, h), texID,
type, filter);
return texID; return texID;
} }
void GfxOpenGL::DeleteTexture(const TextureID& tex) { void GfxOpenGL2::DeleteTexture(const TextureID& tex) {
GLuint tex_ = tex; GLuint tex_ = tex;
glDeleteTextures(1, &tex_); glDeleteTextures(1, &tex_);
} }
} // namespace PD } // namespace PD
#else
namespace PD {
void GfxOpenGL2::SysInit() {
PDLOG(
"GfxOpenGL2::SysInit: OpenGL2 Driver is not included in "
"palladium-system");
}
void GfxOpenGL2::SysDeinit() {}
void GfxOpenGL2::Submit(size_t count, size_t start) {}
void GfxOpenGL2::BindTexture(TextureID id) {}
void GfxOpenGL2::SysReset() {}
TextureID GfxOpenGL2::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
return 0;
}
void GfxOpenGL2::DeleteTexture(const TextureID& tex) {}
void GfxOpenGL2::pSetupShaderAttribs(u32 shader) {}
} // namespace PD
#endif

View File

@@ -0,0 +1,180 @@
#include <pd_system/gfx_opengl3.hpp>
#if defined(PD_ENABLE_OPENGL3)
#include <glad/glad.h>
#include <pd/drivers/drivers.hpp>
#include <pd_system/gl-helper.hpp>
namespace PD {
const char* GfxOpenGL3::pVertCode = R"(
#version 330 core
layout(location = 0) in vec2 pos;
layout(location = 1) in vec2 uv;
layout(location = 2) in vec4 color;
out vec2 oUV;
out vec4 oColor;
// Probably forgot about this matrix and
// searched hours for why the rendering isn't working :/
uniform mat4 projection;
void main() {
gl_Position = projection*vec4(pos, 0.0, 1.0);
oUV = uv;
oColor = color;
}
)";
const char* GfxOpenGL3::pFragCode = R"(
#version 330 core
in vec2 oUV;
in vec4 oColor;
uniform sampler2D tex;
uniform bool alfa;
out vec4 FragColor;
void main() {
vec4 tc = texture(tex, oUV);
if (alfa) {
FragColor = vec4(oColor.rgb, tc.a * oColor.a);
} else {
FragColor = tc * oColor;
}
}
)";
void GfxOpenGL3::SysInit() {
pShader = CreateShaderProgram(pVertCode, pFragCode);
glUseProgram(pShader);
glGenVertexArrays(1, &VAO);
glBindVertexArray(VAO);
glGenBuffers(1, &VBO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, sizeof(PD::Li::Vertex),
(void*)offsetof(PD::Li::Vertex, pos));
glEnableVertexAttribArray(1);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(PD::Li::Vertex),
(void*)offsetof(PD::Li::Vertex, uv));
glEnableVertexAttribArray(2);
glVertexAttribPointer(2, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(PD::Li::Vertex),
(void*)offsetof(PD::Li::Vertex, color));
glGenBuffers(1, &IBO);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
pLocTex = glGetUniformLocation(pShader, "tex");
pLocAlfa = glGetUniformLocation(pShader, "alfa");
pLocProjection = glGetUniformLocation(pShader, "projection");
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() {
glDeleteBuffers(1, &VBO);
glDeleteBuffers(1, &IBO);
glDeleteVertexArrays(1, &VAO);
PDLOG("GfxOpenGL3::SysDeinit()");
}
void GfxOpenGL3::Submit(size_t count, size_t start) {
BindTexture(CurrentTex);
glUseProgram(pShader);
glUniformMatrix4fv(pLocProjection, 1, GL_FALSE, Projection.m.data());
glBindVertexArray(VAO);
glBindBuffer(GL_ARRAY_BUFFER, VBO);
glBufferData(GL_ARRAY_BUFFER, CurrentVertex * sizeof(PD::Li::Vertex),
GetVertexBufPtr(0), GL_DYNAMIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, IBO);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, CurrentIndex * sizeof(u16),
GetIndexBufPtr(0), GL_DYNAMIC_DRAW);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_SHORT,
reinterpret_cast<void*>(start * sizeof(u16)));
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glBindVertexArray(0);
BindTexture(0);
}
void GfxOpenGL3::BindTexture(TextureID id) {
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, (GLuint)id);
glUniform1i(pLocTex, 0);
GLint fmt = 0;
glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_INTERNAL_FORMAT, &fmt);
glUniform1i(pLocAlfa, fmt == GL_ALPHA);
}
void GfxOpenGL3::SysReset() {
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
}
TextureID GfxOpenGL3::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
GLuint texID;
glGenTextures(1, &texID);
glBindTexture(GL_TEXTURE_2D, texID);
// Set base format (Always using RGBA as base)
GLenum fmt = GL_RGBA;
if (type == TextureFormat::RGB24) {
fmt = GL_RGB;
} else if (type == TextureFormat::A8) {
fmt = GL_ALPHA;
}
glTexImage2D(GL_TEXTURE_2D, 0, fmt, w, h, 0, fmt, GL_UNSIGNED_BYTE,
pixels.data());
if (filter == TextureFilter::Linear) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
} else if (filter == TextureFilter::Nearest) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
}
glBindTexture(GL_TEXTURE_2D, 0);
PDLOG("GfxOpenGL3::LoadTexture -> [{}] {}, [{}, {}]", PD::ivec2(w, h), texID,
type, filter);
return texID;
}
void GfxOpenGL3::DeleteTexture(const TextureID& tex) {
GLuint tex_ = tex;
glDeleteTextures(1, &tex_);
}
} // namespace PD
#else
namespace PD {
void GfxOpenGL3::SysInit() {
PDLOG(
"GfxOpenGL3::SysInit: OpenGL3 Driver is not included in "
"palladium-system");
}
void GfxOpenGL3::SysDeinit() {}
void GfxOpenGL3::Submit(size_t count, size_t start) {}
void GfxOpenGL3::BindTexture(TextureID id) {}
void GfxOpenGL3::SysReset() {}
TextureID GfxOpenGL3::LoadTexture(const std::vector<PD::u8>& pixels, int w,
int h, TextureFormat type,
TextureFilter filter) {
return 0;
}
void GfxOpenGL3::DeleteTexture(const TextureID& tex) {}
void GfxOpenGL3::pSetupShaderAttribs(u32 shader) {}
} // namespace PD
#endif

View File

@@ -0,0 +1,46 @@
#include <glad/glad.h>
#include <iostream>
#include <pd_system/gl-helper.hpp>
namespace PD {
GLuint compileShader(const char* src, GLenum type) {
GLuint shader = glCreateShader(type);
glShaderSource(shader, 1, &src, nullptr);
glCompileShader(shader);
GLint success;
glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
if (!success) {
char infoLog[512];
glGetShaderInfoLog(shader, 512, nullptr, infoLog);
std::cerr << "Shader Compilation Error: " << infoLog << std::endl;
}
return shader;
}
u32 CreateShaderProgram(const char* vert, const char* frag) {
GLuint vertexShader = compileShader(vert, GL_VERTEX_SHADER);
GLuint fragmentShader = compileShader(frag, GL_FRAGMENT_SHADER);
GLuint shaderProgram = glCreateProgram();
glAttachShader(shaderProgram, vertexShader);
glAttachShader(shaderProgram, fragmentShader);
glLinkProgram(shaderProgram);
GLint success;
glGetProgramiv(shaderProgram, GL_LINK_STATUS, &success);
if (!success) {
char infoLog[512];
glGetProgramInfoLog(shaderProgram, 512, nullptr, infoLog);
std::cerr << "Shader Program Linking Error: " << infoLog << std::endl;
}
glDeleteShader(vertexShader);
glDeleteShader(fragmentShader);
if (success) PDLOG("Shader [{}] compiled sucessfully", shaderProgram);
return shaderProgram;
}
} // namespace PD

View File

@@ -23,6 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE. SOFTWARE.
*/ */
#include <array>
#include <chrono> #include <chrono>
#include <cmath> #include <cmath>
#include <cstddef> #include <cstddef>
@@ -43,7 +44,7 @@ using u16 = unsigned short;
using u32 = unsigned int; using u32 = unsigned int;
using u64 = unsigned long long; using u64 = unsigned long long;
using ptr = uintptr_t; using ptr = uintptr_t;
void Log(const std::string& txt); PD_API void Log(const std::string& txt);
template <typename... Args> template <typename... Args>
void Log(std::format_string<Args...> fmt, Args&&... args) { void Log(std::format_string<Args...> fmt, Args&&... args) {
std::string msg = std::format(fmt, std::forward<Args>(args)...); std::string msg = std::format(fmt, std::forward<Args>(args)...);

View File

@@ -93,6 +93,6 @@ struct std::formatter<PD::Color> : std::formatter<std::string> {
std::format_parse_context::const_iterator end, std::format_parse_context::const_iterator end,
size_t len, const char* what) { size_t len, const char* what) {
return (end - it >= static_cast<std::ptrdiff_t>(len) && return (end - it >= static_cast<std::ptrdiff_t>(len) &&
std::string_view(it, len) == what); std::string_view(&*it, len) == what); // msvc things...
} }
}; };

View File

@@ -1,4 +1,5 @@
#pragma once #pragma once
#include <pd/drivers/formatters.hpp>
#include <pd/drivers/gfx.hpp>
#include <pd/drivers/os.hpp> #include <pd/drivers/os.hpp>
#include <pd/drivers/gfx.hpp>

View File

@@ -0,0 +1,44 @@
#pragma once
#include <pd/drivers/gfx.hpp>
template <>
struct std::formatter<PD::TextureFilter> {
constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const PD::TextureFilter& value, FormatContext& ctx) const {
std::string_view ret = "Unknown";
switch (value) {
case PD::TextureFilter::Linear:
ret = "Linear";
break;
case PD::TextureFilter::Nearest:
ret = "Nearest";
break;
}
return std::format_to(ctx.out(), "{}", ret);
}
};
template <>
struct std::formatter<PD::TextureFormat> {
constexpr auto parse(std::format_parse_context& ctx) { return ctx.begin(); }
template <typename FormatContext>
auto format(const PD::TextureFormat& value, FormatContext& ctx) const {
std::string_view ret = "Unknown";
switch (value) {
case PD::TextureFormat::RGBA32:
ret = "RGBA32";
break;
case PD::TextureFormat::RGB24:
ret = "RGB24";
break;
case PD::TextureFormat::A8:
ret = "A8";
break;
}
return std::format_to(ctx.out(), "{}", ret);
}
};

View File

@@ -19,6 +19,7 @@ enum class TextureFilter {
enum class TextureFormat { enum class TextureFormat {
RGBA32, RGBA32,
RGB24,
A8, A8,
}; };
@@ -69,20 +70,17 @@ struct DefaultGfxConfig {
// Index Allocator // Index Allocator
template <typename T> template <typename T>
using IndexAlloc = std::allocator<T>; using IndexAlloc = std::allocator<T>;
using IndexType = u16; // Index Type
static constexpr size_t NumVertices = 32768; // 8192*4 static constexpr size_t NumVertices = 32768; // 8192*4
static constexpr size_t NumIndices = 49152; // 8192*6 static constexpr size_t NumIndices = 49152; // 8192*6
}; };
template <typename Config = DefaultGfxConfig> template <typename Config = DefaultGfxConfig>
class PD_API GfxDriverBase : public GfxDriver { class GfxDriverBase : public GfxDriver {
public: public:
using IndexType = Config::IndexType;
using VtxPool = using VtxPool =
Pool<Li::Vertex, typename Config::template VertexAlloc<Li::Vertex>>; Pool<Li::Vertex, typename Config::template VertexAlloc<Li::Vertex>>;
using IdxPool = using IdxPool = Pool<u16, typename Config::template VertexAlloc<u16>>;
Pool<IndexType, typename Config::template VertexAlloc<IndexType>>;
GfxDriverBase(std::string_view name = "Default") : GfxDriver(name) {} GfxDriverBase(std::string_view name = "Default") : GfxDriver(name) {}
virtual ~GfxDriverBase() {} virtual ~GfxDriverBase() {}
@@ -111,17 +109,19 @@ class PD_API GfxDriverBase : public GfxDriver {
for (size_t i = 0; i < c.IndexCount; i++) { for (size_t i = 0; i < c.IndexCount; i++) {
pIdx[i] = CurrentVertex + c.FirstIndex[i]; pIdx[i] = CurrentVertex + c.FirstIndex[i];
} }
CurrentIndex += c.IndexCount;
CurrentVertex += c.VertexCount;
for (size_t i = 0; i < c.VertexCount; i++) { for (size_t i = 0; i < c.VertexCount; i++) {
pVtx[i] = c.FirstVertex[i]; pVtx[i] = c.FirstVertex[i];
} }
index++; index++;
} }
Submit(index - startidx, startidx); Submit(CurrentIndex - startidx, startidx);
} }
} }
protected: protected:
IndexType* GetIndexBufPtr(size_t start) { return &pIdxPool[start]; } u16* GetIndexBufPtr(size_t start) { return &pIdxPool[start]; }
Li::Vertex* GetVertexBufPtr(size_t start) { return &pVtxPool[start]; } Li::Vertex* GetVertexBufPtr(size_t start) { return &pVtxPool[start]; }
void ResetPools() override { void ResetPools() override {
pVtxPool.Reset(); pVtxPool.Reset();

View File

@@ -5,8 +5,8 @@
namespace PD { namespace PD {
namespace Li { namespace Li {
void InitPools(size_t max_vertices = 32768); PD_API void InitPools(size_t max_vertices = 32768);
Vertex* AllocateVertices(size_t count); PD_API Vertex* AllocateVertices(size_t count);
u16* AllocateIndices(size_t count); PD_API u16* AllocateIndices(size_t count);
} // namespace Li } // namespace Li
} // namespace PD } // namespace PD

View File

@@ -1,6 +1,6 @@
#include <iostream> #include <iostream>
#include <pd/common.hpp> #include <pd/common.hpp>
void PD::Log(const std::string& txt) { PD_API void PD::Log(const std::string& txt) {
std::cout << "[PD] " << txt << std::endl; std::cout << "[PD] " << txt << std::endl;
} }

View File

@@ -3,19 +3,20 @@
namespace PD { namespace PD {
PD_API std::unique_ptr<GfxDriver> Gfx::driver; PD_API std::unique_ptr<GfxDriver> Gfx::driver;
GfxDriver::GfxDriver(std::string_view name) : DriverInterface(name) {} PD_API GfxDriver::GfxDriver(std::string_view name) : DriverInterface(name) {}
void GfxDriver::SetViewPort(const ivec2& size) { PD_API void GfxDriver::SetViewPort(const ivec2& size) {
ViewPort = size; ViewPort = size;
Projection = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f); Projection = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f);
} }
void GfxDriver::SetViewPort(int x, int y) {
PD_API void GfxDriver::SetViewPort(int x, int y) {
ViewPort.x = x; ViewPort.x = x;
ViewPort.y = y; ViewPort.y = y;
Projection = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f); Projection = Mat4::Ortho(0.f, ViewPort.x, ViewPort.y, 0.f, 1.f, -1.f);
} }
void GfxDriver::Reset() { PD_API void GfxDriver::Reset() {
CurrentVertex = 0; CurrentVertex = 0;
CurrentIndex = 0; CurrentIndex = 0;
ResetPools(); ResetPools();

View File

@@ -9,16 +9,16 @@ namespace Li {
PD::Pool<Vertex> pVtxPool; PD::Pool<Vertex> pVtxPool;
PD::Pool<u16> pIdxPool; PD::Pool<u16> pIdxPool;
void InitPools(size_t max_vertices) { PD_API void InitPools(size_t max_vertices) {
pVtxPool.Init(max_vertices); pVtxPool.Init(max_vertices);
pIdxPool.Init(max_vertices * 2); pIdxPool.Init(max_vertices * 2);
} }
Vertex* AllocateVertices(size_t count) { return pVtxPool.Allocate(count); } PD_API Vertex* AllocateVertices(size_t count) { return pVtxPool.Allocate(count); }
u16* AllocateIndices(size_t count) { return pIdxPool.Allocate(count); } PD_API u16* AllocateIndices(size_t count) { return pIdxPool.Allocate(count); }
void ResetPools() { PD_API void ResetPools() {
pVtxPool.Reset(); pVtxPool.Reset();
pIdxPool.Reset(); pIdxPool.Reset();
} }

View File

@@ -3,4 +3,4 @@ cmake_minimum_required(VERSION 3.22)
project(gfx-tests) project(gfx-tests)
add_executable(gfx-tests ${CMAKE_CURRENT_SOURCE_DIR}/source/main.cpp) add_executable(gfx-tests ${CMAKE_CURRENT_SOURCE_DIR}/source/main.cpp)
target_link_libraries(gfx-tests PRIVATE palladium::palladium pd-system glfw) target_link_libraries(gfx-tests PRIVATE palladium::palladium pd-system glfw stb)

View File

@@ -3,42 +3,98 @@
#include <GLFW/glfw3.h> #include <GLFW/glfw3.h>
#include <format> #include <format>
#include <gfx_opengl.hpp>
#include <iostream> #include <iostream>
#include <palladium> #include <palladium>
#include <pdsystem>
#include "pd/core/vec2.hpp" #include "pd/core/vec2.hpp"
#include "pd/lithium/pools.hpp" #include "pd/lithium/pools.hpp"
#include "pd/lithium/vertex.hpp" #include "pd/lithium/vertex.hpp"
#ifdef _WIN32
#include <d3d9.h>
#define GLFW_EXPOSE_NATIVE_WIN32
#include <GLFW/glfw3native.h>
#endif
#define STB_IMAGE_IMPLEMENTATION
#include <stb_image.h>
enum class Driver {
Unknown = 0,
OpenGL2 = 1,
OpenGL3 = 2,
DirectX9 = 3,
};
PD::TextureID LoadTex(const std::string& path) {
int w, h, c;
stbi_uc* buf = stbi_load(path.c_str(), &w, &h, &c, 4);
return PD::Gfx::LoadTexture(std::vector<PD::u8>(buf, buf + (w * h * 4)), w,
h);
}
class App { class App {
public: public:
App() { App(Driver d = Driver::OpenGL3) : pDriver(d) {
PD::Os::UseDriver<PD::OsDriver>(); PD::Os::UseDriver<PD::OsDriver>();
PD::Gfx::UseDriver<PD::GfxOpenGL>();
glfwInit(); glfwInit();
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); std::string winname = "gfx_test";
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); if (d == Driver::OpenGL2) {
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 2);
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GLFW_TRUE); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 1);
window = glfwCreateWindow(1280, 720, "gfx_tests", nullptr, nullptr); PD::Gfx::UseDriver<PD::GfxOpenGL2>();
winname += " (OpenGL2)";
} else if (d == Driver::OpenGL3) {
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
PD::Gfx::UseDriver<PD::GfxOpenGL3>();
winname += " (OpenGL3)";
} else if (d == Driver::DirectX9) {
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
winname += " (DirectX9)";
}
window = glfwCreateWindow(1280, 720, winname.c_str(), nullptr, nullptr);
glfwMakeContextCurrent(window); glfwMakeContextCurrent(window);
gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress)); if (d == Driver::OpenGL2 || d == Driver::OpenGL3) {
gladLoadGLLoader(reinterpret_cast<GLADloadproc>(glfwGetProcAddress));
}
#ifdef _WIN32
if (d == Driver::DirectX9) {
d3d = Direct3DCreate9(D3D_SDK_VERSION);
auto hwnd = glfwGetWin32Window(window);
D3DPRESENT_PARAMETERS d3dpp = {};
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hwnd;
HRESULT hr = d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_HARDWARE_VERTEXPROCESSING,
&d3dpp, &dx9_device);
if (FAILED(hr)) {
MessageBoxW(nullptr, L"Failed to create D3D9 device", L"Error", MB_OK);
std::abort();
}
PD::Gfx::UseDriver<PD::GfxDirectX9>(dx9_device);
}
#endif
glfwSwapInterval(1); glfwSwapInterval(1);
PD::Gfx::Init(); PD::Gfx::Init();
PD::Li::InitPools(8192); PD::Li::InitPools(8192);
std::vector<PD::u8> img(16 * 16 * 4, 0xff); pTex = LoadTex("icon.png");
pTex = PD::Gfx::LoadTexture(img, 16, 16); /*std::vector<PD::u8> img(16 * 16 * 4, 0xff);
pTex = PD::Gfx::LoadTexture(img, 16, 16);*/
std::cout << "GfxDriver: " << PD::Gfx::GetDriverName() << std::endl; std::cout << "GfxDriver: " << PD::Gfx::GetDriverName() << std::endl;
pPool.Init(10); pPool.Init(10);
auto cmd = pPool.Allocate(1); auto cmd = pPool.Allocate(1);
cmd->Reserve(4, 6); cmd->Reserve(4, 6);
cmd->Add(PD::Li::Vertex(PD::fvec2(0, 0), PD::fvec2(0, 0), 0xffffffff));
cmd->Add(PD::Li::Vertex(PD::fvec2(50, 0), PD::fvec2(1, 0), 0xffffffff));
cmd->Add(PD::Li::Vertex(PD::fvec2(50, 50), PD::fvec2(1, 1), 0xffffffff));
cmd->Add(PD::Li::Vertex(PD::fvec2(0, 50), PD::fvec2(0, 1), 0xffffffff));
cmd->Add(0, 1, 2); cmd->Add(0, 1, 2);
cmd->Add(0, 2, 3); cmd->Add(0, 2, 3);
cmd->Add(PD::Li::Vertex(PD::fvec2(0, 0), PD::fvec2(0, 0), 0xffffffff));
cmd->Add(PD::Li::Vertex(PD::fvec2(256, 0), PD::fvec2(1, 0), 0xffffffff));
cmd->Add(PD::Li::Vertex(PD::fvec2(256, 256), PD::fvec2(1, 1), 0xffffffff));
cmd->Add(PD::Li::Vertex(PD::fvec2(0, 256), PD::fvec2(0, 1), 0xffffffff));
cmd->Tex = pTex; cmd->Tex = pTex;
} }
~App() { ~App() {
@@ -49,14 +105,33 @@ class App {
void Run() { void Run() {
while (!glfwWindowShouldClose(window)) { while (!glfwWindowShouldClose(window)) {
glViewport(0, 0, 1280, 720); if (pDriver == Driver::OpenGL2 || pDriver == Driver::OpenGL3) {
glClearColor(0.1, 0.1, 0.1, 0.1); glClearColor(0.1, 0.1, 0.1, 0.1);
glClear(GL_COLOR_BUFFER_BIT); glClear(GL_COLOR_BUFFER_BIT);
glViewport(0, 0, 1280, 720);
} else if (pDriver == Driver::DirectX9) {
#ifdef _WIN32
if (dx9_device) {
dx9_device->Clear(0, nullptr, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER,
D3DCOLOR_XRGB(25, 25, 25), 1.0f, 0);
dx9_device->BeginScene();
}
#endif
}
PD::Gfx::Reset(); PD::Gfx::Reset();
PD::Gfx::SetViewPort(1280, 720); PD::Gfx::SetViewPort(1280, 720);
PD::Gfx::Draw(pPool); PD::Gfx::Draw(pPool);
glfwPollEvents(); glfwPollEvents();
glfwSwapBuffers(window); if (pDriver == Driver::DirectX9) {
#ifdef _WIN32
if (dx9_device) {
dx9_device->EndScene();
dx9_device->Present(nullptr, nullptr, nullptr, nullptr);
}
#endif
} else {
glfwSwapBuffers(window);
}
} }
} }
@@ -64,10 +139,25 @@ class App {
GLFWwindow* window = nullptr; GLFWwindow* window = nullptr;
PD::Pool<PD::Li::Command> pPool; PD::Pool<PD::Li::Command> pPool;
PD::ptr pTex = 0; PD::ptr pTex = 0;
Driver pDriver;
#ifdef _WIN32
IDirect3D9* d3d = nullptr;
IDirect3DDevice9* dx9_device = nullptr;
#endif
}; };
int main() { int main(int argc, char** argv) {
App app; Driver drv = Driver::OpenGL3;
if (argc == 2) {
if (std::string(argv[1]) == "gl2") {
drv = Driver::OpenGL2;
} else if (std::string(argv[1]) == "gl3") {
drv = Driver::OpenGL3;
} else if (std::string(argv[1]) == "dx9") {
drv = Driver::DirectX9;
}
}
App app(drv);
app.Run(); app.Run();
return 0; return 0;
} }