Como desenvolvedor WebGL, você pode ficar intimidado e animado para começar a usar a WebGPU, a sucessora do WebGL que traz os avanços das APIs de gráficos modernas para a Web.
É reconfortante saber que o WebGL e a WebGPU compartilham muitos conceitos básicos. As duas APIs permitem executar pequenos programas chamados shaders na GPU. O WebGL é compatível com sombreadores de vértice e fragmento, enquanto o WebGPU também é compatível com sombreadores de computação. O WebGL usa a linguagem de sombreamento OpenGL (GLSL), enquanto o WebGPU usa a linguagem de sombreamento WebGPU (WGSL). Embora os dois idiomas sejam diferentes, os conceitos subjacentes são basicamente os mesmos.
Com isso em mente, este artigo destaca algumas diferenças entre WebGL e WebGPU para ajudar você a começar.
Estado global
O WebGL tem muito estado global. Algumas configurações se aplicam a todas as operações de renderização, como quais texturas e buffers estão vinculados. Você define esse estado global chamando várias funções de API, e ele permanece em vigor até que você o mude. O estado global no WebGL é uma grande fonte de erros, já que é fácil esquecer de mudar uma configuração global. Além disso, o estado global dificulta o compartilhamento de código, já que os desenvolvedores precisam ter cuidado para não mudar acidentalmente o estado global de uma forma que afete outras partes do código.
A WebGPU é uma API sem estado e não mantém um estado global. Em vez disso, ele usa o conceito de um pipeline para encapsular todo o estado de renderização que era global no WebGL. Um pipeline contém informações como quais atributos, topologia e fusão usar. Um pipeline é imutável. Se você quiser mudar algumas configurações, crie outro pipeline. A WebGPU também usa codificadores de comando para agrupar comandos e executá-los na ordem em que foram gravados. Isso é útil no mapeamento de sombras, por exemplo, em que, em uma única passagem pelos objetos, o aplicativo pode gravar vários fluxos de comandos, um para cada mapa de sombras da luz.
Em resumo, como o modelo de estado global do WebGL dificultava e tornava frágil a criação de bibliotecas e aplicativos robustos e combináveis, o WebGPU reduziu significativamente a quantidade de estado que os desenvolvedores precisavam acompanhar ao enviar comandos para a GPU.
Não sincronizar mais
Em GPUs, geralmente é ineficiente enviar comandos e aguardar de forma síncrona, já que isso pode limpar o pipeline e causar bolhas. Isso é especialmente verdadeiro no WebGPU e no WebGL, que usam uma arquitetura multiprocesso com o driver de GPU sendo executado em um processo separado do JavaScript.
No WebGL, por exemplo, chamar gl.getError()
requer um IPC síncrono do processo JavaScript para o processo da GPU e vice-versa. Isso pode causar um estouro no lado da CPU à medida que os dois processos se comunicam.
Para evitar essas bolhas, o WebGPU foi projetado para ser completamente assíncrono. O modelo de erro e todas as outras operações acontecem de forma assíncrona. Por exemplo, ao criar uma textura, a operação parece ser bem-sucedida imediatamente, mesmo que a textura seja um erro. Só é possível descobrir o erro de forma assíncrona. Esse design mantém a comunicação entre processos sem bolhas e oferece aos aplicativos um desempenho confiável.
Sombreadores de computação
Os sombreadores de computação são programas executados na GPU para realizar cálculos de uso geral. Elas estão disponíveis apenas na WebGPU, não na WebGL.
Ao contrário dos shaders de vértice e de fragmento, eles não se limitam ao processamento de gráficos e podem ser usados em uma ampla variedade de tarefas, como machine learning, simulação física e computação científica. Os sombreadores de computação são executados em paralelo por centenas ou até milhares de linhas de execução, o que os torna muito eficientes para processar grandes conjuntos de dados. Saiba mais sobre computação de GPU e mais detalhes neste artigo extenso sobre WebGPU.
Processamento de frames de vídeo
O processamento de frames de vídeo usando JavaScript e WebAssembly tem algumas desvantagens: o custo de copiar os dados da memória da GPU para a memória da CPU e o paralelismo limitado que pode ser alcançado com workers e linhas de execução da CPU. A WebGPU não tem essas limitações, o que a torna uma ótima opção para processar frames de vídeo graças à integração com a API WebCodecs.
O snippet de código a seguir mostra como importar um VideoFrame como uma textura externa no WebGPU e processá-lo. Confira esta demonstração.
// Init WebGPU device and pipeline...
// Configure canvas context...
// Feed camera stream to video...
(function render() {
const videoFrame = new VideoFrame(video);
applyFilter(videoFrame);
requestAnimationFrame(render);
})();
function applyFilter(videoFrame) {
const texture = device.importExternalTexture({ source: videoFrame });
const bindgroup = device.createBindGroup({
layout: pipeline.getBindGroupLayout(0),
entries: [{ binding: 0, resource: texture }],
});
// Finally, submit commands to GPU
}
Portabilidade de aplicativos por padrão
A WebGPU força você a solicitar limits
. Por padrão, requestDevice()
retorna um GPUDevice que pode não corresponder aos recursos de hardware do dispositivo físico, mas sim um denominador comum razoável e mais baixo de todas as GPUs. Ao exigir que os desenvolvedores solicitem limites de dispositivos, a WebGPU garante que os aplicativos sejam executados no maior número possível de dispositivos.
Manuseio de telas
O WebGL gerencia automaticamente a tela depois que você cria um contexto do WebGL e fornece atributos de contexto, como alfa, antialiasing, colorSpace, profundidade, preserveDrawingBuffer ou estêncil.
Por outro lado, o WebGPU exige que você gerencie a tela por conta própria. Por exemplo, para conseguir antialiasing no WebGPU, você criaria uma textura multiamostra e renderizaria nela. Em seguida, você resolveria a textura multiamostra em uma textura regular e a desenharia na tela. Esse gerenciamento manual permite gerar saída para quantas telas você quiser de um único objeto GPUDevice. Em contraste, a WebGL só pode criar um contexto por tela.
Confira a demonstração de várias telas da WebGPU.
Os navegadores têm um limite para o número de telas WebGL por página. No momento da redação deste artigo, o Chrome e o Safari só podem usar até 16 telas WebGL simultaneamente. O Firefox pode criar até 200 delas. Por outro lado, não há limite para o número de telas do WebGPU por página.

Mensagens de erro úteis
O WebGPU fornece uma pilha de chamadas para cada mensagem retornada da API. Isso significa que você pode ver rapidamente onde o erro ocorreu no código, o que é útil para depurar e corrigir erros.
Além de fornecer uma pilha de chamadas, as mensagens de erro da WebGPU também são fáceis de entender e acionáveis. As mensagens de erro geralmente incluem uma descrição do erro e sugestões de como corrigi-lo.
A WebGPU também permite fornecer um label
personalizado para cada objeto da WebGPU. Esse rótulo é usado pelo navegador em mensagens de GPUError, avisos do console e ferramentas para desenvolvedores do navegador.
De nomes a índices
No WebGL, muitas coisas são conectadas por nomes. Por exemplo, é possível declarar uma variável uniforme chamada myUniform
em GLSL e receber a localização dela usando gl.getUniformLocation(program, 'myUniform')
. Isso é útil porque você recebe um erro se digitar errado o nome da variável uniforme.
Por outro lado, no WebGPU, tudo é totalmente conectado por índice ou deslocamento de byte (geralmente chamado de localização). É sua responsabilidade manter os locais do código em WGSL e JavaScript sincronizados.
Geração de mipmap
No WebGL, é possível criar um mip do nível 0 de uma textura e chamar gl.generateMipmap()
. O WebGL vai gerar todos os outros níveis de mip para você.
No WebGPU, você precisa gerar mipmaps por conta própria. Não há uma função integrada para fazer isso. Consulte a discussão sobre a especificação para saber mais sobre a decisão. Você pode usar bibliotecas úteis, como webgpu-utils, para gerar mipmaps ou aprender a fazer isso sozinho.
Buffers e texturas de armazenamento
Os buffers uniformes são compatíveis com WebGL e WebGPU e permitem transmitir parâmetros constantes de tamanho limitado para shaders. Os buffers de armazenamento, que se parecem muito com os buffers uniformes, são compatíveis apenas com o WebGPU e são mais poderosos e flexíveis do que os buffers uniformes.
Os dados de buffers de armazenamento transmitidos para sombreadores podem ser muito maiores do que os buffers uniformes. Embora a especificação diga que as vinculações de buffers uniformes podem ter até 64 KB (consulte
maxUniformBufferBindingSize
) , o tamanho máximo de uma vinculação de buffer de armazenamento é de pelo menos 128 MB no WebGPU (consultemaxStorageBufferBindingSize
).Os buffers de armazenamento podem ser gravados e oferecem suporte a algumas operações atômicas, enquanto os buffers uniformes são apenas de leitura. Isso permite a implementação de novas classes de algoritmos.
As vinculações de buffers de armazenamento oferecem suporte a matrizes dimensionadas em tempo de execução para algoritmos mais flexíveis, enquanto os tamanhos de matrizes de buffers uniformes precisam ser fornecidos no shader.
As texturas de armazenamento só são compatíveis com WebGPU e são para texturas o que os buffers de armazenamento são para buffers uniformes. Elas são mais flexíveis do que as texturas comuns, oferecendo suporte a gravações de acesso aleatório (e leituras também no futuro).
Mudanças de buffer e textura
No WebGL, é possível criar um buffer ou uma textura e mudar o tamanho deles a qualquer momento com gl.bufferData()
e gl.texImage2D()
, respectivamente.
No WebGPU, buffers e texturas são imutáveis. Isso significa que não é possível mudar o tamanho, o uso ou o formato depois da criação. Só é possível mudar o conteúdo delas.
Diferenças nas convenções de espaço
No WebGL, o intervalo do espaço de recorte Z é de -1 a 1. No WebGPU, o intervalo do espaço de corte Z é de 0 a 1. Isso significa que objetos com um valor z de 0 são os mais próximos da câmera, enquanto objetos com um valor z de 1 são os mais distantes.
O WebGL usa a convenção do OpenGL, em que o eixo Y é para cima e o eixo Z é em direção ao espectador. O WebGPU usa a convenção Metal, em que o eixo Y é para baixo e o eixo Z sai da tela. A direção do eixo Y é para baixo na coordenada do framebuffer, da janela de visualização e do fragmento/pixel. No espaço de recorte, a direção do eixo Y ainda é para cima, como no WebGL.
Agradecimentos
Agradecemos a Corentin Wallez, Gregg Tavares, Stephen White, Ken Russell e Rachel Andrew por revisarem este artigo.
Também recomendo WebGPUFundamentals.org para uma análise detalhada das diferenças entre WebGPU e WebGL.