From 23ac5906486152da54701585efa27052b80d577b Mon Sep 17 00:00:00 2001 From: Perfare Date: Tue, 22 Mar 2022 22:54:49 +0800 Subject: [PATCH] Fixed #941 --- AssetStudio/Classes/Shader.cs | 18 +++---- AssetStudioUtility/ShaderConverter.cs | 74 +++++++++++++++++++-------- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/AssetStudio/Classes/Shader.cs b/AssetStudio/Classes/Shader.cs index 5a4744e..e5c6754 100644 --- a/AssetStudio/Classes/Shader.cs +++ b/AssetStudio/Classes/Shader.cs @@ -959,9 +959,9 @@ namespace AssetStudio //5.5 and up public SerializedShader m_ParsedForm; public ShaderCompilerPlatform[] platforms; - public uint[] offsets; - public uint[] compressedLengths; - public uint[] decompressedLengths; + public uint[][] offsets; + public uint[][] compressedLengths; + public uint[][] decompressedLengths; public byte[] compressedBlob; public Shader(ObjectReader reader) : base(reader) @@ -972,15 +972,15 @@ namespace AssetStudio platforms = reader.ReadUInt32Array().Select(x => (ShaderCompilerPlatform)x).ToArray(); if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up { - offsets = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); - compressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); - decompressedLengths = reader.ReadUInt32ArrayArray().Select(x => x[0]).ToArray(); + offsets = reader.ReadUInt32ArrayArray(); + compressedLengths = reader.ReadUInt32ArrayArray(); + decompressedLengths = reader.ReadUInt32ArrayArray(); } else { - offsets = reader.ReadUInt32Array(); - compressedLengths = reader.ReadUInt32Array(); - decompressedLengths = reader.ReadUInt32Array(); + offsets = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray(); + compressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray(); + decompressedLengths = reader.ReadUInt32Array().Select(x => new[] { x }).ToArray(); } compressedBlob = reader.ReadUInt8Array(); reader.AlignStream(); diff --git a/AssetStudioUtility/ShaderConverter.cs b/AssetStudioUtility/ShaderConverter.cs index e2385bc..5ee257d 100644 --- a/AssetStudioUtility/ShaderConverter.cs +++ b/AssetStudioUtility/ShaderConverter.cs @@ -19,6 +19,7 @@ namespace AssetStudio using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) { var program = new ShaderProgram(blobReader, shader.version); + program.Read(blobReader, 0); return header + program.Export(Encoding.UTF8.GetString(shader.m_Script)); } } @@ -33,16 +34,25 @@ namespace AssetStudio private static string ConvertSerializedShader(Shader shader) { - var shaderPrograms = new ShaderProgram[shader.platforms.Length]; - for (var i = 0; i < shader.platforms.Length; i++) + var length = shader.platforms.Length; + var shaderPrograms = new ShaderProgram[length]; + for (var i = 0; i < length; i++) { - var compressedBytes = new byte[shader.compressedLengths[i]]; - Buffer.BlockCopy(shader.compressedBlob, (int)shader.offsets[i], compressedBytes, 0, (int)shader.compressedLengths[i]); - var decompressedBytes = new byte[shader.decompressedLengths[i]]; - LZ4Codec.Decode(compressedBytes, decompressedBytes); - using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) + for (var j = 0; j < shader.offsets[i].Length; j++) { - shaderPrograms[i] = new ShaderProgram(blobReader, shader.version); + var offset = shader.offsets[i][j]; + var compressedLength = shader.compressedLengths[i][j]; + var decompressedLength = shader.decompressedLengths[i][j]; + var decompressedBytes = new byte[decompressedLength]; + LZ4Codec.Decode(shader.compressedBlob, (int)offset, (int)compressedLength, decompressedBytes, 0, (int)decompressedLength); + using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes))) + { + if (j == 0) + { + shaderPrograms[i] = new ShaderProgram(blobReader, shader.version); + } + shaderPrograms[i].Read(blobReader, j); + } } } @@ -854,29 +864,49 @@ namespace AssetStudio "///////////////////////////////////////////\n"; } + public class ShaderSubProgramEntry + { + public int Offset; + public int Length; + public int Segment; + + public ShaderSubProgramEntry(BinaryReader reader, int[] version) + { + Offset = reader.ReadInt32(); + Length = reader.ReadInt32(); + if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up + { + Segment = reader.ReadInt32(); + } + } + } + public class ShaderProgram { + public ShaderSubProgramEntry[] entries; public ShaderSubProgram[] m_SubPrograms; public ShaderProgram(BinaryReader reader, int[] version) { var subProgramsCapacity = reader.ReadInt32(); - m_SubPrograms = new ShaderSubProgram[subProgramsCapacity]; - int entrySize; - if (version[0] > 2019 || (version[0] == 2019 && version[1] >= 3)) //2019.3 and up - { - entrySize = 12; - } - else - { - entrySize = 8; - } + entries = new ShaderSubProgramEntry[subProgramsCapacity]; for (int i = 0; i < subProgramsCapacity; i++) { - reader.BaseStream.Position = 4 + i * entrySize; - var offset = reader.ReadInt32(); - reader.BaseStream.Position = offset; - m_SubPrograms[i] = new ShaderSubProgram(reader); + entries[i] = new ShaderSubProgramEntry(reader, version); + } + m_SubPrograms = new ShaderSubProgram[subProgramsCapacity]; + } + + public void Read(BinaryReader reader, int segment) + { + for (int i = 0; i < entries.Length; i++) + { + var entry = entries[i]; + if (entry.Segment == segment) + { + reader.BaseStream.Position = entry.Offset; + m_SubPrograms[i] = new ShaderSubProgram(reader); + } } }