diff --git a/LICENSE b/LICENSE index bdfc3bbe..ec4ed884 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023-2025 Double Buffer SRL +Copyright (c) 2023-2026 Double Buffer SRL Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index ef83d62c..40624a55 100644 --- a/README.md +++ b/README.md @@ -1,221 +1,111 @@ -# Elemental ![License](https://img.shields.io/github/license/double-buffer/elemental.svg) ![GitHub Repo stars](https://img.shields.io/github/stars/double-buffer/elemental?style=flat) [![GitHub Release Downloads](https://img.shields.io/github/downloads/double-buffer/elemental/total)](https://github.com/double-buffer/elemental/releases) ![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/double-buffer/elemental/build-ci.yml?branch=main) +# Elemental -Elemental is a portable low-level game platform library that targets only next-gen features. -It is exposed as a simple C header and other language bindings also exist. +![License](https://img.shields.io/github/license/double-buffer/elemental.svg) +![GitHub Repo stars](https://img.shields.io/github/stars/double-buffer/elemental?style=flat) +[![GitHub Release Downloads](https://img.shields.io/github/downloads/double-buffer/elemental/total)](https://github.com/double-buffer/elemental/releases) +![GitHub Actions Workflow Status](https://img.shields.io/github/actions/workflow/status/double-buffer/elemental/build-ci.yml?branch=main) -It is a great choice if you want to: -- Create your own game engine. -- Learn game programming. -- Do graphics research projects with the latest available tech. +**Elemental is a low-level, cross-platform library for modern GPU programming.** + +It provides a small C API over Direct3D 12, Vulkan and Metal while deliberately targeting modern GPU capabilities instead of carrying legacy hardware and API constraints. + +> **Elemental does not try to simplify GPU programming. It tries to simplify access to GPU programming.** + +Meaningful GPU concepts such as resources, memory, queues, command lists, pipelines, descriptors, barriers, compute, mesh shaders and ray tracing remain visible. Platform boilerplate and backend-specific ceremony stay behind the library. > [!WARNING] -> The project is currently in heavy development. API may have a lot of breaking changes until the first release. +> Elemental 1.0 is under active development. Breaking API changes are expected before the first stable release. + +## Design principles + +- **Modern GPUs first.** Elemental prefers a clean model built around recent hardware instead of adding legacy fallbacks that permanently complicate the API. +- **Keep meaningful GPU concepts visible.** Learning how the GPU works is part of the point. +- **Hide accidental complexity.** Window-system plumbing and backend-specific ceremony should not leak into application code when they do not represent useful GPU semantics. +- **Small C API.** The public API uses opaque handles, plain structures, spans and explicit functions. +- **Not the lowest common denominator.** Direct3D 12, Vulkan and Metal do not always expose identical capabilities, and Elemental does not require every backend to veto modern ideas supported elsewhere. + +## What can you build with it? + +Elemental is intended for people who want to directly experiment with modern GPU hardware. + +Typical uses include: + +- custom renderers and game engines; +- GPU-driven rendering and mesh-shader experiments; +- rasterization, path tracing and ray tracing; +- simulations and general-purpose compute; +- small tensor or neural-network experiments; +- graphics and GPU research projects. + +Elemental provides the low-level building blocks rather than a renderer, scene system, ECS, ML framework or engine architecture. + +## Current capabilities -## 📖 Purpose +Elemental currently includes: -Elemental aims to simplify and standardize game development across different platforms by offering a unified API. +- cross-platform application lifetime and windows; +- keyboard, mouse, gamepad and touch input; +- graphics and compute command queues; +- command lists and swap chains; +- GPU heaps and resources; +- bindless resource access; +- synchronization and resource barriers; +- graphics and compute pipelines; +- render passes; +- compute shaders; +- mesh shaders; +- ray tracing; +- HLSL shader compilation tools. -Back in the days of DirectX11 and OpenGL, it was very easy to start working on its own game or custom engine that took full advantage of the GPU. -Newer apis give more control to the developpers but they are hard to use. They also provide many ways of doing things because they must maintain backward compatibility. +## Platforms -Elemental bridges this gap by focusing on powerful, next-gen features without the overhead of backward compatibility. -This approach not only facilitates learning and using graphics programming as in earlier times but also gears developers up for future advancements without compromising on performance. - -It doesn't mean that it will simplify or abstract graphics development. -It is a challenging topic but developers can now focus on learning graphics programming like in the old days by focusing on graphics algorithms and not on the complicated platform specific implementation details. +| Platform | GPU backend | +|:--|:--| +| Windows | Direct3D 12, Vulkan | +| Linux | Vulkan / Wayland | +| macOS | Metal | +| iOS | Metal | -The library is still in heavy development stage. The goal is not to be compatible with the majority of graphics cards now but to be ready for the future. - -In order to simplify the API, the library makes the following assumptions: - -- Use of Mesh shaders for the geometry pipeline: so no vertex layout setup, no geometry shaders, no vertex shaders. -- No copy queue exposed: you need to use IO queue to copy data from disk to GPU memory. (Internally the library try to use DirectStorage, MetalIO, etc.) -For dynamic gpu data that is short lived, we use GPU upload heap (rebar memory). -- Use of bindless resources -- No indirect commands: The future will be about work graphs. - -## 📋 Features - -Implemented features for current version **1.0.0-DEV4**: - -- Application: - - Application Lifetime with the same code for all platforms. - - Windows. -- Graphics: - - Graphics Device. - - CommandQueues and CommandLists. - - SwapChain. - - Mesh shaders. -- Inputs: - - Keyboard. - - Mouse. - - Gamepad. (basic for now only work with Xbox one S wireless controller) - - Touch. (iOS and MacOS) -- Tools: - - Shader Compiler. +Feature coverage is still evolving while Elemental 1.0 is under development. -It currently runs on: +## Getting started -| Platform | Graphics API | Tools Supported | -|:--------:|:-----------------:|:---------------:| -| Linux | DirectX12, Vulkan | ✅ | -| Linux | Vulkan/Wayland | ✅ | -| MacOS | Metal3 | ✅ | -| iOS | Metal3 | | - -The library is exposed as a C library but other bindings will be available: - -| Binding | Status | Download | -|:-------:|:------:|:-------------:| -| .NET | WIP | Not available | - -For shader development, the shader compiler supports the following languages and platforms: - -| Shader Language | Target API | Compilation Platforms | -|:---------------:|:----------:|:---------------------:| -| HLSL | DirectX12 | Linux Linux | -| HLSL | Vulkan | Linux Linux MacOS | -| HLSL | Metal3 | Linux MacOS | - -## 🚀 Getting Started - -Here is a minimal application that displays a colored triangle using a mesh shader. - -![Minimal Triangle Application](/doc/GettingStarted.png) - -```c -#include "Elemental.h" -#include "ElementalTools.h" - -const char* shaderSource = - "struct Vertex { float3 Position; float4 Color; };" - "struct VertexOutput { float4 Position: SV_Position; float4 Color: TEXCOORD0; };" - - "static Vertex triangleVertices[] =" - "{" - " { float3(-0.5, 0.5, 0.0), float4(1.0, 0.0, 0.0, 1.0) }," - " { float3(0.5, 0.5, 0.0), float4(0.0, 1.0, 0.0, 1.0) }," - " { float3(-0.5, -0.5, 0.0), float4(0.0, 0.0, 1.0, 1.0) }" - "};" - - "[shader(\"mesh\")]" - "[OutputTopology(\"triangle\")]" - "[NumThreads(32, 1, 1)]" - "void MeshMain(in uint groupThreadId : SV_GroupThreadID, out vertices VertexOutput vertices[3], out indices uint3 indices[1])" - "{" - " const uint meshVertexCount = 3;" - " SetMeshOutputCounts(meshVertexCount, 1);" - - " if (groupThreadId < meshVertexCount)" - " {" - " vertices[groupThreadId].Position = float4(triangleVertices[groupThreadId].Position, 1);" - " vertices[groupThreadId].Color = triangleVertices[groupThreadId].Color;" - " }" - - " if (groupThreadId == 0)" - " {" - " indices[groupThreadId] = uint3(0, 1, 2);" - " }" - "}" - - "[shader(\"pixel\")]" - "float4 PixelMain(const VertexOutput input) : SV_Target0" - "{" - " return input.Color;" - "}"; - -typedef struct -{ - ElemWindow Window; - ElemGraphicsDevice GraphicsDevice; - ElemCommandQueue CommandQueue; - ElemSwapChain SwapChain; - ElemPipelineState GraphicsPipeline; -} ApplicationPayload; - -void UpdateSwapChain(const ElemSwapChainUpdateParameters* updateParameters, void* payload); - -void InitSample(void* payload) -{ - ApplicationPayload* applicationPayload = (ApplicationPayload*)payload; - - applicationPayload->Window = ElemCreateWindow(NULL); - - applicationPayload->GraphicsDevice = ElemCreateGraphicsDevice(NULL); - applicationPayload->CommandQueue= ElemCreateCommandQueue(applicationPayload->GraphicsDevice, ElemCommandQueueType_Graphics, NULL); - applicationPayload->SwapChain= ElemCreateSwapChain(applicationPayload->CommandQueue, applicationPayload->Window, UpdateSwapChain, &(ElemSwapChainOptions) { .UpdatePayload = payload }); - - ElemSwapChainInfo swapChainInfo = ElemGetSwapChainInfo(applicationPayload->SwapChain); - ElemSystemInfo systemInfo = ElemGetSystemInfo(); - ElemGraphicsDeviceInfo graphicsDeviceInfo = ElemGetGraphicsDeviceInfo(applicationPayload->GraphicsDevice); - - ElemShaderSourceData shaderSourceData = { .ShaderLanguage = ElemShaderLanguage_Hlsl, .Data = { .Items = (uint8_t*)shaderSource, .Length = strlen(shaderSource) } }; - ElemShaderCompilationResult compilationResult = ElemCompileShaderLibrary((ElemToolsGraphicsApi)graphicsDeviceInfo.GraphicsApi, (ElemToolsPlatform)systemInfo.Platform, &shaderSourceData, NULL); - - ElemShaderLibrary shaderLibrary = ElemCreateShaderLibrary(applicationPayload->GraphicsDevice, (ElemDataSpan) { .Items = compilationResult.Data.Items, .Length = compilationResult.Data.Length }); - - applicationPayload->GraphicsPipeline = ElemCompileGraphicsPipelineState(applicationPayload->GraphicsDevice, &(ElemGraphicsPipelineStateParameters) { - .ShaderLibrary = shaderLibrary, - .MeshShaderFunction = "MeshMain", - .PixelShaderFunction = "PixelMain", - .TextureFormats = { .Items = (ElemTextureFormat[]) { swapChainInfo.Format }, .Length = 1 } - }); - - ElemFreeShaderLibrary(shaderLibrary); -} - -void FreeSample(void* payload) -{ - ApplicationPayload* applicationPayload = (ApplicationPayload*)payload; - - ElemFreePipelineState(applicationPayload->GraphicsPipeline); - ElemFreeSwapChain(applicationPayload->SwapChain); - ElemFreeCommandQueue(applicationPayload->CommandQueue); - ElemFreeGraphicsDevice(applicationPayload->GraphicsDevice); -} - -void UpdateSwapChain(const ElemSwapChainUpdateParameters* updateParameters, void* payload) -{ - ApplicationPayload* applicationPayload = (ApplicationPayload*)payload; - - ElemCommandList commandList = ElemGetCommandList(applicationPayload->CommandQueue, NULL); - - ElemBeginRenderPass(commandList, &(ElemBeginRenderPassParameters) { - .RenderTargets = - { - .Items = (ElemRenderPassRenderTarget[]) {{ - .RenderTarget = updateParameters->BackBufferTexture, - .LoadAction = ElemRenderPassLoadAction_Clear - }}, - .Length = 1 - } - }); - - ElemBindPipelineState(commandList, applicationPayload->GraphicsPipeline); - ElemDispatchMesh(commandList, 1, 1, 1); - ElemEndRenderPass(commandList); - - ElemCommitCommandList(commandList); - ElemExecuteCommandList(applicationPayload->CommandQueue, commandList, NULL); - - ElemPresentSwapChain(applicationPayload->SwapChain); -} - -int main(int argc, const char* argv[]) -{ - ElemRunApplication(&(ElemRunApplicationParameters) { - .InitHandler = InitSample, - .FreeHandler = FreeSample, - .Payload = &(ApplicationPayload){} - }); -} +Prebuilt development packages are available from [GitHub Releases](https://github.com/double-buffer/elemental/releases). + +To build Elemental from source: + +```bash +git clone --recurse-submodules https://github.com/double-buffer/elemental.git +cd elemental + +cmake --preset default +cmake --build --preset default ``` -> [!TIP] -> Please note that this code uses both Elemental and ElementalTools. In a real world app, you should compile your shaders offline. +The progressive samples are the best introduction to the API: -> [!WARNING] -> This code will only runs on platforms that support shader compilation. (Windows, MacOS, Linux) -> If you want to run code on other platforms you should compile your shaders offline. +1. [`01-HelloTriangle`](samples/Elemental/01-HelloTriangle) +2. [`02-HelloInputs`](samples/Elemental/02-HelloInputs) +3. [`03-HelloCompute`](samples/Elemental/03-HelloCompute) +4. [`04-HelloMesh`](samples/Elemental/04-HelloMesh) +5. [`05-HelloRaytracing`](samples/Elemental/05-HelloRaytracing) + +Larger experiments live in [`samples/Demos`](samples/Demos). + +## Future directions + +Elemental is also a research project around modern GPU programming. + +Areas of interest include: + +- GPU virtual memory and modern resource models; +- GPU-driven execution and Work Graphs; +- advanced ray tracing and geometry processing; +- hardware-accelerated linear algebra and tensor operations; +- hardware video decoding and encoding. + +These are research directions, not promises of stable APIs. + +## License -You will find detailled examples in the [samples folder](samples). +Elemental is released under the [MIT License](LICENSE). diff --git a/samples/Demos/01-Renderer/README.md b/samples/Demos/01-Renderer/README.md new file mode 100644 index 00000000..137cff0f --- /dev/null +++ b/samples/Demos/01-Renderer/README.md @@ -0,0 +1,82 @@ +# Renderer Demo + +This is Elemental's main renderer laboratory and stress test. + +Unlike the progressive `Elemental/*` samples, Renderer is intentionally not minimal. It combines several systems to expose real API friction, synchronization problems, resource-lifetime questions and performance costs while the library evolves. + +## What it exercises + +- compiled scene loading and GPU scene creation; +- meshlet rendering with mesh shaders; +- bindless buffers, textures and samplers; +- depth rendering into an HDR floating-point target; +- ray-tracing acceleration structures; +- compute-based path tracing using inline ray queries; +- resource barriers between compute, graphics and presentation work; +- path-tracing accumulation; +- tonemapping and UI composition; +- GPU timestamps for major rendering phases; +- an in-engine debug UI; +- camera-state persistence. + +The default scene is `Sponza/sponza.scene`. A different compiled `.scene` file can be passed as the final command-line argument. + +## Rendering flow + +Renderer can switch between two main paths: + +```text +raster + -> mesh-shader scene rendering + -> HDR render target + +path tracing + -> compute dispatch + -> HDR render target + +HDR result + debug UI + -> barriers + -> tonemap/composite + -> swap chain +``` + +Scene GPU data and ray-tracing structures are also used to stress loading and synchronization behavior rather than hiding it behind a finished engine abstraction. + +## Controls + +| Input | Action | +|:--|:--| +| `W` / `A` / `S` / `D` | Move camera | +| Arrow keys | Rotate camera | +| Right mouse drag | Rotate camera | +| `Space` | Toggle raster / path tracing | +| `Enter` | Toggle path-tracing accumulation | +| `F1` | Toggle cursor visibility | + +Gamepad camera controls are also available. + +## Command-line options + +- `--vulkan` — prefer the Vulkan backend. +- `--fullscreen` — start fullscreen. +- `--gpu-debug` — enable the graphics debug layer. +- `.scene` — use another compiled scene instead of Sponza. + +## Key files + +- [`main.c`](main.c) — renderer setup and frame graph written explicitly as command recording. +- [`DebugUI.c`](DebugUI.c) / [`DebugUI.h`](DebugUI.h) — renderer debug overlay and statistics. +- [`ElementalArt.c`](ElementalArt.c) / [`ElementalArt.h`](ElementalArt.h) — renderer-specific drawing helpers. +- [`UnityBuild.c`](UnityBuild.c) — unity-build entry point for the demo implementation. +- [`Data`](Data) — renderer shaders. + +## Build + +```bash +cmake --build --preset default --target Renderer +``` + +> [!WARNING] +> Renderer is active R&D code. TODO, HACK and BUG comments are expected here. Treat it as a place where Elemental is stressed and new requirements are discovered, not as a reference engine architecture. + +[Back to samples](../../README.md) diff --git a/samples/Demos/02-AITraining/README.md b/samples/Demos/02-AITraining/README.md new file mode 100644 index 00000000..21dfbd8f --- /dev/null +++ b/samples/Demos/02-AITraining/README.md @@ -0,0 +1,51 @@ +# AI Training Demo + +A small neural-network and automatic-differentiation experiment written in C. + +This demo is currently a **CPU baseline**. It does not run training or tensor operations on the GPU yet. Its role is to keep the learning experiment small and understandable before exploring how the same kind of workload could use Elemental compute and future GPU linear-algebra capabilities. + +## NeuralNetV0 + +`NeuralNetV0.c` implements a tiny scalar automatic-differentiation engine from scratch: + +- values stored behind small integer handles; +- an operation graph with parent dependencies; +- reverse-mode gradient propagation; +- addition, multiplication, subtraction, division, power, exponential and `tanh` operations; +- neurons, layers and a small multilayer neural network; +- forward pass, squared-error loss, backward pass and parameter updates. + +The current network is: + +```text +3 inputs + -> 4 neurons + -> 4 neurons + -> 1 output +``` + +It trains for 20 steps on four small input/output examples and prints the loss and final predictions to the console. + +## NeuralNetV1 + +`NeuralNetV1.c` is currently only a skeleton for the next iteration. The forward, backward and parameter-update stages are intentionally unfinished. + +## Why this is in Elemental + +The interesting future experiment is not to turn Elemental into a machine-learning framework. It is to start from code this small and ask what the minimal GPU programming path should look like when selected tensor or neural-network operations move to modern GPU hardware. + +That GPU version does not exist in this sample yet. + +## Key files + +- [`NeuralNetV0.c`](NeuralNetV0.c) — working CPU autodiff and neural-network experiment. +- [`NeuralNetV1.c`](NeuralNetV1.c) — next-iteration placeholder. +- [`main.c`](main.c) — sample application entry point. + +## Build + +```bash +cmake --build --preset default --target AITraining +``` + +[Back to samples](../../README.md) diff --git a/samples/Elemental/01-HelloTriangle/README.md b/samples/Elemental/01-HelloTriangle/README.md new file mode 100644 index 00000000..d6a35105 --- /dev/null +++ b/samples/Elemental/01-HelloTriangle/README.md @@ -0,0 +1,51 @@ +# Hello Triangle + +The smallest graphics sample and the recommended first look at Elemental's runtime API. + +It creates a window, graphics device, command queue and swap chain, then renders a rotating triangle with a mesh shader. + +## What it demonstrates + +- application and window lifetime; +- graphics-device creation; +- a graphics command queue and command list; +- swap-chain rendering and presentation; +- shader-library loading and graphics-pipeline creation; +- push constants; +- a render pass; +- mesh-shader dispatch. + +The triangle is generated entirely inside the shader, so there is no vertex buffer or asset loading to distract from the basic GPU execution path. + +## Frame flow + +```text +get command list + -> begin render pass + -> bind graphics pipeline + -> push aspect ratio + rotation + -> dispatch mesh shader + -> end render pass + -> commit + execute + -> present +``` + +`Data/Triangle.hlsl` emits three vertices and one triangle from `MeshMain`, then `PixelMain` outputs the interpolated vertex color. + +## Key files + +- [`main.c`](main.c) — application setup and per-frame command recording. +- [`Data/Triangle.hlsl`](Data/Triangle.hlsl) — procedural triangle mesh and pixel shaders. + +## Build + +From the repository root: + +```bash +cmake --preset default +cmake --build --preset default --target HelloTriangle +``` + +The sample also accepts `--vulkan`, primarily to select Vulkan instead of the default Direct3D 12 backend on Windows. + +[Back to samples](../../README.md) diff --git a/samples/Elemental/02-HelloInputs/README.md b/samples/Elemental/02-HelloInputs/README.md new file mode 100644 index 00000000..05f2f191 --- /dev/null +++ b/samples/Elemental/02-HelloInputs/README.md @@ -0,0 +1,48 @@ +# Hello Inputs + +This sample keeps the simple triangle from Hello Triangle and adds cross-platform input handling. + +The important part is not the triangle itself: it is the path from Elemental's raw input event stream to application actions that can be shared across keyboard, mouse, gamepad and touch input. + +## What it demonstrates + +- reading `ElemInputStream` every frame; +- consuming `ElemInputEvent` values; +- mapping several physical inputs to the same logical action; +- keyboard, mouse, gamepad and touch input; +- press/release, toggle and double-release behavior; +- cursor visibility and application exit; +- driving shader parameters from input. + +The small action-binding layer in `main.c` belongs to this sample. It is an example of how application code can consume Elemental input events, not a required high-level input model imposed by Elemental. + +## Controls + +| Input | Action | +|:--|:--| +| `W` / `S` | Rotate up / down | +| `A` / `D` | Rotate left / right | +| `Q` / `E` | Roll | +| `Z` / `X` | Zoom | +| `Space` | Change triangle color | +| `F1` | Toggle cursor visibility | +| `Escape` | Exit | +| Mouse drag / wheel | Rotate / zoom | +| Mouse double-click | Change triangle color | + +Gamepad and touch bindings provide equivalent rotation, zoom and action controls. Two-finger touch input is used for pinch/rotation gestures. + +## Key files + +- [`main.c`](main.c) — input bindings, action updates and triangle rendering. +- [`Data/Triangle.hlsl`](Data/Triangle.hlsl) — mesh and pixel shaders driven by the current input state. + +## Build + +```bash +cmake --build --preset default --target HelloInputs +``` + +The sample also accepts `--vulkan`, primarily to select Vulkan instead of the default Direct3D 12 backend on Windows. + +[Back to samples](../../README.md) diff --git a/samples/Elemental/03-HelloCompute/README.md b/samples/Elemental/03-HelloCompute/README.md new file mode 100644 index 00000000..135421ca --- /dev/null +++ b/samples/Elemental/03-HelloCompute/README.md @@ -0,0 +1,58 @@ +# Hello Compute + +This sample introduces general-purpose GPU compute by rendering an interactive Julia fractal into a texture and then displaying that texture through the graphics pipeline. + +It is also the first sample where resource descriptors and barriers become an important part of the frame. + +## What it demonstrates + +- creating a GPU heap and texture resource; +- creating separate bindless read and write descriptors for the same texture; +- compiling and dispatching a compute pipeline; +- writing an `RWTexture2D` through `ResourceDescriptorHeap`; +- transitioning the texture from compute-write access to graphics-read access; +- displaying a compute result with a fullscreen graphics pass; +- recreating GPU resources when the swap chain changes size. + +## Frame flow + +```text +bind compute pipeline + -> barrier for texture write + -> dispatch 16x16 compute groups + -> barrier for texture read + -> begin render pass + -> draw fullscreen mesh + -> end render pass + -> commit + execute + -> present +``` + +`Data/Fractal.hlsl` currently renders a Julia set. A Mandelbrot implementation is also present in the shader as an alternate experiment. + +## Controls + +| Input | Action | +|:--|:--| +| `W` / `A` / `S` / `D` | Move around the fractal | +| `Q` / `E` | Rotate | +| `Z` / `X` | Zoom | +| `F1` | Toggle cursor visibility | +| `Escape` | Exit | +| Mouse / touch / gamepad | Equivalent navigation controls | + +## Key files + +- [`main.c`](main.c) — texture allocation, descriptors, barriers, compute dispatch and presentation. +- [`Data/Fractal.hlsl`](Data/Fractal.hlsl) — 16x16 compute shader that generates the fractal. +- [`Data/Tonemap.hlsl`](Data/Tonemap.hlsl) — fullscreen pass used to display the generated texture. + +## Build + +```bash +cmake --build --preset default --target HelloCompute +``` + +The sample also accepts `--vulkan`, primarily to select Vulkan instead of the default Direct3D 12 backend on Windows. + +[Back to samples](../../README.md) diff --git a/samples/Elemental/04-HelloMesh/README.md b/samples/Elemental/04-HelloMesh/README.md new file mode 100644 index 00000000..e496cbff --- /dev/null +++ b/samples/Elemental/04-HelloMesh/README.md @@ -0,0 +1,50 @@ +# Hello Mesh + +Hello Mesh moves from procedural geometry to compiled mesh data and meshlets. + +The sample loads a small scene, creates a depth buffer and dispatches a mesh shader using the meshlet data for the first mesh primitive. It is intentionally a focused mesh-rendering sample rather than a general scene renderer. + +## What it demonstrates + +- loading the sample `.scene` format; +- using mesh and meshlet data produced by the Scene Compiler sample; +- allocating GPU memory for scene data; +- creating and resizing a depth buffer; +- configuring depth testing; +- passing mesh-buffer offsets to a mesh shader; +- dispatching one mesh-shader workgroup per meshlet; +- interactive model-viewer controls. + +The sample currently renders the first primitive from `kitten.scene`. The surrounding scene/GPU-memory helpers are shared sample code and are still evolving. + +## Controls + +| Input | Action | +|:--|:--| +| `W` / `S` | Rotate up / down | +| `A` / `D` | Rotate left / right | +| `Q` / `E` | Roll | +| `Z` / `X` | Zoom | +| `Space` | Toggle meshlet visualization | +| `F1` | Toggle cursor visibility | +| `Escape` | Exit | +| Mouse / touch / gamepad | Equivalent model-viewer controls | + +## Key files + +- [`main.c`](main.c) — scene loading, GPU resources, depth buffer and mesh dispatch. +- [`Data/RenderMesh.hlsl`](Data/RenderMesh.hlsl) — meshlet-based mesh and pixel shaders. +- [`../../ElementalTools/02-SceneCompiler`](../../ElementalTools/02-SceneCompiler) — creates the sample scene data consumed here. + +## Build + +```bash +cmake --build --preset default --target HelloMesh +``` + +Supported sample flags include `--vulkan`, `--fullscreen` and `--gpu-debug`. + +> [!NOTE] +> This sample deliberately contains some shared helper code and temporary memory/scene-loading choices. It demonstrates the mesh-shader path; it is not intended to define a final renderer architecture. + +[Back to samples](../../README.md) diff --git a/samples/Elemental/05-HelloRaytracing/README.md b/samples/Elemental/05-HelloRaytracing/README.md new file mode 100644 index 00000000..137c586f --- /dev/null +++ b/samples/Elemental/05-HelloRaytracing/README.md @@ -0,0 +1,55 @@ +# Hello Raytracing + +This sample introduces Elemental's ray-tracing resources and acceleration structures using a small Cornell Box scene. + +It builds GPU scene data plus BLAS/TLAS acceleration structures, then uses **inline ray queries (`RayQuery`) inside regular shaders** rather than a traditional ray-generation / miss / closest-hit shader pipeline. + +## What it demonstrates + +- creating GPU scene data for ray tracing; +- building bottom-level and top-level acceleration structures; +- exposing a TLAS through a bindless descriptor; +- using `RayQuery` and `TraceRayInline` from HLSL; +- recovering triangle, barycentric, vertex and material data after a hit; +- raster and ray/path-traced rendering paths in the same application; +- accumulating path-tracing samples in a floating-point render target; +- tonemapping the result to the swap chain. + +## Controls + +| Input | Action | +|:--|:--| +| `W` / `A` / `S` / `D` | Move camera | +| Arrow keys | Rotate camera | +| Right mouse drag | Rotate camera | +| `Space` | Toggle raster / path tracing | +| `Enter` | Toggle path-tracing accumulation | +| `F` | Toggle scene animation | +| `1` / `2` | Decrease / increase path length | +| `F1` | Toggle cursor visibility | +| `Escape` | Exit | + +Gamepad bindings are also available through the shared camera input helper. + +The camera state is saved between runs in `SavedState.bin`. + +## Key files + +- [`main.c`](main.c) — scene setup, acceleration structures, render paths and accumulation. +- [`Data/Raytracing.hlsl`](Data/Raytracing.hlsl) — inline ray queries and path-tracing logic. +- [`Data/RenderMesh.hlsl`](Data/RenderMesh.hlsl) — raster comparison path. +- [`Data/Tonemap.hlsl`](Data/Tonemap.hlsl) — final display pass. +- [`Data/ShaderData.h`](Data/ShaderData.h) — CPU/shader shared data layout. + +## Build + +```bash +cmake --build --preset default --target HelloRaytracing +``` + +Supported sample flags include `--vulkan`, `--fullscreen` and `--gpu-debug`. + +> [!NOTE] +> This is intentionally a larger sample than the previous four. Shared scene, GPU-memory and ray-tracing helpers keep the application focused on the high-level flow, but those helpers are sample infrastructure rather than additional Elemental API layers. + +[Back to samples](../../README.md) diff --git a/samples/ElementalTools/01-ShaderCompiler/README.md b/samples/ElementalTools/01-ShaderCompiler/README.md new file mode 100644 index 00000000..df57c37a --- /dev/null +++ b/samples/ElementalTools/01-ShaderCompiler/README.md @@ -0,0 +1,59 @@ +# Shader Compiler + +A minimal command-line example of offline shader compilation with ElementalTools. + +The tool reads an HLSL source file, compiles it for an Elemental graphics backend/platform and writes the resulting shader-library binary to disk. + +## Usage + +```text +ShaderCompiler [options] inputfile outputfile +``` + +Example: + +```bash +ShaderCompiler MyShader.hlsl MyShader.shader +``` + +Host defaults are: + +| Host | Default target | +|:--|:--| +| Windows | Direct3D 12 / Windows | +| Linux | Vulkan / Linux | +| macOS | Metal / macOS | + +The current sample parser also handles: + +- `--debug` — include shader debug information; +- `--target-api vulkan` — select Vulkan; +- `--target-platform iOS` — target iOS. + +The parser is intentionally basic and does not yet expose every target combination supported by ElementalTools. + +## Flow + +```text +HLSL source + -> ElemCompileShaderLibrary + -> compiler messages / errors + -> compiled shader-library data + -> output file +``` + +The generated binary can be loaded at runtime with `ElemCreateShaderLibrary`. + +## Key file + +- [`main.c`](main.c) — argument parsing, shader compilation and output writing. + +## Build + +```bash +cmake --build --preset default --target ShaderCompiler +``` + +This command-line sample is not built for iOS. + +[Back to samples](../../README.md) diff --git a/samples/ElementalTools/02-SceneCompiler/README.md b/samples/ElementalTools/02-SceneCompiler/README.md new file mode 100644 index 00000000..3dfa83b7 --- /dev/null +++ b/samples/ElementalTools/02-SceneCompiler/README.md @@ -0,0 +1,61 @@ +# Scene Compiler + +A command-line example that turns a source scene into the compact binary scene format used by Elemental's samples. + +It uses ElementalTools to load the source scene, builds meshlets for every mesh primitive and serializes the data needed by the mesh and ray-tracing samples. + +## Usage + +```text +SceneCompiler [options] inputfile outputfile +``` + +Example: + +```bash +SceneCompiler model.gltf model.scene +``` + +The current option parser is still experimental; the `--meshlet-triangle-count` entry printed by the tool is a placeholder and is not implemented yet. + +## What it does + +For each scene, the sample: + +- loads meshes, materials and nodes with `ElemLoadScene`; +- builds meshlets with `ElemBuildMeshlets`; +- packs vertex and index data; +- packs meshlet metadata, meshlet vertex indices and meshlet triangle indices; +- records material references and a small texture table; +- writes offsets so the runtime sample loader can access each data block directly. + +Conceptually: + +```text +source scene + -> ElementalTools scene loader + -> meshlet generation + -> sample-specific packing + -> .scene file +``` + +The generated files are consumed by samples such as Hello Mesh, Hello Raytracing and Renderer. + +> [!NOTE] +> `.scene` is a format owned by the sample code. It is not a stable public Elemental asset format or a general-purpose scene standard. + +The sample also contains a few hard-coded import adjustments for known test assets while the asset pipeline is still evolving. + +## Key file + +- [`main.c`](main.c) — scene import, meshlet generation and binary serialization. + +## Build + +```bash +cmake --build --preset default --target SceneCompiler +``` + +This command-line sample is not built for iOS. + +[Back to samples](../../README.md) diff --git a/samples/ElementalTools/03-TextureCompiler/README.md b/samples/ElementalTools/03-TextureCompiler/README.md new file mode 100644 index 00000000..1588b11d --- /dev/null +++ b/samples/ElementalTools/03-TextureCompiler/README.md @@ -0,0 +1,51 @@ +# Texture Compiler + +A command-line example that converts image data into the binary texture format used by Elemental's samples. + +The tool loads the source texture through ElementalTools, generates a mip chain when necessary and stores BC7-compressed mip data for runtime use. + +## Usage + +```text +TextureCompiler [options] inputfile outputfile +``` + +Example: + +```bash +TextureCompiler albedo.png albedo.texture +``` + +There are no meaningful command-line options implemented yet; the parser currently only reserves space for future options. + +## What it does + +```text +source image + -> ElemLoadTexture + -> generate mip levels when needed + -> BC7 compression + -> write mip offsets + data + -> .texture file +``` + +If the loaded texture contains only one mip level, the sample calls `ElemGenerateTextureMipData` to build the rest of the chain. Each mip is then compressed with `ElemCompressTextureMipData` unless the input data is already BC7. + +The output format is currently hard-coded to BC7. + +> [!NOTE] +> `.texture` is a format owned by the sample code. It is not a stable public Elemental asset format or a general-purpose texture container. + +## Key file + +- [`main.c`](main.c) — texture loading, mip generation, compression and binary serialization. + +## Build + +```bash +cmake --build --preset default --target TextureCompiler +``` + +This command-line sample is not built for iOS. + +[Back to samples](../../README.md) diff --git a/samples/README.md b/samples/README.md index 2e48bef4..c9308fb6 100644 --- a/samples/README.md +++ b/samples/README.md @@ -1,28 +1,53 @@ # Elemental Samples -List of available samples: +The sample tree is split into three groups with different goals: -Foundations: -- [01 - Hello World](#01HelloWorld) -- [02 - Hello Window](#02HelloWindow) +- [`Elemental`](Elemental) contains small, progressive samples focused on the public runtime API. +- [`Demos`](Demos) contains larger experiments used to stress Elemental and explore renderer or GPU-programming ideas. +- [`ElementalTools`](ElementalTools) contains small command-line examples for offline asset and shader processing. -Graphics: -- [01 - Hello Triangle] +The runtime samples are intentionally low level. They keep resources, queues, command lists, descriptors, barriers and pipelines visible instead of hiding them behind a sample framework. -## 01 - Hello World +## Build -[This sample](01-Foundations/01-HelloWorld/Program.cs) shows how to create a new native application and do some basic logic at each main loop iteration. +From the repository root: -![](screenshots/01-Foundations/01-HelloWorld.png) +```bash +cmake --preset default +cmake --build --preset default +``` -## 02 - HelloWindow +A single sample can also be built by target, for example: -[This sample](01-Foundations/02-HelloWindow/Program.cs) shows how to create a new native window. It also displays the current available render width in the title bar. +```bash +cmake --build --preset default --target HelloTriangle +``` -![](screenshots/01-Foundations/02-HelloWindow.png) +Prebuilt sample packages are also published with Elemental development releases. -## 02 - HelloWindow +## Elemental -[This sample](01-Foundations/02-HelloWindow/Program.cs) shows how to create a new native window. It also displays the current available render width in the title bar. +These are the best place to start. Each sample introduces another part of the runtime API. -![](screenshots/01-Foundations/02-HelloWindow.png) \ No newline at end of file +1. [`01-HelloTriangle`](Elemental/01-HelloTriangle) — create the basic graphics objects and draw a procedural triangle with a mesh shader. +2. [`02-HelloInputs`](Elemental/02-HelloInputs) — consume Elemental's input stream from keyboard, mouse, gamepad and touch devices. +3. [`03-HelloCompute`](Elemental/03-HelloCompute) — generate a Julia fractal with a compute shader, synchronize the texture and display it through the graphics pipeline. +4. [`04-HelloMesh`](Elemental/04-HelloMesh) — load compiled mesh data, use meshlets and render a real mesh with a depth buffer. +5. [`05-HelloRaytracing`](Elemental/05-HelloRaytracing) — build acceleration structures and use inline ray queries for interactive ray/path-tracing experiments. + +## Demos + +Demos are larger laboratories rather than minimal tutorials. They intentionally combine several systems and may contain active TODOs, experiments and temporary implementation choices. + +- [`01-Renderer`](Demos/01-Renderer) — Elemental's main renderer stress test, combining scene loading, mesh shaders, bindless resources, ray tracing, compute path tracing, GPU timings and a debug UI. +- [`02-AITraining`](Demos/02-AITraining) — a small CPU-side neural-network/autodiff experiment used as a baseline for future GPU-compute exploration. It does **not** run neural-network training on the GPU yet. + +## ElementalTools + +These command-line samples demonstrate the offline side of the project. + +- [`01-ShaderCompiler`](ElementalTools/01-ShaderCompiler) — compile HLSL into an Elemental shader library for a target backend/platform. +- [`02-SceneCompiler`](ElementalTools/02-SceneCompiler) — load a source scene, build meshlets and serialize the sample scene format. +- [`03-TextureCompiler`](ElementalTools/03-TextureCompiler) — load a texture, generate mip levels and write BC7-compressed sample texture data. + +The `.scene` and `.texture` files produced by these samples are formats used by the sample code. They should not be treated as stable public Elemental asset formats.