diff --git a/renderdoc/driver/vulkan/vk_postvs.cpp b/renderdoc/driver/vulkan/vk_postvs.cpp index b3156850e..a5f0e2f7b 100644 --- a/renderdoc/driver/vulkan/vk_postvs.cpp +++ b/renderdoc/driver/vulkan/vk_postvs.cpp @@ -1443,6 +1443,55 @@ struct OutMeshletLayout uint32_t primArrayLength; }; +static void LayOutStorageStruct(rdcspv::Editor &editor, const rdcarray &specInfo, + rdcspv::SparseIdMap &outputTypeReplacements, + const rdcspv::DataType &type, rdcspv::Id &structType, + uint32_t &byteSize); + +static rdcspv::Id GetArraySizeAndAlign(rdcspv::Editor &editor, const rdcarray &specInfo, + rdcspv::SparseIdMap &outputTypeReplacements, + const rdcspv::DataType &type, uint32_t &size) +{ + const rdcspv::DataType &arrayInnerType = editor.GetDataType(type.InnerType()); + + rdcspv::Id innerId; + + // handle arrays-of-arrays and arrays-of-struts + if(arrayInnerType.type == rdcspv::DataType::StructType) + { + innerId = arrayInnerType.InnerType(); + LayOutStorageStruct(editor, specInfo, outputTypeReplacements, + editor.GetDataType(arrayInnerType.InnerType()), innerId, size); + } + else if(arrayInnerType.type == rdcspv::DataType::ArrayType) + { + innerId = GetArraySizeAndAlign(editor, specInfo, outputTypeReplacements, + editor.GetDataType(arrayInnerType.InnerType()), size); + } + else + { + size = VarTypeByteSize(arrayInnerType.scalar().Type()); + if(arrayInnerType.type == rdcspv::DataType::VectorType) + size *= arrayInnerType.vector().count; + + // use the same type, nothing changed + innerId = type.InnerType(); + } + + // make a new array type so we can decorate it with a stride + rdcspv::Id memberTypeId = + editor.AddType(rdcspv::OpTypeArray(editor.MakeId(), innerId, type.length)); + outputTypeReplacements[type.id] = memberTypeId; + editor.SetName(memberTypeId, StringFormat::Fmt("stridedArray%d", type.id.value())); + + editor.AddDecoration(rdcspv::OpDecorate( + memberTypeId, rdcspv::DecorationParam(size))); + + size *= editor.EvaluateConstant(type.length, specInfo).value.u32v[0]; + + return memberTypeId; +} + static void LayOutStorageStruct(rdcspv::Editor &editor, const rdcarray &specInfo, rdcspv::SparseIdMap &outputTypeReplacements, const rdcspv::DataType &type, rdcspv::Id &structType, @@ -1468,9 +1517,6 @@ static void LayOutStorageStruct(rdcspv::Editor &editor, const rdcarray(size))); - - offset += size * editor.EvaluateConstant(childType.length, specInfo).value.u32v[0]; - } - else - { - offset += size; - } + offset += size; members.push_back(memberTypeId); } @@ -2290,9 +2317,43 @@ static void AddMeshShaderOutputStores(const ShaderReflection &refl, stride, }; } + else if(type.type == rdcspv::DataType::ArrayType) + { + // handle arrays-of-arrays and arrays-of-structs here + arrayInnerType = GetArraySizeAndAlign(editor, specInfo, outputTypeReplacements, type, byteSize); + + stride = byteSize; + + outputTypeReplacements[type.id] = arrayInnerType; + + uint32_t offset = 0; + bool perPrim = false; + + if(d.others.contains(rdcspv::Decoration::PerPrimitiveEXT)) + { + primOutByteCount = AlignUp16(primOutByteCount); + offset = primOutByteCount; + perPrim = true; + primOutByteCount += byteSize * arrayLength; + } + else + { + vertOutByteCount = AlignUp16(vertOutByteCount); + offset = vertOutByteCount; + perPrim = false; + vertOutByteCount += byteSize * arrayLength; + } + + outputGlobals[var.id] = { + offset, + perPrim, + false, + byteSize, + }; + } else { - // loose variable + // loose variable, vector/matrix/scalar const uint32_t scalarAlign = VarTypeByteSize(type.scalar().Type()); byteSize = scalarAlign; if(type.type == rdcspv::DataType::VectorType)