diff options
Diffstat (limited to 'doc/ASSET_SYSTEM.md')
| -rw-r--r-- | doc/ASSET_SYSTEM.md | 136 |
1 files changed, 48 insertions, 88 deletions
diff --git a/doc/ASSET_SYSTEM.md b/doc/ASSET_SYSTEM.md index f52e382..6104353 100644 --- a/doc/ASSET_SYSTEM.md +++ b/doc/ASSET_SYSTEM.md @@ -1,42 +1,50 @@ # Compact Asset System for the 64k Demo -This file describes the asset system architecture and runtime API. - -## Core Concept - All assets are const byte arrays embedded in the binary. Runtime retrieval via `GetAsset(AssetId)` returns direct pointers with O(1) lookup. -## Runtime Asset Retrieval - -```cpp -#include "assets.h" -const uint8_t* mysample = GetAsset(ASSET_SAMPLE_142, &size); -// ... use asset -DropAsset(ASSET_SAMPLE_142, mysample); // For lazy decompression cleanup -``` - ## Asset Manifest Format Files: `workspaces/main/assets.txt`, `workspaces/test/assets.txt` Format (CSV): ``` -ASSET_NAME, COMPRESSION, filename.ext, "Description" +ASSET_NAME, COMPRESSION, path/to/file.ext, "Description" ``` -Example: +### Compression Types + +| Type | Behavior | +|------|----------| +| `NONE` | Raw binary embed (shaders, meshes, `.spec` files) | +| `MP3` | MP3 audio; decoded to spectrogram at init | +| `PROC(func, ...)` | CPU procedural generation at init | +| `PROC_GPU(func, ...)` | GPU compute procedural generation at init | + +## AssetType Enum + +Each `AssetRecord` carries an `AssetType` field (replaces the former `is_procedural`/`is_gpu_procedural` bools): + +```cpp +enum class AssetType : uint8_t { STATIC, PROC, PROC_GPU, MP3 }; ``` -SAMPLE_142, sample_142.spec, NONE, "This is a drum kick sample" -SHADER_COMMON, shaders/common.wgsl, NONE, "Common utilities" + +Query at runtime: +```cpp +if (GetAssetType(AssetId::NEVER_MP3) == AssetType::MP3) { ... } ``` -This generates: +## Runtime API + ```cpp -enum class AssetId : uint16_t { - ASSET_SAMPLE_142 = 6323, - SHADER_COMMON = 6324, - // ... -}; +#include "util/asset_manager.h" + +// Retrieve asset data +size_t size; +const uint8_t* data = GetAsset(AssetId::MY_ASSET, &size); +DropAsset(AssetId::MY_ASSET, data); // Release procedural/cached data + +// Query type +AssetType t = GetAssetType(AssetId::MY_ASSET); ``` ## Build Pipeline @@ -44,80 +52,32 @@ enum class AssetId : uint16_t { Tool: `tools/asset_packer.cc` 1. Parse workspace `assets.txt` -2. Read files from workspace `assets/` or `assets/common/` -3. Generate `assets.h` (enum definitions) -4. Generate `assets_data.cc` (embedded byte arrays) +2. Read/process files (images → RGBA8 header, meshes → vertex/index binary, others → raw) +3. Generate `src/generated/assets.h` (enum + declarations) +4. Generate `src/generated/assets_data.cc` (byte arrays + `AssetRecord` table) 5. Auto-triggered by CMake on manifest changes ## Technical Guarantees -1. **Alignment**: All arrays declared `alignas(16)` for safe `reinterpret_cast` -2. **String Safety**: Null-terminator appended (safe as C-string) -3. **Size Reporting**: `size` reflects original file size (buffer is `size + 1`) +- **Alignment**: All arrays declared `alignas(16)` for safe `reinterpret_cast` +- **String Safety**: Null-terminator appended (safe as C-string) +- **Size**: `size` reflects original file size (buffer is `size + 1`) -## Shader Asset Usage +## Developer Workflow -```cpp -size_t size; -const uint8_t* shader_src = GetAsset(AssetId::SHADER_COMMON, &size); -std::string_view code(reinterpret_cast<const char*>(shader_src), size); -ShaderComposer::register_snippet("common", code); +**Add a static asset:** +``` +MY_ASSET, NONE, path/to/file.ext, "Description" ``` -## Procedural Assets - -Format: `PROC(function_name, params...)` - -Example: +**Add an MP3 sample:** ``` -NOISE_TEX, PROC(gen_noise, 1234, 16), NONE, "Noise texture seed=1234 freq=16" +MY_SAMPLE, MP3, music/sample.mp3, "Description" ``` -Runtime: First `GetAsset()` call invokes generator, caches result. - -## Design Strengths - -- Enum-based type safety (no magic numbers) -- Zero runtime cost for static assets -- Procedural generation support (size savings) -- Thread-safe for immutable assets - -## Design Weaknesses - -- **No compression**: Only `NONE` supported (critical blocker for 64k) -- **STL dependencies**: `std::map` in runtime code (conflicts with CRT removal) -- **Hardcoded procedural dimensions**: Assumes 256×256 RGBA8 -- **No integrity checks**: No CRC/hash validation - -## Developer Workflow - -**Add new asset:** -1. Place file in workspace `assets/` (or `assets/common/` for shared) -2. Edit workspace `assets.txt`: - ``` - MY_ASSET, NONE, assets/myfile.ext, "Description" - ``` -3. Rebuild: `cmake --build build -j4` (auto-triggered) -4. Use in code: `GetAsset(AssetId::MY_ASSET, &size)` - -**Modify existing asset:** -- Edit source file in `assets/final/` -- CMake auto-detects change and rebuilds - -## Planned Improvements - -See **TODO.md** for detailed task breakdown: -- **Task #27**: Asset compression (zlib, RLE) -- **Task #28**: Spectrogram quantization (float32 → uint16_t) -- **Task #29**: WGSL shader minification -- **Task #30**: Procedural asset generalization -- **Task #31**: Asset integrity validation (CRC32) -- **Task #32**: Hot-reloading (dev builds) -- **Task #33**: Dead asset elimination - -## Current Manifest +**Add a procedural texture:** +``` +MY_TEX, PROC(gen_noise, 1234, 16), _, "Description" +``` -33 assets total: -- 15 audio samples (`.spec`) -- 17 WGSL shaders -- 1 procedural texture +Rebuild: `cmake --build build -j4` — CMake detects manifest changes automatically. |
