[Vulkan] Fix SPIR-V 1.4+ entry-point interfaces - #20028
Conversation
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.
There was a problem hiding this comment.
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.
| # 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. |
There was a problem hiding this comment.
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.
| # 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.
|
FYI, this is completely ChatGPT/Codex generated. I was just experimenting with it and it found this issue. HTH. |
| binary_path = tmp_path / "storage_buffer.spv" | ||
| assembly_path.write_text(assembly, encoding="utf-8") | ||
|
|
||
| # Reassembling the generated instructions for SPIR-V 1.5 |
There was a problem hiding this comment.
given this depends on spriv tools, i would skip this test, instead rely on local validaiton that the patch works
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.
What changed
This updates Vulkan code generation for targets requesting SPIR-V 1.4 or newer:
max_spirv_versionintoSPIRVSupportand emit that version in the SPIR-V header;OpEntryPointinterface list for SPIR-V 1.4+;Why this is necessary
SPIR-V 1.4 changed the
OpEntryPointcontract: 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:
Local validation used the smallest useful kernel,
B[0] = A[0] + 1. Its generated instructions were reassembled withspirv-as --target-env spv1.5and independently validated withspirv-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:
Validation
Built TVM's Vulkan and LLVM-enabled compiler successfully.
Ran the complete repository lint suite:
Ran the complete Vulkan codegen test module:
Confirmed
git diff --checkpasses.