검증 방식

검증 방식

푸시마다 도는 검사

저장소의 CI는 푸시와 풀 리퀘스트마다 CI 워크플로에서 다음을 실행합니다.

  1. 같은 모듈을 f64 산술로 도는 CPU 함수로도 컴파일합니다. 이것이 기준값을 내는 오라클입니다. 기본 모드에서는 동등 비교만 먼저 f32로 반올림해 GPU와 맞추고, 연산마다 반올림하는 f32 모드는 따로 켭니다. 테스트는 이 함수를 알려진 답과 맞춰 보고, 생성된 JavaScript라는 두 번째 CPU 백엔드와도 맞춰 봅니다. 둘은 비트 단위로 같아야 합니다. 드라이버의 반올림에 대해서는 아무것도 말해 주지 않고, 이 저장소에서 GPU 출력을 여기에 맞춰 보지는 않습니다. src/core/oracle.ts
  2. 컴파일 게이트는 등록된 예제를 전부 출력합니다. WGSL은 헤드리스 Chromium 안의 Tint에 넘기고, 렌더링 가능한 예제의 GLSL ES 3.00 두 단계는 실제 WebGL2 컨텍스트에서 컴파일하고 링크합니다. 컴파일될 수 없는 셰이더도 각 컴파일러에 하나씩 넘깁니다. 어느 쪽이든 그것을 받아들이면 게이트는 실패하고, 예제에 대한 판정은 무효가 됩니다. scripts/compile-gate.ts
  3. 골든 파일에는 모든 예제의 출력 바이트가 들어 있어서, 백엔드가 조금이라도 바뀌면 리뷰에서 diff로 드러납니다. emit-goldens.test.ts

두 백엔드에서 같은 패스

첫 페이지의 gradient 패스를 백엔드마다 한 번씩 그렸습니다. 두 백엔드의 픽셀 비교는 아직 커밋되어 있지 않습니다.

컴파일된 WGSL로 빌드할 때 WebGPU에서 그렸습니다.
컴파일된 GLSL ES 3.00으로 빌드할 때 WebGL2에서 그렸습니다.

코드를 쓰는 동안

유니폼 블록은 한 번 선언하고, 필드를 읽는 곳마다 그 선언에 맞춰 타입 검사를 받습니다. 하나만 잘못 써도 문자열이 GPU에 닿기 전에 편집기에서 TypeScript가 알려 줍니다.

typed-error-shader.ts
const U = uniformStruct('Uniforms', { group: 0, binding: 0, as: 'U' }, {
time: f32T, top: vec4fT, bottom: vec4fT,
})
const fsGradient = fn('fs_gradient', { vo: VsOut }, (p) => {
const t = p.vo.uv.y.add(U.field.time.mul(0.05))
return vec4(mix(U.field.bottom.rgb, U.field.colour.rgb, t), f32(1))
}, { stage: 'fragment', retAttr: '@location(0)' })

오류 TS2339, 7행 47열: Property 'colour' does not exist on type '{ readonly time: ReadonlyNode<"f32">; readonly top: ReadonlyNode<"vec4<f32>">; readonly bottom: ReadonlyNode<"vec4<f32>">; }'.

reflect(), std140, 48바이트
필드 타입 오프셋 크기
time f32 0 4
top vec4<f32> 16 16
bottom vec4<f32> 32 16
7행에서 잘못 읽은 필드, 그 줄이 내는 진단, 그리고 읽으려던 블록에 대해 reflect()가 복원한 std140 레이아웃입니다. 필드 3개에 48바이트이고, 첫 필드 뒤의 빈 공간은 정렬입니다.

이 페이지 편집