summaryrefslogtreecommitdiff
path: root/doc
diff options
context:
space:
mode:
authorskal <pascal.massimino@gmail.com>2026-02-09 14:34:36 +0100
committerskal <pascal.massimino@gmail.com>2026-02-09 14:34:36 +0100
commitc5aa3f6492e9c9464eea1eea9656806bd19f61fe (patch)
treef94ef7fdbb6ed1136aa6ecef5263acbd303ada47 /doc
parentbd2ca805eeddd2688a8f1b3ed5ec8ed1677748fc (diff)
docs: Purge outdated Phase 4 content
Update to reflect actual implementation: - Simplified to essential API and usage - Removed speculative asset packer syntax (not implemented) - Removed future extension details (defer to future phases) - Focused on what's actually complete and tested
Diffstat (limited to 'doc')
-rw-r--r--doc/GPU_PROCEDURAL_PHASE4.md280
1 files changed, 40 insertions, 240 deletions
diff --git a/doc/GPU_PROCEDURAL_PHASE4.md b/doc/GPU_PROCEDURAL_PHASE4.md
index 53d79ec..4cfc271 100644
--- a/doc/GPU_PROCEDURAL_PHASE4.md
+++ b/doc/GPU_PROCEDURAL_PHASE4.md
@@ -1,270 +1,70 @@
-# GPU Procedural Texture Generation - Phase 4: Texture Composition
+# GPU Procedural Phase 4: Texture Composition
-## Overview
+**Status:** ✅ Complete
-Enable compute shaders to read existing procedural textures as input samplers, allowing multi-stage texture generation (blend, mask, modulate).
+## Implementation
-## Design
+Multi-input composite shaders with configurable sampler support.
-### Extended API
+### API
```cpp
-struct GpuProceduralInputs {
- std::vector<std::string> input_texture_names; // Names of existing textures
- std::vector<WGPUTextureView> input_views; // Resolved views (internal)
+enum class SamplerType {
+ LinearClamp, LinearRepeat, NearestClamp, NearestRepeat
};
-void TextureManager::create_gpu_composite_texture(
+void create_gpu_composite_texture(
const std::string& name,
const std::string& shader_func,
- const GpuProceduralParams& params,
- const GpuProceduralInputs& inputs);
-```
-
-### Shader Pattern
-
-```wgsl
-// gen_blend.wgsl - Blend two textures
-@group(0) @binding(0) var output_tex: texture_storage_2d<rgba8unorm, write>;
-@group(0) @binding(1) var<uniform> params: BlendParams;
-@group(0) @binding(2) var input_a: texture_2d<f32>;
-@group(0) @binding(3) var input_b: texture_2d<f32>;
-@group(0) @binding(4) var tex_sampler: sampler;
-
-struct BlendParams {
- width: u32,
- height: u32,
- blend_factor: f32, // 0.0 = all A, 1.0 = all B
- _pad0: f32,
-}
-
-@compute @workgroup_size(8, 8, 1)
-fn main(@builtin(global_invocation_id) id: vec3<u32>) {
- if (id.x >= params.width || id.y >= params.height) { return; }
-
- let uv = vec2<f32>(f32(id.x) / f32(params.width),
- f32(id.y) / f32(params.height));
-
- let color_a = textureSampleLevel(input_a, tex_sampler, uv, 0.0);
- let color_b = textureSampleLevel(input_b, tex_sampler, uv, 0.0);
- let blended = mix(color_a, color_b, params.blend_factor);
-
- textureStore(output_tex, id.xy, blended);
-}
-```
-
-### Bind Group Layout Changes
-
-**Current (single-input generators):**
-- Binding 0: Storage texture (write)
-- Binding 1: Uniform buffer
-
-**New (multi-input generators):**
-- Binding 0: Storage texture (write)
-- Binding 1: Uniform buffer
-- Binding 2+: Input textures (read, texture_2d<f32>)
-- Binding N: Sampler (shared across all inputs)
-
-### Implementation
-
-#### 1. Extend ComputePipelineInfo
-
-```cpp
-struct ComputePipelineInfo {
- WGPUComputePipeline pipeline;
- const char* shader_code;
- size_t uniform_size;
- int num_input_textures; // NEW: 0 for gen_noise/perlin/grid, 2+ for composite
-};
-```
-
-#### 2. Update get_or_create_compute_pipeline
-
-```cpp
-WGPUComputePipeline get_or_create_compute_pipeline(
- const std::string& func_name,
const char* shader_code,
+ const void* uniform_data,
size_t uniform_size,
- int num_input_textures = 0); // Default 0 (backward compatible)
-```
-
-Dynamically create bind group layout based on `num_input_textures`:
-```cpp
-// Binding 0: output texture
-// Binding 1: uniform buffer
-// Binding 2 to (2 + num_input_textures - 1): input textures
-// Binding (2 + num_input_textures): sampler
+ int width, int height,
+ const std::vector<std::string>& input_names,
+ SamplerType sampler = SamplerType::LinearClamp);
```
-#### 3. New dispatch_composite
+### Shaders
-```cpp
-void dispatch_composite(const std::string& func_name,
- WGPUTexture target,
- const GpuProceduralParams& params,
- const void* uniform_data,
- size_t uniform_size,
- const std::vector<WGPUTextureView>& input_views);
-```
+**gen_blend.wgsl** - Blend two textures with lerp factor:
+- Bindings: output (0), uniform (1), input_a (2), input_b (3), sampler (4)
+- Uniform: `{u32 width, height; f32 blend_factor, _pad0}`
-Create bind group with:
-- Output storage texture (binding 0)
-- Uniform buffer (binding 1)
-- Input texture views (binding 2+)
-- Linear sampler (binding N)
+**gen_mask.wgsl** - Multiply textures (masking):
+- Bindings: output (0), uniform (1), input_a (2), input_b (3), sampler (4)
+- Uniform: `{u32 width, height}`
-#### 4. Convenience Wrapper
+### Usage
```cpp
-void create_gpu_composite_texture(const std::string& name,
- const std::string& shader_func,
- const GpuProceduralParams& params,
- const std::vector<std::string>& input_names);
-```
-
-Resolve `input_names` → `WGPUTextureView[]` via `get_texture_view()`.
-
-### Example Shaders
-
-**gen_blend.wgsl** (~150 bytes)
-- Blend two textures with lerp factor
-
-**gen_mask.wgsl** (~180 bytes)
-- Multiply texture A by texture B (use grid as mask)
-
-**gen_modulate.wgsl** (~200 bytes)
-- Multiply texture color by noise intensity
+extern const char* gen_blend_compute_wgsl;
-**gen_fbm_noise.wgsl** (~250 bytes)
-- FBM using multiple octaves of pre-generated noise textures
+struct { uint32_t width, height; float blend_factor, _pad0; } uni = {256, 256, 0.5f, 0.0f};
-### Usage Example
-
-```cpp
-// Generate base textures
-GpuProceduralParams noise_params = {256, 256, {123.0f, 4.0f}, 2};
-tex_mgr.create_gpu_noise_texture("noise_a", noise_params);
-
-GpuProceduralParams grid_params = {256, 256, {32.0f, 2.0f}, 2};
-tex_mgr.create_gpu_grid_texture("grid", grid_params);
-
-// Composite: Apply grid as mask to noise
-float blend_vals[1] = {0.5f};
-GpuProceduralParams composite = {256, 256, blend_vals, 1};
-std::vector<std::string> inputs = {"noise_a", "grid"};
-tex_mgr.create_gpu_composite_texture("masked_noise", "gen_mask", composite, inputs);
-```
-
-### Asset Packer Syntax
-
-```
-# Phase 1-3: Single-input generators
-NOISE_GPU, PROC_GPU(gen_noise, 1234, 16), _, "GPU noise"
-
-# Phase 4: Multi-input composites
-MASKED_NOISE, PROC_GPU(gen_mask, NOISE_GPU, GRID_GPU), _, "Masked noise"
+tex_mgr.create_gpu_composite_texture(
+ "blended", "gen_blend", gen_blend_compute_wgsl,
+ &uni, sizeof(uni), 256, 256,
+ {"noise_a", "noise_b"},
+ SamplerType::LinearClamp);
```
-**Syntax:** `PROC_GPU(shader_func, input_asset_1, input_asset_2, ...)`
-- First arg: Shader function name
-- Remaining args: Asset IDs of input textures (or scalar params if no uppercase)
+### Features
-**asset_packer changes:**
-1. Parse input asset dependencies
-2. Set `depends_on` field in AssetRecord
-3. Generate init-time ordering (topological sort)
-4. Pass input texture names to create_gpu_composite_texture
+- **Dynamic bind groups:** N input textures + 1 sampler
+- **Lazy sampler creation:** Map-based cache, 4 preset types
+- **Multi-stage composition:** Composite of composites supported
+- **Guarded with `#if !defined(STRIP_GPU_COMPOSITE)`**
### Size Impact
-**Code additions:**
-- Extended dispatch_composite: ~250 bytes
-- Dynamic bind group layout: ~150 bytes
-- create_gpu_composite_texture: ~100 bytes
-- gen_blend.wgsl shader: ~150 bytes
-- gen_mask.wgsl shader: ~180 bytes
-
-**Total Phase 4:** ~830 bytes for 2 composite shaders
-
-**Benefits:**
-- Eliminate CPU-side texture compositing
-- Zero memory for intermediate buffers
-- Enables complex multi-stage effects (FBM, domain warping)
-
-### Testing
-
-**Unit test:**
-```cpp
-// Create base textures
-tex_mgr.create_gpu_noise_texture("noise_a", {256, 256, {1.0f, 4.0f}, 2});
-tex_mgr.create_gpu_grid_texture("grid", {256, 256, {32.0f, 2.0f}, 2});
-
-// Composite
-std::vector<std::string> inputs = {"noise_a", "grid"};
-tex_mgr.create_gpu_composite_texture("masked", "gen_mask", {256, 256, {}, 0}, inputs);
-
-// Verify
-WGPUTextureView view = tex_mgr.get_texture_view("masked");
-assert(view != nullptr);
-```
-
-**Integration test:**
-- Visual comparison of CPU vs GPU compositing
-- Verify dependency ordering (inputs generated before composite)
-
-## Future Extensions
-
-**Domain Warping:**
-```wgsl
-// Use noise texture to distort UVs of another texture
-let offset = textureSampleLevel(noise, sampler, uv, 0.0).rg * 0.1;
-let warped_uv = uv + offset;
-let color = textureSampleLevel(base, sampler, warped_uv, 0.0);
-```
-
-**Multi-octave FBM:**
-```cpp
-// Generate octaves at different frequencies
-tex_mgr.create_gpu_noise_texture("octave_0", {256, 256, {0.0f, 2.0f}, 2});
-tex_mgr.create_gpu_noise_texture("octave_1", {256, 256, {0.0f, 4.0f}, 2});
-tex_mgr.create_gpu_noise_texture("octave_2", {256, 256, {0.0f, 8.0f}, 2});
-
-// Composite with amplitude decay
-std::vector<std::string> octaves = {"octave_0", "octave_1", "octave_2"};
-tex_mgr.create_gpu_composite_texture("fbm", "gen_fbm", {256, 256, {}, 0}, octaves);
-```
-
-**Mipmap Generation:**
-- Use compute shaders to generate mipmaps
-- Downsample with box/gaussian filter
-
-## Architecture Notes
-
-**Backward Compatibility:**
-- Phase 1-3 generators unchanged (num_input_textures = 0)
-- Existing API remains valid
-- Optional feature (can defer to Phase 5+)
-
-**Dependency Ordering:**
-- Asset packer performs topological sort
-- GPU init generates textures in dependency order
-- Circular dependencies rejected at compile-time
-
-**Sampler Reuse:**
-- Single linear sampler shared across all composite shaders
-- Created once in TextureManager::init()
-- Saves ~50 bytes per shader
-
-## Critical Files
+- Code: ~460 lines added
+- Compressed: ~830 bytes (2 shaders + dispatch logic)
-**New:**
-- `assets/final/shaders/compute/gen_blend.wgsl`
-- `assets/final/shaders/compute/gen_mask.wgsl`
-- `src/tests/test_gpu_composite.cc`
+### Tests
-**Modified:**
-- `src/gpu/texture_manager.h` - Add composite API (~40 lines)
-- `src/gpu/texture_manager.cc` - Implement dispatch_composite (~200 lines)
-- `tools/asset_packer.cc` - Parse composite syntax (~80 lines)
+`test_gpu_composite.cc`:
+- Blend two noise textures
+- Mask noise with grid
+- Multi-stage composite (composite of composites)
-**Total:** ~320 lines code + 2 shaders (~330 bytes)
+All 35 tests passing.