Skip to content

Add VK_MESA_fragment_coverage_mask#2724

Open
mjkrol wants to merge 1 commit into
KhronosGroup:mainfrom
mjkrol:fragment-coverage-mask
Open

Add VK_MESA_fragment_coverage_mask#2724
mjkrol wants to merge 1 commit into
KhronosGroup:mainfrom
mjkrol:fragment-coverage-mask

Conversation

@mjkrol
Copy link
Copy Markdown
Contributor

@mjkrol mjkrol commented May 6, 2026

Publish VK_MESA_fragment_coverage_mask, exposing the SPV_MESA_fragment_coverage_mask SPIR-V extension to Vulkan. The new FragmentCoverageMaskMESA fragment shader input built-in contains the complete set of samples covered by the fragment regardless of the fragment shader's execution mode, addressing the limitation that SampleMask is masked to the sample(s) processed by the current invocation under per-sample shading.

Adds VkPhysicalDeviceFragmentCoverageMaskFeaturesMESA to query and enable the feature, registers the SPV_MESA_fragment_coverage_mask SPIR-V extension and FragmentCoverageMESA capability, and adds the proposal, appendix, and built-in variable description.

@mjkrol mjkrol force-pushed the fragment-coverage-mask branch 3 times, most recently from d82d90b to f727185 Compare May 6, 2026 11:51
Comment thread chapters/interfaces.adoc Outdated
@oddhack
Copy link
Copy Markdown
Contributor

oddhack commented May 6, 2026

Aside from my VUID comment, is this ready to publish from your perspective?

Publish VK_MESA_fragment_coverage_mask, exposing the
SPV_MESA_fragment_coverage_mask SPIR-V extension to Vulkan. The new
FragmentCoverageMaskMESA fragment shader input built-in contains the
complete set of samples covered by the fragment regardless of the
fragment shader's execution mode, addressing the limitation that
SampleMask is masked to the sample(s) processed by the current
invocation under per-sample shading.

Adds VkPhysicalDeviceFragmentCoverageMaskFeaturesMESA to query and
enable the feature, registers the SPV_MESA_fragment_coverage_mask
SPIR-V extension and FragmentCoverageMESA capability, and adds the
proposal, appendix, and built-in variable description.
@mjkrol mjkrol force-pushed the fragment-coverage-mask branch from f727185 to 5b51ddc Compare May 6, 2026 12:52
@mjkrol
Copy link
Copy Markdown
Contributor Author

mjkrol commented May 6, 2026

Aside from my VUID comment, is this ready to publish from your perspective?

Yes.

Comment thread xml/vk.xml
@gfxstrand
Copy link
Copy Markdown
Contributor

Can you provide a little more context around this? It's using the MESA prefix but I'm not seeing a merge request for it against any driver nor have I seen any discussion about this. Also, it's all braodcom people on the authors list so is this really a MESA extension or a BROADCOM extension?

@mjkrol
Copy link
Copy Markdown
Contributor Author

mjkrol commented May 6, 2026

Can you provide a little more context around this? It's using the MESA prefix but I'm not seeing a merge request for it against any driver nor have I seen any discussion about this. Also, it's all braodcom people on the authors list so is this really a MESA extension or a BROADCOM extension?

Target implementation is lavapipe, Mesa's software Vulkan driver, which is why the prefix is MESA rather than BRCM. MESA tracks the implementation home, not contributor affiliation. The Mesa MR isn't public yet; I'll start it now and link it here once it's drafted.

@Triang3l
Copy link
Copy Markdown

Triang3l commented May 7, 2026

This definitely should be an EXT extension since it's a general-purpose graphics feature (also available in Direct3D and probably Metal), rather than being something specific to Mesa, that can be implemented pretty much universally (maybe with some exceptions, I'll check how real drivers implement SampleMask in the near future, and whether SampleMask and FragmentCoverage can coexist in the same shader on all hardware, including taking partial sample shading via minSampleShading into account, though it's fine to fall back to 100% sample shading if in the hardware, the D3D or GL/VK behavior is toggled as fixed-function, and for the two inputs to coexist, the driver would have to do single-sample SampleID masking behind the scenes in the shader to construct one from the other — the two inputs that can always both be used in the same shader do in fact seem to be a realistic way to provide this functionality).

