Skip to content

Prevent DXC from adding Geometry or MultiViewport when the shader already declares one of these capabilities - #9076

Open
Philip Degarmo (aclysma) wants to merge 4 commits into
microsoft:mainfrom
aclysma:user/aclysma/spirv-primitive-id-capability
Open

Philip Degarmo (aclysma) wants to merge 4 commits into
microsoft:mainfrom
aclysma:user/aclysma/spirv-primitive-id-capability

Conversation

@aclysma

Copy link
Copy Markdown

I stumbled across an issue with combining PrimitiveId usage with mesh shaders when the Vulkan device does NOT have geometry shaders enabled.


DXC adds OpCapability Geometry to every pixel or mesh shader that reads or writes SV_PrimitiveID or SV_RenderTargetArrayIndex, and OpCapability MultiViewport for SV_ViewportArrayIndex. Geometry requires geometry shaders to be enabled on the device.

Other capabilities also cover these values. Mesh shading covers all three (VUID-PrimitiveId-Fragment-04333 for primitive ID). ShaderViewportIndexLayerEXT, ShaderLayer and ShaderViewportIndex cover the other two.

This change stops DXC from adding Geometry or MultiViewport when the shader already declares one of these capabilities. Mesh shaders never get it. A pixel shader gets it only if it declares none of them (for example, it can declare mesh shading with [[vk::ext_capability(5283)]] and [[vk::ext_extension("SPV_EXT_mesh_shader")]] on the entry point). A plain pixel shader is unchanged.

…ds or writes SV_PrimitiveID or SV_RenderTargetArrayIndex, and OpCapability MultiViewport for SV_ViewportArrayIndex. Geometry requires geometry shaders to be enabled on the device.

Other capabilities also cover these values. Mesh shading covers all three (VUID-PrimitiveId-Fragment-04333 for primitive ID). ShaderViewportIndexLayerEXT, ShaderLayer and ShaderViewportIndex cover the other two.

This change stops DXC from adding Geometry or MultiViewport when the shader already declares one of these capabilities. Mesh shaders never get it. A pixel shader gets it only if it declares none of them (for example, it can declare mesh shading with [[vk::ext_capability(5283)]] and [[vk::ext_extension("SPV_EXT_mesh_shader")]] on the entry point). A plain pixel shader is unchanged.
Copilot AI balanced review requested due to automatic review settings October 28, 2026 05:37
@azure-pipelines

Copy link
Copy Markdown
Azure Pipelines:
There may be pipelines that require an authorized user to comment /azp run to run.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The user-visible fix removing unnecessary Geometry/MultiViewport capabilities lacks the release-note entry required by the contribution policy.

1 open issue
What changed in this PR

This PR updates DXC’s SPIR-V capability selection to avoid unnecessary geometry-shader requirements when declared capabilities already support the affected mesh and fragment shader builtins.

Changes:

  • Defers fragment builtin capability selection until all module capabilities are known.
  • Uses existing mesh, tessellation, and viewport/layer capabilities instead of adding redundant Geometry or MultiViewport.
  • Adds regression tests for alternative capabilities, late capability declarations, and preservation of geometry-stage requirements.
File Description
tools/​clang/​test/​CodeGenSPIRV/​semantic.viewport-array-index.shader-viewport-index.ps.hlsl Tests ShaderViewportIndex as an alternative capability.
tools/​clang/​test/​CodeGenSPIRV/​semantic.viewport-array-index.shader-viewport-index-layer.ps.hlsl Tests viewport-index support through the layer extension.
tools/​clang/​test/​CodeGenSPIRV/​semantic.viewport-array-index.mesh-shading-ext.ps.hlsl Tests fragment viewport-index support through mesh shading.
tools/​clang/​test/​CodeGenSPIRV/​semantic.render-target-array-index.shader-viewport-index-layer.ps.hlsl Tests layer support through the viewport/layer extension.
tools/​clang/​test/​CodeGenSPIRV/​semantic.render-target-array-index.shader-layer.ps.hlsl Tests ShaderLayer as an alternative capability.
tools/​clang/​test/​CodeGenSPIRV/​semantic.render-target-array-index.mesh-shading-ext.ps.hlsl Tests fragment layer support through mesh shading.
tools/​clang/​test/​CodeGenSPIRV/​semantic.primitive-id.mesh-shading-nv.ps.hlsl Tests fragment primitive IDs with NV mesh shading.
tools/​clang/​test/​CodeGenSPIRV/​semantic.primitive-id.mesh-shading-ext.ps.hlsl Tests EXT mesh shading and late capability declarations.
tools/​clang/​test/​CodeGenSPIRV/​semantic.primitive-id.mesh-shading-ext.gs.hlsl Verifies geometry stages retain Geometry.
tools/​clang/​test/​CodeGenSPIRV/​meshshading.nv.primitive-builtins.mesh.hlsl Tests NV mesh primitive outputs without redundant capabilities.
tools/​clang/​test/​CodeGenSPIRV/​meshshading.ext.primitive-builtins.mesh.hlsl Tests EXT mesh primitive outputs without redundant capabilities.
tools/​clang/​lib/​SPIRV/​CapabilityVisitor.h Declares deferred capability selection and pending builtin storage.
tools/​clang/​lib/​SPIRV/​CapabilityVisitor.cpp Implements capability reuse and deferred fragment handling.

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 05:43

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The added fragment-shader tests bypass the Tessellation exception, leaving it without regression coverage verifying that Tessellation is retained and Geometry is absent both with and without -fcgl.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Low severity Add pixel-shader regression test for Tessellation capability handling

tools/​clang/​lib/​SPIRV/​CapabilityVisitor.cpp:919

