함수

함수

모든 함수는 모듈의 함수입니다. 함수 값도, 가둬 둘 환경도, 호출 스택도 없습니다.

  • 모듈 값과 같은 이름

    매개변수나 함수 본문의 지역 변수는 모듈 값과 같은 이름을 쓸 수 있습니다. 클로저는 가장 가까운 선언을 찾으며, 같은 스코프의 중복 선언은 여전히 오류입니다.

    TypeScript
    const gain: f32 = 0.25;
    function scale(gain: f32): f32 { return gain * 2.; }
    export function answer(): f32 {
    const gain: f32 = 1.;
    return scale(gain);
    }
    생성된 WGSL
    fn scale(gain: f32) -> f32 {
    return (gain * 2.0);
    }
    fn answer() -> f32 {
    return scale(1.0);
    }
  • 매개변수 재대입

    입력값을 지역 복사본에 담습니다. 다시 대입해도 호출자의 값은 바뀌지 않습니다.

    TypeScript
    export function brighter(value: f32): f32 {
    value += 0.25;
    return value;
    }
    생성된 WGSL
    fn brighter(value: f32) -> f32 {
    var value_1: f32 = value;
    value_1 += 0.25;
    return value_1;
    }
  • 최상위 함수

    이름과 매개변수와 반환 타입이 같은 모듈 함수가 됩니다.

    TypeScript
    export function lum(c: vec3): f32 {
    return dot(c, vec3(0.2126, 0.7152, 0.0722))
    }
    생성된 WGSL
    fn lum(c: vec3<f32>) -> f32 {
    return dot(c, vec3<f32>(0.2126, 0.7152, 0.0722));
    }
  • 지역 함수

    모듈의 함수가 됩니다. 이름은 이를 선언한 함수에서 따옵니다.

    TypeScript
    export function ramp(x: f32): f32 {
    const twice = (v: f32): f32 => v * 2.
    return twice(x)
    }
    생성된 WGSL
    fn ramp_twice(v: f32) -> f32 {
    return (v * 2.0);
    }
    fn ramp(x: f32) -> f32 {
    return ramp_twice(x);
    }
  • 이름 캡처

    로컬 함수는 바깥 함수에서 읽는 이름을 매개변수로 받고, 쓰는 이름은 참조로 받습니다.

    TypeScript
    export function ramp(x: f32): f32 {
    const twice = (v: f32): f32 => v * x
    return twice(x)
    }
    생성된 WGSL
    fn ramp_twice(x: f32, v: f32) -> f32 {
    return (v * x);
    }
    fn ramp(x: f32) -> f32 {
    return ramp_twice(x, x);
    }
  • 기본 인자

    매개변수는 모두 남고, 빠뜨린 인자는 호출 지점에 적힙니다. default-args

    TypeScript
    function vignette(
    uv: vec2, strength: f32 = 0.8
    ): f32 {
    return 1. - length(uv) * strength
    }
    생성된 WGSL
    fn vignette(uv: vec2<f32>, strength: f32) -> f32 {
    return (1.0 - (length(uv) * strength));
    }
    fn shade(uv: vec2<f32>) -> f32 {
    return vignette(uv, 0.8);
    }
  • 오버로드 시그니처

    시그니처는 건너뛰고 구현 하나만 하향 변환합니다.

    TypeScript
    export function lum(c: vec3): f32
    export function lum(c: vec3): f32 {
    return dot(c, vec3(0.2126, 0.7152, 0.0722))
    }
    생성된 WGSL
    fn lum(c: vec3<f32>) -> f32 {
    return dot(c, vec3<f32>(0.2126, 0.7152, 0.0722));
    }
  • 재귀 호출

    거절

    WGSL에는 호출 스택이 없고, 검사는 호출 그래프를 읽습니다.

    TypeScript
    export function fall(x: f32): f32 {
    return fall(x * 0.5)
    }

    컴파일러 진단

    TS8031 Recursive call: "fall" -> "fall". WGSL has no call stack, so a function must not take part in a call cycle.

  • 문으로 쓴 호출

    문 하나가 됩니다. 값을 돌려주는 내장 함수가 홀로 서면 계산하는 것이 없어 최적화가 지웁니다.

    TypeScript
    @compute([64, 1, 1])
    export function main_k(
    @builtin("global_invocation_id") gid: vec3u
    ): void {
    store(gid.x, 1.)
    }
    생성된 WGSL
    @compute @workgroup_size(64)
    fn main_k(@builtin(global_invocation_id) gid: vec3<u32>) {
    store(gid.x, 1.0);
    }
  • 효과가 있는 호출

    값을 돌려주면서 효과도 있는 내장 함수에는 WGSL의 _ = 대입이 붙습니다. Tint가 반환값을 반드시 쓰도록 요구하기 때문입니다. atomic-histogram

    TypeScript
    @compute([64, 1, 1])
    export function main_k(
    @builtin("global_invocation_id") gid: vec3u
    ): void {
    atomicAdd(hits[gid.x], 1)
    }
    생성된 WGSL
    @compute @workgroup_size(64)
    fn main_k(@builtin(global_invocation_id) gid: vec3<u32>) {
    _ = atomicAdd(&hits[gid.x], 1u);
    }
  • Math 이름

    Math.sin은 sin과 같은 내장 함수이고, Math.PI는 값으로 접힙니다.

    TypeScript
    export function wave(x: f32): f32 {
    return Math.sin(x * Math.PI)
    }
    생성된 WGSL
    fn wave(x: f32) -> f32 {
    return sin((x * 3.141592653589793));
    }

이 페이지 편집 문제 보고