Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
7c363bf
Add Matrix4 and Quaternion to Core; rebuild Transform on native math
jayrulez Jul 13, 2026
047a3ff
Remove bgfx/bx/bimg and the rendering/scene stack
jayrulez Jul 13, 2026
bc5bce2
Add backend-agnostic RHI interface module (rhi)
jayrulez Jul 5, 2026
01941c3
Add Null RHI backend (rhi.null)
jayrulez Jul 5, 2026
322d4f2
Add RHI validation backend
jayrulez Jul 5, 2026
7342c39
Add Vulkan RHI backend
jayrulez Jul 5, 2026
1f1e3cd
Add DX12 RHI backend
jayrulez Jul 5, 2026
59635c2
Fix Windows build: DX12 casing + ambiguous cos in math test
jayrulez Jul 5, 2026
90d7525
Add shaders module: HLSL compilation via DXC
jayrulez Jul 5, 2026
f3a20a8
Add RHI sample framework
jayrulez Jul 5, 2026
5a88af2
Add RHI samples
jayrulez Jul 5, 2026
06bd602
Vendor DXC runtime libraries
jayrulez Jul 5, 2026
ca8006e
Add shader variant system
jayrulez Jul 5, 2026
80cf439
Add graphics render host module
jayrulez Jul 5, 2026
c0877db
Add render graph module
jayrulez Jul 5, 2026
0051742
Add Color and Color32 to core
jayrulez Jul 5, 2026
0f99e98
Remove the image loader from core
jayrulez Jul 5, 2026
3c45e15
Add image module
jayrulez Jul 5, 2026
a49c831
Add texture module
jayrulez Jul 5, 2026
b489ddb
Add packed vectors and AABB to core math
jayrulez Jul 5, 2026
aab6064
Add geometry module: runtime mesh format
jayrulez Jul 5, 2026
4181e1c
Add materials module: data-driven material model
jayrulez Jul 6, 2026
b594723
Vendor ufbx and cgltf model-loader libraries
jayrulez Jul 6, 2026
f961e55
Add model module: import representation + FBX/GLTF loaders
jayrulez Jul 6, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
11 changes: 1 addition & 10 deletions .gitmodules
Original file line number Diff line number Diff line change
@@ -1,12 +1,3 @@
[submodule "Engine/cpp/ThirdParty/bx"]
path = Engine/cpp/ThirdParty/bx
url = https://github.com/bkaradzic/bx
[submodule "Engine/cpp/ThirdParty/bimg"]
path = Engine/cpp/ThirdParty/bimg
url = https://github.com/bkaradzic/bimg
[submodule "Engine/cpp/ThirdParty/bgfx"]
path = Engine/cpp/ThirdParty/bgfx
url = https://github.com/bkaradzic/bgfx
[submodule "Engine/cpp/ThirdParty/sdl"]
[submodule "Engine/cpp/thirdparty/sdl"]
path = Engine/cpp/ThirdParty/sdl
url = https://github.com/libsdl-org/SDL
25 changes: 1 addition & 24 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ project(DraconicEngine LANGUAGES C CXX)

find_package(Git QUIET)
find_package(Threads REQUIRED)
find_package(Vulkan REQUIRED)

if(GIT_FOUND AND EXISTS "${CMAKE_SOURCE_DIR}/.git")
message(STATUS "Updating submodules...")
Expand All @@ -20,36 +21,12 @@ endif()

list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake")

option(BUILD_BENCHMARKS "Build micro-benchmarks (nanobench)" OFF)

include(CTest)
include(Compiler)
include(Modules)
include(Shaders)

# Engine runtime (C++)
add_subdirectory(Engine/cpp)

# Samples (C++)
add_subdirectory(Samples/cpp)

# Aggregate benchmark targets: `benchmarks` builds them all, `run-benchmarks`
# builds and runs each in turn.
if(BUILD_BENCHMARKS)
get_property(DRACO_BENCH_TARGETS GLOBAL PROPERTY DRACO_BENCH_TARGETS)
if(DRACO_BENCH_TARGETS)
add_custom_target(benchmarks)
add_dependencies(benchmarks ${DRACO_BENCH_TARGETS})

