Conf42 JavaScript 2023 - Online

Migration from WebGL to WebGPU

Video size:

Abstract

We’ll explore the transition from WebGL to WebGPU, demonstrating how these changes affect game development. The talk will include practical examples and code snippets to illustrate critical differences and their implications on performance and efficiency.

Summary

  • There has been a growing interest in new graphics API that offer developers more control and flexibility. These include Vulcan, direct, these to twelve, and Metal. Together, these three APIs create a foundation for Web GPU. Learn how to prepare your projects for this transition.
  • WebGL and WebGPu are two distinct methods for managing and organizing the graphic pipeline. WebGpu encapsulates more aspects of rendering into a single object. By following these steps, developer can create optimized and efficient graphics for the web with ease.
  • With the advent of WebGL, two developers are now able to group uniform variables into buffers. Using uniform buffers, all uniform data can be transmitted to the GPU advance, leading to reduced API calls and superior performance. Transitioning from WebGL to WebGPU involves modifying both API and shaders.
  • When you migrate, you may come across an unexpected issue where u images are flipped. WebGL and WebGPu have different definitions of the depth range of the clip space. One useful way to make adjustments to a code is to ensure that the projection matrix generates outputs from zero to one.
  • The more pipelines you use, the more states which you have and the less performance it result. Render bundles are prerecorded partial reusable render passes. So transitioning to web GPU is more than just switching graphic APIs. It is a step towards the future of web graphics.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
