cultmath: compile-hlsl.ps1 fails on warnings and on a missing shader without its path; compile-glsl.ps1 passes struct arguments
dxc runs with -WX; a ShaderPath that is not a file throws naming the parameter and entry index, never the path; the GLSL wrapper builds a struct parameter from its declaration's field zeros. design.md and README state the struct-argument twin rule, the span twins and the missing shader identity. No C# change; the compiles run on Starfire after the last commit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
parent
d172e7f71f
commit
4250dd28d5
4 changed files with 43 additions and 15 deletions
|
|
@ -82,9 +82,10 @@ shader semantics.
|
|||
the analytic Hessian of `snoise(float3)` on the same lattice, hash and tie order as
|
||||
`snoise_grad` (a symmetric `float3x3`; GLSL `mat3`), and `integral_clamp_linear(a,
|
||||
b, lo, hi, t0, t1)`, the closed-form integral over `[t0, t1]` of `clamp(a + b t,
|
||||
lo, hi)`; and, in C# for now (shaders follow), the octave stages `span_fbm(path, stage,
|
||||
octaves, lacunarity, gain)` and `span_ridged`, over a `SpanPath` and a `SpanStage` (`SpanStage.Identity`
|
||||
is the plain fbm), which return a `SpanNoise` (`field` as `float4(gradient, value)`,
|
||||
lo, hi)`; and the octave stages `span_fbm(path, stage,
|
||||
octaves, lacunarity, gain)` and `span_ridged` (shader twins `cultmath_span_fbm` and `cultmath_span_ridged`,
|
||||
whose callers build the `SpanStage` themselves), over a `SpanPath` and a `SpanStage` (`SpanStage.Identity`
|
||||
is the plain fbm in C#), which return a `SpanNoise` (`field` as `float4(gradient, value)`,
|
||||
`curvature`, `fold`) for a stretched, offset, shifted octave sum over a span. Three measured bounds describe `snoise`: `SNOISE_LIPSCHITZ` (gradient
|
||||
length, `NoiseBoundTests.MeasureLipschitz`), `SNOISE_HESSIAN` (Hessian spectral
|
||||
norm, `MeasureHessian`) and `SNOISE_THIRD` (third-derivative operator norm,
|
||||
|
|
@ -178,7 +179,7 @@ CultMath keeps portable DXC outside git under `packages/cultmath/.tools/`:
|
|||
-OutputPath E:\Projects\Odin\crates\muninn-move-tracker\artifacts\shader\MoveSphereCandidate.comp.metal
|
||||
```
|
||||
|
||||
`compile-hlsl.ps1` compiles both `CultMath.hlsl` copies as a `lib_6_3` library with the x64 DXC.
|
||||
`compile-hlsl.ps1` compiles both `CultMath.hlsl` copies as a `lib_6_3` library with the x64 DXC; a warning fails it too (`-WX`).
|
||||
|
||||
DXC emits Vulkan SPIR-V with `-spirv`. `-TargetEnv vulkan1.2` is exposed by the
|
||||
script, but the current Windows DXC release compiled this shader successfully
|
||||
|
|
|
|||
|
|
@ -113,8 +113,9 @@ modifying a temporary).
|
|||
|
||||
The HLSL side is checked too: `tools/get-dxc.ps1` fetches Microsoft's
|
||||
DirectXShaderCompiler (x64), and `tools/compile-hlsl.ps1` compiles both copies of
|
||||
`CultMath.hlsl` with it (`dxc -T lib_6_3 -HV 2021`); the script throws when dxc cannot
|
||||
launch or exits non-zero, so a stale exit code never reads as a pass.
|
||||
`CultMath.hlsl` with it (`dxc -T lib_6_3 -HV 2021 -WX`, so a warning fails like an error and the
|
||||
text must compile cleanly); the script throws when a shader file is missing, when dxc cannot
|
||||
launch or when it exits non-zero, so a stale exit code never reads as a pass.
|
||||
|
||||
The mirror test compares bit patterns (any NaN equals any NaN; -0 differs from
|
||||
0). It proves the text of `CultMath.hlsl` computes the same float32 results as
|
||||
|
|
@ -124,13 +125,20 @@ compiled under `using static CultMath.math;`, so its intrinsics are C# `math`
|
|||
itself: the test proves the composition in the text, not the intrinsic rules,
|
||||
which only `HlslSemanticsTests` pins.
|
||||
|
||||
Every mirror function is compared, internals included: its counterpart is the `math`
|
||||
function of the same name, public or private (`snoise_mod289` and `snoise_permute` are
|
||||
private), and a function with no counterpart fails by name. A struct parameter maps to the
|
||||
CultMath type of the same name, and only if both have the same instance fields by name, type
|
||||
and order (`SpanPath`, `SpanStage`); the argument is built from the case's scalars field by
|
||||
field and copied to its C# twin by field name.
|
||||
|
||||
The comparison also allows exactly one struct return shape: a mirror function
|
||||
whose HLSL return type is a plain struct of `float`/`floatN`/`int`/`intN`
|
||||
fields is compared to its C# counterpart field by field, recursing into each
|
||||
field's own components, down to bit-for-bit scalars, matching each leaf's
|
||||
declaration path (field names, not just position) and declared type as well
|
||||
as its value. `CultCellular` (`math.cs`, `cellular`) and `CultPhasor`
|
||||
(`math.Phacelle.cs`, `phacelle`) are its consumers. A struct return with a mismatched, reordered-by-name, or
|
||||
as its value. `CultCellular` (`math.cs`, `cellular`), `CultPhasor`
|
||||
(`math.Phacelle.cs`, `phacelle`) and `SpanNoise` (`math.Span.cs`, `span_fbm`) are its consumers. A struct return with a mismatched, reordered-by-name, or
|
||||
retyped field does not get a second comparison path or a shape of its own;
|
||||
it fails the same walk that already handles a bare vector return.
|
||||
|
||||
|
|
@ -809,7 +817,8 @@ configuration bound. A change to the kernels must re-run the measurements.
|
|||
|
||||
### Span stages
|
||||
|
||||
`span_fbm` and `span_ridged` (`math.Span.cs`, C# only so far) are the octave stages
|
||||
`span_fbm` and `span_ridged` (`math.Span.cs`; `cultmath_span_fbm` and `cultmath_span_ridged` in HLSL over
|
||||
the same struct types, `cultmath_span_stage` behind both, and GLSL derived) are the octave stages
|
||||
of a warp chain, `span_fbm(path, stage, octaves, lacunarity, gain)`, each returning
|
||||
one `SpanNoise { float4 field; float curvature; float fold; }`. The inputs are two
|
||||
structs with named public fields and no positional constructor, so the three floats
|
||||
|
|
@ -831,6 +840,12 @@ Lab's stage is `1 - 2|n|` per octave: with `G` the sum of `gain^o` over the
|
|||
octaves (signed, so the alternating sum for a negative gain), its value is `2 value
|
||||
- G`, and its gradient, curvature and fold are twice `span_ridged`'s.
|
||||
|
||||
The shaders have no `SpanStage.Identity`: a shader caller builds every stage field itself (in GLSL,
|
||||
`SpanStage(1.0, 1.0, vec3(0.0), vec3(0.0), vec3(0.0), vec3(0.0))` is the identity). A constant would
|
||||
need a second transformation rule (C# has no const structs, GLSL wants a constructor) and a mirror
|
||||
exemption, for one value; the mirror test proves instead that the shader text at a C#-built identity
|
||||
returns `cultmath_fbm_grad` and `cultmath_ridged_grad`'s field bit for bit.
|
||||
|
||||
Bounds come from the three pins only. With `|M| = |frequency| max(1, 1/stretch)` and
|
||||
`nu = f_o |M| speed` the noise-space speed, the Hessian of the noise on the span has
|
||||
operator norm at most `Hl = min(SNOISE_HESSIAN, ||snoise_hessian(x_mid)||_F + e_h +
|
||||
|
|
|
|||
|
|
@ -29,12 +29,21 @@ if ($Phacelle) {
|
|||
if ($Cycles) {
|
||||
$library += Get-Content -LiteralPath (Join-Path $repoRoot "shaders\CultMath.Cycles.glsl") -Raw
|
||||
}
|
||||
# A parameter of a struct type the library declares is passed as that struct's constructor with each
|
||||
# field's zero, read from its declaration (a field may be a struct itself); every other type is its zero.
|
||||
$structs = @{}
|
||||
foreach ($declaration in [regex]::Matches($library, '(?s)struct (\w+)\s*\{(.*?)\};')) {
|
||||
$structs[$declaration.Groups[1].Value] = @([regex]::Matches($declaration.Groups[2].Value, '(?m)^\s*(\w+)\s+\w+\s*;') | ForEach-Object { $_.Groups[1].Value })
|
||||
}
|
||||
function Get-Zero([string]$type) {
|
||||
if ($structs.ContainsKey($type)) { return "$type($((@($structs[$type] | ForEach-Object { Get-Zero $_ })) -join ', '))" }
|
||||
if ($type -eq 'int' -or $type -like 'ivec*') { return "$type(0)" }
|
||||
if ($type -eq 'uint' -or $type -like 'uvec*') { return "$type(0u)" }
|
||||
return "$type(0.0)"
|
||||
}
|
||||
$calls = foreach ($match in [regex]::Matches($library, '(?m)^\w+\s+(cultmath_\w+)\s*\(([^)]*)\)')) {
|
||||
$arguments = foreach ($parameter in ($match.Groups[2].Value -split ',')) {
|
||||
$type = ($parameter.Trim() -split '\s+')[0]
|
||||
if ($type -eq 'int' -or $type -like 'ivec*') { "$type(0)" }
|
||||
elseif ($type -eq 'uint' -or $type -like 'uvec*') { "$type(0u)" }
|
||||
else { "$type(0.0)" }
|
||||
Get-Zero (($parameter.Trim() -split '\s+')[0])
|
||||
}
|
||||
" $($match.Groups[1].Value)($($arguments -join ', '));"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,11 +29,14 @@ New-Item -ItemType Directory -Force -Path $outputDirectory | Out-Null
|
|||
$index = 0
|
||||
foreach ($shader in $ShaderPath) {
|
||||
$index++
|
||||
if (-not (Test-Path -LiteralPath $shader -PathType Leaf)) {
|
||||
throw "shader not found (parameter ShaderPath, entry $index)."
|
||||
}
|
||||
$shaderFile = Get-Item -LiteralPath $shader
|
||||
$output = Join-Path $outputDirectory "$index-$($shaderFile.BaseName).dxil"
|
||||
& $DxcPath -T lib_6_3 -HV 2021 -I $shaderFile.DirectoryName $shaderFile.FullName -Fo $output
|
||||
& $DxcPath -T lib_6_3 -HV 2021 -WX -I $shaderFile.DirectoryName $shaderFile.FullName -Fo $output
|
||||
if ($LASTEXITCODE -ne 0) {
|
||||
throw "dxc failed with exit code $LASTEXITCODE (parameter ShaderPath, entry $index)."
|
||||
}
|
||||
Write-Host "compiled shader $index of $(@($ShaderPath).Count) (lib_6_3, -HV 2021)"
|
||||
Write-Host "compiled shader $index of $(@($ShaderPath).Count) (lib_6_3, -HV 2021, -WX)"
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue