Skip to content

spirv-val: Add VUID 04681 check for specialization constant initializers - #6948

Open
Tyagiquamar wants to merge 3 commits into
KhronosGroup:mainfrom
Tyagiquamar:fix/vuid-spec-constant-initializer-04681
Open

Tyagiquamar wants to merge 3 commits into
KhronosGroup:mainfrom
Tyagiquamar:fix/vuid-spec-constant-initializer-04681

Conversation

@Tyagiquamar

@Tyagiquamar Tyagiquamar commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #6603.

Root Cause

VUID-StandaloneSpirv-Function-04681 requires that a type T which is an array sized with a specialization constant must neither be, nor be contained in, the type T2 of a variable V, unless one of the listed exceptions applies (T equals T2, Function/Private, non-Block Workgroup, or arrayed interface IO where T is the member of T2).

The Constant decoration is Kernel-only and is not valid in Vulkan, so it must not be part of this check.

Changes

  1. source/val/validation_state.cpp: map 4681 to VUID-StandaloneSpirv-Function-04681.
  2. source/val/validate_memory.cpp: in ValidateVariableVulkanArray, enforce the array containment rule with the VU exceptions. Interface arrayness matches validate_interfaces.cpp and requires the variable to appear in an OpEntryPoint interface list.
  3. test/val/val_memory_test.cpp: positive and negative coverage for Uniform/StorageBuffer/PushConstant/Workgroup Block (bad), Function/Private/non-Block Workgroup/equal-type/Geometry and TessellationControl arrayed inputs (good), Vertex nested and Geometry output nested (bad).

Verification

  • Relies on GitHub PR CI (Bazel build/test) after push of ec8b24e8.
  • Prior focused Docker ValidateMemory.VulkanSpecConstant* runs were green on the previous commit; this push adds tests and tightens interface matching.

Check that an OpVariable with a specialization constant initializer
either has an OpDecorate with Constant or is in the Function storage
class in Vulkan environments (VUID-StandaloneSpirv-Function-04681).

Fixes KhronosGroup#6603.
Comment thread source/val/validate_memory.cpp Outdated
Comment on lines +470 to +471
if (storage_class != spv::StorageClass::Function &&
!_.HasDecoration(inst->id(), spv::Decoration::Constant)) {

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.

The Constant decoration is only allowed with the Kernel capability so it won't ever be in the Vulkan environment.

Separately, I don't see how this matches the VU:

A type T that is an array sized with a specialization constant must neither be, nor be contained in, the type T2 of a variable V, unless either: a) T is equal to T2, b) V is declared in the Function, or Private Storage Class, c) V is a non-Block variable in the Workgroup Storage Class, or d) V is an interface variable with an additional level of arrayness, as described in interface matching, and T is the member type of the array type T2

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.

Thanks for the correction. Constant decoration is Kernel-only, so it is not used for Vulkan.

The check now enforces VUID-StandaloneSpirv-Function-04681 as written: a spec-constant-sized array type T must not be (or be contained in) a variable type T2 unless (a) T equals T2, (b) Function/Private, (c) non-Block Workgroup, or (d) an OpEntryPoint interface variable with the extra interface-matching arrayness where T is the member of T2 (aligned with validate_interfaces.cpp).

Latest commit: ec8b24e

PTAL.

@Tyagiquamar

Copy link
Copy Markdown
Contributor Author

Updated the validation in commit 21fd663 to accurately enforce VUID-StandaloneSpirv-Function-04681:

  1. Removed the check on OpVariable initializers and OpDecorate Constant.
  2. Validated in ValidateVariableVulkanArray that a type T which is an array sized with a specialization constant must neither be, nor be contained in, the type T2 of a variable V, allowing the explicit exceptions:
    • T is equal to T2 (bare spec-constant array variable)
    • V is declared in Function or Private storage class
    • V is a non-Block variable in Workgroup storage class
    • V is an arrayed interface variable (e.g. Geometry/Tessellation per-vertex inputs or Mesh per-vertex outputs) where T is the member type of T2
  3. Added test coverage in val_memory_test.cpp covering each disallowed and allowed configuration.

Signed-off-by: Tyagiquamar <mohdquamartyagi@gmail.com>
@Tyagiquamar
Tyagiquamar force-pushed the fix/vuid-spec-constant-initializer-04681 branch from 21fd663 to 865d829 Compare October 12, 2026 12:50
@spencer-lunarg
spencer-lunarg self-requested a review October 12, 2026 16:47
Match the StandaloneSpirv VU exceptions without Constant decoration,
require OpEntryPoint interface listing for arrayed I/O, and cover
StorageBuffer, PushConstant, TessellationControl, and Geometry output.

Signed-off-by: Tyagiquamar <mohdquamartyagi@gmail.com>
@Tyagiquamar

Copy link
Copy Markdown
Contributor Author

Ready for review. Addressed the Constant-decoration feedback and aligned the check with VUID-StandaloneSpirv-Function-04681 in ec8b24e. PTAL.

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.

spirv-val: Add missing specialization constant check

2 participants