From 7a1bd1ebb14ae9fcc7e7a8bf72980f5db1b4c999 Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Mon, 14 Sep 2026 13:57:03 +0200 Subject: [PATCH] Document the full HLSL target and its source transformations design.md states the generated swizzle and mixed-constructor surface, writable matrix rows, HLSL intrinsic types and NaN behavior, the deferred matrix items (float4x4, transpose, determinant, _11 names), the exact HLSL-to-C# transformations the compatibility test applies, and the dxc check. Co-Authored-By: Claude Opus 5 --- packages/cultmath/README.md | 4 ++- packages/cultmath/docs/design.md | 57 ++++++++++++++++++++++++++++---- 2 files changed, 53 insertions(+), 8 deletions(-) diff --git a/packages/cultmath/README.md b/packages/cultmath/README.md index 8fd3888c..0be46738 100644 --- a/packages/cultmath/README.md +++ b/packages/cultmath/README.md @@ -16,7 +16,9 @@ shader semantics. - `float2`, `float3`, `float4` - component-wise arithmetic - scalar-to-vector splats -- swizzles for common lanes +- every HLSL swizzle (`xyzw` and `rgba`, repeats readable, non-repeating + masks writable) and every HLSL mixed constructor, generated by + `tools/generate-swizzles.ps1` - conversions to and from `System.Numerics` - `Random`, a compact deterministic XORShift stream with scalar and vector draws - `BatchMath` SoA kernels over `Span` / `ReadOnlySpan` using diff --git a/packages/cultmath/docs/design.md b/packages/cultmath/docs/design.md index da28079f..a2ce5e33 100644 --- a/packages/cultmath/docs/design.md +++ b/packages/cultmath/docs/design.md @@ -12,20 +12,63 @@ rest of the spelling should survive the move. That makes these HLSL rules, not options: -- Components and swizzles are writable. `v.xz = f2;` and `v[1] = s;` work. - Swizzle setters exist only for non-repeating masks, because HLSL rejects - `v.xx = ...`. +- Every swizzle exists. `float2/3/4`, `int2/3/4`, and `bool2/3/4` expose every + read swizzle of length 2 to 4, repeats included (`v.wwxy`), in both `xyzw` and + `rgba` naming (never mixed), plus single-component `r/g/b/a`. `double2/3` get + lengths 2 and 3 only, because there is no `double4`. Components and swizzles are + writable: `v.xz = f2;`, `c.rgb *= 0.5f;`, and `v[1] = s;` work. Setters exist + only for non-repeating masks, because HLSL rejects `v.xx = ...`. +- Every HLSL mixed constructor exists, as a struct constructor and as a `math` + function: `float4(float2, float2)`, `float4(float, float2, float)`, + `float3(float, float2)`, the copy form `float3(float3)`, and the rest, for the + float, int, and bool families (double gets constructors only; a `math.double3` + function would hide the `double3` type name). +- Swizzles and mixed constructors are generated. `tools/generate-swizzles.ps1` + writes the checked-in `src/CultMath/Swizzles.g.cs` (partial structs plus a + partial `math`). Edit the generator, rerun it, and commit both; never edit the + output by hand. - Comparison operators (`<`, `>`, `<=`, `>=`, `==`, `!=`) are component-wise and return `bool2`/`bool3`/`bool4`. Reduce them with `any` and `all`. `Equals`/`GetHashCode` stay value-based so vectors still work as dictionary keys. - `select(condition, whenTrue, whenFalse)` uses HLSL's argument order. -- Matrices are row-major: constructors take rows, `m[i]` is row i, `_mRC` is - row R column C, and products go through `mul` (`mul(m, v)` treats `v` as a - column, `mul(v, m)` as a row). `*` on matrices would be component-wise in HLSL, - so CultMath does not define it. +- Matrices are row-major: constructors take rows, `m[i]` returns a reference to + row i (so `m[1][2] = s;` writes one element), `_mRC` is row R column C, and + products go through `mul` (`mul(m, v)` treats `v` as a column, `mul(v, m)` as a + row). `*` on matrices would be component-wise in HLSL, so CultMath does not + define it. - Scalar/vector arithmetic and comparisons have explicit overloads on both sides rather than leaning on implicit scalar splat. +- Intrinsics return HLSL's types and edge cases: `sign` returns `int`/`intN` + (NaN gives 0); `step(y, x)` is `x >= y ? 1 : 0` (NaN gives 0), in C# and in the + HLSL mirror; `any`/`all` accept numeric vectors (a component is true when it is + not 0); `min`, `max`, and `abs` on int vectors return int vectors. + +Deferred until a consumer needs them: `float4x4`, `transpose`, `determinant`, +and HLSL's one-based `_11`..`_33` element names. + +### HLSL Target: Source Transformations + +`HlslSourceCompatibilityTests` compiles the real `shaders/CultMath.hlsl` with +Roslyn against CultMath. These transformations are the complete list; if a body +needs anything else, the test fails: + +1. Include guards (`#ifndef`/`#define`/`#endif`) are dropped. +2. Functions taking `Texture2D`/`SamplerState` are dropped; GPU resources have + no CultMath analog. +3. File-scope `static const` becomes `const`. +4. Floating literals gain `f` (`0.5` becomes `0.5f`). +5. The file body is wrapped in a class, since C# has no free functions; HLSL + functions become private instance methods. + +HLSL constructs that stay outside the target and must not appear in the mirror: +`const` locals of vector type (C# `const` is primitives only; write a plain +local) and writes through a swizzle component (`v.xy.x = s`, which C# rejects as +modifying a temporary). + +The HLSL side is checked too: `tools/get-dxc.ps1` fetches Microsoft's +DirectXShaderCompiler, and +`dxc -T lib_6_3 -HV 2021 shaders/CultMath.hlsl` must compile cleanly. Where HLSL is silent, CultMath keeps its own decisions and does not defer to Unity.Mathematics: `normalize` is safe (divides by `max(length, 1e-20)`),