variantFamily
이 페이지에서

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>

매개변수

spec VariantFamilySpec<A>

the axes, the per-point builder, and the key derivation.

반환값

VariantFamily<A>

the built family: every variant with its module, reflection and key, plus the three emit shapes.

예외

Error

Error when 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, keyed
family.emitGuarded({ shadows: 'SHADOWS', blend: { add: 'BLEND_ADD', mix: 'BLEND_MIX' } })

관련 가이드

함께 보기

소스

src/core/variant-family.ts, 266행, 커밋 c66579bf 기준

이 페이지 편집 문제 보고