set(BENCH_RUN_CMDS "")
foreach(BENCH_TARGET IN LISTS DRACO_BENCH_TARGETS)
list(APPEND BENCH_RUN_CMDS COMMAND $<TARGET_FILE:${BENCH_TARGET}>)
endforeach()
add_custom_target(run-benchmarks
${BENCH_RUN_CMDS}
DEPENDS ${DRACO_BENCH_TARGETS}
USES_TERMINAL
VERBATIM
)
endif()
endif()
5 changes: 1 addition & 4 deletions Engine/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
add_subdirectory(ThirdParty SYSTEM)

add_modules_library(Runtime SHARED)
# Runtime exposes the whole engine through the `draconic` module. Shell (the single
# library holding both backends) is linked PUBLIC, so a consumer only links Runtime and
# does `import draconic;`; createShell() resolves from Shell.
target_link_libraries(Runtime PUBLIC Core Shell Scene Rendering)
target_link_libraries(Runtime PUBLIC Core)

# TODO: binding library
88 changes: 83 additions & 5 deletions Engine/cpp/Runtime/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,10 +1,35 @@
add_modules_library(Core PIC)
add_modules_library(Shell)
add_modules_library(Rendering PIC)
add_modules_library(Scene)
add_modules_library(Rendering/Shaders)
add_modules_library(Rendering/RHI PIC)
add_modules_library(Rendering/RHI/Null)
add_modules_library(Rendering/RHI/Validation)
add_modules_library(Rendering/RHI/Vulkan)
if(WIN32)
add_modules_library(Rendering/RHI/DX12)
endif()
add_modules_library(Rendering/Shaders/System)
add_modules_library(Rendering/Graphics)
add_modules_library(Rendering/RenderGraph)
add_modules_library(Rendering/Image)
add_modules_library(Rendering/Image/IO)
add_modules_library(Rendering/Texture)
add_modules_library(Rendering/Geometry)
add_modules_library(Rendering/Materials)
add_modules_library(Rendering/Materials/PSO)
# Model is one module whose partitions keep their folder separation: the loaders (FBX,
# GLTF) and the IO registry live in subdirs, so append them (and the ufbx/cgltf impl
# TUs) to the target the glob created from the top-level interface partitions.
add_modules_library(Rendering/Model)
target_sources(Rendering_Model PUBLIC FILE_SET CXX_MODULES FILES
Rendering/Model/IO/ModelIOModule.cppm
Rendering/Model/FBX/FbxLoader.cppm
Rendering/Model/GLTF/GltfLoader.cppm)
target_sources(Rendering_Model PRIVATE
Rendering/Model/FBX/ufbx_impl.cpp
Rendering/Model/GLTF/cgltf_impl.cpp)

target_link_libraries(Core PUBLIC Definitions Math IO Memory Logging)

