variantFamily()
함수, 배리언트 분류
Build a family of shader variants from a typed axis matrix.
import { variantFamily } from 'typeshade'
시그니처, 설명, 예제는 커밋 c66579bf의 컴파일러 소스에서 그대로 가져온 영어 원문입니다.
구문
function variantFamily<A extends Record<string, readonly unknown[]>>( spec: VariantFamilySpec<A>,): VariantFamily<A>매개변수
specVariantFamilySpec<A>the axes, the per-point builder, and the key derivation.
반환값
the built family: every variant with its module, reflection and key, plus the three emit shapes.
예외
ErrorErrorwhen an axis declares no values, or when two points derive the same key, which means the key does not name every axis the builder read.
설명
Give it the axes a host can select, a builder for one point in the space, and a key derivation, and it builds every point once.
Each axis is a name mapped to the list of values the host chooses among, so the family is
the product of the axes and every point is type-checked: the builder receives one value per
axis, and a typo in an axis name is a tsc error. The builder is ordinary TypeScript, so the
variation is a plain if and the losing arm is never built, which means its bindings are
never declared and never reach reflect.
variants holds one entry per point: the axis values, the built ModuleDecl, its
reflect result, and the derived key. keys lists those keys and get(key) looks a
variant up. The key is the part that outlives everything else, because a specialized
program is a different program and every axis has to appear in every key that names it: a
pipeline cache keyed without an axis serves one variant’s program to another variant’s
draw, which compiles, links, renders and is wrong. Deriving the key from the axis values is
what makes omitting one impossible, and two points deriving the same key throws here.
emit(target) returns one preprocessor-free source per key. That is the WGSL path, and it
is what a pipeline cache should prefer on either target.
emitGuarded(defines, opts) is the GLSL-only alternative, for a host that owns the define
and decides at draw time. It generates one source with an #if ladder over the arms, one
arm per variant, from the same typed matrix, so the ladder can be checked against that
matrix. Every arm is byte-identical to the standalone variant of the same key,
which is what keeps the guarded and unguarded paths from being two programs.
emitGuardedFragment(defines, opts) returns the same ladder as a header-less fragment: the
source, and the preamble, the declares and the requires as data. It exists because the
ladder usually goes inside an include, and an include cannot carry a second #version.
Joining the preamble to the source reproduces emitGuarded byte for byte.
예제
예제
import { variantFamily } from 'typeshade'
const family = variantFamily({ axes: { shadows: [false, true], blend: ['add', 'mix'] }, build: ({ shadows, blend }) => buildModule(shadows, blend), key: ({ shadows, blend }) => `${shadows ? 's' : 'n'}:${blend}`,})
family.emit('wgsl') // four sources, keyedfamily.emitGuarded({ shadows: 'SHADOWS', blend: { add: 'BLEND_ADD', mix: 'BLEND_MIX' } })관련 가이드
함께 보기
소스
src/core/variant-family.ts, 266행, 커밋 c66579bf 기준