WebGPU

После выхода Vulkan в 2015 году мы рассуждали о том, сможет ли новый графический API полностью заменить OpenGL, и сделали вывод, что в обозримом будущем этого не произойдет. Масса запутанного boilerplate-кода, непривычные для прикладной разработки концепции, множество вариантов неопределенного поведения, отсутствие нативной поддержки на macOS – все это делает Vulkan менее привлекательным выбором для написания типовых приложений. Vulkan более пригоден для машин, а не людей – он используется в бэкендах некоторых графических движков, но писать на нем напрямую слишком сложно и дорого. Отдельно стоял вопрос о судьбе Vulkan в браузерах – сейчас уже ясно, что WebVulkan не появится. Ну а после новости о том, что Apple прекращает поддержку OpenGL на macOS в пользу Metal, всем стало очевидно, что нужен новый абстрактный графический API, адаптированный под современные видеокарты, но при этом более дружественный к пользователю, чем Vulkan или Direct3D 12 – и, конечно, способный работать на всех платформах.

Стать таким API имеет все шансы WebGPU - новый веб-стандарт, предложенный W3C, основное применение которого – высокопроизводительный рендеринг и параллельные вычисления на GPU. В отличие от WebGL, WebGPU не является портом OpenGL или какого-то иного нативного API – по уровню абстракции он значительно выше Vulkan, но ниже OpenGL.

WebGPU создается, в первую очередь, для браузеров, и на момент написания этой статьи доступен лишь в Safari Technology Preview. Тем не менее, попробовать новый API вы можете уже сейчас в его нативной реализации в рамках проекта wgpu. Для сборки нужен тулчейн языка Rust, скомпилированную же библиотеку можно использовать в любом C-совместимом языке. wgpu работает на Windows, Linux и macOS, в качестве бэкенда используя Vulkan, Metal или Direct3D 12.

Особенности

Основным принципом WebGPU является сокращение вызовов API при изменении состояния конвейера и привязки ресурсов. Параметры конвейера создаются и валидируются заранее, что значительно снижает покадровую нагрузку. Заметна тенденция к сокращению числа функций в пользу больших и разветвленных инициализирующих структур, которые в терминологии WebGPU называются дескрипторами.

Важнейшая концепция WebGPU – группы биндинга (bind groups), которые похожи на descriptor sets в Vulkan. Это особые контейнеры, предназначенные для привязки данных к шейдерам – о них удобно думать как о наборах uniform-параметров. Вместо того, чтобы явно передавать значения каждому параметру, как это делалось в классическом OpenGL (до появления UBO), все данные передаются едиными буферами, что значительно быстрее и проще. Кроме того, можно заранее создать несколько готовых групп биндинга с разными данными, а потом просто переключаться между ними, что также очень эффективно. WebGPU поддерживает одновременную привязку четырех групп биндинга, их рекомендуется использовать для разделения параметров, обновляющихся с разной частотой (например, покадрово, для каждого материала и для каждого объекта).

Еще одной особенностью API является повсеместное использование буферов для обмена данными с приложением. WebGPU использует неструктурированные байтовые буферы, отображаемые в пользовательскую память, так что на стороне API даже не требуется уточнять типы uniform-данных – они задаются только в шейдере (но, разумеется, нужно следить за тем, чтобы структура в шейдере совпадала со структурой uniform-буфера). Также создание буфера необходимо для передачи данных в текстуру и для хранения вершинных атрибутов и индексов. Преимуществом такого подхода является единообразие – для хранения любых данных используется один и тот же тип буферного объекта (в отличие от того же OpenGL, где есть множество разных несовместимых типов буферов).

Приложение WebGPU выглядит как предельно сжатый аналог приложения на Vulkan – инициализация устройства, определение лэйаутов групп биндинга, создание буферов и текстур, инициализация конвейера, свапчейна и аттачментов. В главном цикле – обновление uniform-буферов, установка конвейера, группы биндинга, вершинного буфера – и, наконец, отрисовка. Все вызовы отрисовки (как и другие команды видеокарте) не выполняются немедленно, а заносятся в специальный command encoder, который затем отправляется в очередь на выполнение – таким образом, можно вызовы отрисовки определить заранее, до начала цикла (если, конечно, логика программы не предполагает изменений порядка рисования объектов).

Шейдерный язык WebGPU черновиком стандарта пока не определен, но существующие реализации используют SPIR-V, благодаря чему можно легко использовать готовые шейдеры на GLSL 4.5. Как и Vulkan, WebGPU не оперирует символьными именами и требует явного указания layout-спецификаторов set, binding и location для входных и выходных данных. Вероятнее всего, стандарт будет включать некий язык на основе HLSL – к примеру, Apple уже предложила Web High Level Shading Language (WHLSL).

Чего не будет в WebGPU

Серебряной пули не существует. Будучи переносимым, WebGPU неизбежно окажется более ограниченным, чем Direct3D и OpenGL. Вот несколько важных фич, которые, по всей видимости, не войдут в ядро стандарта:

  • transform feedback
  • occlusion queries
  • тесселяция
  • сжатие текстур (только как расширение)

Итог

WebGPU – не только для более быстрых браузерных игр и вычислений. Думаю, не будет преувеличением сказать, что нативные реализации WebGPU в будущем начнут частично занимать нишу десктопного OpenGL, а в совокупности с WebAssembly позволят писать единый код для нативных платформ и веба. Это означает, что графические приложения (3D-пакеты, графические и видеоредакторы, CAD-системы и пр.) можно будет запускать в браузере на всех платформах. WebGPU – это еще один шаг к стандартизации графических API, столь же значительный, каким в свое время стал OpenGL.

Если у вас уже есть готовая отлаженная кодовая база под OpenGL или Direct3D, то задумываться о полном переходе пока, конечно, рановато – стандарт еще не устоялся, реализации в активной разработке, толковой документации нет, и многое сказанное в этой статье может утратить актуальность. Но разве это может остановить нас, энтузиастов? :) WebGPU может стать отличным выбором для тех, кто испытывает трудности с изучением Vulkan – ведь это и есть то самое «отсутствующее звено» между современными и классическими API, которое должно было рано или поздно появиться.


Copyright © 2008-2021 Тимур Гафаров и соавторы. Доступно по СС BY-NC-SA 3.0.