제어 흐름

제어 흐름

루프는 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 = x
    let w: i32 = 0
    while (w < 4) {
    acc = acc * 0.5
    w = 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;
    }
  • switch

    switch가 됩니다. case는 저마다 break로 끝나고, 하향 변환이 그것을 떼어 냅니다. 본문 끝까지 실행이 이어질 수 있는 case는 거절합니다(TS8017). TypeScript에서는 그런 case가 다음 case까지 이어서 실행되지만, WGSL은 case 하나만 실행합니다. bitfield-bands

    TypeScript
    export function band(m: i32): f32 {
    let v: f32 = 0.
    switch (m) {
    case 0:
    v = 0.25
    break
    default:
    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-composite

    TypeScript
    export function chosen(
    warm: Palette, cool: Palette, c: bool
    ): vec3 {
    const shade: Palette = c ? warm : cool
    return 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;
    }
  • break

    break입니다. 횟수가 정해진 루프를 일찍 빠져나오는 방법입니다. julia-twin

    TypeScript
    export function escape(x: f32): f32 {
    let acc: f32 = x
    for (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;
    }
  • continue

    continue입니다. 루프가 감싸지 않은 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;
    }
  • discard

    discard입니다. 프래그먼트 진입점이나 그 진입점이 부르는 함수에 씁니다. cutout

    TypeScript
    @fragment
    export function fs(
    @builtin("position") frag: vec4
    ): vec4 {
    if (frag.x < 0.5) {
    discard
    }
    return vec4(1.)
    }
    생성된 WGSL
    @fragment
    fn 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);
    }

이 페이지 편집 문제 보고