summaryrefslogtreecommitdiffstats
path: root/source/slang/slang-emit-spirv.cpp
diff options
context:
space:
mode:
authorkaizhangNV <149626564+kaizhangNV@users.noreply.github.com>2024-03-27 13:30:34 -0700
committerGitHub <noreply@github.com>2024-03-27 13:30:34 -0700
commit56928794d0800824dc91e150cb345b5fec24d930 (patch)
tree63f07c0dfad1eb998a683f089755280fde1cc73b /source/slang/slang-emit-spirv.cpp
parentb346a9333ae6d09f053db60b3006e6e074332ac2 (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/slang/slang-emit-spirv.cpp')
-rw-r--r--source/slang/slang-emit-spirv.cpp29
1 files changed, 27 insertions, 2 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;
}