Record Class Expr.Loop
- Record Components:
states- the names of the state's values, asof(limn.render3d.shader.Expr, int, java.util.function.Function<? super limn.render3d.shader.Expr, ? extends limn.render3d.shader.Expr>)gives them:ir_state, the loop's level (one more than the highest level of a loop in its turn, 0 for none),_and the value's placeinitial- each value before the first turn; a float or vector typemaxIterations- how many turns at most, 1 toMAX_ITERATIONSnext- each value after one turn, of its initial value's typeuntil- a float that ends the loop where it is above zero, ornullto take every turnindex- which value of the state this node is, from 0
- All Implemented Interfaces:
Expr
- Enclosing interface:
Expr
maxIterations times. Build one with
of(limn.render3d.shader.Expr, int, java.util.function.Function<? super limn.render3d.shader.Expr, ? extends limn.render3d.shader.Expr>), which hands the turn its state as nodes.
Each turn first asks until, when there is one, of the state as it stands: above
zero ends the loop; otherwise every value of the state becomes its next at once, each
computed from the state before the turn. The loop's values are the state when it ends. The
node is the first of them, and value(int) reads the others: a loop read for two of
its values is still one loop, computed once. A part of next or until that
does not read the state is computed once, before the loop.
// An escape-time fractal: z ↦ z² + c, counting turns, until |z|² passes 256.
// The state is (z.x, z.y, turns, 0).
Expr.Loop escape = Expr.Loop.of(Expr.Lit.of(0, 0, 0, 0), 256,
s -> vec4(plus(square(xy(s)), c), plus(z(s), 1), 0), // the next state
s -> minus(dot(xy(s), xy(s)), 256)); // above zero: escaped
// A ray marched through a volume: the colour gathered and the distance travelled.
Expr.Loop march = Expr.Loop.of(List.of(Expr.Lit.of(0, 0, 0, 0), Expr.Lit.of(0)), 64,
s -> List.of(plus(s.get(0), gathered(s.get(0), s.get(1))), plus(s.get(1), step)),
s -> minus(alpha(s.get(0)), 0.99f)); // all but opaque: stop
Expr colour = march; // the first value
Expr travelled = march.value(1); // the second
The state is nodes, not names. of(limn.render3d.shader.Expr, int, java.util.function.Function<? super limn.render3d.shader.Expr, ? extends limn.render3d.shader.Expr>) gives next and until
each value of the state as a Expr.Ref of its initial value's type, under names it
chooses, which a surface's inputs cannot take (they may not start ir_). Those are the
record's states: a record keeps its components, and the IR has to say which
references a loop binds, but nothing else names them. A loop is named by its level: one more
than the highest level of a loop in its turn, 0 for a turn that holds none. So a loop in
another's turn, built there or apart, on any thread, has names of its own and may read the
outer state. The state means nothing outside its loop: SurfaceOutputs refuses a
surface that reads it where no loop binds it, and of(limn.render3d.shader.Expr, int, java.util.function.Function<? super limn.render3d.shader.Expr, ? extends limn.render3d.shader.Expr>) refuses a turn that reads the
state of a loop already built, which a part of that loop's turn read back from the record,
or a reference made by hand under a state's name, does. A loop made with the canonical
constructor is the IR as given: in its turn a state's name is its own state, wherever the
reference came from. A loop that of builds inside such a turn cannot name that state
by hand, which it refuses as it refuses any name made by hand; build that one with the
constructor as well. Expr.Raw text that names a state is not checked at all: it is the
escape from portability, and the generator names a loop's variables itself, so such text
may read an identifier no shader declares.
Bounded across a whole surface. The count is a constant from 1 to
MAX_ITERATIONS, and so is every turn a pixel takes in all the loops of one surface.
The count is what the generated shader runs. A loop runs once for each turn of the innermost
loop whose state it reads, however deep it was built; when it reads none, once for the
surface, or once a light when only the diffuse response reads it. Loops side by side, and a
loop in another's initial value, add their turns. A loop read twice, for one value or
several, or two built alike in one turn or both reading no state, is computed and counted
once; two built alike in the turns of two loops side by side read two states, and run in
each. So a loop of 32 turns may hold one of 32 that reads its state, not one of 64 nor two
of 32 side by side, and it may hold a loop of 512 that reads none. A loop holds itself and
what it holds to the cap, and SurfaceOutputs holds the whole surface, counting the
turns of its diffuse response once for each of the eight lights a pass shades with at most.
So no surface asks a pixel for more than 1024 turns, in any profile.
The cap bounds turns, not what a turn costs, which is the surface's as it is without a loop.
until is a float rather than a boolean, so a threshold is a subtraction away; an
iteration count, when a surface wants one, is a value of its state.
An early end is non-uniform control flow. A loop with an until ends at
different turns in neighbouring pixels, where the shading languages leave a derivative and
a texture lookup that picks its own level of detail undefined, so its next and
until may hold no Expr.Sample, no call to dFdx, dFdy or
fwidth, and no call to texture, textureProj, textureOffset or
textureProjOffset; textureLod, textureGrad, their variants,
texelFetch and textureSize are defined there. A generator also refuses there
any Expr.Raw text and every call it does not know to be defined, its own helpers that
sample or take derivatives among them. A loop without an until runs every turn in
every pixel and may hold them all.
-
Nested Class Summary
Nested classes/interfaces inherited from interface limn.render3d.shader.Expr
Expr.Binary, Expr.Call, Expr.Construct, Expr.Lit, Expr.Loop, Expr.Op, Expr.Raw, Expr.Ref, Expr.Sample, Expr.Swizzle -
Field Summary
FieldsModifier and TypeFieldDescriptionstatic final intThe most turns a pixel may take across every loop of a surface. -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionbooleanIndicates whether some other object is "equal to" this one.inthashCode()Returns a hash code value for this object.intindex()Returns the value of theindexrecord component.initial()Returns the value of theinitialrecord component.intReturns the value of themaxIterationsrecord component.next()Returns the value of thenextrecord component.static Expr.Loopof(List<? extends Expr> initial, int maxIterations, Function<? super List<Expr>, ? extends List<? extends Expr>> next) A loop of several values that takes every turn, in every pixel.static Expr.Loopof(List<? extends Expr> initial, int maxIterations, Function<? super List<Expr>, ? extends List<? extends Expr>> next, Function<? super List<Expr>, ? extends Expr> until) A loop of several values that may end early: before each turn,untilof the state above zero ends it.static Expr.LoopA loop of one value that takes every turn, in every pixel.static Expr.Loopof(Expr initial, int maxIterations, Function<? super Expr, ? extends Expr> next, Function<? super Expr, ? extends Expr> until) A loop of one value that may end early: before each turn,untilof the state above zero ends it.states()Returns the value of thestatesrecord component.toString()Returns a string representation of this record class.type()@Nullable Expruntil()Returns the value of theuntilrecord component.value(int index) Valueindexof this loop's state when it ends: the same loop, computed once however many of its values are read.
-
Field Details
-
MAX_ITERATIONS
public static final int MAX_ITERATIONSThe most turns a pixel may take across every loop of a surface.- See Also:
-
-
Constructor Details
-
Loop
public Loop(List<String> states, List<Expr> initial, int maxIterations, List<Expr> next, @Nullable Expr until, int index) Checks the loop as the class describes.- Throws:
IllegalArgumentException- if the count, the turns with the loops it holds, a type (each value's wherever it is read included), the number of values, a name or the index is out of these bounds, or a loop that can end early samples or takes a derivative
-
-
Method Details
-
of
public static Expr.Loop of(Expr initial, int maxIterations, Function<? super Expr, ? extends Expr> next) A loop of one value that takes every turn, in every pixel.- Parameters:
initial- the state before the first turn; a float or vector typemaxIterations- how many turns, 1 toMAX_ITERATIONSnext- the state after one turn, given the state- Returns:
- the loop, whose value is the state after the last turn
- Throws:
IllegalArgumentException- as the constructor, or if the turn reads the state of a loop already built where no loop in the turn binds it
-
of
public static Expr.Loop of(Expr initial, int maxIterations, Function<? super Expr, ? extends Expr> next, Function<? super Expr, ? extends Expr> until) A loop of one value that may end early: before each turn,untilof the state above zero ends it.- Parameters:
initial- the state before the first turn; a float or vector typemaxIterations- how many turns at most, 1 toMAX_ITERATIONSnext- the state after one turn, given the stateuntil- a float above zero where the loop ends, given the state- Returns:
- the loop, whose value is the state when it ends
- Throws:
IllegalArgumentException- as the constructor, or if the turn reads the state of a loop already built where no loop in the turn binds it
-
of
public static Expr.Loop of(List<? extends Expr> initial, int maxIterations, Function<? super List<Expr>, ? extends List<? extends Expr>> next) A loop of several values that takes every turn, in every pixel.- Parameters:
initial- each value before the first turn; floats or vectors, one or moremaxIterations- how many turns, 1 toMAX_ITERATIONSnext- the values after one turn, in the same order, given the state's- Returns:
- the loop, whose first value it is;
value(int)reads the others - Throws:
IllegalArgumentException- as the constructor, or if the turn reads the state of a loop already built where no loop in the turn binds it
-
of
public static Expr.Loop of(List<? extends Expr> initial, int maxIterations, Function<? super List<Expr>, ? extends List<? extends Expr>> next, Function<? super List<Expr>, ? extends Expr> until) A loop of several values that may end early: before each turn,untilof the state above zero ends it.- Parameters:
initial- each value before the first turn; floats or vectors, one or moremaxIterations- how many turns at most, 1 toMAX_ITERATIONSnext- the values after one turn, in the same order, given the state'suntil- a float above zero where the loop ends, given the state's values- Returns:
- the loop, whose first value it is;
value(int)reads the others - Throws:
IllegalArgumentException- as the constructor, or if the turn reads the state of a loop already built where no loop in the turn binds it
-
value
Valueindexof this loop's state when it ends: the same loop, computed once however many of its values are read.- Parameters:
index- the value's place in the state, from 0- Returns:
- the node that reads it
- Throws:
IllegalArgumentException- if the loop has no such value
-
type
-
equals
Indicates whether some other object is "equal to" this one. The objects are equal if the other object is of the same class and if all the record components are equal. Reference components are compared withObjects::equals(Object,Object); primitive components are compared with '=='. -
hashCode
public int hashCode()Returns a hash code value for this object. The value is derived from the hash code of each of the record components. -
toString
Returns a string representation of this record class. The representation contains the name of the class, followed by the name and value of each of the record components. -
states
Returns the value of thestatesrecord component.- Returns:
- the value of the
statesrecord component
-
initial
Returns the value of theinitialrecord component.- Returns:
- the value of the
initialrecord component
-
maxIterations
public int maxIterations()Returns the value of themaxIterationsrecord component.- Returns:
- the value of the
maxIterationsrecord component
-
next
Returns the value of thenextrecord component.- Returns:
- the value of the
nextrecord component
-
until
Returns the value of theuntilrecord component.- Returns:
- the value of the
untilrecord component
-
index
public int index()Returns the value of theindexrecord component.- Returns:
- the value of the
indexrecord component
-