The new Tessellation exception is not covered by the added fragment-shader tests, which declare mesh-shading capabilities and bypass this branch. Please add an SV_PrimitiveID pixel-shader regression declaring [[vk::ext_capability(3)]] that checks Tessellation is retained and Geometry is absent, both with and without -fcgl.

1 resolved since last review

Review effort: Balanced

Copilot AI balanced review requested due to automatic review settings October 28, 2026 06:16

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues are reported for the SPIR-V capability-selection changes.

No open issues 🎉

Review effort: Balanced

@aclysma

Copy link
Copy Markdown
Author

I received an email that indicated there was a comment on this PR. I don't see the comment here, but maybe GitHub is just broken right now. It asked for more info and a godbolt link.

I expected to be able to compile and use a mesh shader with vulkan that writes to PrimitiveId, without enabling geometry shaders on the device. This change fixes that specific problem and a few similar problems.

The root cause is that DXC puts unnecessary capabilities in the spirv, which limits the conditions under which the shader can be used. There are several examples in the included tests, but here is a specific case of a mesh shader that writes SV_PrimitiveID, and it results in being unable to use it without enabling geometry shaders.

https://godbolt.org/z/1oYoz4P8s

The produced spirv has "OpCapability Geometry". In Vulkan, a module that declares Geometry is invalid unless the device enables the geometryShader feature. So this mesh shader, as compiled by DXC today, can't be used on a device without geometry shader support.

The capability is unnecessary because the spec (https://registry.khronos.org/SPIR-V/specs/unified1/SPIRV.html#BuiltIn) states that the MeshShadingEXT capability is sufficient to make PrimitiveId available.

@jzakharovnv

Copy link
Copy Markdown
Collaborator

Philip Degarmo (@aclysma) Yeah that was me deleting my message after I had understood a little better and started reviewing (was having a brain fart). If for this PR and future ones, you could file an issue with a body just like you've done here, that would be greatly appreciated and make reviewing easier and quicker. Otherwise, thanks for this PR, I'm still reviewing but it looks good so far!

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR and thanks for your patience. It took me a while to get context, and I still might have gaps in my understanding, but the code looks pretty good. I just have some nits and follow ups on documentation such that it best reflects the new changes.

Comment thread docs/ReleaseNotes.md Resolved
@github-project-automation github-project-automation Bot moved this from New to In progress in HLSL Roadmap Oct 30, 2026
… add a footnote in SPIR-V that describes the behavior this change introduces.
Copilot AI balanced review requested due to automatic review settings October 30, 2026 21:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues block the change to avoid redundant SPIR-V capability requirements.

No open issues 🎉

Review effort: Balanced

@aclysma

Copy link
Copy Markdown
Author

Thanks for taking a look. I think this revision addresses all of the feedback and has significantly more readable comment/doc changes.

@jzakharovnv

Copy link
Copy Markdown
Collaborator

Thanks for the changes. One small, optional idea: a test where a capability is declared that doesn't enable the builtin (e.g. ShaderLayer with SV_PrimitiveID), to assert that Geometry is still added. Otherwise LGTM!

@pow2clk Gregory Roth (pow2clk) left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nothing worth holding up the change, just some better potential clarity and test consolidation.

In the meantime, the merge conflicts need to be resolved. I can't even see what they are I think because you didn't allow maintainers to push to your branch. No shame in that, but it means I can't do anything to merge it until they are resolved.

Comment thread docs/SPIR-V.rst
Comment on lines +1688 to +1689
.. [1] ``Geometry`` or ``MultiViewport`` is not added if the module declares
one of these capabilities, which also enable the builtin:

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a little more suggested detail

Suggested change
.. [1] ``Geometry`` or ``MultiViewport`` is not added if the module declares
one of these capabilities, which also enable the builtin:
.. [1] When the following semantic values with a PSIn Signature point,
``Geometry`` or ``MultiViewport`` is not added if the module declares
one of these capabilities, which also enable the builtin:

Comment on lines +3 to +4
// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 -DCAPABILITY_ON_INSTRUCTION %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 -DCAPABILITY_ON_INSTRUCTION -fcgl %s -spirv | FileCheck %s

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This includes two entry points with different annotations using the same run lines. The following three test files also involve entry points with different annotations, the same run lines, and only slightly different CHECK directives. I won't insist, but you might consider consolidating the entry points into one file, renaming the entry functions differently, and adding run lines with corresponding -E main2 flags as well as --check-prefixes flags to FileCheck where needed.

Suggested change
// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 -DCAPABILITY_ON_INSTRUCTION %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 -DCAPABILITY_ON_INSTRUCTION -fcgl %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 -E main2 %s -spirv | FileCheck %s
// RUN: %dxc -T ps_6_0 -E main -fspv-target-env=vulkan1.3 -E main2 -fcgl %s -spirv | FileCheck %s


// CHECK: OpDecorate %gl_PrimitiveID BuiltIn PrimitiveId

#ifdef CAPABILITY_ON_INSTRUCTION

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#ifdef CAPABILITY_ON_INSTRUCTION

float4 main(uint id : SV_PrimitiveID) : SV_Target {
return copyId(id);
}
#else

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#else

#else
[[vk::ext_capability(/* MeshShadingEXT */ 5283)]]
[[vk::ext_extension("SPV_EXT_mesh_shader")]]
float4 main(uint id : SV_PrimitiveID) : SV_Target {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
float4 main(uint id : SV_PrimitiveID) : SV_Target {
float4 main2(uint id : SV_PrimitiveID) : SV_Target {

float4 main(uint id : SV_PrimitiveID) : SV_Target {
return id;
}
#endif

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
#endif

This branch has not been deployed

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

Labels

None yet

Projects

Status: In progress

Development

Successfully merging this pull request may close these issues.

4 participants