Hello everyone, my name is Dmitrii Ivashchenko and I'm a software engineer at Mygames and this talk. We'll look at these differences between WebGL and soon to be released Web GPU and learn how to prepare your projects for this transition. Let's begin by exploring the timeline of WebGL and WebGPU, as well as the current state of the WebGPU. WebGL, similar to other technologies, has a history that dates back to the past. These desktop version of OpenGL debuted way back in 1990. These in 2011, WebgL 10 was released as the first stable version of WebGL. It was based on OpenGlas 20, which was introduced in 2007. This release allowed web developers to incorporate videographics into web browsers without requiring any extra plugins. In 2017, a new version of WebGL was introduced called WebGL 20. This version was released six years after the initial version and was based on Openjlas 30, which was released in 2012. WebGL 20 came with several improvements and new features, making it even more capable of producing powerful treaty graphics on the web. Lately, there has been a growing interest in new graphics API that offer developers more control and flexibility, and three notable APIs. Here are Vulcan, direct, these to twelve, and Metal. Together, these three APIs create a foundation for Web GPU. Vulcan, developed by the Kronos Group, is a cross platform API that provides developers with lower level access to the graphics resource hardware. This allows for high performance applications with better control over graphics hardware direct these D twelve, created by Microsoft, is exclusively for Windows and Xbox and offers developers deeper control over graphics resources. Metal, an exclusive API for Apple devices, was designed by Apple with maximum performance in mind on their hardware. WebGPU has been making significant progress lately. It's expanded to platforms like Mac, Windows and Chrome OS and available in Chrome 130 and H 130 versions. Linux and Android support is expected to be added soon. There are several engines that either support or are experimenting with WebGPU. Babylon JS fully supports WebGPU, while these JS currently has experimental support. Blake Canvas is still in development, but its future looks promising. Unity made an announcement of early and experimental web GPU support in Alpha version 2023.2 and cost creator 3.6.2 officially supports web GPU and finally construct is currently only supported in Chrome version 130 or later on Windows, macOS and Chrome OS machines. Taking this into consideration, it seems like wise move to start transitioning towards web GPU or at least preparing projects for a future transition. Let's take a closer look at some of the code pieces of the API. This won't be comprehensive, but WebGL touch on all the most important bits. The GPU adapter is a pivotal component. Adapters represent the gpus. The device can be axed. This can be even software based like Swift shader, and typically it returns one adapter at a time. However, you can specify an adapter based on certain criteria, like power performance, low power, and it provides a snapshot of the GPU specifications such as vendor Nvidia architecture, tuning, and furthermore it outlines the features and limits of the capable to the GPU device. The GPU device plays a central role. It serves as a main interface for the API. This company is responsible for creating resources such as textures, buffers and pipelines. It comes equipped with GPU queue to carry out comments, and functionally it's quite akin to WebGL rendering contexts. Webgl extensions are roughly equivalent to those in WebGPU. However, they are not universally supported across all systems. Each adapter provides a list of available extensions to activate them. They must be specified when requesting the device. There are numerical constraints on GPU capabilities. Baseline exists that every web GPU implementation must meet. The adapter indicates the actual limits of the system. By default, only these limits are active unless specified during the device request. WebGPU enables rendering to the canvas after creation. It needs configuration to link with device. Multiple canvases can share the same device, and they can be reconfigured as necessary. It supplies a texture for rendering and there are several resource types in web GPU. First, we have the GPU buffer. It defines the size and its usage. It can be used from uniforms, vertices, indices and general data. Next is the GPU texture. It designates dimensions as along with size maps, samples, formats and usage. Then there is a GPU texture view. It is a subset of a texture used for sampling or as rendering targets. You can specify its use as a cube map, array, texture, and more. The GPU sampler is also important. It dictates these textures, filtering and wrapping behavior. It's crucial to note that all these resources maintain a fixed shape post creation. However, their content can be modified. The device comes with a default GPU queue. Currently, it's the only queue available for use. However, future API versions might offer more options. This queue is essential for submitting comments to the GPU. Additionally, it features useful helper functions. These assist in writing to buffers and textures, and these are the simplest method to update the content of these resources. It's highly recommended to make use of them. To record GPU comments, start by creating GPU comment encoder from your device. This allows you to transfer data between buffers and textures. You can then initiate render or compute passes. Once you're done, it generates the CPU comment buffer. Remember, comment buffer remains inactive until they are queued, and once a comment buffer is submitted, it can be reused. Passes play a significant role in GPU operations. A render pass can utilize GPU render pipelines. It binds to vertex or index buffers, issues, draw calls, and write to one or multiple textures. On the other hand, a compute pass taps into GPU compute pipelines. It's responsible for issuing dispatch calls. It's essential to note that when a pass is active, you can't record other comment types. However, both render and compute passes have capability to set bind groups. Initially, a render pass requires you to provide details about its attachments. This includes these output designation and methods to load and save these. Here, the clearing of data types take place. It's also where you establish multi sample results, ensuring accuracy at the past. Conclusion now let's explore the main high level differences when beginning to work with GraphQL APIs, the first step is to initialize the main object for interaction. This process has some differences between WebGL and WebGPu, which can cause some issues in both systems. In WebGL, this object is called context and represent these interface for drawing on an HTML five canvas element. Obtaining this context is quite easy, but it's important to note that it's tied to a specific canvas. This means that if you need to render on multiple canvases, you will need multiple contexts. WebGPU introduces a new concept called device. The device represents a gpu abstraction that you will interact with. The initialization process is a bit more complex than in webgl, but it provides more flexibility. One advantage of this model is that one device can render on multiple canvases, or even none. This provides additional flexibility, allowing for one device to control rendering on multiple windows or contexts. Buffer management in both APIs looks the same. However, in WebGPu, once a buffer is created, its size and destination are fixed. It's also worth noting that don't bind the desired buffer. Instead, it simply passed as an argument. This approach can be found throughout the whole API for shaders. The big change is that WebGL uses GLSL and WebGPU uses a new shader language called WGSL. It's designed to cross compile nicely to the various Buchanan's preferred shader variants. Note that in WGSL, the fragment and vertex shaders can be part of the same shader as long as they have different function names. This can be very convenient. WebGL and WebGPU are two distinct methods for managing and organizing the graphic pipeline. In WebGL, the primary emphasis is on the shader program, which is combined vertex and fragment shaders to determine how vertices are transformed and how each pixel is colored. To create a program in WebGL, you need to follow simple steps. Just write and compile a shader code for source code for shaders. Attach these compiled shaders to the program and these link them. Activate the program before rendering and transmit data to activated program. That's all? Yeah. This process provides flexible control over graphics, but can be complicated and prone to errors, particularly for large and complex projects. When developing graphics for the web, it's essential to have a streamlined and efficient process, and in web GPU it's achieved through the use of a pipeline. The pipeline replaces these need for separate programs and includes not only shaders, but also other critical information that's established as state in WebGL. Creating a pipeline in WebGPU may seem more complicated initially, but it offers greater flexibility and modularity. The process involves three key steps. First, you must define the shader by writing compiling the shader source code just as you would in WebGL. Second, you create these pipeline by combining the shader and other rendering parameters into adhesive unit. Finally, you must activate the pipeline before rendering. Compared to WebGL, WebGpu encapsulates more aspects of rendering into a single object. This approach creates a more predictable and error resistant process. Instead of managing shaders and rendering states separately, everything is combined into one pipeline object. By following these steps, developer can create optimized and efficient graphics for the web with ease. Finally, we get to drawing again. WebGPU looks more complex, but that's actually in this case, we are more explicit about setting up render target, whereas WebGl there is a default one, but during the actual rendering, web GPU avoids setting up the vertex attribute layout because that's part of the pipeline. Let's now compare uniforms in WebGL and WebGPU uniforms, variables offer constant data that can be accessed by all shader instances. With basic WebGL, we can set uniform variables directly via API calls. However, this approach is straightforward, but necessities multiple API calls for each uniform variable. With these advent of WebGL, two developers are now able to group uniform variables into buffers, a highly efficient alternative to using separate uniform shaders, and by consolidating different uniforms into a larger structure. Using uniform buffers, all uniform data can be transmitted to the GPU advance, leading to reduced API calls and superior performance. In these case of webGl, two subsets of a large uniform buffers can be bound through a special API call known as bind buffer range. Similarly, in web GPU, dynamic uniform buffers offsets are utilized for the same purpose. Eleven is the passing of a list of offsets when invoking the setbind group API. This level of flexibility and optimization has made uniform buffers a valuable tool for developers looking to optimize their WebGL and WebGPU projects. A better method is available through Webgpu. Instead of supporting individual uniform variables, work is exclusively done through uniform buffers. Loading data in one large block is preferred by modern gpus instead of many small ones. Rather than recreating and rebiding small buffers each time, creating one large buffer is using different part width for different row calls can significantly increase performance, while WebGL is more imperative resetting global state with each call and striving to be as simple as possible. WebGPU aims to be more object oriented and focused on resource reuse, which leads to efficiency. Although transitioning from WebgL to WebGpu may seem difficult due to differences in methods, starting with transition to Webgl two as an immediate step can simplifies our work. Transitioning from WebGL to WebGPU involves modifying both API and shaders. The WGSL specification facilitates a seamless and intuitive transition while ensuring optimal efficiency and performance for contemporary gpus. I have an example shader for texture that uses GLSL and WGSL. GLSL serves as a connection between web gpu and these native APIs. Although WGSL appears to be more worthy than GLSL, the format is still recognizable. The following tables display a comparison between the basic and metrics data types found in GLSL and WGSL. Moving from GLSL to WGSL indicates a preference for these more stringent typing and clear specification of data sizes, resulting in better code legibility and lower chains to make mistakes. The meta declaring structures has been altered with these addition of explicit syntax for declaring fields in WGSL structures. This highlights the need for improved clarity and simplification of data structures and shaders. By altering the syntax of function in WGSL, it promotes a unified approach to declarations and return values, which results in more consistent and predictable code. If you are working with WGSL, you'll notice that some of the built in GLSL functions have different names or have been replaced. This is actually helpful because it simplifies the function names and make them more intuitive. This will make it easier for developers who are familiar with these graphic APIs to transition to WGSL if you are planning to convert your WebGL projects to WebGPu, there are a lot of tools available that can automate the process of converting GLSL to WGSL, and one such tool is Naga. It's a rust library that can be used to convert GLSL to WGSL, and best of all, it can be even used right from your browser with the help of webassembly. Now, let's talk about some differences in conventions between WebGL and WebGPu. Specifically, we will go over the disparities in textures, viewport and clip spaces. When you migrate, you may come across an unexpected issue where u images are flipped. This is a common problem for those who have moved. Implications from OpenGL to direct OpenGL and WebGL images are usually loaded so that the first pixel is on the bottom left corner. However, many developers load images starting from the top left corner, which results in flipped images. Directory D and metal systems, on the other hand, use the upper left corner as a start point for textures. The developers of WebGPU have decided to follow this practice since it's appear to be more straightforward approach for most developers. If your WebGL code selects pixels from the frame buffer, it's important to keep in mind that WebGpU uses a different coordinate system to adjust. For this, you may need to apply a straightforward y equal one minus y operation to correct these coordinates. If a developer encounters a problem where objects are disappearing or being clipped too soon, it may be due to differences in the depth domain. WebGL and Webgpu have different definitions of the depth range of the clip space, while WebGl uses a range from minus one to one, WebgpU uses a range from zero to one, which is similar to other graphics APIs like direct to D, Metal and Vulcan. This definition was made based on advantages of using the range from zero to one that were discovered while working with our graphics APIs. The projection matrix is primarily responsible for transforming a position of your model into a clip space. One useful way to make adjustments to a code is to ensure that the projection matrix generates outputs ranging from zero to one. This can be achieved by implementing certain functions available in libraries like GL matrix, such as the perspective co function. Other metrics operations also offer comparable functions that you can utilize in the event you're working with an existing matrix projection and that can be modified. Yeah, there is still a solution. You can transform the projection matrix to fit the zero to one range by applying another matrix that modifies these range before the projection matrix. This pre multiplication technique can be an effective way to adjust the range of your projection matrix to fit your needs. Now let's discuss some tips and tricks of working in this web GPU. First of all, of course, minimize the number of pipelines you use. The more pipelines you use, the more states which you have and the less performance it result. It may be not trivial depending on where your assets come from. Creating a pipeline and then immediately using it it works but don't do it. Yeah, just create functions, return immediately and it start work on a different thread when you use it. The queue execution needs to wait for pending pipeline creation to finish. This causes a significant junk. Make sure you leave some time between create and first use, or even better, use the Create pipeline async variants. The promise resolves when the pipeline is ready to use without any styling. Render bundles are prerecorded partial reusable render passes. They can contain most rendering comments, except for things like setting the viewport. They can be replayed as part of an actual render passes later on. Render bundles can be executed alongside regular render passes comments. The render pass state is reset to defaults before and after every bundle execution, primarily for reducing JavaScript overheat or drop in. So GPU performance is the same either way. So transitioning to web GPU is more than just switching graphic APIs. It is a step towards the future of web graphics, combining successful features and practices from various graphics APIs. These migrations requires thorough understanding of technical and philosophical changes, but the benefits are really significant. So thank you for your attention and I hope you enjoy the conference. See you.
...

Dmitrii Ivashchenko

Lead Unity Developer @ MY.GAMES

Dmitrii Ivashchenko's LinkedIn account Dmitrii Ivashchenko's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways