mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-10-04 00:18:11 +08:00
Remove concept of sampled nodes
This commit is contained in:
@@ -330,7 +330,6 @@ that decomposition is hoisted per run.
|
|||||||
| plain parameters | wired value inputs | as today |
|
| plain parameters | wired value inputs | as today |
|
||||||
| `impl Node<Context<'_>, Output = Concrete>` | lazy value input | the value flows, attributes do not |
|
| `impl Node<Context<'_>, Output = Concrete>` | lazy value input | the value flows, attributes do not |
|
||||||
| `impl Node<Context<'_>, Output = T>` (unbounded) | source of an opaque record family | routing, see below |
|
| `impl Node<Context<'_>, Output = T>` (unbounded) | source of an opaque record family | routing, see below |
|
||||||
| `impl SampledNode<Context<'_>, Output = T>` (unbounded) | sampled record input | routing at a kernel-chosen index, see below |
|
|
||||||
| `-> List<W>` with `level_extent =` | per-lane level production | structural skeleton emitted by the macro |
|
| `-> List<W>` with `level_extent =` | per-lane level production | structural skeleton emitted by the macro |
|
||||||
| `-> List<W>` without | store form | whole-level body, node owns storage |
|
| `-> List<W>` without | store form | whole-level body, node owns storage |
|
||||||
|
|
||||||
@@ -344,8 +343,8 @@ the tuple's, so multi-write lanes pay no extra nesting. A literal
|
|||||||
the feature gate while parsing the item, before attribute macros run.
|
the feature gate while parsing the item, before attribute macros run.
|
||||||
|
|
||||||
The rule behind all the lazy forms: kernels control whether, when, and
|
The rule behind all the lazy forms: kernels control whether, when, and
|
||||||
(for sampled inputs) at which index their inputs are evaluated, but
|
at which index their inputs are evaluated, but never how the records
|
||||||
never how the records move. Attributes travel inside record values or
|
move. Attributes travel inside record values or
|
||||||
through generated machinery, so kernel-controlled evaluation cannot
|
through generated machinery, so kernel-controlled evaluation cannot
|
||||||
misalign them, and domain declarations stay with the extent system.
|
misalign them, and domain declarations stay with the extent system.
|
||||||
|
|
||||||
@@ -408,8 +407,7 @@ multiplexers, and per-lane data-driven choice among inputs are all plain
|
|||||||
kernels over the same mechanism, and none of them needs anything from
|
kernels over the same mechanism, and none of them needs anything from
|
||||||
the macro beyond the family lowering. Whole-list switching vs. per-item
|
the macro beyond the family lowering. Whole-list switching vs. per-item
|
||||||
zip is just the residency of the condition: an invariant condition
|
zip is just the residency of the condition: an invariant condition
|
||||||
collapses through nullification, a varying one selects per lane. This
|
collapses through nullification, a varying one selects per lane.
|
||||||
is why Bundle and Unbundle are no longer needed.
|
|
||||||
|
|
||||||
The one-source shape also covers the registry's infrastructure rows.
|
The one-source shape also covers the registry's infrastructure rows.
|
||||||
Monitor, context modification, memoize, and the lend and clone adapters
|
Monitor, context modification, memoize, and the lend and clone adapters
|
||||||
@@ -428,38 +426,28 @@ The genuine conversion rows (the Into and Convert matrix) remain,
|
|||||||
because those do real per-type work; the type-erased attribute
|
because those do real per-type work; the type-erased attribute
|
||||||
conversion rows disappear with the representation they serve.
|
conversion rows disappear with the representation they serve.
|
||||||
|
|
||||||
Sampling extends routing with a chosen index. A sampled input's handle
|
A kernel that modifies the index on the context evaluates an input at a
|
||||||
takes the index as an evaluation argument, and the value it yields
|
lane other than its own, which makes index-computable reorders plain
|
||||||
carries the record of that lane. The rule that used to forbid
|
kernels:
|
||||||
kernel-chosen indices existed to protect attribute alignment, and record
|
|
||||||
values dissolve it: the record moves as one unit, so a sampled row
|
|
||||||
cannot come apart. Soundness needs one addition, because a different
|
|
||||||
index yields a genuinely different record rather than an identical one:
|
|
||||||
each sampled input gets an intermediate slot in the sampling node's
|
|
||||||
frame allocation, and a sampled value is stable until the same input is
|
|
||||||
sampled again. One live sample per declared input, and a kernel that
|
|
||||||
needs two rows of one input side by side declares the input twice.
|
|
||||||
|
|
||||||
This makes index-computable reorders plain kernels:
|
|
||||||
|
|
||||||
```rs
|
```rs
|
||||||
/// Reverses the order of the input list.
|
/// Reverses the order of the input list.
|
||||||
#[node_macro::node(category("General"))]
|
#[node_macro::node(category("General"))]
|
||||||
fn reverse<T>(
|
fn reverse<T>(
|
||||||
ctx: impl Ctx + ExtractIndex,
|
ctx: impl Ctx + DeriveCtx + ModifyIndex,
|
||||||
_: (),
|
_: (),
|
||||||
content: impl SampledNode<Context<'_>, Output = T>,
|
content: impl Node<Context<'_>, Output = T>,
|
||||||
) -> T {
|
) -> T {
|
||||||
content.eval(ctx, content.extent() - 1 - ctx.index())
|
content.eval(&ctx.with_index(content.extent(&ctx)? - 1 - ctx.innermost_index()))
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Shift, slice, and read-item-at-index are the same shape. Sort and
|
Shift, slice, and read-item-at-index are the same shape. Sort and
|
||||||
shuffle still compute a whole-extent permutation once per sweep, which a
|
shuffle still compute a whole-extent permutation once per sweep, which a
|
||||||
pure per-lane kernel cannot hold, so they keep the remap-returning
|
pure per-lane kernel cannot hold, so they keep the remap-returning
|
||||||
kernel. Applying a remap now has a spec, though: per lane, sample the
|
kernel. Applying a remap has a spec: per lane, evaluate the input at the
|
||||||
input at the permuted index. The generated batch kernel is the
|
permuted index. The generated batch kernel is the law-bound override of
|
||||||
law-bound override of that spec, materializing the input's columns once
|
that spec, materializing the input's columns once
|
||||||
and gathering each index-varying column through the wiring-resolved
|
and gathering each index-varying column through the wiring-resolved
|
||||||
table with index-invariant columns skipped (about 1.4ns per varying
|
table with index-invariant columns skipped (about 1.4ns per varying
|
||||||
column per lane; the comparison work of the sort itself does not depend
|
column per lane; the comparison work of the sort itself does not depend
|
||||||
@@ -578,9 +566,10 @@ from shading languages for residency.
|
|||||||
contain.
|
contain.
|
||||||
- The graph UX of the map/enter construct, and whether attribute-typed
|
- The graph UX of the map/enter construct, and whether attribute-typed
|
||||||
parameters can ever be ordinary exposed inputs.
|
parameters can ever be ordinary exposed inputs.
|
||||||
- Naming: `Attribute` trait vs. `Attr` wrapper, whether the authoring
|
- Naming: `Attribute` trait vs. `Attr` wrapper, and whether the
|
||||||
`List` sharing the wire type's name helps or confuses, and the sampled
|
authoring `List` sharing the wire type's name helps or confuses.
|
||||||
input trait's name.
|
- Whether evaluating at a lane outside the input's extent is clamped,
|
||||||
|
wrapped, or a debug assertion.
|
||||||
- `List<List<W>>` outputs, i.e. one node pushing two levels.
|
- `List<List<W>>` outputs, i.e. one node pushing two levels.
|
||||||
- How chatty the editor boundary becomes per frame, given that tools
|
- How chatty the editor boundary becomes per frame, given that tools
|
||||||
consume materialized views today.
|
consume materialized views today.
|
||||||
|
|||||||
Reference in New Issue
Block a user