제어 흐름
루프는 GPU가 끝낼 수 있는 모양이어야 하고, 두 값 중 하나를 고르는 식은 타깃에 연산자가 있는 모양이어야 합니다.
-
if적은 그대로
if입니다.TypeScript export function capped(x: f32): f32 {if (x > 1.) {return 1.}return x}생성된 WGSL fn capped(x: f32) -> f32 {if ((x > 1.0)) {return 1.0;}return x;} -
횟수를 세는
for횟수를 세는 루프입니다. 정수 변수와 상수 증가가 있고, 종료 조건은 본문이 쓰지 않는 경계와 변수를 비교합니다. block-scope
TypeScript export function ramp(x: f32): f32 {let acc: f32 = 0.for (let i = 0; i < 4; i += 1) {acc = acc + x * f32(i)}return acc}생성된 WGSL fn ramp(x: f32) -> f32 {var acc: f32 = 0.0;for (var i: i32 = 0; (i < 4); i += 1) {acc = (acc + (x * f32(i)));}return acc;} -
런타임 경계까지 도는
for시작값과 경계는 실행 중에야 알게 되는 값이어도 되고, 반복 횟수에 상한이 없습니다.
TypeScript export function ramp(x: f32, n: i32): f32 {let acc: f32 = 0.for (let i = 0; i < n; i += 1) {acc = acc + x}return acc}생성된 WGSL fn ramp(x: f32, n: i32) -> f32 {var acc: f32 = 0.0;for (var i: i32 = 0; (i < n); i += 1) {acc = (acc + x);}return acc;} -
while컴파일러가 카운터를 붙인 루프가 됩니다. 본문이 경계로 다가가는지는 아무것도 검사하지 않습니다.
TypeScript export function halve(x: f32): f32 {let acc: f32 = xlet w: i32 = 0while (w < 4) {acc = acc * 0.5w = w + 1}return acc}생성된 WGSL fn halve(x: f32) -> f32 {var acc: f32 = x;var w: i32 = 0;for (var _w: i32 = 0; (w < 4); _w = (_w + 1)) {acc = (acc * 0.5);w = (w + 1);}return acc;} -
switchswitch가 됩니다. case는 저마다break로 끝나고, 하향 변환이 그것을 떼어 냅니다. 본문 끝까지 실행이 이어질 수 있는 case는 거절합니다(TS8017). TypeScript에서는 그런 case가 다음 case까지 이어서 실행되지만, WGSL은 case 하나만 실행합니다. bitfield-bandsTypeScript export function band(m: i32): f32 {let v: f32 = 0.switch (m) {case 0:v = 0.25breakdefault:v = 1.break}return v}생성된 WGSL fn band(m: i32) -> f32 {var v: f32 = 0.0;switch m {case 0: {v = 0.25;}default: {v = 1.0;}}return v;} -
스칼라 삼항 연산
WGSL에서는
select가 되고, GLSL ES 3.00에서는 삼항 연산자가 됩니다.TypeScript export function nearer(a: f32, b: f32): f32 {return a < b ? a : b}생성된 WGSL fn nearer(a: f32, b: f32) -> f32 {return select(b, a, (a < b));} -
구조체 삼항 연산
두 타깃 모두 이런 연산자가 없어서, 값을 슬롯 하나와
if로 끌어올립니다. pick-compositeTypeScript export function chosen(warm: Palette, cool: Palette, c: bool): vec3 {const shade: Palette = c ? warm : coolreturn shade.lo}생성된 WGSL fn chosen(warm: Palette, cool: Palette, c: bool) -> vec3<f32> {var _sel0: Palette;if (c) {_sel0 = warm;} else {_sel0 = cool;}let shade = _sel0;return shade.lo;} -
breakbreak입니다. 횟수가 정해진 루프를 일찍 빠져나오는 방법입니다. julia-twinTypeScript export function escape(x: f32): f32 {let acc: f32 = xfor (let i = 0; i < 8; i += 1) {acc = acc * 2.if (acc > 1.) {break}}return acc}생성된 WGSL fn escape(x: f32) -> f32 {var acc: f32 = x;for (var i: i32 = 0; (i < 8); i += 1) {acc = (acc * 2.0);if ((acc > 1.0)) {break;}}return acc;} -
continuecontinue입니다. 루프가 감싸지 않은switch안에서는 거절합니다.TypeScript export function odds(x: f32): f32 {let acc: f32 = 0.for (let i = 0; i < 4; i += 1) {if (i === 2) {continue}acc = acc + x}return acc}생성된 WGSL fn odds(x: f32) -> f32 {var acc: f32 = 0.0;for (var i: i32 = 0; (i < 4); i += 1) {if ((i == 2)) {continue;}acc = (acc + x);}return acc;} -
discarddiscard입니다. 프래그먼트 진입점이나 그 진입점이 부르는 함수에 씁니다. cutoutTypeScript @fragmentexport function fs(@builtin("position") frag: vec4): vec4 {if (frag.x < 0.5) {discard}return vec4(1.)}생성된 WGSL @fragmentfn fs(@builtin(position) frag: vec4<f32>) -> @location(0) vec4<f32> {if ((frag.x < 0.5)) {discard;}return vec4<f32>(1.0, 1.0, 1.0, 1.0);}