Что нового в WebGPU (Chrome 129)

François Beaufort
François Beaufort

Поддержка HDR с режимом сопоставления тонов на холсте

У веб-разработчиков не так много способов передавать HDR-контент. В основном они используют элементы <img> и <video>. Элемент <canvas> по-прежнему ограничен SDR. Чтобы создать динамический HDR-контент на холсте, необходимо закодировать его содержимое как HDR-изображение, прежде чем показывать его (пример можно посмотреть в демонстрации).

Новый параметр GPUCanvasToneMappingMode в конфигурации холста WebGPU позволяет WebGPU рисовать цвета ярче белого (#FFFFFF). Это можно делать в следующих режимах:

  • "standard": по умолчанию контент будет воспроизводиться в диапазоне SDR. В этом режиме все значения цвета в цветовом пространстве экрана ограничиваются интервалом [0, 1].

  • "extended" – разблокирует весь диапазон HDR экрана. В этом режиме "standard" соответствует [0, 1] диапазону экрана. Ограничение или проецирование выполняется для расширенного динамического диапазона экрана, но не для [0, 1].

В приведенном ниже фрагменте кода показано, как настроить холст для широкого динамического диапазона.

const adapter = await navigator.gpu.requestAdapter();
const device = await adapter.requestDevice();

const canvas = document.querySelector("canvas");
const context = canvas.getContext("webgpu");

context.configure({
  device,
  format: "rgba16float",
  toneMapping: { mode: "extended" },
});

Чтобы узнать больше о HDR с WebGPU, посмотрите пример частиц (HDR) и пример HDR с WebGPU, а также запись в chromestatus.

Ноутбук с HDR-экраном, на котором отображается яркое изображение.
Пример "Частицы" (HDR), показанный на HDR-экране.

Расширенная поддержка подгрупп

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

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

Кроме того, добавлены следующие встроенные функции подгрупп:

  • subgroupAdd(value) – возвращает сумму всех активных вызовов value в подгруппе.
  • subgroupExclusiveAdd(value): возвращает сумму всех активных вызовов values в подгруппе.
  • subgroupMul(value): возвращает произведение всех активных вызовов value в подгруппе.
  • subgroupExclusiveMul(value): возвращает исключительное произведение всех активных вызовов value в подгруппе.

  • subgroupAnd(value): возвращает результат побитового И для всех активных вызовов values в подгруппе.
  • subgroupOr(value): возвращает побитовое ИЛИ всех активных вызовов values в подгруппе.
  • subgroupXor(value) – возвращает двоичную операцию XOR для всех активных вызовов values в подгруппе.

  • subgroupMin(value) – возвращает минимальное значение всех активных вызовов values в подгруппе.
  • subgroupMax(value) – возвращает максимальное значение всех активных вызовов values в подгруппе.

  • subgroupAll(value): возвращает значение true, если value имеет значение true для всех активных вызовов в подгруппе.
  • subgroupAny(value): возвращает значение true, если value имеет значение true для любого активного вызова в подгруппе.

  • subgroupElect(): возвращает значение true, если у этого вызова самое низкое значение subgroup_invocation_id среди активных вызовов в подгруппе.
  • subgroupBroadcastFirst(value): передает value из активного вызова с наименьшим значением subgroup_invocation_id в подгруппе всем остальным активным вызовам.

  • subgroupShuffle(value, id): возвращает value из активного вызова, subgroup_invocation_id которого соответствует id.
  • subgroupShuffleXor(value, mask): возвращает value из активного вызова, subgroup_invocation_id которого соответствует subgroup_invocation_id ^ mask. Значение параметра mask должно быть динамически равномерным.
  • subgroupShuffleUp(value, delta): возвращает value из активного вызова, subgroup_invocation_id которого соответствует subgroup_invocation_id - delta.
  • subgroupShuffleDown(value, delta): возвращает value из активного вызова, subgroup_invocation_id которого соответствует subgroup_invocation_id + delta.

  • quadBroadcast(value, id) – передает value из четырех вызовов с идентификатором id. id должно быть константным выражением.
  • quadSwapX(value) – меняет местами value между вызовами в квадранте в направлении X.
  • quadSwapY(value): меняет местами value между вызовами в квадранте по оси Y.
  • quadSwapDiagonal(value): меняет местами value между вызовами в квадранте по диагонали.

Обновления на рассвете

Структура wgpu::PrimitiveState теперь напрямую включает настройку управления глубиной, поэтому отдельная структура wgpu::PrimitiveDepthClipControl больше не нужна. Чтобы узнать больше, ознакомьтесь с приведенным ниже фрагментом кода и запросом на добавление заголовков WebGPU.

// Before
wgpu::PrimitiveState primitive = {};
wgpu::PrimitiveDepthClipControl depthClipControl;
depthClipControl.unclippedDepth = true;
primitive.nextInChain = &depthClipControl;
// Now
wgpu::PrimitiveState primitive = {};
primitive.unclippedDepth = true;

Это лишь некоторые из основных изменений. Ознакомьтесь с полным списком коммитов.

Что нового в WebGPU

Список всех тем, которые были рассмотрены в серии статей Что нового в WebGPU.

Chrome 155–156

Chrome 153–154

Chrome 151–152

Chrome 149–150

Chrome 147–148

Chrome 146

Chrome 145

Chrome 144

Chrome 143

Chrome 142

Chrome 141

Chrome 140

Chrome 139

Chrome 138

Chrome 137

Chrome 136

Chrome 135

Chrome 134

Chrome 133

Chrome 132

Chrome 131

Chrome 130

Chrome 129

Chrome 128

Chrome 127

Chrome 126

Chrome 125

Chrome 124

Chrome 123

Chrome 122

Chrome 121

Chrome 120

Chrome 119

Chrome 118

Chrome 117

Chrome 116

Chrome 115

Chrome 114

Chrome 113