Skip to content

[Vulkan] Fix SPIR-V 1.4+ entry-point interfaces - #20028

Merged
tqchen merged 4 commits into
apache:mainfrom
wilx:vulkan12-entrypoint-interface-test
Jul 20, 2026
Merged

[Vulkan] Fix SPIR-V 1.4+ entry-point interfaces#20028
tqchen merged 4 commits into
apache:mainfrom
wilx:vulkan12-entrypoint-interface-test

Conversation

@wilx

@wilx wilx commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

What changed

This updates Vulkan code generation for targets requesting SPIR-V 1.4 or newer:

  • propagate max_spirv_version into SPIRVSupport and emit that version in the SPIR-V header;
  • track storage-buffer arguments, uniform buffers, push constants, and other module-scope variables;
  • include those variables in the OpEntryPoint interface list for SPIR-V 1.4+;
  • retain TVM's historical SPIR-V 1.0 output for older targets.

Why this is necessary

SPIR-V 1.4 changed the OpEntryPoint contract: every module-scope variable used by an entry point must be listed in its interface operands. TVM previously listed only built-in variables.

TVM also always emitted a SPIR-V 1.0 header, even when the Vulkan target advertised SPIR-V 1.5. That caused validation to use the older rules and masked the incomplete interface list. Reassembling a generated storage-buffer kernel as SPIR-V 1.5 and validating it for Vulkan 1.2 produced:

Interface variable id <4> is used by entry point 'main_kernel' id <2>,
but is not listed as an interface
%A_ptr = OpVariable ... StorageBuffer

Local validation used the smallest useful kernel, B[0] = A[0] + 1. Its generated instructions were reassembled with spirv-as --target-env spv1.5 and independently validated with spirv-val --target-env vulkan1.2. This external-tool validation is intentionally not part of the Python test suite.

After the fix, its entry point contains both storage buffers:

OpEntryPoint GLCompute ... "main_kernel" %BuiltInLocalInvocationId %A_ptr %B_ptr

Validation

  • Built TVM's Vulkan and LLVM-enabled compiler successfully.

  • Ran the complete repository lint suite:

    pre-commit run --all-files
    All hooks passed
    
  • Ran the complete Vulkan codegen test module:

    30 passed, 24 skipped
    
  • Confirmed git diff --check passes.

wilx added 2 commits July 18, 2026 20:42
Add a minimal one-element storage-buffer kernel to the Vulkan codegen tests and validate its generated instructions as SPIR-V 1.5 under Vulkan 1.2 rules. This isolates the conformance failure where storage-buffer variables used by the kernel are omitted from the OpEntryPoint interface list.\n\nTVM currently emits a SPIR-V 1.0 header even when the target advertises SPIR-V 1.5, which masks the stricter Vulkan 1.2 validation rule. The test therefore reassembles the generated text for SPIR-V 1.5 before invoking spirv-val. It verifies the exact known diagnostic and records it as an expected failure, while allowing unrelated assembler or validator failures to fail normally. Once code generation includes the storage-buffer variables, the test will pass without the expected-failure path.
Vulkan 1.2 uses SPIR-V 1.5 validation rules, which require every module-scope variable used by an entry point to appear in that OpEntryPoint interface list. TVM previously always wrote a SPIR-V 1.0 header and listed only built-in variables. The old header masked the stricter rule, while reassembling the same instructions as SPIR-V 1.5 correctly rejected ordinary storage-buffer kernels.\n\nPropagate max_spirv_version from the target into SPIRVSupport and emit the requested header version for SPIR-V 1.4 and newer. Preserve the historical 1.0 header for older targets so extension-based code generation remains unchanged. Track buffer arguments, push constants, uniform buffers, and non-function allocations as module-scope entry-point interfaces, and append them for SPIR-V 1.4+ alongside the existing built-ins.\n\nTurn the minimal Vulkan 1.2 reproducer into a passing regression test. It now requires a SPIR-V 1.5 header and independently reassembles and validates the generated one-element storage-buffer kernel with spirv-val under Vulkan 1.2 rules.

@gemini-code-assist gemini-code-assist Bot 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.

Code Review

This pull request updates the Vulkan SPIR-V code generator to support and emit SPIR-V versions 1.4 and above, rather than hardcoding SPIR-V 1.0. Specifically, it adds support for tracking and emitting module-scope variables in the OpEntryPoint interface list, which is required starting with SPIR-V 1.4. It also introduces a max_spirv_version target attribute and adds a test to validate SPIR-V 1.5 output. The review feedback correctly points out an outdated comment in the new test file that should be updated to reflect the new behavior.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +131 to +133
# TVM currently emits a SPIR-V 1.0 header even when the target supports
# SPIR-V 1.5. Reassembling the generated instructions for SPIR-V 1.5
# makes spirv-val enforce the Vulkan 1.2 entry-point interface rules.

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.

medium

The comment states that 'TVM currently emits a SPIR-V 1.0 header even when the target supports SPIR-V 1.5.' However, this PR specifically fixes this behavior so that TVM now correctly emits the requested SPIR-V version (e.g., 1.5) in the header. This comment should be updated to reflect the new correct behavior.

Suggested change
# TVM currently emits a SPIR-V 1.0 header even when the target supports
# SPIR-V 1.5. Reassembling the generated instructions for SPIR-V 1.5
# makes spirv-val enforce the Vulkan 1.2 entry-point interface rules.
# Reassembling the generated instructions for SPIR-V 1.5
# makes spirv-val enforce the Vulkan 1.2 entry-point interface rules.

Update the regression-test comment now that the generated header correctly advertises SPIR-V 1.5, and accept the repository's pinned clang-format output for max_spirv_version propagation.\n\nThe complete pre-commit suite and Vulkan codegen tests pass after this cleanup.
@wilx

wilx commented Jul 18, 2026

Copy link
Copy Markdown
Contributor Author

FYI, this is completely ChatGPT/Codex generated. I was just experimenting with it and it found this issue. HTH.

@wilx
wilx marked this pull request as ready for review July 18, 2026 19:00
binary_path = tmp_path / "storage_buffer.spv"
assembly_path.write_text(assembly, encoding="utf-8")

# Reassembling the generated instructions for SPIR-V 1.5

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

given this depends on spriv tools, i would skip this test, instead rely on local validaiton that the patch works

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Removed.

Remove the Vulkan 1.2 regression test that shells out to spirv-as and spirv-val, as requested in review. The generated SPIR-V 1.5 module and entry-point interfaces remain validated locally and documented in the pull request without adding external executable requirements to the Python test suite.
@tqchen
tqchen merged commit 551be33 into apache:main Jul 20, 2026
8 checks passed
@wilx
wilx deleted the vulkan12-entrypoint-interface-test branch July 24, 2026 23:14
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.

2 participants