Specialization constant

Specialization constant

파이프라인에서 덮어쓸 수 있는 quality 상수.

// ═══ typeshade example — pipeline specialization constant (#923) ═══
//
// The ubershader / shader-variant mechanism: ONE authored module, `overrideConst`
// declares a `quality` knob whose value is chosen at PIPELINE CREATION (not module
// build). A branch guarded by `quality > 1` does EXTRA work in the high-quality
// variant and is DEAD-CODE-ELIMINATED BY THE DRIVER in the low-quality one — the DSL
// optimizer keeps the branch OPAQUE (a specialization constant is symbolic until the
// host specializes it), so the same emitted module yields N driver-specialized
// variants.
//
// • WGSL: emits `override quality: f32 = 1.0;` — the host picks the variant with
// `device.createRenderPipeline({ ..., constants: { quality: 2.0 } })`.
// • GLSL ES 3.00 (no `override`): emits a `#ifndef/#define/#endif` default so the
// module compiles standalone, and the host specializes a variant by re-emitting with
// `emitGlslModule(m, stage, { overrideValues: { quality: 2.0 } })` — GLSL forbids a
// prepended `#define` (`#version` must lead), so the emitter places + spells it. Both
// host shapes derive from `reflect().overrides`.
//
// NOT WebGL2-renderable (`renderable: false`) as a helper module with no entry point —
// the site shows its WGSL + Reflection (the override set). The emit goldens + the
// dedicated override-constants.test.ts pin the `override` line and the `#define` block.
import { module, fn, f32, f32T, If, Var, overrideConst } from '../src/index.js';
import type { ShaderExample } from './_shared.js';
// The specialization constant: default 1.0 (the low-quality variant), host-overridable.
const quality = overrideConst('quality', f32T, 1.0);
// Shade a base intensity, doing an extra refinement step ONLY in the high-quality
// variant. The `if` is guarded by the override read, so the driver — not the DSL —
// eliminates it per pipeline variant.
const shade = fn('shade', { base: f32T }, ({ base }) => {
const acc = Var(base);
If(quality.node.gt(f32(1)), () => {
// High-quality refinement — compiled out when the pipeline pins quality <= 1.
acc.assign(acc.mul(f32(2)).add(f32(0.5)));
});
return acc;
});
const overrideModule = module({
overrides: [quality.decl],
funcs: [shade],
});
export const overrideQuality: ShaderExample = {
id: 'override-quality',
title: 'Specialization constant',
blurb:
'A pipeline-overridable `quality` constant (#923): WGSL `override` + GLSL `#define`, guarding a branch the DRIVER dead-code-eliminates per variant. One authored module → N driver-specialized pipelines. Shows WGSL + reflection.',
category: 'generic',
file: 'override-quality.ts',
module: overrideModule,
renderable: false,
};
override quality: f32 = 1.0;
fn shade(base: f32) -> f32 {
var _v0: f32 = base;
if ((quality > 1.0)) {
_v0 = ((_v0 * 2.0) + 0.5);
}
return _v0;
}

이 예제는 GLSL ES 3.00 형태가 없고 캔버스는 두 백엔드에서 같은 프로그램을 돌리므로, 이 페이지에는 그림이 없습니다.

WGSL과 GLSL 탭은 커밋 c66579bf의 컴파일러가 직접 낸 출력입니다. 컴파일러의 출력 검사가 구워 둔 골든 파일에서 그대로 읽어 왔습니다(emit-goldens.test.ts).

이 예제는 fn() 빌더 API로 작성해서 Playground의 편집기가 받지 않습니다.

GitHub의 파일

이 페이지 편집 문제 보고