Skip to content

Investigation: Multisample Coverage #267

Closed
@Jiawei-Shao

Description

@Jiawei-Shao

Introduction

When the color attachment is multi-sampled, the explicit APIs provide the following additional configurations to affect the coverage of the samples for each pixel:

  • Sample Mask (In pipeline state object)
  • Sample Mask (In fragment shader)
  • Alpha-to-coverage

This document discusses how to expose these configurations to WebGPU.

Native APIs

D3D12

D3D12 supports specifying a 32-bit UINT as the sample mask in the structure D3D12_GRAPHICS_PIPELINE_STATE_DESC.

D3D12 supports SV_Coverage in HLSL as a mask in pixel shaders.

D3D12 supports enabling alpha-to-coverage in D3D12_BLEND_DESC. According to the document for alpha-to-coverage on MSDN, “AlphaToCoverageEnable is used to toggle if the runtime converts the .a component (alpha) of output register SV_Target0 from the pixel shader to an n-step coverage mask (given an n-sample RenderTarget). The runtime performs an AND operation of this mask with the typical sample coverage for the pixel in the primitive (in addition to the sample mask) to determine which samples to update in all the active RenderTargets”.

Note that D3D12 document mentions “if the pixel shader outputs SV_Coverage, the runtime disables alpha-to-coverage”.

D3D12 document also mentions "graphics hardware doesn't precisely specify exactly how it converts pixel shader SV_Target0.a (alpha) to a coverage mask. Hardware might perform area dithering to provide some better quantization of alpha values at the cost of spatial resolution and noise."

Metal

Metal does not support the configuration of sample mask in MTLRenderPipelineDescriptor.

According to Metal Shading Language Specification (Chapter 5.2.3.4, Chapter 5.2.3.5), Metal shading language supports an uint attribute [[sample_mask]] as the coverage mask.

Metal supports enabling alpha-to-coverage in the rendering pipeline through alphaToCoverageEnabled in MTLRenderPipelineDescriptor.

Metal document provides a Pseudo-Code for computing a coverage mask. This Pseudo-Code implies alpha-to-coverage only works for colorAttachment0.

if (alphaToCoverageEnabled) then
    alphaCoverageMask = coverageToMask(colorAttachment0.alpha);
finalCoverageMask = originalRasterizerCoverageMask & alphaCoverageMask & fragShaderSampleMaskOutput;

Metal document mentions the algorithm to convert the alpha channel of the fragment output to a coverage mask is implementation-dependent.

Vulkan

Vulkan supports configuring sample mask in the rendering pipeline by setting pSampleMask in VkPipelineMultisampleStateCreateInfo. pSampleMask is an array of uint32_t, which means Vulkan allows sample mask to have more than 32 bits.

SPIR-V supports SampleMask as a built-in variable in fragment shader.

Vulkan supports enabling alpha-to-coverage in the rendering pipeline by setting alphaToCoverageEnable in VkPipelineMultisampleStateCreateInfo to VK_TRUE.

Vulkan specification mentions alpha-to-coverage only works for “the alpha component of the fragment shader output that has a Location and Index decoration of zero”, and “if alphaToCoverageEnable is enabled, a temporary coverage value with rasterizationSamples bits is generated where each bit is determined by the fragment’s alpha value. The temporary coverage value is then ANDed with the fragment coverage value to generate a new fragment coverage value”.

Vulkan specification mentions “no specific algorithm is specified for converting the alpha value to a temporary coverage mask”.

Proposal

Here is the summary on the support of multisample coverage on D3D12, Metal and Vulkan.

D3D12 Metal Vulkan
Sample Mask (PSO) Yes No Yes
Sample Mask (shader) Yes Yes Yes
Alpha-to-coverage Yes for SV_target0 when pixel shader doesn’t output SV_Coverage Yes for colorAttachments0 (?) Yes for the fragment shader output that has a Location and Index decoration of 0

Based on the above investigations, one feasible way to support the configuration on multisample coverage in WebGPU is as follows:

  • Do not expose sample mask in pipeline state objects because Metal does not support such usage. Another choice is to re-compile the fragment shader when building pipeline state object on Metal.
  • Support sample mask in the fragment shader as it is available in HLSL, Metal shading language and SPIR-V.
  • Support alpha-to-coverage and always disable alpha-to-coverage when the fragment shader outputs sample mask. It is because on D3D12 when the pixel shader outputs SV_Coverage, the runtime always disables alpha-to-coverage.

Note that another challenge to support alpha-to-coverage in WebGPU is the algorithm of converting the alpha value to a coverage mask is implementation-dependent, which means the behaviors of alpha-to-coverage may differ among different WebGPU implementations.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions