WebGPU
      • Sharing URL Link copied
      • /edit
      • View mode
        • Edit mode
        • View mode
        • Book mode
        • Slide mode
        Edit mode View mode Book mode Slide mode
      • Customize slides
      • Note Permission
      • Read
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Write
        • Owners
        • Signed-in users
        • Everyone
        Owners Signed-in users Everyone
      • Engagement control Commenting, Suggest edit, Emoji Reply
    • Invite by email
      Invitee

      This note has no invitees

    • Publish Note

      Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

      Your note will be visible on your profile and discoverable by anyone.
      Your note is now live.
      This note is visible on your profile and discoverable online.
      Everyone on the web can find and read all notes of this public team.
      See published notes
      Unpublish note
      Please check the box to agree to the Community Guidelines.
      View profile
    • Commenting
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
      • Everyone
    • Suggest edit
      Permission
      Disabled Forbidden Owners Signed-in users Everyone
    • Enable
    • Permission
      • Forbidden
      • Owners
      • Signed-in users
    • Emoji Reply
    • Enable
    • Versions and GitHub Sync
    • Note settings
    • Note Insights
    • Engagement control
    • Transfer ownership
    • Delete this note
    • Insert from template
    • Import from
      • Dropbox
      • Google Drive
      • Gist
      • Clipboard
    • Export to
      • Dropbox
      • Google Drive
      • Gist
    • Download
      • Markdown
      • HTML
      • Raw HTML
Menu Note settings Versions and GitHub Sync Note Insights Sharing URL Help
Menu
Options
Engagement control Transfer ownership Delete this note
Import from
Dropbox Google Drive Gist Clipboard
Export to
Dropbox Google Drive Gist
Download
Markdown HTML Raw HTML
Back
Sharing URL Link copied
/edit
View mode
  • Edit mode
  • View mode
  • Book mode
  • Slide mode
Edit mode View mode Book mode Slide mode
Customize slides
Note Permission
Read
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Write
Owners
  • Owners
  • Signed-in users
  • Everyone