Also, this is likely going to have interactions with VK_KHR_fragment_shading_rate. Though the whole interaction between sample shading and fragment shading rate is underspecified in Direct3D (which is probably the primary purpose of this extension — implementing Direct3D SV_Coverage without data loss when sample shading is active), and I haven't tested it by myself, but I asked Jesse Natalie from Microsoft (who works on a lot of Direct3D functionality including the WARP software renderer) on the official DirectX Discord server, and he told me that in WARP, sample shading properly works with coarse shading (with each pixel shader invocation corresponding to one sample of all fine pixels at once — and SV_Coverage in each receiving the mask for all samples of all fine pixels; I don't know what per-sample interpolation locations would be in this case, but with SV_SampleIndex alone this seems reasonable), the hardware implementation behavior may be different though, maybe some hardware forces 1x1 shading rate with sample shading, maybe I'll check at some point within a week.

But at least it's possible that an equivalent of the fragmentShadingRateWithShaderSampleMask property may be needed for the new built-in — but maybe not, maybe fragmentShadingRateWithShaderSampleMask itself would be enough (though in this case, its description needs to be updated to include the new built-in), we need feedback from hardware and driver developers here.

Though Vulkan has the If any of the following conditions are met, Cxy' is set to {1,1} by the implementation: - If Sample Shading is enabled restriction in fragment shading rate, so maybe this is not relevant at all really, if FragmentCoverage only differs from Coverage when sample shading is used (taking into account that both partial sample shading via minSampleShading and full sample shading with Sample inputs or SampleID are considered enabled sample shading), and when it's not, it can be safely replaced with Coverage. In Direct3D, as far as I know, sample shading is activated only from the pixel shader itself, so whether FragmentCoverage (with sample shading, which is fine-only on Vulkan) or SampleMask (without sample shading, thus possibly coarse, but in this case, receiving the full coverage anyway) needs to be used in the shader binary can be determined from the shader binary alone in Direct3D emulation, without the need to create shader combinations based on fixed-function pipeline state.

I'm not sure though how the previous paragraph should work in a situation where the implementation implicitly enables some sample shading even when the application did not explicitly ask it to (like with fixed-function blending implemented as programmable in shaders on some hardware, or like what the dEQP-VK.pipeline.*_library.misc.frag_lib_varying_samples_* pass condition allows — the per-pixel invocation count obtained using atomic incrementing must be between 1 and the sample count, not specifically 1). Would SampleMask be limited to the samples actually corresponding to the invocation in the hardware, yet from the API perspective, sample shading still wouldn't be explicitly enabled? In this case, FragmentCoverage would provide additional info without explicit sample shading too — not only when fragment shading rate is used, but even regardless of it.

By the way, I think the name "fragment coverage" isn't descriptive enough, because that's basically what SampleMask already is, if we consider that a fragment is what a fragment shader invocation corresponds to (I'm not sure about the exact terminology though). Maybe "primitive sample mask" would be more descriptive (although we'll need to take into account the interaction with the sample mask pipeline state, in Direct3D it's not the unmodified primitive coverage directly, rather, "The InputCoverage bitfield is not affected by depth/stencil tests, but it is ANDed with the SampleMask Rasterizer state"), or "pixel coverage" (raises the question about coarse vs. fine pixels though).

VK_EXT_post_depth_coverage also mentions SampleMask, and though the interaction with post-depth coverage is discussed in the issues section of the proposal, I think references to the SampleMask input throughout the specification also need to be revisited, with FragmentCoverage explicitly mentioned everywhere in addition to SampleMask.

If ultimately introducing a new variable turns out to be too complex or intrusive, I think it may actually be possible to add an execution mode that alters the meaning of SampleMask itself — although this will make it impossible for applications to know which samples actually correspond to the invocation when fractional sample shading is used, as well as in cases where sample shading is applied implicitly by the implementation as described 3 paragraphs above.

@mjkrol
Copy link
Copy Markdown
Contributor Author

mjkrol commented May 7, 2026

Draft implementation in lavapipe: https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/41423

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants