Overview
Null Engine is a high-performance, cross-platform 3D model viewer and rendering engine built from scratch using C++20 and modern Vulkan 1.4.
Rather than relying on legacy graphics abstractions or third-party game frameworks, Null Engine is designed to explore modern GPU-driven rendering techniques, zero-overhead hardware abstractions, and explicit synchronization models utilized in contemporary AAA production pipelines.
NoteNull Engine is actively developed with a modern Vulkan 1.4 Dynamic Rendering foundation, programmable vertex pulling via 64-bit Buffer Device Addresses (BDA), and Multi-Draw Indirect (MDI) batching. Comprehensive unit testing and strict memory management ensure zero validation layer warnings.
Core Technical Architecture
1. Modern Vulkan 1.4 RHI & Dynamic Rendering
Legacy Vulkan architectures often carry significant boilerplate around VkRenderPass and VkFramebuffer compatibility matching. Null Engine bypasses legacy render passes completely:
- Dynamic Rendering (
VK_KHR_dynamic_rendering): Streamlines draw execution directly into swapchain color and depth image views with explicit attachment descriptions. - Synchronization2 (
VK_KHR_synchronization2): Replaces ambiguous subpass dependencies and legacy pipeline barriers with granular, self-documenting stage and access masks (VkDependencyInfo,VkImageMemoryBarrier2). volkMeta-Loader: Dynamically loads Vulkan symbols per-instance and per-device, eliminating static loader linkage overhead.VK_EXT_debug_utilsInstrumentation: Every Vulkan resource (buffers, images, pipelines, pools, queues, semaphores, fences) is tagged viavkSetDebugUtilsObjectNameEXTfor crystal-clear RenderDoc captures and validation diagnostics.
2. Programmable Vertex Pulling via Buffer Device Address (BDA)
Traditional graphics pipelines bind vertex buffers to fixed pipeline state objects (PSO) via vkCmdBindVertexBuffers and input attribute layouts. Null Engine adopts Programmable Vertex Pulling:
- 64-bit Device Pointers: The shader receives direct GPU memory addresses (
VkDeviceAddress) of vertex and instance storage buffers through a 24-byte push-constant block (vkCmdPushConstants, well within Vulkan’s guaranteed 128 bytes). - Flexible Data Layout: Vertices are pulled dynamically inside the vertex shader as raw structures:
struct Vertex {
float3 pos;
float3 normal;
float2 uv;
float4 color;
};
struct DrawInfo {
Vertex* vertices;
uint instanceBaseOffset;
uint padding;
};
- Decoupled PSOs: Shaders and pipelines no longer need to match rigid input attribute descriptions, drastically cutting PSO permutation counts.
3. Multi-Draw Indirect (MDI) & Geometry Pool Management
To eliminate CPU draw submission overhead:
- Batched Submission: Geometry batches are dispatched using a single indirect command via
vkCmdDrawIndexedIndirect. - Pre-Allocated Geometry Pools: The engine maintains a 64MB global vertex pool and 32MB global index pool managed by a dedicated
GeometryAllocator, preventing per-mesh heap allocations. - Double-Buffered Uploads: Per-frame host-visible staging upload buffers (16MB each) safely stream dynamic instance data (model matrices, normal matrices, material colors) across frames-in-flight (
MAX_FRAMES_IN_FLIGHT = 2).
4. Modern Shader Pipeline with Slang
Null Engine uses Slang for its shading pipeline:
- Compile-Time SPIR-V Generation: Shaders are compiled ahead-of-time into optimized SPIR-V modules via
slangcintegrated into CMake build presets. - Direct Pointer Semantics: Slang natively supports standard C-style pointer arithmetic and type-safe Buffer Device Address (BDA) dereferencing.
- Modular Shading: Clean separation of uniform buffers, draw metadata, and instance buffers without descriptor set sprawl.
5. Unreal Coordinate Conventions & Reverse-Z Depth
Engine geometry and math adhere strictly to Unreal Engine standards:
- Coordinate System: Left-handed system with +X Forward, +Y Right, and +Z Up.
- Reverse-Z Floating-Point Depth:
- Utilizes a 32-bit floating-point depth buffer (
VK_FORMAT_D32_SFLOAT_S8_UINT), falling back to 24/16-bit formats with a warning on hardware that lacks it. - Clears depth to
0.0fand uses greater-or-equal comparison (VK_COMPARE_OP_GREATER_OR_EQUAL). - Distributes floating-point precision near infinity, virtually eliminating z-fighting across massive view distances.
- Utilizes a 32-bit floating-point depth buffer (
6. Custom C++20 SIMD Linear Algebra (Zero-GLM Dependency)
To achieve zero third-party math overhead and total layout predictability:
- Custom, strongly typed math library:
Vec2,Vec3,Vec4,Mat4,Quat, andTransform. - Pure
constexprlinear algebra operations where applicable. - Platform SIMD acceleration with hardware-accelerated Newton-Raphson inverse square root (
invSqrt). - Transform component with automatic local/world matrix caching and dirty-flag propagation.
7. Engine Telemetry & Dear ImGui Integration
- Real-Time Telemetry: Frame times, FPS counter, draw call metrics, and pool occupancies.
- Interactive Controls: Free-fly WASD + QE camera controller, dynamic aspect ratio tracking, camera parameter sliders (FOV, near/far clips).
- Time Dilation: Scalable
timeScalecontrols (0x pause to 3x fast-forward) with unscaled frame metrics.
8. Verification & Test Engineering
The engine features a custom automated unit test framework running in-process via --run-tests:
- 58 Unit Test Suites with 345 Automated Checks verifying math POD invariants, quaternion SLERP rotations, transform hierarchies, ECS entity lifecycles, and camera projection reversals.
Legacy Foundations & Engine History (2017 – 2022)
Null Engine builds upon years of independent engine architecture and low-level graphics experiments:
- Vulkan Engine (2022): Initial exploratory Vulkan testbed to study raw command buffer recording, synchronization barriers, and validation layers.
- Null Engine (2019 – 2021): Custom 2D/3D experimental framework integrating the UE4 Core library, a custom sparse-set ECS, an OpenGL renderer, and a Dear ImGui editor, built with Premake.
- Legacy OpenGL Engine (2017): Foundational research into asset import pipelines, instancing, and shader techniques.
FBX SDK Integration & Material Import
Developed a robust asset importer starting from raw vertex data and progressing to full material and texture importing via the Autodesk FBX SDK.
Stencil Testing & Scene Hierarchies
Refactored engine core to support shader-agnostic pipelines, custom stencil-based object outlining, and complex transform hierarchies.
Instanced Rendering (100,000 Asteroids)
Using OpenGL hardware instancing, rendered 100,000 unique asteroid meshes orbiting a planet with zero CPU bottleneck, demonstrating draw call batching principles.
CubeMap Skybox, Reflection & Refraction
Implemented environmental CubeMap skyboxes and developed real-time reflection and refraction shaders simulating dynamic glass and mirror materials.