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 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, whether
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 three anchors must match arithmetic, not each other:
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) and `texture.sl` (a texture's orientation and sRGB decode).
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 eight lowercase hex characters
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
- - **`SL_IR_VERSION`** (`ir.ts`) is on every `Program` and in the hash, and is
318
- bumped whenever an opcode, a shape or what one computes changes. Because it
319
- is in the hash, a bump recompiles every cached shader. `toJSON` and
320
- `fromJSON` (`serial.ts`) are the IR as JSON for a host that stores programs;
321
- `fromJSON` checks everything an emitter relies on, refuses a newer version,
322
- and migrates an older one.
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 a constant 1 to 4, the helper loops in the noise
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