summaryrefslogtreecommitdiffstats
path: root/source/slang
diff options
context:
space:
mode:
authorHarsh Aggarwal (NVIDIA) <haaggarwal@nvidia.com>2025-09-10 17:31:36 +0530
committerGitHub <noreply@github.com>2025-09-10 12:01:36 +0000
commit3d0f5ee55788dca324641ae9268ee37dc4d7d9d5 (patch)
tree71100ca80c7646853858cd4e244f971d6485ee6c /source/slang
parent2020a102e9e0ea2f39a0f2b2a75085c3607ce734 (diff)
CUDA: Fix compiler crash with unsized array field - nonuniformres-as-… (#8380)
…function-parameter.slang #8315 Root Cause: CUDA compilation crashed with `assert failure: !seenFinalUnsizedArrayField` because unsized arrays like `RWStructuredBuffer<uint> globalBuffer[]` were not the final field in generated parameter structs, violating the layout constraint in slang-ir-layout.cpp. Fix: Extended `collectGlobalUniformParameters` to automatically reorder struct fields for CUDA targets - regular fields first, unsized arrays last. Other targets preserve original order. Impact: - Enables CUDA support for nonuniform resource indexing as function parameters - Zero impact on existing GLSL/HLSL/SPIRV targets - Automatic handling - no manual parameter reordering required Files: slang-emit.cpp, slang-ir-collect-global-uniforms.cpp/.h, test file --------- Co-authored-by: slangbot <ellieh+slangbot@nvidia.com> Co-authored-by: slangbot <186143334+slangbot@users.noreply.github.com> Co-authored-by: Ellie Hermaszewska <ellieh@nvidia.com>
Diffstat (limited to 'source/slang')
-rw-r--r--source/slang/slang-emit.cpp2
-rw-r--r--source/slang/slang-ir-collect-global-uniforms.cpp49
-rw-r--r--source/slang/slang-ir-collect-global-uniforms.h5
3 files changed, 52 insertions, 4 deletions
diff --git a/source/slang/slang-emit.cpp b/source/slang/slang-emit.cpp
index f5b818c5d..31e6d17be 100644
--- a/source/slang/slang-emit.cpp
+++ b/source/slang/slang-emit.cpp
@@ -802,7 +802,7 @@ Result linkAndOptimizeIR(
// can assume that all ordinary/uniform data is strictly
// passed using constant buffers.
//
- collectGlobalUniformParameters(irModule, outLinkedIR.globalScopeVarLayout);
+ collectGlobalUniformParameters(irModule, outLinkedIR.globalScopeVarLayout, target);
#if 0
dumpIRIfEnabled(codeGenContext, irModule, "GLOBAL UNIFORMS COLLECTED");
#endif
diff --git a/source/slang/slang-ir-collect-global-uniforms.cpp b/source/slang/slang-ir-collect-global-uniforms.cpp
index fb2a2233c..aad0de44f 100644
--- a/source/slang/slang-ir-collect-global-uniforms.cpp
+++ b/source/slang/slang-ir-collect-global-uniforms.cpp
@@ -49,6 +49,7 @@ struct CollectGlobalUniformParametersContext
//
IRModule* module;
IRVarLayout* globalScopeVarLayout;
+ CodeGenTarget target = CodeGenTarget::Unknown;
IRGlobalParam* _getGlobalParamFromLayoutFieldKey(IRInst* key)
{
@@ -174,7 +175,47 @@ struct CollectGlobalUniformParametersContext
// parameters that were present in the layout information (they are
// represented as the fields of the global-scope `struct` layout).
//
- for (auto fieldLayoutAttr : globalParamsStructTypeLayout->getFieldLayoutAttrs())
+ // For CUDA targets, we need to ensure unsized arrays come last to satisfy
+ // the layout constraint in slang-ir-layout.cpp
+ auto fieldAttrs = globalParamsStructTypeLayout->getFieldLayoutAttrs();
+
+ // Create ordered field list - for CUDA, put unsized arrays last
+ List<IRStructFieldLayoutAttr*> orderedFields;
+
+ if (target == CodeGenTarget::CUDASource)
+ {
+ // For CUDA: separate regular and unsized array fields
+ List<IRStructFieldLayoutAttr*> regularFields;
+ List<IRStructFieldLayoutAttr*> unsizedArrayFields;
+
+ for (auto fieldLayoutAttr : fieldAttrs)
+ {
+ auto globalParam =
+ _getGlobalParamFromLayoutFieldKey(fieldLayoutAttr->getFieldKey());
+ if (globalParam && as<IRUnsizedArrayType>(globalParam->getDataType()))
+ {
+ unsizedArrayFields.add(fieldLayoutAttr);
+ }
+ else
+ {
+ regularFields.add(fieldLayoutAttr);
+ }
+ }
+
+ // Add regular fields first, then unsized arrays
+ for (auto field : regularFields)
+ orderedFields.add(field);
+ for (auto field : unsizedArrayFields)
+ orderedFields.add(field);
+ }
+ else
+ {
+ // For other targets: preserve original order
+ for (auto field : fieldAttrs)
+ orderedFields.add(field);
+ }
+
+ for (auto fieldLayoutAttr : orderedFields)
{
// We expect the IR layout pass to have encoded field per-field
// layout so that the "key" for the field is the corresponding
@@ -339,11 +380,15 @@ struct CollectGlobalUniformParametersContext
}
};
-void collectGlobalUniformParameters(IRModule* module, IRVarLayout* globalScopeVarLayout)
+void collectGlobalUniformParameters(
+ IRModule* module,
+ IRVarLayout* globalScopeVarLayout,
+ CodeGenTarget target)
{
CollectGlobalUniformParametersContext context;
context.module = module;
context.globalScopeVarLayout = globalScopeVarLayout;
+ context.target = target;
context.processModule();
}
diff --git a/source/slang/slang-ir-collect-global-uniforms.h b/source/slang/slang-ir-collect-global-uniforms.h
index 76f56f074..5f9393a9b 100644
--- a/source/slang/slang-ir-collect-global-uniforms.h
+++ b/source/slang/slang-ir-collect-global-uniforms.h
@@ -11,6 +11,9 @@ struct IRVarLayout;
/// Collect global-scope shader parameters that use uniform/ordinary
/// storage into a single `struct` (possibly wrapped in a constant buffer).
///
-void collectGlobalUniformParameters(IRModule* module, IRVarLayout* globalScopeVarLayout);
+void collectGlobalUniformParameters(
+ IRModule* module,
+ IRVarLayout* globalScopeVarLayout,
+ CodeGenTarget target = CodeGenTarget::Unknown);
} // namespace Slang