Skip to content

Commit

Permalink
feat(shader-ast): simplify fn dep/call graph handling, fix allChildren()
Browse files Browse the repository at this point in the history
  • Loading branch information
postspectacular committed Jun 18, 2019
1 parent bb12d5b commit 6ee63ea
Show file tree
Hide file tree
Showing 3 changed files with 82 additions and 76 deletions.
28 changes: 19 additions & 9 deletions packages/shader-ast/src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,34 +260,34 @@ export type FnBody8<
Term<any>[]
>;

export type Func0<T extends Type> = Fn0<Term<T>>;
export type Func1<A extends Type, T extends Type> = Fn<Term<A>, Term<T>>;
export type Func0<T extends Type> = Fn0<FnCall<T>>;
export type Func1<A extends Type, T extends Type> = Fn<Term<A>, FnCall<T>>;
export type Func2<A extends Type, B extends Type, T extends Type> = Fn2<
Term<A>,
Term<B>,
Term<T>
FnCall<T>
>;
export type Func3<
A extends Type,
B extends Type,
C extends Type,
T extends Type
> = Fn3<Term<A>, Term<B>, Term<C>, Term<T>>;
> = Fn3<Term<A>, Term<B>, Term<C>, FnCall<T>>;
export type Func4<
A extends Type,
B extends Type,
C extends Type,
D extends Type,
T extends Type
> = Fn4<Term<A>, Term<B>, Term<C>, Term<D>, Term<T>>;
> = Fn4<Term<A>, Term<B>, Term<C>, Term<D>, FnCall<T>>;
export type Func5<
A extends Type,
B extends Type,
C extends Type,
D extends Type,
E extends Type,
T extends Type
> = Fn5<Term<A>, Term<B>, Term<C>, Term<D>, Term<E>, Term<T>>;
> = Fn5<Term<A>, Term<B>, Term<C>, Term<D>, Term<E>, FnCall<T>>;
export type Func6<
A extends Type,
B extends Type,
Expand All @@ -296,7 +296,7 @@ export type Func6<
E extends Type,
F extends Type,
T extends Type
> = Fn6<Term<A>, Term<B>, Term<C>, Term<D>, Term<E>, Term<F>, Term<T>>;
> = Fn6<Term<A>, Term<B>, Term<C>, Term<D>, Term<E>, Term<F>, FnCall<T>>;
export type Func7<
A extends Type,
B extends Type,
Expand All @@ -306,7 +306,16 @@ export type Func7<
F extends Type,
G extends Type,
T extends Type
> = Fn7<Term<A>, Term<B>, Term<C>, Term<D>, Term<E>, Term<F>, Term<G>, Term<T>>;
> = Fn7<
Term<A>,
Term<B>,
Term<C>,
Term<D>,
Term<E>,
Term<F>,
Term<G>,
FnCall<T>
>;
export type Func8<
A extends Type,
B extends Type,
Expand All @@ -326,7 +335,7 @@ export type Func8<
Term<F>,
Term<G>,
Term<H>,
Term<T>
FnCall<T>
>;

export type ArgQualifier = "in" | "out" | "inout";
Expand Down Expand Up @@ -512,6 +521,7 @@ export interface FnCall<T extends Type> extends Term<T> {
id: string;
args: Term<any>[];
info?: string;
fn?: Func<T>;
}

