-
Notifications
You must be signed in to change notification settings - Fork 405
Change Conditional<> to Use Vector internally #9655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR fixes a SPIR-V validation error that occurs when using Conditional<float, true> with the SV_Depth semantic. The issue arises because Conditional<T, true> internally expands to a single-element array T[1], but Vulkan's SPIR-V specification requires FragDepth to be a scalar float, not an array.
Changes:
- Added a new legalization pass
legalizeDepthOutputTypes()that transforms depth-related outputs from pointer-to-single-element-array to pointer-to-scalar - Added helper function
isDepthSystemValue()to identify depth-related system value semantics - Added test case to verify the fix generates valid SPIR-V with scalar FragDepth
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| tests/bugs/conditional-sv-depth.slang | Regression test that verifies Conditional<float, true> with SV_Depth generates valid SPIR-V with scalar FragDepth variable |
| source/slang/slang-ir-spirv-legalize.cpp | Implements legalization pass to unwrap single-element arrays from depth outputs, fixing store/load instructions to maintain correct types |
|
/format |
|
🌈 Formatted, please merge the changes from this PR |
Automated code formatting for #9655 Co-authored-by: slangbot <[email protected]>
|
|
||
| // Legalize depth output types before other processing. | ||
| // This unwraps single-element arrays from SV_Depth system values. | ||
| legalizeDepthOutputTypes(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am wondering the legalization may need to happen in another place.
| legalizeSystemValueParameters(entryPoint); |
Automated code formatting for #9655 Co-authored-by: slangbot <[email protected]>
2a6e27d to
b28de5d
Compare
## Problem When using `Conditional<float, true>` with the `SV_Depth` semantic, the SPIR-V emitter was generating invalid SPIR-V code. The issue stemmed from `Conditional<T, hasValue>` being implemented using `T[hasValue]` (arrays), which caused: 1. **Invalid SPIR-V for FragDepth**: Vulkan requires `gl_FragDepth` to be a scalar `float`, but the array-based implementation resulted in an array type pointer 2. **Type layout crashes**: Non-constant array sizes in conditionals caused crashes during varying parameter processing when `getIntVal()` expected a compile-time constant Related to #9578 ## Solution ### 1. Change Conditional Implementation to Use Vectors **Before:** ```slang struct Conditional<T, bool hasValue> { internal T storage[hasValue]; // ... } ``` **After:** ```slang struct Conditional<T, bool hasValue> { internal vector<T, hasValue ? 1 : 0> storage; // ... } ``` This change: - Uses `vector<T, 1>` when `hasValue = true` (which gets legalized to scalar `T`) - Uses `vector<T, 0>` when `hasValue = false` (which gets legalized to void) ### 2. Implement 0-Length Vector Legalization Added comprehensive support for 0-length vectors in `slang-ir-legalize-vector-types.cpp`: - **Detection**: Added `is0Vector()` and related helper functions - **Value operations**: Operations that create or access 0-vectors are replaced with appropriate values: - `IRMakeVector` / `IRMakeVectorFromScalar` → `void` value - `IRGetElement` / `IRSwizzle` → `poison` (undefined behavior) - `IRGetElementPtr` → `poison` - `IRSwizzledStore` → removed (no-op) - **Type replacement**: 0-vector types are replaced with `IRVoidType` ### 3. Fix Type Layout for Non-Constant Vector Sizes Added safety checks in `slang-type-layout.cpp` to handle vectors with non-constant element counts: ```cpp auto elementCountVal = context.tryResolveLinkTimeVal(vecType->getElementCount()); if (!as<ConstantIntVal>(elementCountVal)) { // Fall back to default layout, defer to IR legalization RefPtr<TypeLayout> typeLayout = new TypeLayout(); typeLayout->type = type; typeLayout->rules = rules; return TypeLayoutResult(typeLayout, element.info); } ``` This prevents crashes in two locations: - General type layout creation (line ~5346) - Varying parameter layout creation (line ~6052) ### 4. Move Vector Legalization Pass Earlier Moved `legalizeVectorTypes` to run immediately after `legalizeEmptyArray` and before resource/existential type legalization. This ensures: - 0-vectors are eliminated before they can cause issues in downstream passes - Consistent with the empty array handling approach ### 5. Update Validation Updated `slang-ir-validate.cpp` to allow 0-length vectors as they are now used internally for conditional varying values and will be legalized away. ## Testing - ✅ Added `tests/bugs/conditional-sv-depth.slang` - Verifies correct SPIR-V generation for `Conditional<float, true>` with `SV_Depth` - ✅ Updated `tests/diagnostics/invalid-vector-element-count.slang` - Removed error check for 0-length vectors as they're now valid internally - ✅ Existing tests pass with the new implementation ## Impact - **Breaking Changes**: None for user code - this is an internal implementation detail - **Performance**: Minimal - 1-vectors and 0-vectors are legalized to more efficient representations - **Targets**: All targets benefit from proper legalization, especially SPIR-V/Vulkan ## Key Files Changed - `source/slang/core.meta.slang` - Conditional implementation change - `source/slang/slang-ir-legalize-vector-types.cpp` - 0-vector legalization - `source/slang/slang-type-layout.cpp` - Non-constant vector size handling - `source/slang/slang-emit.cpp` - Pass ordering - `source/slang/slang-ir-validate.cpp` - Validation update --------- Co-authored-by: slangbot <[email protected]> Co-authored-by: slangbot <[email protected]>
Problem
When using
Conditional<float, true>with theSV_Depthsemantic, the SPIR-V emitter was generating invalid SPIR-V code. The issue stemmed fromConditional<T, hasValue>being implemented usingT[hasValue](arrays), which caused:gl_FragDepthto be a scalarfloat, but the array-based implementation resulted in an array type pointergetIntVal()expected a compile-time constantRelated to #9578
Solution
1. Change Conditional Implementation to Use Vectors
Before:
After:
This change:
vector<T, 1>whenhasValue = true(which gets legalized to scalarT)vector<T, 0>whenhasValue = false(which gets legalized to void)2. Implement 0-Length Vector Legalization
Added comprehensive support for 0-length vectors in
slang-ir-legalize-vector-types.cpp:is0Vector()and related helper functionsIRMakeVector/IRMakeVectorFromScalar→voidvalueIRGetElement/IRSwizzle→poison(undefined behavior)IRGetElementPtr→poisonIRSwizzledStore→ removed (no-op)IRVoidType3. Fix Type Layout for Non-Constant Vector Sizes
Added safety checks in
slang-type-layout.cppto handle vectors with non-constant element counts:This prevents crashes in two locations:
4. Move Vector Legalization Pass Earlier
Moved
legalizeVectorTypesto run immediately afterlegalizeEmptyArrayand before resource/existential type legalization. This ensures:5. Update Validation
Updated
slang-ir-validate.cppto allow 0-length vectors as they are now used internally for conditional varying values and will be legalized away.Testing
tests/bugs/conditional-sv-depth.slang- Verifies correct SPIR-V generation forConditional<float, true>withSV_Depthtests/diagnostics/invalid-vector-element-count.slang- Removed error check for 0-length vectors as they're now valid internallyImpact
Key Files Changed
source/slang/core.meta.slang- Conditional implementation changesource/slang/slang-ir-legalize-vector-types.cpp- 0-vector legalizationsource/slang/slang-type-layout.cpp- Non-constant vector size handlingsource/slang/slang-emit.cpp- Pass orderingsource/slang/slang-ir-validate.cpp- Validation update