public static ShaderType Parse(BytecodeReader reader, BytecodeReader typeReader, ShaderVersion target, int indent, bool isFirst, uint parentOffset) { var result = new ShaderType(indent, isFirst) { VariableClass = (ShaderVariableClass)typeReader.ReadUInt16(), VariableType = (ShaderVariableType)typeReader.ReadUInt16(), Rows = typeReader.ReadUInt16(), Columns = typeReader.ReadUInt16(), ElementCount = typeReader.ReadUInt16() }; var memberCount = typeReader.ReadUInt16(); var memberOffset = typeReader.ReadUInt32(); if (target.MajorVersion >= 5) { var subTypeOffset = typeReader.ReadUInt32(); // Guessing if (subTypeOffset != 0) { var parentTypeReader = reader.CopyAtOffset((int)subTypeOffset); result.SubType = ShaderType.Parse(reader, parentTypeReader, target, indent + 4, true, parentOffset); Debug.Assert( result.SubType.VariableClass == ShaderVariableClass.Vector || result.SubType.VariableClass == ShaderVariableClass.InterfaceClass); } var baseClassOffset = typeReader.ReadUInt32(); if (baseClassOffset != 0) { var baseClassReader = reader.CopyAtOffset((int)baseClassOffset); result.BaseClass = ShaderType.Parse(reader, baseClassReader, target, indent + 4, true, parentOffset); Debug.Assert( result.BaseClass.VariableClass == ShaderVariableClass.Scalar || result.BaseClass.VariableClass == ShaderVariableClass.Struct); } var interfaceCount = typeReader.ReadUInt32(); var interfaceSectionOffset = typeReader.ReadUInt32(); if (interfaceSectionOffset != 0) { var interfaceSectionReader = reader.CopyAtOffset((int)interfaceSectionOffset); for (int i = 0; i < interfaceCount; i++) { var interfaceTypeOffset = interfaceSectionReader.ReadUInt32(); var interfaceReader = reader.CopyAtOffset((int)interfaceTypeOffset); result.Interfaces.Add(ShaderType.Parse(reader, interfaceReader, target, indent + 4, i == 0, parentOffset)); } } var parentNameOffset = typeReader.ReadUInt32(); if (parentNameOffset > 0) { var parentNameReader = reader.CopyAtOffset((int)parentNameOffset); result.BaseTypeName = parentNameReader.ReadString(); } } if (memberCount > 0) { var memberReader = reader.CopyAtOffset((int)memberOffset); for (int i = 0; i < memberCount; i++) { result.Members.Add(ShaderTypeMember.Parse(reader, memberReader, target, indent + 4, i == 0, parentOffset)); } } if (target.ProgramType == ProgramType.LibraryShader && target.MajorVersion == 4) { var unk1 = typeReader.ReadUInt32(); var unk2 = typeReader.ReadUInt32(); var unk3 = typeReader.ReadUInt32(); var unk4 = typeReader.ReadUInt32(); var typeNameOffset = typeReader.ReadUInt32(); var typeNameReader = reader.CopyAtOffset((int)typeNameOffset); result.BaseTypeName = typeNameReader.ReadString(); Debug.Assert(unk1 == 0, $"ShaderType.Unk1={unk1}"); Debug.Assert(unk2 == 0, $"ShaderType.Unk2={unk2}"); Debug.Assert(unk3 == 0, $"ShaderType.Unk3={unk3}"); Debug.Assert(unk4 == 0, $"ShaderType.Unk4={unk4}"); } return(result); }