New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Investigation: Multisample Coverage #267
Comments
@Kangz @kainino0x @kvark @litherum @RafaelCintron PTAL, thanks! |
LGTM, we'll have to ask IHVs if only doing the sample mask in the shader is slower than specifiying it at the pipeline level. That the alpha-to-coverage computation isn't defined is really unfortunate. We should see if we can emulate it to be consistent but I worry that it might be slower than specifying at the pipeline level as well: looking at open-source Vulkan drivers, it seems like it is a hardware state. |
@Jiawei-Shao thank you for the detailed investigation!
At first, this doesn't look like a big issue to me. The Metal backend can just provide a value to the shader to AND with, effectively producing the same result. It's not "re-compiling" per se - when using SPIRV-Cross we generate the shader code at pipeline creation anyway (not shader module creation), so by this time (and it's the first and only compilation of the shader) we know if the sample mask needs to be introduced. There is a problem, however, that just occurred to me. In Vulkan and D3D12 we can set the sample mask for a pipeline and at the same time enable alpha-to-coverage. The output of that would be ANDed with the sample mask. If we emulate the mask with the shader logic, this would be conflicting with alpha-to-coverage (since the shader can't output both that alpha and the sample mask...). We could think of a way for hand-rolled alpha-to-coverage logic in Metal backend in this case, but anyway this seems pretty annoying. |
@kvark thanks for your comment!
According to D3D12 document:
So I think in WebGPU if sample mask is in the output of fragment shader, then alpha-to-coverage should always be disabled. |
@Jiawei-Shao I think you misunderstood my concern. I'm talking about the case where the Metal backend would use SV_Coverage-like semantics internally since its pipeline state doesn't support masking. The user would still expect alpha-to-coverage to work in this case. |
@kvark sorry that I am still a bit puzzled about your comment. if (alphaToCoverageEnabled) then
alphaCoverageMask = coverageToMask(colorAttachment0.alpha);
finalCoverageMask = originalRasterizerCoverageMask & alphaCoverageMask & fragShaderSampleMaskOutput; |
@Jiawei-Shao great, then we have no problem with emulating the pipeline sample mask in Metal. I think we should expose it then in the API. |
Discussed at the 29 April 2019 meeting. |
…iptor This patch adds sample mask and alpha-to-coverage state to the render pipeline descriptor after the discussion in issue gpuweb#267.
Closing. |
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:
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 registerSV_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 ofuint32_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
inVkPipelineMultisampleStateCreateInfo
toVK_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 “ifalphaToCoverageEnable
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.
SV_target0
when pixel shader doesn’t outputSV_Coverage
colorAttachments0
(?)Location
and Index decoration of 0Based on the above investigations, one feasible way to support the configuration on multisample coverage in WebGPU is as follows:
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.
The text was updated successfully, but these errors were encountered: