diff options
| author | Yong He <yonghe@outlook.com> | 2025-10-03 12:52:26 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-10-03 19:52:26 +0000 |
| commit | 6a2cf239a89340ed2985d04609499e8c4a2d8f89 (patch) | |
| tree | c80f3c8dc7e89762aeab0ee7830d1ad728665460 /source/slang/slang-ir-lower-buffer-element-type.h | |
| parent | cc8f6a241edb47c43c5698ee33abed4fe57d4566 (diff) | |
Fix legalization crash when processing metal parameter blocks. (#8591)
Closes #7606.
When Slang compile for a bindful target, we will run the resource type
legalization pass to hoist resource typed struct fields outside of the
struct type and define them as global parameters and passing them around
via dedicated function parameters.
When we compile for a bindless target, we don't run this pass.
However, Metal is a hybrid bindful and bindless target. We need to run
type legalization for the constant buffer, but skip type legalization
for parameter block.
The previous attempt to support this behavior is to hack the type
legalization pass to return `LegalVal::simple` when it sees a
`ParameterBlock<T>`. However, whenever the code is accessing
`parameterBlock.someNestedField`, the type of the nested field may get a
`LegalType::tuple`, and now we will run into inconsistent scenarios
where we have a `LegalVal::simple` on the operand val, and but the
legalization logic is expecting that val to be a `LegalType::tuple`.
This breaks a lot of assumptions and invariants in the type legalization
pass, resulting unstable/fragile behavior.
To systematically solve this problem, this change generalizes the
existing legalize buffer element type pass to translate
`ParameterBlock<Texture2D>` (and similar cases) to
`ParameterBlock<Texture2D.Handle>`. So that such parameter block will
always be legalized to `LegalType:::simple` during type legalization,
and we will never run into any inconsistent cases. This allowed us to
get rid of the hacky logic in the type legalization pass to try to
workaround the inconsistencies.
Diffstat (limited to 'source/slang/slang-ir-lower-buffer-element-type.h')
| -rw-r--r-- | source/slang/slang-ir-lower-buffer-element-type.h | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/source/slang/slang-ir-lower-buffer-element-type.h b/source/slang/slang-ir-lower-buffer-element-type.h index 9d6e53609..81ce73ddb 100644 --- a/source/slang/slang-ir-lower-buffer-element-type.h +++ b/source/slang/slang-ir-lower-buffer-element-type.h @@ -1,19 +1,28 @@ #ifndef SLANG_IR_LOWER_BUFFER_ELEMENT_TYPE_H #define SLANG_IR_LOWER_BUFFER_ELEMENT_TYPE_H +#include "slang.h" + namespace Slang { struct IRModule; class TargetProgram; struct IRTypeLayoutRules; struct IRType; +enum class IRTypeLayoutRuleName; -struct BufferElementTypeLoweringOptions +enum class BufferElementTypeLoweringPolicyKind { - bool lowerBufferPointer = true; + Default, + KhronosTarget, + MetalParameterBlock, + WGSL +}; - // For WGSL, we can only create arrays that has a stride of 16 bytes for constant buffers. - bool use16ByteArrayElementForConstantBuffer = false; +struct BufferElementTypeLoweringOptions +{ + BufferElementTypeLoweringPolicyKind loweringPolicyKind = + BufferElementTypeLoweringPolicyKind::Default; }; // For each struct type S used as element type of a ConstantBuffer, ParameterBlock or @@ -31,6 +40,8 @@ void lowerBufferElementTypeToStorageType( // Returns the type layout rules should be used for a buffer resource type. IRTypeLayoutRules* getTypeLayoutRuleForBuffer(TargetProgram* target, IRType* bufferType); +IRTypeLayoutRuleName getTypeLayoutRuleNameForBuffer(TargetProgram* target, IRType* bufferType); + } // namespace Slang #endif |