# Shell is a single library: the interface plus both backends, separated only by folder
# (Desktop/ = SDL3, Null/ = headless). SDL3 is a PRIVATE implementation detail; nothing
# outside Shell sees it. createShell() dispatches to the backend chosen at compile time
Expand Down Expand Up @@ -33,5 +58,58 @@ if(CMAKE_TESTING_ENABLED)
add_test(NAME ${SHELL_TEST_TARGET} COMMAND ${SHELL_TEST_TARGET} --reporter junit --out "Testing/${SHELL_TEST_TARGET}.xml")
endforeach()
endif()
target_link_libraries(Rendering PUBLIC RHI RenderGraph Mesh Material QuadRenderer Renderer)
target_link_libraries(Scene PUBLIC Renderable TransformComponent Camera)
# Rendering: RHI is the backend-agnostic interface module; Null is the headless
# no-op backend (for tests/tools). GPU backends (Vulkan, DX12) come later.
# Shaders: HLSL compilation via DXC. DXC's headers come from Draco::DXCHeaders
# (which also carries DRACO_DXC_PATH); the runtime library is dlopen'd, so only
# the platform's dl library is linked.
target_link_libraries(Rendering_Shaders PUBLIC Core Draco::DXCHeaders PRIVATE ${CMAKE_DL_LIBS})
# ShaderSystem: variant compile-on-demand + cache. Needs the RHI (to create GPU
# modules) on top of the RHI-free shaders module. Its test uses the Null backend.
target_link_libraries(Rendering_Shaders_System PUBLIC Rendering_Shaders Rendering_RHI Rendering_RHI_Null)
target_link_libraries(Rendering_RHI PUBLIC Core)
target_link_libraries(Rendering_RHI_Null PUBLIC Rendering_RHI)
# Validation wraps any backend; its test wraps the Null backend, so Null is
# PUBLIC here to give the test the rhi.null module interface.
target_link_libraries(Rendering_RHI_Validation PUBLIC Rendering_RHI Rendering_RHI_Null)
# Vulkan GPU backend. The Vulkan loader is PRIVATE: VkIncludes.h/vulkan.h live in
# the module's global fragment, so importers of rhi.vk don't need the headers, but
# the static lib's loader symbols still propagate to the final link.
target_link_libraries(Rendering_RHI_Vulkan PUBLIC Rendering_RHI PRIVATE Vulkan::Vulkan)
# DX12 GPU backend (Windows only). Links the D3D12/DXGI system libraries privately;
# IID_PPV_ARGS uses __uuidof, which Clang flags as a language extension.
if(WIN32)
target_link_libraries(Rendering_RHI_DX12 PUBLIC Rendering_RHI PRIVATE d3d12 dxgi dxguid d3dcompiler)
target_compile_options(Rendering_RHI_DX12 PRIVATE $<$<CXX_COMPILER_ID:Clang>:-Wno-language-extension-token>)
endif()
# Graphics render host: one target holding the graphics / graphics.null / graphics.gpu
# modules. The core `graphics` interface imports only base RHI + Shell; graphics.gpu
# pulls the backends. Shell is PUBLIC for the headless test. DX12 is added
# (with DRACO_HAS_DX12) only on Windows.
# RenderGraph: pass dependency resolution, transient aliasing, automatic barriers
# over the RHI. Backend-agnostic (base RHI only); Null is PUBLIC for its headless tests.
target_link_libraries(Rendering_RenderGraph PUBLIC Core Rendering_RHI Rendering_RHI_Null)
# Image: CPU-side image data + manipulation (no RHI). IO adds stb load/save; stb is
# PRIVATE (its headers live in the module's global fragment / the stb_impl TU).
target_link_libraries(Rendering_Image PUBLIC Core)
target_link_libraries(Rendering_Image_IO PUBLIC Rendering_Image Core PRIVATE stb_image)
# Texture: image->RHI format descriptors (bridges CPU image data and the GPU RHI).
target_link_libraries(Rendering_Texture PUBLIC Core Rendering_Image Rendering_RHI)
# Geometry: CPU mesh data (static/skinned vertex streams, index buffers, primitives).
target_link_libraries(Rendering_Geometry PUBLIC Core)
# Materials: data-driven material model (PipelineConfig, Material/Builder/Instance, and
# the bind-group-inferring MaterialSystem). Needs the RHI + Shaders (ShaderFlags); Null
# is PUBLIC for the headless test.
target_link_libraries(Rendering_Materials PUBLIC Core Rendering_RHI Rendering_Shaders Rendering_RHI_Null)
# PSO cache: bridges the ShaderSystem (variants) and Materials (PipelineConfig). Its test
# compiles real shaders via the ShaderSystem against the Null backend.
target_link_libraries(Rendering_Materials_PSO PUBLIC Rendering_Materials Rendering_Shaders_System Rendering_RHI Rendering_RHI_Null)
# Model: importer representation + FBX(ufbx)/GLTF(cgltf) loaders. Loads embedded/external
# textures via Image; the ufbx/cgltf single-header libs are compiled in the impl TUs.
target_link_libraries(Rendering_Model PUBLIC Core Rendering_Image Rendering_Image_IO PRIVATE ufbx cgltf)
target_link_libraries(Rendering_Graphics PUBLIC
Rendering_RHI Rendering_RHI_Null Rendering_RHI_Vulkan Rendering_RHI_Validation Shell)
if(WIN32)
target_link_libraries(Rendering_Graphics PUBLIC Rendering_RHI_DX12)
target_compile_definitions(Rendering_Graphics PUBLIC DRACO_HAS_DX12)
endif()
19 changes: 10 additions & 9 deletions Engine/cpp/Runtime/Core/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
add_modules_library(Definitions)
add_modules_library(Math)
add_modules_library(IO)
add_modules_library(Memory)
add_modules_library(Logging)
add_modules_library(Containers)
# PIC: these are linked into the shared Runtime library (via Core), so their objects
# must be position-independent - a non-PIC static (e.g. Quaternion::identity) otherwise
# fails to relocate when making the shared object.
add_modules_library(Definitions PIC)
add_modules_library(Math PIC)
add_modules_library(IO PIC)
add_modules_library(Memory PIC)
add_modules_library(Logging PIC)

