onejs-sl 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +38 -13
- package/goldens/goldens.json +98 -63
- package/package.json +1 -1
- package/src/body.ts +29 -6
- package/src/core.ts +1 -1
- package/src/hlsl.ts +6 -3
- package/src/ir.ts +130 -14
- package/src/lang/README.md +2 -2
- package/src/lang/builtins.ts +5 -17
- package/src/lang/check.ts +24 -11
- package/src/lang/glsl.ts +1 -2
- package/src/lang/lower.ts +23 -27
- package/src/ops.ts +4 -3
- package/src/params.ts +2 -0
- package/src/serial.ts +66 -14
- package/src/sl.ts +90 -24
- package/src/web.ts +44 -11
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,20 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.4.0
|
|
4
|
+
|
|
5
|
+
Every hash changes once, so a program built in code is recorded again: run the app in the editor once, then build. A program from a `.sl` file needs only the app rebuilt. A host reading programs as JSON reads 0.3.0's files as before.
|
|
6
|
+
|
|
7
|
+
- Every hash changes once: `a + b` and `b + a` share one, as do `8 * uv` and `uv * 8` (`SL_HASH_VERSION` 2)
|
|
8
|
+
- A generated shader names its hash scheme on a line of its own (`// SL_HASH_VERSION 2`); `SL_HASH_VERSION` is exported from `onejs-sl/core`
|
|
9
|
+
- `tex2Dlod(t, uv, lod)` samples a mip level; `sampleLevel` on `sl.texture`
|
|
10
|
+
- `BodyTarget.sampleLevel` is required, for `tex2Dlod`
|
|
11
|
+
- `fromGLSL` turns `textureLod` into `tex2Dlod`
|
|
12
|
+
- A shape's parameters may be any value, a uniform included; a vector counts as its components
|
|
13
|
+
- `fbm`, `turbulence` and `ridged` take an octave count that is a value, rounded and held to 1 to 4
|
|
14
|
+
- IR 3: a shape's parameters and an octave count are always operands; `fromJSON` migrates an older file
|
|
15
|
+
- `toJSON` writes the hash scheme (`h`), so `fromJSON` rehashes a file an older scheme wrote instead of refusing it
|
|
16
|
+
- A ramp's stop may be a colour uniform or a const holding a hex, as well as a hex
|
|
17
|
+
|
|
3
18
|
## 0.3.0
|
|
4
19
|
|
|
5
20
|
The VM is gone: every program is compiled, so there is no instruction buffer, wire version or VM limit left to import. A host on `compile` changes nothing; one still importing `onejs-sl/vm` or `onejs-sl/limits` moves to `onejs-sl/compile` and `onejs-sl/core`.
|
package/README.md
CHANGED
|
@@ -51,7 +51,8 @@ only what it calls.
|
|
|
51
51
|
HLSL and Metal shared subset (HLSL spelling, `fmod`, no `mul`, no `static`, no
|
|
52
52
|
derivatives, no swizzle of a scalar, and every literal and scalar in an
|
|
53
53
|
intrinsic at its exact type, since Metal overloads where HLSL converts). The `BodyTarget` says what differs between hosts: an expression
|
|
54
|
-
for each input, the float4 holding a uniform slot, a texture sample
|
|
54
|
+
for each input, the float4 holding a uniform slot, a texture sample and a
|
|
55
|
+
sample at a mip level (`sampleLevel`, for `tex2Dlod`), whether
|
|
55
56
|
`toLinear` is real (`colour: "linear"`) or the identity (`"gamma"`), and
|
|
56
57
|
optionally a local to assign the result to. It returns the uniform and texture
|
|
57
58
|
slots the body uses and the library functions it calls. The sample's contract
|
|
@@ -131,9 +132,13 @@ what a WebGL player draws.
|
|
|
131
132
|
|
|
132
133
|
`npm run goldens` draws it on WebGPU and WebGL2 in a Chrome with its own
|
|
133
134
|
profile (set `CHROME` to choose one). The two backends must agree within 1/255
|
|
134
|
-
over every pixel, and
|
|
135
|
+
over every pixel, and seven anchors must match arithmetic, not each other:
|
|
135
136
|
`orient.sl` (orientation, and the linear to sRGB store), `hex.sl` (a hex colour
|
|
136
|
-
stores as written)
|
|
137
|
+
stores as written), `texture.sl` (a texture's orientation and sRGB decode) and
|
|
138
|
+
`lod.sl` (each mip level `tex2Dlod` reads, the texture's smaller levels being
|
|
139
|
+
solid colours). `sdf-values.sl`, `fbm-values.sl` and `ramp-values.sl` are black unless a
|
|
140
|
+
shape, a noise or a ramp draws differently with its parameters as values than
|
|
141
|
+
as constants.
|
|
137
142
|
The whole translated library must also compile on both backends, including
|
|
138
143
|
the functions no fixture reaches. The file describes the sampling grid, the
|
|
139
144
|
times and the texture every sampled slot gets. A host imports it as
|
|
@@ -305,7 +310,11 @@ So it is a Merkle hash over the graph reachable from the result, not a walk of
|
|
|
305
310
|
the node array. An earlier version hashed storage order, which meant hoisting a
|
|
306
311
|
shared subexpression into a `const` changed the hash without changing what the
|
|
307
312
|
program computed. Constants go through a fixed precision, so `0.1 + 0.2` and
|
|
308
|
-
`0.3` do not produce different shaders. It is
|
|
313
|
+
`0.3` do not produce different shaders. It is normalised, so two ways of
|
|
314
|
+
writing one computation share a hash: `a + b` and `b + a` (and `*`, `dot`,
|
|
315
|
+
`distance`), and `8 * uv`, whose 8 is a broadcast, and `uv * 8`, whose 8 is a
|
|
316
|
+
float2. `min` and `max` keep their order, since which of -0 and +0 they return
|
|
317
|
+
depends on it. It is eight lowercase hex characters
|
|
309
318
|
from FNV-1a, chosen so a C# implementation can produce the same string rather
|
|
310
319
|
than for any cryptographic reason.
|
|
311
320
|
|
|
@@ -314,15 +323,25 @@ than for any cryptographic reason.
|
|
|
314
323
|
Two numbers, with one rule: a reader accepts every version up to its own and
|
|
315
324
|
refuses a newer one with a message naming both.
|
|
316
325
|
|
|
317
|
-
- **`
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
326
|
+
- **`SL_HASH_VERSION`** (`ir.ts`) is bumped when the hashing scheme changes,
|
|
327
|
+
which changes every hash. 2 is the normalised hash above. `toJSON` writes it
|
|
328
|
+
beside the hash, and `fromJSON` checks a file's hash only when it was written
|
|
329
|
+
under the same scheme and IR version, and otherwise rehashes it.
|
|
330
|
+
|
|
331
|
+
- **`SL_IR_VERSION`** (`ir.ts`) is bumped whenever an opcode, a shape or what
|
|
332
|
+
one computes changes. A program carries the lowest version that has all its
|
|
333
|
+
nodes (`programVersion`), and that is what its hash carries, so a bump
|
|
334
|
+
rehashes only the programs using what it added: every other program keeps
|
|
335
|
+
the hash its shader was recorded under. `toJSON` and `fromJSON`
|
|
336
|
+
(`serial.ts`) are the IR as JSON for a host that stores programs; `fromJSON`
|
|
337
|
+
checks everything an emitter relies on, refuses a newer version, and
|
|
338
|
+
migrates an older one.
|
|
323
339
|
IR 2 came with #129. A shape takes as many parameters as it reads
|
|
324
340
|
(`SL_SDF_PARAMS`, six at most, and never fewer than four accepted), where it
|
|
325
|
-
used to take four and lose the rest.
|
|
341
|
+
used to take four and lose the rest. IR 3 added `SAMPLE_LOD`, and made an
|
|
342
|
+
SDF's shape parameters and a noise's octave count operands, where they were
|
|
343
|
+
immediates, so they can be any value; a constant one still prints as its
|
|
344
|
+
number. `fromJSON` moves an older file's immediates to operands.
|
|
326
345
|
|
|
327
346
|
## Control flow
|
|
328
347
|
|
|
@@ -338,8 +357,8 @@ shaders loop for. A loop with a runtime count is `Specs/SL_NEXT.md` proposal
|
|
|
338
357
|
does; `corpus/long.sl` is over a thousand operations.
|
|
339
358
|
|
|
340
359
|
Every loop that reaches a GPU is therefore bounded by a constant: `repeat` is
|
|
341
|
-
unrolled, fbm's octaves are
|
|
342
|
-
and Voronoi functions have fixed trip counts. No program can hang a GPU today,
|
|
360
|
+
unrolled, fbm's octaves are held to 1 to 4 even when the count is a value, the
|
|
361
|
+
helper loops in the noise and Voronoi functions have fixed trip counts. No program can hang a GPU today,
|
|
343
362
|
so the compiled backends carry no loop cap. A data dependent loop (the
|
|
344
363
|
raymarching tier) would need one emitted into every loop it prints, since a GPU
|
|
345
364
|
reset takes the whole page's device, Unity's included.
|
|
@@ -408,6 +427,12 @@ own for a vec4 built from raw components. Both backends implement it gamma
|
|
|
408
427
|
aware (`sl_toLinear` in `lib/common.hlsl`), so a Gamma project gets the value
|
|
409
428
|
as written. Alpha is coverage and is never converted. Same rule as `fx`.
|
|
410
429
|
|
|
430
|
+
A ramp's stop can also be a colour value that was written as one: a colour
|
|
431
|
+
uniform, or a const holding a hex. The ramp takes the value from under the
|
|
432
|
+
conversion that reading it applied (`writtenColour` in `ir.ts`), so it blends
|
|
433
|
+
as written like a hex stop. A value computed in linear light has no written
|
|
434
|
+
form to take, so it is refused, with lerp as the way to blend it.
|
|
435
|
+
|
|
411
436
|
## Noise
|
|
412
437
|
|
|
413
438
|
`sl.noise`, `sl.simplex`, `sl.fbm(p, octaves, base)`, `sl.turbulence` and
|