Voronoi 셰이더가 윈도우 RTX 4070에서만 버벅인 이유를 일주일간 파헤친 디버깅기
- Bruno Croci가 음악 영상 배경용 Voronoi 셰이더를 만들던 중 한 대의 Windows PC(RTX 4070)에서만 애니메이션이 버벅이는 문제를 발견해 약 일주일간 셰이더를 디스어셈블하며 디버깅함.
- 인텔 내장 GPU 리눅스 노트북 2대, 픽셀 9 프로, RTX 2070을 단 리눅스 PC에서는 모두 정상이었고 Windows RTX 4070 한 대에서만 증상이 재현됨.
- 원인은 GPU 드라이버가 아니라 DirectX 11의 HLSL 컴파일러(fxc) 쪽이었고, 작성자가 이후 다른 Windows 머신에서도 같은 증상을 재현함.
- 문제 구간은 Voronoi 중심을 만드는 코드의 noise 호출 부분이었고,
fract(x)는 x >= 0일 때만x - floor(x)와 같아 음수 입력에서는 결과가 달라진다는 지적이 토론에서 나옴. - 작성자는 브라우저 렌더링 캡처와 셰이더 역어셈블 과정을 글에 그대로 공개했고, 최종 셰이더는 Shadertoy에 올라가 있음.
Hacker News opinions
와 이 글 진짜 재밌게 읽었음. 몇 년 전 해커뉴스가 이런 글로 넘쳤는데 요즘은 드물더라. 셰이더는 main도 없고 for 루프도 없이 픽셀마다 매 프레임 불리는 구조라 처음 배울 때 진짜 힘들었음.
프롬프트로 셰이더를 뽑아도 이해는 못 함. LLM은 그 효과가 보기 좋은지 판단하는 감각이 전혀 없음.
Claude는 셰이더 꽤 잘 짬. 설명 넣으면 복잡한 효과도 돌아가는 GLSL로 나옴. 어쨌든 나보단 낫더라.
게임 개발자인데 셰이더가 제일 직관적이지 않음. 머릿속으로 시각·기하 데이터를 굴리는 능력이 없어서 그래픽 쪽은 늘 남 일 같음.
GLSL에도 main 있고 for 루프, if문 다 있음. 픽셀마다 불리는 건 프래그먼트 셰이더의 특성이고 프레임당 호출 횟수도 직접 정함. thebookofshaders.com 강추, 끝까지 완성 안 된 게 아쉬울 정도임.
셰이더 출력이 갈리는 훨씬 흔한 원인은 float을 가까운 정수로 클램프해서 인덱스나 텍스처 좌표로 쓸 때 생기는 off-by-one임. GPU 부동소수점 연산이 IEEE-754를 엄격히 따른다고 믿으면 안 됨.
CUDA 쪽에서 온 사람인데 이건 좀 충격임. 그래픽 하드웨어 부동소수점은 대체 무슨 표준을 따르는 건지.
HLSL 컴파일러 fxc는 버그로 악명 높음. 브라우저 렌더닥 캡처 과정을 낱낱이 설명한 부분이 좋았음. 40xx에서만 터진 게 fxc 문제라면 좀 이상한데, fxc랑 드라이버가 겹친 문제 아닐까.
작성자임. 40xx에서만 재현된 건 아니고 그게 첫 가설이었음. DirectX11 문제로 파악한 뒤 다른 윈도우 머신에서도 재현했는데, 애초에 윈도우 머신이 많지 않았음.
LLM이 수정 방법에서 역으로 추론해 Nvidia 드라이버 595.79가 fract()를 잘못 컴파일한다고 진단을 지어낸 것 같음. 근데 글 끝까지 읽어보니 조사가 더 진행됐고 드라이버 문제가 아니었음.
fract(x)가 x - floor(x)와 같은 건 x >= 0일 때만임. 이번엔 양수였지만 음수도 들어올 수 있는 자리면 후자를 써야 함. 흔히 하는 실수임.
웹GL 스택 진짜 엉망이네.
웹GL 문제 아님. 네이티브 3D 엔진도 공통 셰이딩 언어로 여러 API를 지원하면 같은 일이 터짐. 오히려 웹GL2가 write once, run everywhere에 제일 가까운 API임.