target_link_libraries(Math PUBLIC Definitions bx)
target_link_libraries(IO PUBLIC Definitions stb_image)
target_link_libraries(Math PUBLIC Definitions)
target_link_libraries(IO PUBLIC Definitions)
target_link_libraries(Memory PUBLIC Definitions Math)
target_link_libraries(Logging PUBLIC Definitions)
target_link_libraries(Containers PUBLIC Definitions Memory Math)
1 change: 1 addition & 0 deletions Engine/cpp/Runtime/Core/Core.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ export module core;
export import core.defs;
export import core.version;
export import core.math;
export import core.color;
export import core.memory;
export import core.io;
export import core.logging;
1 change: 1 addition & 0 deletions Engine/cpp/Runtime/Core/Definitions/Definitions.cppm
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ module;

export module core.defs;
export import core.stdtypes;
export import core.status;

static_assert(__cplusplus >= 202207L, "Minimum of C++23 required.");

Expand Down
38 changes: 38 additions & 0 deletions Engine/cpp/Runtime/Core/Definitions/Status.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Status / ErrorCode - success or an error code, no payload. For operations
// that return a value-or-error, use std::expected instead.

export module core.status;

import core.stdtypes;

export namespace draco
{
enum class ErrorCode : u32
{
Ok = 0,
Unknown,
InvalidArgument,
OutOfRange,
OutOfMemory,
NotFound,
NotSupported,
AlreadyExists,
Internal,
};

class Status
{
public:
constexpr Status() = default;
constexpr Status(ErrorCode code) : m_code(code) {}

[[nodiscard]] constexpr ErrorCode code() const { return m_code; }
[[nodiscard]] constexpr bool isOk() const { return m_code == ErrorCode::Ok; }
[[nodiscard]] constexpr explicit operator bool() const { return isOk(); }

friend constexpr bool operator==(Status a, Status b) { return a.m_code == b.m_code; }

private:
ErrorCode m_code = ErrorCode::Ok;
};
}
1 change: 0 additions & 1 deletion Engine/cpp/Runtime/Core/IO/IO.cppm
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
export module core.io;

export import core.io.filesystem;
export import core.io.loader.image;
63 changes: 0 additions & 63 deletions Engine/cpp/Runtime/Core/IO/ImageLoader.cpp

This file was deleted.

23 changes: 0 additions & 23 deletions Engine/cpp/Runtime/Core/IO/ImageLoader.cppm

This file was deleted.

33 changes: 33 additions & 0 deletions Engine/cpp/Runtime/Core/Math/AABB.cppm
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module;

#include <algorithm>
#include <limits>

export module core.math.aabb;

import core.defs;
import core.stdtypes;
import core.math.types;

export namespace draco::math {

// An axis-aligned bounding box defined by its min/max corners.
struct AABB {
Vector3 min{ 0, 0, 0 };
Vector3 max{ 0, 0, 0 };

// An inverted box (min = +inf, max = -inf) so the first expand() sets both corners.
[[nodiscard]] static AABB empty() noexcept {
constexpr f32 inf = std::numeric_limits<f32>::infinity();
return AABB{ Vector3{ inf, inf, inf }, Vector3{ -inf, -inf, -inf } };
}
// Grows the box to contain point `p`.
void expand(Vector3 p) noexcept {
min = Vector3{ std::min(min.x, p.x), std::min(min.y, p.y), std::min(min.z, p.z) };
max = Vector3{ std::max(max.x, p.x), std::max(max.y, p.y), std::max(max.z, p.z) };
}
[[nodiscard]] Vector3 center() const noexcept { return (min + max) * 0.5f; }
[[nodiscard]] Vector3 size() const noexcept { return max - min; }
};

} // namespace draco::math
Loading
Loading