export interface ForLoop extends Term<"void">, Scoped {
Expand Down
44 changes: 26 additions & 18 deletions packages/shader-ast/src/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,8 +138,12 @@ export const allChildren = (t: Term<any>) =>
? (<FnCall<any>>t).args
: t.tag === "sym" && (<Sym<any>>t).init
? [(<Sym<any>>t).init]
: t.tag === "decl"
? [(<Decl<any>>t).id]
: t.tag === "op2"
? [(<Op2<any>>t).l, (<Op2<any>>t).r]
: t.tag === "assign"
? [(<Assign<any>>t).r]
: isVec(t) || isMat(t)
? (<Lit<any>>t).val
: undefined;
Expand Down Expand Up @@ -597,25 +601,25 @@ const defArg = <T extends Type>([type, id, opts]: Arg<T>): FuncArg<T> => ({
* @param deps array of userland functions called from this function
*/
// prettier-ignore
export function defn<T extends Type>(type: T, name: string, args: [], body: FnBody0, deps?: Func<any>[]): TaggedFn0<T>;
export function defn<T extends Type>(type: T, name: string, args: [], body: FnBody0): TaggedFn0<T>;
// prettier-ignore
export function defn<T extends Type, A extends Type>(type: T, name: string, args: Arg1<A>, body: FnBody1<A>, deps?: Func<any>[]): TaggedFn1<A,T>;
export function defn<T extends Type, A extends Type>(type: T, name: string, args: Arg1<A>, body: FnBody1<A>): TaggedFn1<A,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type>(type: T, name: string, args: Arg2<A,B>, body: FnBody2<A,B>, deps?: Func<any>[]): TaggedFn2<A,B,T>;
export function defn<T extends Type, A extends Type, B extends Type>(type: T, name: string, args: Arg2<A,B>, body: FnBody2<A,B>): TaggedFn2<A,B,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type, C extends Type>(type: T, name: string, args: Arg3<A,B,C>, body: FnBody3<A,B,C>, deps?: Func<any>[]): TaggedFn3<A,B,C,T>;
export function defn<T extends Type, A extends Type, B extends Type, C extends Type>(type: T, name: string, args: Arg3<A,B,C>, body: FnBody3<A,B,C>): TaggedFn3<A,B,C,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type>(type: T, name: string, args: Arg4<A,B,C,D>, body: FnBody4<A,B,C,D>, deps?: Func<any>[]): TaggedFn4<A,B,C,D,T>;
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type>(type: T, name: string, args: Arg4<A,B,C,D>, body: FnBody4<A,B,C,D>): TaggedFn4<A,B,C,D,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type>(type: T, name: string, args: Arg5<A,B,C,D,E>, body: FnBody5<A,B,C,D,E>, deps?: Func<any>[]): TaggedFn5<A,B,C,D,E,T>;
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type>(type: T, name: string, args: Arg5<A,B,C,D,E>, body: FnBody5<A,B,C,D,E>): TaggedFn5<A,B,C,D,E,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type, F extends Type>(type: T, name: string, args: Arg6<A,B,C,D,E,F>, body: FnBody6<A,B,C,D,E,F>, deps?: Func<any>[]): TaggedFn6<A,B,C,D,E,F,T>;
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type, F extends Type>(type: T, name: string, args: Arg6<A,B,C,D,E,F>, body: FnBody6<A,B,C,D,E,F>): TaggedFn6<A,B,C,D,E,F,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type, F extends Type, G extends Type>(type: T, name: string, args: Arg7<A,B,C,D,E,F,G>, body: FnBody7<A,B,C,D,E,F,G>, deps?: Func<any>[]): TaggedFn7<A,B,C,D,E,F,G,T>;
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type, F extends Type, G extends Type>(type: T, name: string, args: Arg7<A,B,C,D,E,F,G>, body: FnBody7<A,B,C,D,E,F,G>): TaggedFn7<A,B,C,D,E,F,G,T>;
// prettier-ignore
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type, F extends Type, G extends Type, H extends Type>(type: T, name: string, args: Arg8<A,B,C,D,E,F,G,H>, body: FnBody8<A,B,C,D,E,F,G,H>, deps?: Func<any>[]): TaggedFn8<A,B,C,D,E,F,G,H,T>;
export function defn<T extends Type, A extends Type, B extends Type, C extends Type, D extends Type, E extends Type, F extends Type, G extends Type, H extends Type>(type: T, name: string, args: Arg8<A,B,C,D,E,F,G,H>, body: FnBody8<A,B,C,D,E,F,G,H>): TaggedFn8<A,B,C,D,E,F,G,H,T>;
// prettier-ignore
export function defn(type: Type, id: string, _args: Arg<any>[], _body: (...xs: Sym<any>[]) => Term<any>[], deps: Func<any>[]=[]): Func<any> {
export function defn(type: Type, id: string, _args: Arg<any>[], _body: (...xs: Sym<any>[]) => Term<any>[]): Func<any> {
const args = _args.map(defArg);
const body = _body(...args.map((x) => sym(x.type, x.id, x.opts)));
// count & check returns
Expand All @@ -641,16 +645,18 @@ export function defn(type: Type, id: string, _args: Arg<any>[], _body: (...xs: S
}
// verify all non-builtin functions called are also
// provided as deps to ensure complete call graph later
walk(
(_, t) => t.tag === "call" && assert(
!!deps.find((y) => y.id === (<FnCall<any>>t).id),
`function '${id}' calls function '${(<FnCall<any>>t).id}' not given in deps`
),
const deps = walk(
(acc, t) => {
if (t.tag === "call" && (<FnCall<any>>t).fn) {
acc.push((<FnCall<any>>t).fn!);
}
return acc;
},
allChildren,
<any>null,
<Func<any>[]>[],
body
);
const $: any = (...xs: any[]) => funcall(id, type, ...xs);
const $: any = (...xs: any[]) => (<any>funcall)($, ...xs);
return Object.assign($, <Func<any>>{
tag: "fn",
type,
Expand All @@ -673,6 +679,7 @@ export function ret(val?: Term<any>): FuncReturn<any> {

// prettier-ignore
export function funcall<T extends Type>(fn: string, type: T, ...args: Term<any>[]): FnCall<T>;
export function funcall<T extends Type>(fn: TaggedFn0<T>): FnCall<T>;
// prettier-ignore
export function funcall<A extends Type, T extends Type>(fn: TaggedFn1<A,T>, a: Term<A>): FnCall<T>;
// prettier-ignore
Expand Down Expand Up @@ -702,7 +709,8 @@ export function funcall(fn: string | Func<any>, ...args: Term<any>[]): FnCall<an
tag: "call",
type: fn.type,
id: fn.id,
args
args,
fn
};
}

Expand Down
86 changes: 37 additions & 49 deletions packages/shader-ast/src/std/raymarch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,37 +45,31 @@ export const raymarch = (
bias: 0.7,
..._opts
};
return defn(
"vec2",
opts.name,
[["vec3"], ["vec3"]],
(pos, dir) => {
let total: Sym<"f32">;
let res: Sym<"vec2">;
return [
(total = sym(float(opts.near))),
(res = sym("vec2")),
forLoop(
sym("i32", int(0)),
(i) => lt(i, int(opts.steps)),
(i) => assign(i, inc(i)),
() => [
assign(res, scene(add(pos, mul(dir, total)))),
ifThen(lt($(res, "x"), float(opts.eps)), [
ret(vec2(total, $(res, "y")))
]),
assign(
total,
add(total, mul($(res, "x"), float(opts.bias)))
),
ifThen(gt(total, float(opts.far)), [brk])
]
),
ret(vec2(opts.far, 0))
];
},
[scene]
);
return defn("vec2", opts.name, [["vec3"], ["vec3"]], (pos, dir) => {
let total: Sym<"f32">;
let res: Sym<"vec2">;
return [
(total = sym(float(opts.near))),
(res = sym("vec2")),
forLoop(
sym("i32", int(0)),
(i) => lt(i, int(opts.steps)),
(i) => assign(i, inc(i)),
() => [
assign(res, scene(add(pos, mul(dir, total)))),
ifThen(lt($(res, "x"), float(opts.eps)), [
ret(vec2(total, $(res, "y")))
]),
assign(
total,
add(total, mul($(res, "x"), float(opts.bias)))
),
ifThen(gt(total, float(opts.far)), [brk])
]
),
ret(vec2(opts.far, 0))
];
});
};

/**
Expand All @@ -91,24 +85,18 @@ export const raymarchNormal = (
scene: TaggedFn1<"vec3", "vec2">,
name = "raymarchNormal"
) =>
defn(
"vec3",
name,
[["vec3"], ["f32"]],
(p, smooth) => {
let dn: Sym<"vec2">;
let comp = (id: Swizzle2_3) =>
sub(
$(scene(add(p, $(dn, id))), "x"),
$(scene(sub(p, $(dn, id))), "x")
);
return [
(dn = sym(vec2(smooth, 0))),
ret(normalize(vec3(comp("xyy"), comp("yxy"), comp("yyx"))))
];
},
[scene]
);
defn("vec3", name, [["vec3"], ["f32"]], (p, smooth) => {
let dn: Sym<"vec2">;
let comp = (id: Swizzle2_3) =>
sub(
$(scene(add(p, $(dn, id))), "x"),
$(scene(sub(p, $(dn, id))), "x")
);
return [
(dn = sym(vec2(smooth, 0))),
ret(normalize(vec3(comp("xyy"), comp("yxy"), comp("yyx"))))
];
});

/**
* @param eyePos vec3
Expand Down

0 comments on commit 6ee63ea

Please sign in to comment.