diff options
| author | kaizhangNV <149626564+kaizhangNV@users.noreply.github.com> | 2024-03-27 13:30:34 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-27 13:30:34 -0700 |
| commit | 56928794d0800824dc91e150cb345b5fec24d930 (patch) | |
| tree | 63f07c0dfad1eb998a683f089755280fde1cc73b /source | |
| parent | b346a9333ae6d09f053db60b3006e6e074332ac2 (diff) | |
Fix incorrect SPV stride for unsized array (#3837)
* Fix incorrect SPV stride for unsized array (#3825)
In '-emit-spirv-directly' mode, slang generates the stride 0
for unsized array in `OpDecorate` instructions.
For unsized array, the stride is invalid, but we need to provide
a non-zero value to pass the spirv validator.
* Decorate struct with unsized array field as 'Block'
For the struct having unsized array fields, it has to be decorated
as "Block", otherwise it will fails the spirv-val.
So we add a check at in 'emitGlobalInst' when emitting spirv for
'kIROp_StructType', where if there is unsized array field inside
the struct, emit a decorate instruction for above purpose.
* Update decoration for kIROp_SizeAndAlignmentDecoration
When add a decoration node for kIROp_SizeAndAlignmentDecoration,
we implicitly convert the 64 bit size to 32 bit. In most cases, this
should not be a problem because we won't have that large data type.
However, we use 64-bit -1 to represent the size of unsized-array,
so in that case, the conversion will change the size to 0, which is
incorrect. So change that decoration to use 64-bit size.
---------
Co-authored-by: Yong He <yonghe@outlook.com>
Diffstat (limited to 'source')
| -rw-r--r-- | source/slang/slang-emit-spirv.cpp | 29 | ||||
| -rw-r--r-- | source/slang/slang-ir-insts.h | 1 | ||||
| -rw-r--r-- | source/slang/slang-ir-layout.cpp | 3 | ||||
| -rw-r--r-- | source/slang/slang-ir.cpp | 5 |
4 files changed, 35 insertions, 3 deletions
diff --git a/source/slang/slang-emit-spirv.cpp b/source/slang/slang-emit-spirv.cpp index ddcd5ae4d..ae7c9bcc8 100644 --- a/source/slang/slang-emit-spirv.cpp +++ b/source/slang/slang-emit-spirv.cpp @@ -1415,12 +1415,21 @@ struct SPIRVEmitContext if (m_decoratedSpvInsts.add(getID(resultSpvType))) { IRSizeAndAlignment sizeAndAlignment; - getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), ptrType->getValueType(), &sizeAndAlignment); + uint32_t stride; + + getNaturalSizeAndAlignment(m_targetProgram->getOptionSet(), valueType, &sizeAndAlignment); + uint64_t valueSize = sizeAndAlignment.size; + + // Any unsized data type (e.g. struct or array) will have size of kIndeterminateSize, + // in such case the stride is invalid, so we have to provide a non-zero value to pass the + // spirv validator. + stride = (valueSize >= (uint64_t)sizeAndAlignment.kIndeterminateSize) ? + 0xFFFF : (uint32_t)sizeAndAlignment.getStride(); emitOpDecorateArrayStride( getSection(SpvLogicalSectionID::Annotations), nullptr, resultSpvType, - SpvLiteralInteger::from32((uint32_t)sizeAndAlignment.getStride())); + SpvLiteralInteger::from32(stride)); } } return resultSpvType; @@ -1431,12 +1440,28 @@ struct SPIRVEmitContext { List<IRType*> types; for (auto field : static_cast<IRStructType*>(inst)->getFields()) + { types.add(field->getFieldType()); + } auto spvStructType = emitOpTypeStruct( inst, types ); emitDecorations(inst, getID(spvStructType)); + + auto structType = as<IRStructType>(inst); + uint64_t structSize = 0; + if (auto layoutDecor = structType->findDecoration<IRSizeAndAlignmentDecoration>()) + { + structSize = layoutDecor->getSize(); + } + + if (structSize >= (uint64_t)IRSizeAndAlignment::kIndeterminateSize) + { + IRBuilder builder(inst); + auto decoration = builder.addDecoration(inst, kIROp_SPIRVBlockDecoration); + emitDecoration(getID(spvStructType), decoration); + } emitLayoutDecorations(as<IRStructType>(inst), getID(spvStructType)); return spvStructType; } diff --git a/source/slang/slang-ir-insts.h b/source/slang/slang-ir-insts.h index c884dd35f..51129c28f 100644 --- a/source/slang/slang-ir-insts.h +++ b/source/slang/slang-ir-insts.h @@ -3323,6 +3323,7 @@ public: IRBasicType* getVoidType(); IRBasicType* getBoolType(); IRBasicType* getIntType(); + IRBasicType* getInt64Type(); IRBasicType* getUIntType(); IRBasicType* getUInt64Type(); IRBasicType* getCharType(); diff --git a/source/slang/slang-ir-layout.cpp b/source/slang/slang-ir-layout.cpp index 313761d2c..3ac022f68 100644 --- a/source/slang/slang-ir-layout.cpp +++ b/source/slang/slang-ir-layout.cpp @@ -363,11 +363,12 @@ Result getSizeAndAlignment(CompilerOptionSet& optionSet, IRTypeLayoutRules* rule IRBuilder builder(module); auto intType = builder.getIntType(); + auto int64Type = builder.getInt64Type(); builder.addDecoration( type, kIROp_SizeAndAlignmentDecoration, builder.getIntValue(intType, (IRIntegerValue)rules->ruleName), - builder.getIntValue(intType, sizeAndAlignment.size), + builder.getIntValue(int64Type, sizeAndAlignment.size), builder.getIntValue(intType, sizeAndAlignment.alignment)); } diff --git a/source/slang/slang-ir.cpp b/source/slang/slang-ir.cpp index 104735c3e..68c6a33b3 100644 --- a/source/slang/slang-ir.cpp +++ b/source/slang/slang-ir.cpp @@ -2649,6 +2649,11 @@ namespace Slang return (IRBasicType*)getType(kIROp_IntType); } + IRBasicType* IRBuilder::getInt64Type() + { + return (IRBasicType*)getType(kIROp_Int64Type); + } + IRBasicType* IRBuilder::getUIntType() { return (IRBasicType*)getType(kIROp_UIntType); |