Owners Signed-in users Everyone
Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       owned this note    owned this note      
    Published Linked with GitHub
    Subscribed
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    Subscribe
    # PSA for Chromium / Dawn WebGPU API updates 2021-04-07 Chromium's WebGPU implementation and Dawn's API try to closely follow changes to the WebGPU specification. When the WebGPU IDL changes, Chromium and Dawn will try to support both the deprecated and the new version of the IDL at the same time so prototypes can be updated. In JavaScript, uses of the deprecated path will result in a console warning, while when using Dawn directly, the deprecated path will print a warning to stderr. Note that all changes to Dawn's API make it closer to [`webgpu.h`](https://github.com/webgpu-native/webgpu-headers/blob/master/webgpu.h) that we hope will allow applications to target both [Dawn](https://dawn.googlesource.com/dawn), and [wgpu](https://github.com/gfx-rs/wgpu/) in native before being compiled in WASM. Emscripten will also be updated from the "old" to the "new" API but won't have the smooth transition since developers control which version of emscripten they use. A couple weeks after an update like this one, the "old" version will be removed. This means that the "old" version of the items below will start being removed from Chromium/Dawn starting on 2021-04-21. Previous PSAs: - [PSA for Chromium / Dawn WebGPU API updates 2020-10-19](https://hackmd.io/uH1MI9cnQBG9GGOZG20COw) - [PSA for Chromium / Dawn WebGPU API updates 2020-07-28](https://hackmd.io/szV68rOVQ56GYzPJMBko8A) - [PSA for Chromium / Dawn WebGPU API updates 2020-04-28](https://hackmd.io/Et7xlhoaThmi8dEX_s-xSw) ## WGSL improvements The WGSL specification has made a lot of progress with most of the builtin functions specified and nice ergonomics improvements (with more likely coming). The implementation in Chromium is still evolving rapidly to catch up with the specification so we aren't offering a gradual deprecation like for the WebGPU API yet. Around the last PSA, WGSL code looked like this: ```rust= type MyData = [[block]] struct { [[offset 0]] modelViewProjectionMatrix : mat4x4<f32>; [[offset 64]] positionOffset : vec4<f32>; }; [[binding 0, set 0]] var<uniform> u : MyData; [[location 0]] var<in> position : vec4<f32>;] [[builtin position]] var<out> Position : vec4<f32>; [[location 0]] var<out> FragUV : vec2<f32>; fn main() -> void { const fixedPosition : vec4<f32> = position + u.positionOffset; FragUV = position.xy * 0.5; Position = u.modelViewProjectionMatrix * fixedPosition; return; } entry_point vertex as "main" = main; ``` It now looks like this: ```rust= [[block]] struct MyData { modelViewProjectionMatrix : mat4x4<f32>; positionOffset : vec4<f32>; }; [[group(0), binding(0)]] var<uniform> u : MyData; struct Outputs { [[builtin(position)]] position : vec4<f32>; [[location(0)]] fragUV: vec2<f32>; }; [[stage(vertex)]] fn main([[location(0)]] position : vec2<f32>) -> Outputs { let fixedPosition = position + u.positionOffset; var outputs : Outputs; outputs.fragUV = position.xy * 0.5; outputs.position = u.modelViewProjectionMatrix * fixedPosition; return outputs; } ``` ## Breaking changes There are a lot of breaking changes this time, and a couple of them might require large changes (`GPUBindGroupLayoutEntry` and `GPURenderPipelineDescriptor`). The changes come both from feedback of WebGPU early adopters as well as some more focus on ergonomics from the WebGPU group. The group looked at most of the API to see if changes are needed and no breaking changes are in the pipeline. That's why we are hopeful that there will be fewer breaking changed in the future. ### `OUTPUT_ATTACHMENT` -> `RENDER_ATTACHMENT` WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1168) Contrary to Vulkan, WebGPU doesn't have "input attachment" so there is not symmetry needed with `OUTPUT_ATTACHMENT`. For clarity it is renamed to `RENDER_ATTACHMENT`. In JavaScript the following changes are needed: ```diff= const texture = device.createTexture({ dimension: '2d', size: [4, 4], format: 'rgba8unorm', - usage: GPUTextureUsage.OUTPUT_ATTACHMENT, + usage: GPUTextureUsage.RENDER_ATTACHMENT, }); ``` Likewise when using Dawn’s API, changes are needed: ```diff= wgpu::TextureDescriptor desc; desc.dimension = wgpu::TextureDimension::e2D; desc.size = {4, 4}; desc.format = wgpu::TextureFormat::RGBA8Unorm; -desc.usage = wgpu::TextureUsage::OutputAttachment; +desc.usage = wgpu::TextureUsage::RenderAttachment; wgpu::Texture texture = device.CreateTexture(&desc); ``` ### `GPUBindGroupLayoutEntry` changes Main WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1223) In order to keep the complexity of `BindGroupLayoutEntry` from exploding as more capabilities are added, it was refactored to isolate the properties needed for each type of binding. An example of the change needed in JavaScript: ```diff= const bindGroupLayout = device.createBindGroupLayout({ entries: [{ binding: 0, visibility: GPUShaderStage.VERTEX, - type: 'uniform-buffer' + buffer: {} }, { binding: 1, visibility: GPUShaderStage.FRAGMENT, - type: 'sampler' + sampler: {} }, { binding: 2, visibility: GPUShaderStage.FRAGMENT, - type: 'sampled-texture' + texture: {} }, { binding: 3, visibility: GPUShaderStage.COMPUTE, - type: 'storage-buffer' + buffer: { type: 'storage' } }, { binding: 4, visibility: GPUShaderStage.FRAGMENT, - type: 'sampled-texture' - viewDimension: 'cube' + texture: { viewDimension: 'cube' } }] }); ``` An example of the changes needed when using Dawn's API (note that at least one of `buffer.type`, `sampler.type`, `texture.sampleType` or `storageTexture.access+format` must be set): ```diff= wgpu::BindGroupLayoutEntry entries[5]; entries[0].binding = 0; entries[0].visibility = wgpu::ShaderStage::Vertex; -entries[0].bindingType = wgpu::BindingType::UniformBuffer; +entries[0].buffer.type = wgpu::BufferBindingType::Uniform; entries[1].binding = 1; entries[1].visibility = wgpu::ShaderStage::Fragment; -entries[1].bindingType = wgpu::BindingType::Sampler; +entries[1].sampler.type = wgpu::SamplerBindingType::Filtering; entries[2].binding = 2; entries[2].visibility = wgpu::ShaderStage::Fragment; -entries[2].bindingType = wgpu::BindingType::SampledTexture; +entries[2].texture.sampleType = wgpu::TextureSampleType::Float; entries[3].binding = 3; entries[3].visibility = wgpu::ShaderStage::Compute; -entries[3].bindingType = wgpu::BindingType::StorageBuffer; +entries[0].buffer.type = wgpu::BufferBindingType::Storage; entries[4].binding = 4; entries[4].visibility = wgpu::ShaderStage::Compute; -entries[4].bindingType = wgpu::BindingType::StorageTexture; -entries[4].format = wgpu::TextureFormat::RGBA8Unorm; +entries[4].storageTexture.access = wgpu::StorageTextureAccess::ReadOnly; +entries[4].storageTexture.format = wgpu::TextureFormat::RGBA8Unorm; ``` ### Render pipeline changes Main WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1352) The GPURenderPipelineDescriptor format has been re-organized for clarity. See the table below for converting deprecated GPURenderPipelineDescriptors to the new format. [Dawn Tracking Bug](https://bugs.chromium.org/p/dawn/issues/detail?id=642) | Old key | New Key | |------------------------------------------|--------------------------------------| | `vertexStage.module` | `vertex.module` | | `vertexStage.entryPoint` | `vertex.entryPoint` | | `vertexState.vertexBuffers` | `vertex.buffers` | | `vertexState.indexFormat` | `primitive.stripIndexFormat` | | `primitiveTopology` | `primitive.topology` | | `rasterizationState.frontFace` | `primitive.frontFace` | | `rasterizationState.cullMode` | `primitive.cullMode` | | `rasterizationState.depthBias` | `depthStencil.depthBias` | | `rasterizationState.depthBiasSlopeScale` | `depthStencil.depthBiasSlopeScale` | | `rasterizationState.depthBiasClamp` | `depthStencil.depthBiasClamp` | | `depthStencilState.format` | `depthStencil.format` | | `depthStencilState.depthWriteEnabled` | `depthStencil.depthWriteEnabled` | | `depthStencilState.depthCompare` | `depthStencil.depthCompare` | | `depthStencilState.stencilFront` | `depthStencil.stencilFront` | | `depthStencilState.stencilBack` | `depthStencil.stencilBack` | | `depthStencilState.stencilReadMask` | `depthStencil.stencilReadMask` | | `depthStencilState.stencilWriteMask` | `depthStencil.stencilWriteMask` | | `sampleCount` | `multisample.count` | | `sampleMask` | `multisample.mask` | | `alphaToCoverageEnabled` | `multisample.alphaToCoverageEnabled` | | `fragmentStage.module` | `fragment.module` | | `fragmentStage.entryPoint` | `fragment.entryPoint` | | `colorStates[i].format` | `fragment.targets[i].format` | | `colorStates[i].writeMask` | `fragment.targets[i].writeMask` | | `colorStates[i].colorBlend` | `fragment.targets[i].blend.color` | | `colorStates[i].alphaBlend` | `fragment.targets[i].blend.alpha` | Note that Chromium/Dawn will now validate that `fragment.targets[i].blend` is `undefined` / `nullptr` if `fragment.targets[i].format` is a non-filterable format (i.e. integer or float32). Some types part of the `GPUPipelineDescriptor` have been renamed. No changes are needed in JavaScript, but the following updates are required when using Dawn's API: | Previous type | New type | |-|-| |`wgpu::BlendDescriptor`|`wgpu::BlendComponent`| |`wgpu::StencilFaceStateDescriptor`|`wgpu::StencilFaceState`| |`wgpu::VertexAttributeDescriptor`|`wgpu::VertexAttributes`| |`wgpu::VertexBufferLayoutDescriptor`|`wgpu::VertexBufferLayout`| Also when using Dawn's API the new render pipeline descriptor is called `wgpu::RenderPipelineDescriptor2` and passed to `wgpu::Device::CreateRenderPipeline2`. Of course this is only temporary and after the deprecation period, the "2" variant will be deprecated in favor of the old names (but with the new structure). ### `GPUDevice.defaultQueue` -> `GPUDevice.queue` WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1367) Since WebGPU does not yet support multiple queues, and many applications will only ever need one queue, the `GPUDevice`'s default queue has been renamed to simply `queue` to reduce the amount of typing needed. An example of the change needed in JavaScript: ```diff= -device.defaultQueue.submit([commandEncoder.finish()]); +device.queue.submit([commandEncoder.finish()]); ``` Likewise when using Dawn’s API, changes are needed: ```diff= -wgpu::Queue queue = device.GetDefaultQueue(); +wgpu::Queue queue = device.GetQueue(); ``` ### `GPUFence` -> `GPUQueue.onSubmittedWorkDone` WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1217) Since WebGPU does not yet support multiple queues, the `GPUFence` could only be used to watch the completion of work submitted to queues. Because of this extremely limited use, they are replaced with `GPUQueue.onSubmittedWorkDone` which is a `Promise` that resolves when the queue is done processing work submitted until this point. In JavaScript the following changes are needed: ```diff= -const fence = queue.createFence(); -queue.signal(fence, 1); -await fence.onCompletion(1); +await queue.onSubmittedWorkDone(); ``` Likewise when using Dawn’s API, changes are needed: ```diff= -wgpu::Fence fence = queue.CreateFence(); -queue.Signal(fence, 1); -fence.OnCompletion(CompletionCallback, userdata); +queue.OnSubmittedWorkDone(CompletionCallback, userdata); ``` ### VertexFormat rename. WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1322) WebGPU's vertex formats were using `"char"`, `"short"` and similar terminology which wasn't used anywhere else (and isn't very descriptive if you don't know C/C++). To make it more clear it has been changed to use names like `"uint8"`, `"sint16"` and `"float32"`. See the table below for correspondances in the JavaScript API and Dawn's API. | Old Javascript | New Javascript | Old Dawn | New Dawn | |-|-|-|-| | `"uchar2"` | `"uint8x2"` | `UChar2` | `Uint8x2` | | `"uchar4"` | `"uint8x4"` | `UChar4` | `Uint8x4` | | `"char2"` | `"sint8x2"` | `Char2` | `Sint8x2` | | `"char4"` | `"sint8x4"` | `Char4` | `Sint8x4` | | `"uchar2norm"` | `"unorm8x2"` | `UChar2Norm` | `Unorm8x2` | | `"uchar4norm"` | `"unorm8x4"` | `UChar4Norm` | `Unorm8x4` | | `"char2norm"` | `"snorm8x2"` | `Char2Norm` | `Snorm8x2` | | `"char4norm"` | `"snorm8x4"` | `Char4Norm` | `Snorm8x4` | | `"ushort2"` | `"uint16x2"` | `UShort2` | `Uint16x2` | | `"ushort4"` | `"uint16x4"` | `UShort4` | `Uint16x4` | | `"short2"` | `"sint16x2"` | `Short2` | `Sint16x2` | | `"short4"` | `"sint16x4"` | `Short4` | `Sint16x4` | | `"ushort2norm"` | `"unorm16x2"` | `UShort2Norm` | `Unorm16x2` | | `"ushort4norm"` | `"unorm16x4"` | `UShort4Norm` | `Unorm16x4` | | `"short2norm"` | `"snorm16x2"` | `Short2Norm` | `Snorm16x2` | | `"short4norm"` | `"snorm16x4"` | `Short4Norm` | `Snorm16x4` | | `"half2"` | `"float16x2"` | `Half2` | `Float16x2` | | `"half4"` | `"float16x4"` | `Half4` | `Float16x4` | | `"float"` | `"float32"` | `Float` | `Float32` | | `"float2"` | `"float32x2"` | `Float2` | `Float32x2` | | `"float3"` | `"float32x3"` | `Float3` | `Float32x3` | | `"float4"` | `"float32x4"` | `Float4` | `Float32x4` | | `"uint"` | `"uint32"` | `UInt` | `Uint32` | | `"uint2"` | `"uint32x2"` | `UInt2` | `Uint32x2` | | `"uint3"` | `"uint32x3"` | `UInt3` | `Uint32x3` | | `"uint4"` | `"uint32x4"` | `UInt4` | `Uint32x4` | | `"int"` | `"sint32"` | `SInt` | `Uint32` | | `"int2"` | `"sint32x2"` | `Int2` | `Sint32x2` | | `"int3"` | `"sint32x3"` | `Int3` | `Sint32x3` | | `"int4"` | `"sint32x4"` | `Int4` | `Sint32x4` | ### CopyView type renames WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1375) To avoid confusion with the concept of `TextureView`s, the types `BufferCopyView`, `TextureCopyView`, and `ImageBitmapCopyView` have been renamed to `ImageCopyBuffer`, `ImageCopyTexture`, and `ImageCopyImageBitmap` respectively. Since these types are dictionaries this rename has no effect on JavaScript code, other than to make the documentation a bit clearer. When using Dawn's API, changes are needed: ```diff= -wgpu::BufferCopyView bufferSrc; +wgpu::ImageCopyBuffer bufferSrc; bufferSrc.buffer = buffer; bufferSrc.layout.offset = 0; bufferSrc.layout.bytesPerRow = 1024; bufferSrc.layout.rowsPerImage = wgpu::kCopyStrideUndefined; -wgpu::TextureCopyView textureDst; +wgpu::ImageCopyTexture textureDst; textureDst.texture = texture; textureDst.mipLevel = 0; textureDst.origin = {0, 0, 0}; textureDst.aspect = wgpu::TextureAspect::All; wgpu::Extent3D copySize = {1024, 1024, 1}; wgpu::CommandEncoder encoder = device.CreateCommandEncoder(); encoder.CopyBufferToTexture(&bufferSrc, &textureDst, &copySize); ``` ### Dawn API `bytesPerRow` and `rowsPerImage` changes Previously when doing 1D copies, validation ignored the value `bytesPerRow` so it was valid to set it to 0, or another value too small. This will now cause a validation error. Instead set `bytesPerRow` to `wgpu::kCopyStrideUndefined` (the default struct member value) or a value larger than the copy's size in bytes. Likewise previously when doing 2D copies, validation ignored the value `rowsPerImage`. To avoid a validation error it must now be set to `wgpu::kCopyStrideUndefined` (the default struct member value) or a value larger than the copy's height. Finally when doing 3D copies, a 0 value for `rowsPerImage` caused it to default to the copy height. This will now produce a validation error and you should use `wgpu::kCopyStrideUndefined` instead (the default struct member value These changes are made to be closer to the Javascript API where `undefined` and 0 have different behaviors, and makes it easier to implement the Javascript API using Dawn's API. ### GPUExtent3DDict depth -> depthOrArrayLayers WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1390) Depending on context, the 3rd element of a `GPUExtent3DDict` may represent either a depth, as in the case of a 3D texture, or the number of layers, as in the case of a 2D array texture. To clarify this dual purpose, the `depth` attribute has been renamed to `depthOrArrayLayers`. An example of the change needed in JavaScript: ```diff= const texture = device.createTexture({ - size: { width: 16, height: 16, depth: 16 }, + size: { width: 16, height: 16, depthOrArrayLayers: 16 }, dimension: '3d'; format: 'rgba8unorm', usage: GPUTextureUsage.COPY_DST | GPUTextureUsage.SAMPLED }); ``` Likewise when using Dawn’s API, changes are needed: ```diff= wgpu::TextureDescriptor descriptor; descriptor.size.width = 16; descriptor.size.height = 16; -descriptor.size.depth = 16; +descriptor.size.depthOrArrayLayers = 16; descriptor.dimension = wgpu::TextureDimension::e3D; descriptor.format = wgpu::TextureFormat::RGBA8Unorm; descriptor.usage = wgpu::TextureUsage::CopyDst | wgpu::TextureUsage::Sampled; wgpu::Texture texture = device.CreateTexture(&descriptor); ``` Note that both Javascript and Dawn's API support shorthand declarations with unspecified values defaulting to one. In Javascript: ```js [w, h] // Same as {width: w, height: h, depthOrArrayLayers: 1} ``` Using Dawn's API: ```cpp= wgpu::Extent3D extent = {w, h}; // Is the same as wgpu::Extent3D extent; extent.width = w; extent.height = h; extent.depthOrArrayLayers = 1; ``` ### getSwapChainPreferredFormat It was determined that `getSwapChainPreferredFormat` didn't need to be asynchronous, and that it was more appropriate for it to accept a `GPUAdapter` than a `GPUDevice`. An example of the change needed in JavaScript: ```diff= const context = canvas.getContext('gpupresent'); -const swapChainFormat = await context.getSwapChainPreferredFormat(device); +const swapChainFormat = context.getSwapChainPreferredFormat(adapter); const swapChain = context.configureSwapChain({ device: device, format: swapChainFormat }); ``` The Dawn API does not currently have an equivalent call, so no changes are needed. ### `SetIndexBufferWithFormat` -> `SetIndexBuffer` In Dawn's API `SetIndexBuffer` was temporarily renamed to `SetIndexBufferWithFormat` while its signature was changed. Now that the signature is changed, `SetIndexBufferWithFormat` is deprecated in favor of `SetIndexBuffer` (with the updated signature). ### extensions->features rename WebGPU [PR](https://github.com/gpuweb/gpuweb/pull/1097) The WebGPU specification has started referring to what was previously called "Extensions" as "Features". This is because they include functionality that is present in the base spec but is not universally supported, and as such needs to be enabled explicitly (such as compressed texture formats). In service of this change the `extensions` attribute on both `GPUAdapter` and `GPUDevice` has been renamed to `features`. Also, the `extensions` key of the `GPUDeviceDescriptor` dictionary has beed renamed to `nonGuaranteedFeatures`. The name `nonGuaranteedFeatures` was chosen to emphasize that the features requested in this array are not guaranteed to be supported on all platforms and devices, and as such should be verified against the `GPUAdapter.features` list prior to requesting. As was the case prior to the rename, specifying a feature in the `nonGuaranteedFeatures` that is not supported by the `GPUAdapter` will cause `requestDevice()` to fail. An example of the change needed in JavaScript: ```diff= let deviceDescriptor = {}; -const hasBCCompression = adapter.extensions.indexOf('texture-compression-bc') != -1; +const hasBCCompression = adapter.features.indexOf('texture-compression-bc') != -1; if (hasBCCompression) { - deviceDescriptor.extensions = ['texture-compression-bc']; + deviceDescriptor.nonGuaranteedFeatures = ['texture-compression-bc']; } let device = await adapter.requestDevice(deviceDescriptor); ``` This change has not yet been made in Dawn, so no changes are required yet. ## New features and improvements Most of the improvements to Dawn / Chromium for WebGPU are happening under the hood. Recently our focus has been on massively improving the security of our implementation in preparation for a future WebGPU Origin Trial. This includes reworking large parts of our cross-process remoting architecture, vastly expanded test coverage (and fixing all the tiny issues found in the spec etc), automatic fuzzing, etc. Another huge effort is expanding usage of [Tint](https://dawn.googlesource.com/tint), our WGSL compiler. Previously it directly converted WGSL to SPIR-V and we were using [SPIRV-Cross](https://github.com/KhronosGroup/SPIRV-Cross) for translation to MSL / HLSL / GLSL and reflection. SPIRV-Cross is a mature library but is not meant to handle untrusted/malicious inputs like you can find on the Web. Tint has been expanded to the point where Dawn can use it for shader reflection and WGSL -> HLSL translation. ### OffscreenCanvas support OffscreenCanvas now supports the `"gpupresent"` context type! It can currently be used to detach the content of the canvas into and ImageBitmap with `transferToImageBitmap()`. Additional features like using WebGPU on an `OffscreenCanvas` received from `transferToOffscreenCanvas()` and `OffscreenCanvas.convertToBlob()` will follow shortly. ### Create\*PipelineAsync When a `GPURenderPipeline` or `GPUComputePipeline` is created with `GPUDevice.createRenderPipeline()` or `GPUDevice.createComputePipeline()` respectively, they return immediately. On the GPU process side it means that the pipelines have to be compiled immediately and stall the execution of further commands (because they could be used for drawing immediately). This can easily cause frame hitching and at worst compiling a lot of pipelines can trigger the "GPU watchdog" that will lose the WebGPU devices. New methods for creating pipelines asynchronously, `GPUDevice.createRenderPipelineAsync()` and `GPUDevice.createComputePipelineAsync()`, have been added to address this. These methods accept the same descriptors as their synchronous counterparts but asynchronously return the pipeline once it is fully ready to be used. Using pipelines returned from the `create*PipelineAsync()` methods can help reduce hitches on first use compared to those returned from `create*Pipeline()`. This is a similar idea to WebGL's [`KHR_parallel_shader_compile`](https://www.khronos.org/registry/webgl/extensions/KHR_parallel_shader_compile/) but more Javacript-idiomatic. Note that currently these methods aren't completely asynchronous internally but work is ongoing to improve their performance. Using the feature in Javascript is done like below: ```javascript= const computePipeline = await device.createComputePipelineAsync({ compute: { module: device.createShaderModule({ code }), entryPoint: 'main' } }); const commandEncoder = device.createCommandEncoder(); const passEncoder = commandEncoder.beginComputePass(); passEncoder.setPipeline(computePipeline); passEncoder.dispatch(1024, 1024); passEncoder.endPass(); device.queue.submit([commandEncoder.finish()]); ``` Using the feature in Dawn's API is done like below: ```cpp= wgpu::ComputePipelineDescriptor desc; // Fill `desc` as usual. device->CreateComputePipeline(&desc, [](WGPUCreatePipelineAsyncStatus status, WGPUComputePipeline pipeline, const char* message, void* userdata) { if (status == WGPUCreatePipelineAsyncStatus::WGPUCreatePipelineAsyncStatus_Success) { // pipeline can now be used as usual. } }, nullptr // userdata passed to the callback. ); ``` ### Depth clamping `"depth-clamping"` is a new optional WebGPU feature that allows controlling the behavior of fragments with a depth that fall outside of the `[0, 1]` range. By default without this extension they are discarded, instead when setting `GPUPrimitiveState.clampDepth = true` the fragments will be kept and their depth clamped to [0, 1]. This is particularly useful when rendering shadow maps so that geometry outside of the light's frustum still occludes geometry correctly (otherwise it would just "disappear" from the shadow). Using the feature in Javascript is done like below: ```javascript= // Check that our adapter has the feature available. const adapter = await navigator.gpu.requestAdapter(); if (!adapter.features.includes("depth-clamping")) { alert("Need GPUAdapter with depth clamping support!"); return; } // Create the device, requesting the feature to be enabled. const device = await adapter.requestDevice({ nonGuaranteedFeatures: ["depth-clamping"] }); // Create a pipeline that uses the feature. const pipeline = device.createRenderPipeline({ primitive: { clampDepth: true, // ... }, // ... }); ``` Using the feature in Dawn's API, when a `wgpu::Device` with the feature has been created is done like below. Extensibility of descriptors in C++ is done with "chained structures" a bit like Vulkan: ```cpp= wgpu::RenderPipelineDescriptor desc; // Fill `desc` as usual. // Chain our depth clamping state in desc.primitive. wgpu::PrimitiveDepthClampingState depthClampState; depthClampState.clampDepth = true; desc.primitive.nextInChain = &depthClampState; wgpu::RenderPipeline pipeline = device.CreateRenderPipeline(&desc); ``` ### maxAnisotropy It is now possible to specify a `GPUSampler`'s maximum anisotropy for [anisotropic filtering](https://en.wikipedia.org/wiki/Anisotropic_filtering). For historical reasons this features is not guaranteed to be everywhere so the WebGPU specification doesn't require that values higher than 1 do something, but that should be the case everywhere in practice. Using the feature is done by adding `maxAnisotropy` to the descriptor passed to `GPUDevice.createSampler`: ```js= const sampler = device.createSampler({ magFilter: "linear", minFilter: "linear", mipmapFilter: "linear", maxAnisotropy: 4, }); ``` When using Dawn's API `maxAnisotropy` can be set in a similar way: ```cpp= wgpu::SamplerDescriptor desc; desc.magFilter = wgpu::FilterMode::Linear; desc.minFilter = wgpu::FilterMode::Linear; desc.mipmapFilter = wgpu::FilterMode::Linear; desc.maxAnisotropy = 4; wgpu::Sampler sampler = device.CreateSampler(&desc); ```

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password

    or

    By clicking below, you agree to our terms of service.

    Sign in via Facebook Sign in via Twitter Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully