Компьютерная графика
Шейдеры: GLSL, HLSL, WGSL
Как GPU знает, каким цветом покрасить каждый пиксель персонажа в игре? Как Stable Diffusion генерирует изображения прямо на видеокарте? Ответ - шейдеры: крошечные программы, исполняемые параллельно на тысячах ядер GPU. Эта тема - сердце GPU-программирования.
- **PBR в играх (Unreal, Unity):** fragment shader с моделью Disney BRDF - каждый пиксель считает уравнение рассеивания света в реальном времени
- **Stable Diffusion / DLSS:** compute shaders - нейросети работают как матричные операции на GPU без graphics pipeline
- **Shader compilation stutter:** причина фризов в новых играх - драйвер компилирует SPIR-V в нативный код при первом использовании pipeline
- **WebGPU и WGSL:** новый стандарт браузерной графики, позволяющий запускать сложные шейдеры в браузере с нативной производительностью
Vertex Shader
Каждый кадр в Cyberpunk 2077 содержит миллионы вершин. GPU не рисует их по одной вручную - вместо этого запускает крошечную программу (vertex shader) параллельно для каждой вершины. Именно шейдеры позволяют GPU рисовать 10 миллионов треугольников в секунду.
**Vertex shader** - первый программируемый этап GPU pipeline. Он получает данные одной вершины (позиция, нормаль, UV-координаты) и обязан вернуть её положение в clip space. Между этим он может делать что угодно: деформировать меш, анимировать персонажа, передавать данные дальше в fragment shader.
**Главное правило:** vertex shader запускается ровно по одному разу на каждую вершину, и все они выполняются параллельно. Нет никакой возможности обратиться к соседней вершине из шейдера - только к данным своей вершины и uniform-буферам.
Что обязан вернуть vertex shader в обязательном порядке?
Fragment Shader и PBR
После растеризации треугольника GPU знает, какие пиксели он занимает. Для каждого такого пикселя (fragment) запускается fragment shader - именно здесь определяется итоговый цвет. Все фотореалистичные эффекты в современных играх - отражения, тени, металлический блеск - это код в fragment shader.
**PBR (Physically Based Rendering)** - стандарт в индустрии с 2013 года (Disney BRDF). Идея: цвет пикселя - это результат физически корректного уравнения рассеивания света. Два ключевых параметра материала: **metallic** (металл/диэлектрик) и **roughness** (гладкость поверхности).
**GLSL vs HLSL vs WGSL:** GLSL - язык OpenGL и Vulkan (в SPIR-V компилируется). HLSL - язык DirectX, де-факто стандарт для AAA-игр на Windows. WGSL - новый язык WebGPU, безопасный по типам, запускается в браузере. Синтаксис похожий, семантика почти идентична.
В PBR материале параметр metallic = 1.0 означает, что поверхность:
Compute Shader
Stable Diffusion генерирует изображение 512x512 за секунды прямо на вашей видеокарте. Никаких вершин, никаких треугольников - только математика над тензорами. Это возможно благодаря compute shaders: GPU-программам без привязки к graphics pipeline.
**Compute shader** запускается в виде трёхмерной сетки рабочих групп (workgroups). Каждая группа состоит из потоков (invocations), которые разделяют быструю shared memory и могут синхронизироваться через барьеры. Именно эта модель делает GPU мощным для GPGPU-задач: физика, ray tracing, machine learning.
**Применения compute shaders в играх:** генерация частиц, постобработка (bloom, SSAO, TAA), подготовка draw calls (GPU culling), ray tracing (BVH traversal), симуляция ткани и жидкостей. Современные игры выполняют сотни compute dispatches за кадр.
Что такое `barrier()` в compute shader и зачем он нужен?
SPIR-V и компиляция шейдеров
До 2015 года каждый GPU-вендор (NVIDIA, AMD, Intel) имел собственный компилятор шейдеров в драйвере. Разработчики жаловались: один и тот же GLSL код компилировался по-разному, давая разный результат и разную производительность. Khronos решил проблему радикально: ввёл **SPIR-V** - промежуточное представление, которое компилятор вендора получает вместо исходного GLSL.
**SPIR-V** (Standard Portable Intermediate Representation) - бинарный байткод для шейдеров, аналог LLVM IR для CPU. Разработчик компилирует GLSL/HLSL/WGSL в SPIR-V заранее (при сборке игры), а драйвер уже переводит SPIR-V в нативные инструкции конкретного GPU. Это разделение ответственности убирает недетерминизм из драйверной компиляции.
**Pipeline cache:** даже компиляция SPIR-V -> нативный код занимает время (причина «shader compilation stutter» в играх). Vulkan позволяет кешировать результат через VkPipelineCache и сохранять на диск. Современные игры (God of War, Spider-Man) делают этот прогрев в фоне при первом запуске.
SPIR-V - это финальный машинный код, который сразу исполняется на GPU
SPIR-V - промежуточное представление. Драйвер GPU компилирует его в нативный ISA (PTX для NVIDIA, GCN для AMD) в момент создания pipeline.
GPU у разных вендоров имеют разные системы команд (ISA). Было бы невозможно создать единый «нативный» формат. SPIR-V - это стандартный контракт между разработчиком и драйвером.
Зачем нужен SPIR-V, если Vulkan уже принимает GLSL напрямую?
Шейдеры: GLSL, HLSL, WGSL
- Vertex shader запускается на каждую вершину параллельно - обязан вернуть gl_Position в clip space
- Fragment shader определяет цвет каждого пикселя - здесь живёт PBR (metallic/roughness модель)
- Compute shader - GPU-вычисления без graphics pipeline: ML, физика, постобработка
- GLSL (OpenGL/Vulkan), HLSL (DirectX), WGSL (WebGPU) - разный синтаксис, одна модель
- SPIR-V - промежуточное представление: шейдер компилируется в .spv при сборке, драйвер переводит в ISA при runtime
- Pipeline cache решает проблему shader stutter - результат компиляции SPIR-V сохраняется на диск
Связанные темы
Шейдеры - программируемая часть GPU pipeline. Чтобы запустить их в Vulkan, нужно понять pipeline objects и memory model.
- GPU Pipeline и растеризация — Шейдеры встроены в pipeline на фиксированных стадиях
- Vulkan и Modern Graphics API — Как загрузить SPIR-V шейдеры и создать pipeline в Vulkan
Вопросы для размышления
- Почему vertex shader не может обратиться к данным соседних вершин, и как это ограничение обходят при skin animation?
- В чём принципиальная разница между fragment shader и compute shader для постобработки изображения?
- Если SPIR-V решает проблему вендорных компиляторов, почему 'shader compilation stutter' всё ещё существует в играх?