@@ -2475,6 +2475,32 @@ static LayoutSize GetElementCount(IntVal* val)
24752475 }
24762476 else if (const auto varRefVal = as<DeclRefIntVal>(val))
24772477 {
2478+ // Check if this is a specialization constant
2479+ if (auto declRef = varRefVal->getDeclRef ())
2480+ {
2481+ auto varDecl = declRef.as <VarDeclBase>();
2482+ if (varDecl && (varDecl.getDecl ()->hasModifier <SpecializationConstantAttribute>() ||
2483+ varDecl.getDecl ()->hasModifier <VkConstantIdAttribute>()))
2484+ {
2485+ // Specialization constants can be overridden at pipeline-creation time
2486+ // (e.g., in vkCreateComputePipelines), so we cannot rely on their default values
2487+ // during layout calculation. The actual runtime value may differ from the default,
2488+ // and the default itself could even be zero.
2489+ //
2490+ // We treat specialization-constant-sized arrays as "unbounded" (infinite) for
2491+ // layout purposes to ensure descriptor bindings are allocated regardless of the
2492+ // default value:
2493+ // - If default is 0 but runtime is 128, we still need the binding
2494+ // - The containing type must be recognized as having uniform data
2495+ // - Descriptor set/binding allocation is independent of array size
2496+ // - Array sizes are expressed symbolically (via OpSpecConstantOp) during SPIR-V
2497+ // emission, then evaluated to concrete bytes at pipeline-creation time
2498+ //
2499+ // This differs from generic parameters, which are resolved at Slang compile-time
2500+ return LayoutSize::infinite ();
2501+ }
2502+ }
2503+
24782504 // TODO: We want to treat the case where the number of
24792505 // elements in an array depends on a generic parameter
24802506 // much like the case where the number of elements is
0 commit comments