Lobsters

Rust to WGSL transpiler `wgsl-rs` released

Rust-to-WGSL 변환기 `wgsl-rs` 베타 출시

`wgsl-rs`가 Rust 코드를 WGSL 셰이더로 바꾸는 0.1.0-beta를 공개했습니다. 연산자 우선순위와 벡터 비교처럼 두 언어의 의미가 다른 부분을 보정하고, 런타임 IR에서 `wgpu` 파이프라인을 생성하도록 개선했습니다.

AI 요약

wgsl-rs는 Rust 코드를 WGSL 셰이더로 변환하는 도구입니다. 개발자는 4개월 동안 wgpu 코드 생성을 런타임 IR 기반으로 전환하고, Rust와 WGSL이 조용히 다르게 해석하는 부분을 정리했습니다. WGSL 어휘 지원과 문서, 버그 수정도 마쳐 0.1.0-beta를 출시했습니다.

언어 간 의미 차이 처리

Rust와 WGSL은 일부 연산자를 서로 다른 우선순위로 해석합니다. Rust에서는 &, ^, |, <<, >>가 ==보다 먼저 묶이지만 WGSL에서는 반대입니다. 변환기가 괄호 없이 이항식을 출력하면 Rust의 (0 & 0) == 0이 WGSL에서 0 & (0 == 0)으로 다시 해석될 수 있습니다. -(a + b)가 -a + b로 바뀌는 문제도 같은 종류입니다. wgsl-rs는 우선순위를 따져 출력하는 대신 모든 이항식에 괄호를 붙여 올바른 해석을 우선했습니다.

벡터 비교도 두 언어의 차이가 있습니다. Rust의 ==는 bool을 반환하지만 WGSL은 각 성분을 비교한 vecN 마스크를 반환합니다. Rust 코드가 성분별 비교 마스크를 직접 표현하지 않으므로, wgsl-rs는 모노모피제이션 후 벡터 ==를 all(lhs == rhs)로, !=를 !(all(...))로 바꾸는 단계를 추가했습니다. 성분별 비교가 필요하면 cmp_eq와 cmp_ne 함수를 사용합니다. 타입을 추론하지 못하는 경우에는 이 변환을 강제하지 않아 CPU 전용 코드의 컴파일을 유지합니다.

정수 리터럴의 기본 타입도 다릅니다. Rust는 문맥에 따라 0을 u32로 추론하지만 WGSL은 타입을 지정하지 않은 정수를 i32로 취급합니다. 그래서 Rust에서 컴파일되는 select(0, 1, data)가 naga 검증 단계에서 실패할 수 있습니다. 이를 해결하려고 스코프를 추적하며 리터럴 타입을 추론하는 앵커링 단계를 넣었습니다. 이 단계는 이름을 정리하는 deshadow 지점에 배치해 소스 리터럴, 상수 치환, 타입 치환, 확장 구문 변환에서 들어오는 리터럴을 모두 확인합니다. 구현은 표현식을 아래에서 위로 살피는 infer(expr) -> Option 방식이며, 모든 경우를 명시적으로 처리합니다. 반복 변수 타입은 제약 조건을 푸는 방식이 아니라 역방향 추론을 시험하는 절차로 처리합니다.

IR 기반 런타임 파이프라인 생성

기존에는 syn 트리를 순회하는 프로시저 매크로가 약 650줄의 wgpu 코드를 생성했습니다. 이를 런타임 IR 순회로 바꿨습니다. 덕분에 제네릭 템플릿 모듈을 런타임에 인스턴스화한 뒤 실제 wgpu 파이프라인으로 만들 수 있습니다. 버퍼 크기도 size_of() 대신 WGSL 명세 §14.4.1을 따르도록 수정했습니다. repr(C)가 아닌 구조체에서는 size_of() 결과가 WGSL의 메모리 배치와 맞지 않았기 때문입니다.

API 역할도 나눴습니다. wgsl_rs::Source는 명세를, ir::Module은 AST를 나타냅니다. wgsl-rs-ir가 wgsl-rs에 의존하면 순환 참조가 생기므로, 관련 메서드는 확장 트레이트에 둡니다.

셰이더 바인딩과 실제 사용

초기 분석기는 모든 셰이더 단계를 사용한다고 가정해 ShaderStages::all()을 지정했습니다. 이 설정은 필요하지 않은 VERTEX_WRITABLE_STORAGE 기능까지 요구했고, read_write 저장소를 쓰는 컴퓨트 디스패치를 실패하게 했습니다. 처음에는 진입점별 식별자를 검사했고, 이후 헬퍼 함수에서 사용하는 바인딩도 찾도록 호출 그래프의 전이적 도달 가능성을 분석했습니다. 모듈 전체를 훑으면 실제로 쓰지 않는 단계의 기능까지 요구할 수 있어 채택하지 않았습니다.

wgsl-rs는 셰이더를 게임 프로젝트에 이식하는 사용자들의 버그 제보를 반영했고, Zed의 gpui를 커뮤니티가 포크한 gpui-ce도 셰이더 계층에 이 도구를 도입했습니다. 개발자는 다음 단계로 crabslab과 craballoc을 Rust-GPU에서 wgsl-rs로 옮기고, GPU에서 실행되는 ECS를 만든 뒤 Renderling의 셰이더와 연결 방식을 다시 작성할 계획입니다.

원문: Renderling / 번역·요약: Trawling