- Macrostep 00: Model contract and retained historical options. - Macrostep 01: Project foundation and configuration, including schema, presets, CLI, and CI setup. - Macrostep 02: Mathematical core implementation and deterministic oracles. - Macrostep 03: CPU-based planar simulation engine, FFT backend, and headless runner. Provides exhaustive objectives, phase breakdowns, validation policies, and deliverables for each macrostep.
157 lines
7.0 KiB
Markdown
157 lines
7.0 KiB
Markdown
# Macrostep 05 — GPU resources and 2-D FFT proof
|
||
|
||
## Objective
|
||
|
||
Build a narrow, safe GPU layer under the raylib context and prove both selectable FFT algorithms against CPU oracles: the standard default and retained `LegacyPackedUnitary`. Do not implement the complete simulator until resource safety, stage fidelity, and numerical parity are demonstrated.
|
||
|
||
## Dependencies
|
||
|
||
Macrosteps 00–04 complete.
|
||
|
||
## Phase 5.1 — Capability and backend policy
|
||
|
||
### Substep 5.1.1 — Capability report
|
||
|
||
Probe and record:
|
||
|
||
- OpenGL and GLSL versions;
|
||
- maximum 2-D texture size, texture units, and draw buffers;
|
||
- `R32F` and `RG32F` texture/render-target support;
|
||
- framebuffer completeness;
|
||
- timer-query availability;
|
||
- estimated resource budget.
|
||
|
||
`Backend::Auto` with `FftAlgorithm::Standard` falls back to CPU with a visible explanation. `LegacyPackedUnitary` is an explicit GPU-only request; unsupported capabilities or shapes fail clearly and never silently substitute the standard algorithm.
|
||
|
||
### Substep 5.1.2 — Portability target
|
||
|
||
Primary path: desktop OpenGL 3.3 core-compatible GLSL. Do not copy legacy compatibility constructs (`gl_TexCoord`, `ftransform`, `gl_FragColor`, implicit shader versions). GLES/Web is a later secondary target.
|
||
|
||
## Phase 5.2 — Isolated resource layer
|
||
|
||
### Substep 5.2.1 — Unsafe boundary
|
||
|
||
Place all raw OpenGL/`rlgl` operations in `src/gpu/resource/`. Public wrappers are RAII-managed, non-cloneable owners of:
|
||
|
||
- texture IDs and format/extent metadata;
|
||
- framebuffers and attachment ownership;
|
||
- shader programs and uniform locations;
|
||
- fullscreen pass geometry;
|
||
- optional timer queries.
|
||
|
||
Every creation checks errors/completeness. Every custom pass flushes/restores raylib state according to a documented protocol.
|
||
|
||
### Substep 5.2.2 — Ping-pong discipline
|
||
|
||
Make sampling a current render target impossible through the safe pass API. A pass declares read textures and a distinct write target; debug mode asserts no alias. This prevents legacy feedback-loop defects across all later variants.
|
||
|
||
### Substep 5.2.3 — Shader assets
|
||
|
||
Embed release shaders and fail shader compilation/link with source name plus complete log. Support explicit development overrides only. Add shader preprocessing for shared curve/palette code if it produces deterministic, debuggable output.
|
||
|
||
## Phase 5.3 — GPU data layouts
|
||
|
||
Use 2-D textures as the portable baseline:
|
||
|
||
- scalar fields: `R32F`;
|
||
- standard full-complex fields: `RG32F` at logical extent;
|
||
- legacy packed fields: `RG32F` at the historical half-x packed extent;
|
||
- 1-D later: one row;
|
||
- 2-D: direct layout;
|
||
- 3-D later: tiled z-slice atlas.
|
||
|
||
Define exact texel-center and logical-to-physical mappings. Compute shaders and native 3-D render targets may be optional optimizations, never the only correctness path.
|
||
|
||
## Phase 5.4 — Standard 2-D FFT implementation
|
||
|
||
### Substep 5.4.1 — Standard algorithm spike
|
||
|
||
Select Stockham autosort or a conventional staged radix-2 butterfly after comparing pass count, addressing clarity, and driver portability. Use integer `texelFetch`; never rely on filtering or normalized-coordinate rounding.
|
||
|
||
### Substep 5.4.2 — Transform passes
|
||
|
||
Implement:
|
||
|
||
- real-to-complex copy;
|
||
- x and y forward stages;
|
||
- x and y inverse stages;
|
||
- exactly one `1/(Nx·Ny)` inverse scale;
|
||
- round-trip readback harness.
|
||
|
||
Cache twiddles/plans by shape. Require power-of-two GPU extents initially and report this distinction from the more flexible CPU backend.
|
||
|
||
### Substep 5.4.3 — Spectral convolution
|
||
|
||
Upload or generate kernel spectra, multiply state spectrum by disk/ring spectra, inverse transform, and normalize by sampled sums consistent with CPU convention. Reuse the state forward FFT for both kernels.
|
||
|
||
## Phase 5.5 — Legacy packed-unitary 2-D FFT
|
||
|
||
### Substep 5.5.1 — CPU stage oracle
|
||
|
||
Implement a small, clear CPU oracle for adjacent-real packing, packed-spectrum conversion, historical plan entries, unitary butterflies, and inverse unpacking. It exists for fixtures and diagnosis, not as a production CPU backend.
|
||
|
||
### Substep 5.5.2 — Modern GPU port of the historical algorithm
|
||
|
||
Retain the algorithmic behavior while rewriting its infrastructure:
|
||
|
||
- adjacent x samples packed into real/imaginary components;
|
||
- historical half-x complex layout and conjugate/Nyquist handling;
|
||
- bit-reversal and twiddle plan stages for x/y;
|
||
- forward/inverse unitary scaling at each stage;
|
||
- ping-pong FFT scratch textures;
|
||
- convolution multiplier `sqrt(Nx·Ny)/kernel_sum`.
|
||
|
||
Use GLSL 330, integer texel addressing, embedded shaders, checked resources, and the common safe pass API. Do not copy compatibility-profile GLSL or resource hazards.
|
||
|
||
### Substep 5.5.3 — Algorithm-specific constraints
|
||
|
||
Require power-of-two extents and enough texture/FBO resources. Keep standard and legacy plans, spectra, and scratch caches separate. Changing `FftAlgorithm` is a cold transactional rebuild and invalidates integration history.
|
||
|
||
## Phase 5.6 — Numerical proof harness
|
||
|
||
For each algorithm and test field, read back explicit stages:
|
||
|
||
- input complex copy;
|
||
- forward spectrum;
|
||
- inverse round trip;
|
||
- disk/ring spectral products;
|
||
- `M` and `N`.
|
||
|
||
Compare to CPU with max absolute, mean absolute, and L2 error. Include zero, constant, impulse, checkerboard, random seeded, and asymmetric patterns at multiple small powers of two.
|
||
|
||
Initial targets:
|
||
|
||
- standard round-trip max error `≤1e-4`;
|
||
- standard convolution max error `≤2e-4` on agreed fixtures;
|
||
- legacy packed stage outputs match the CPU stage fixtures within documented `f32` tolerances;
|
||
- legacy final convolution agrees with direct/standard CPU convolution within `2e-4` on agreed fixtures;
|
||
- constant-field density error is small enough to preserve the documented tolerance.
|
||
|
||
Tolerances must be measured and recorded per GPU/driver class before broadening; never hide systematic normalization errors behind a loose bound.
|
||
|
||
## Phase 5.7 — Lifecycle and failure testing
|
||
|
||
- Recreate FFT resources repeatedly across sizes.
|
||
- Simulate allocation/shader failures and preserve the CPU backend.
|
||
- Check for GL errors and incomplete FBOs in debug validation mode.
|
||
- Verify no resource growth after repeated switches.
|
||
- Confirm no synchronous readback in the normal frame path.
|
||
- Preflight memory estimates before allocation and retain the prior valid backend on failure.
|
||
|
||
## Deliverables
|
||
|
||
- GPU capability report and automatic fallback policy.
|
||
- Auditable unsafe/RAII resource layer.
|
||
- Validated standard and legacy packed-unitary 2-D GPU FFT/convolution proofs.
|
||
- Legacy packing/plan/unitary CPU stage oracle.
|
||
- Per-algorithm stage-comparison harness and initial GPU benchmark metadata.
|
||
|
||
## Exit gate
|
||
|
||
- Standard CPU/GPU round trip and convolution tolerances pass on the reference environment.
|
||
- Legacy packing, plans, scaling, round trip, spectra, and convolution pass their stage/final tolerances.
|
||
- Resource alias checks prevent read/write feedback.
|
||
- Shader and allocation failures are actionable and non-destructive.
|
||
- Repeated recreation shows no incomplete framebuffer or resource leak.
|
||
- GPU simulation work does not begin until the 2-D proof is stable.
|