mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-05-25 05:40:21 -04:00
784 lines
35 KiB
C#
784 lines
35 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Text.RegularExpressions;
|
|
using Lz4;
|
|
|
|
namespace AssetStudio
|
|
{
|
|
public static class ShaderConverter
|
|
{
|
|
public static string Convert(this Shader shader)
|
|
{
|
|
if (shader.m_SubProgramBlob != null) //5.3 - 5.4
|
|
{
|
|
var decompressedBytes = new byte[shader.decompressedSize];
|
|
using (var decoder = new Lz4DecoderStream(new MemoryStream(shader.m_SubProgramBlob)))
|
|
{
|
|
decoder.Read(decompressedBytes, 0, (int)shader.decompressedSize);
|
|
}
|
|
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
|
|
{
|
|
var program = new ShaderProgram(blobReader, shader.version);
|
|
return header + program.Export(Encoding.UTF8.GetString(shader.m_Script));
|
|
}
|
|
}
|
|
|
|
if (shader.compressedBlob != null) //5.5 and up
|
|
{
|
|
return header + ConvertSerializedShader(shader);
|
|
}
|
|
|
|
return header + Encoding.UTF8.GetString(shader.m_Script);
|
|
}
|
|
|
|
private static string ConvertSerializedShader(Shader shader)
|
|
{
|
|
var shaderPrograms = new ShaderProgram[shader.platforms.Length];
|
|
for (var i = 0; i < shader.platforms.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]];
|
|
using (var decoder = new Lz4DecoderStream(new MemoryStream(compressedBytes)))
|
|
{
|
|
decoder.Read(decompressedBytes, 0, (int)shader.decompressedLengths[i]);
|
|
}
|
|
using (var blobReader = new BinaryReader(new MemoryStream(decompressedBytes)))
|
|
{
|
|
shaderPrograms[i] = new ShaderProgram(blobReader, shader.version);
|
|
}
|
|
}
|
|
|
|
return ConvertSerializedShader(shader.m_ParsedForm, shader.platforms, shaderPrograms);
|
|
}
|
|
|
|
private static string ConvertSerializedShader(SerializedShader m_ParsedForm, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.Append($"Shader \"{m_ParsedForm.m_Name}\" {{\n");
|
|
|
|
sb.Append(ConvertSerializedProperties(m_ParsedForm.m_PropInfo));
|
|
|
|
foreach (var m_SubShader in m_ParsedForm.m_SubShaders)
|
|
{
|
|
sb.Append(ConvertSerializedSubShader(m_SubShader, platforms, shaderPrograms));
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(m_ParsedForm.m_FallbackName))
|
|
{
|
|
sb.Append($"Fallback \"{m_ParsedForm.m_FallbackName}\"\n");
|
|
}
|
|
|
|
if (!string.IsNullOrEmpty(m_ParsedForm.m_CustomEditorName))
|
|
{
|
|
sb.Append($"CustomEditor \"{m_ParsedForm.m_CustomEditorName}\"\n");
|
|
}
|
|
|
|
sb.Append("}");
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedSubShader(SerializedSubShader m_SubShader, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.Append("SubShader {\n");
|
|
if (m_SubShader.m_LOD != 0)
|
|
{
|
|
sb.Append($" LOD {m_SubShader.m_LOD}\n");
|
|
}
|
|
|
|
sb.Append(ConvertSerializedTagMap(m_SubShader.m_Tags, 1));
|
|
|
|
foreach (var m_Passe in m_SubShader.m_Passes)
|
|
{
|
|
sb.Append(ConvertSerializedPass(m_Passe, platforms, shaderPrograms));
|
|
}
|
|
sb.Append("}\n");
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedPass(SerializedPass m_Passe, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)
|
|
{
|
|
var sb = new StringBuilder();
|
|
switch (m_Passe.m_Type)
|
|
{
|
|
case PassType.kPassTypeNormal:
|
|
sb.Append(" Pass ");
|
|
break;
|
|
case PassType.kPassTypeUse:
|
|
sb.Append(" UsePass ");
|
|
break;
|
|
case PassType.kPassTypeGrab:
|
|
sb.Append(" GrabPass ");
|
|
break;
|
|
}
|
|
if (m_Passe.m_Type == PassType.kPassTypeUse)
|
|
{
|
|
sb.Append($"\"{m_Passe.m_UseName}\"\n");
|
|
}
|
|
else
|
|
{
|
|
sb.Append("{\n");
|
|
|
|
if (m_Passe.m_Type == PassType.kPassTypeGrab)
|
|
{
|
|
if (!string.IsNullOrEmpty(m_Passe.m_TextureName))
|
|
{
|
|
sb.Append($" \"{m_Passe.m_TextureName}\"\n");
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sb.Append(ConvertSerializedShaderState(m_Passe.m_State));
|
|
|
|
if (m_Passe.progVertex.m_SubPrograms.Length > 0)
|
|
{
|
|
sb.Append("Program \"vp\" {\n");
|
|
sb.Append(ConvertSerializedSubPrograms(m_Passe.progVertex.m_SubPrograms, platforms, shaderPrograms));
|
|
sb.Append("}\n");
|
|
}
|
|
|
|
if (m_Passe.progFragment.m_SubPrograms.Length > 0)
|
|
{
|
|
sb.Append("Program \"fp\" {\n");
|
|
sb.Append(ConvertSerializedSubPrograms(m_Passe.progFragment.m_SubPrograms, platforms, shaderPrograms));
|
|
sb.Append("}\n");
|
|
}
|
|
|
|
if (m_Passe.progGeometry.m_SubPrograms.Length > 0)
|
|
{
|
|
sb.Append("Program \"gp\" {\n");
|
|
sb.Append(ConvertSerializedSubPrograms(m_Passe.progGeometry.m_SubPrograms, platforms, shaderPrograms));
|
|
sb.Append("}\n");
|
|
}
|
|
|
|
if (m_Passe.progHull.m_SubPrograms.Length > 0)
|
|
{
|
|
sb.Append("Program \"hp\" {\n");
|
|
sb.Append(ConvertSerializedSubPrograms(m_Passe.progHull.m_SubPrograms, platforms, shaderPrograms));
|
|
sb.Append("}\n");
|
|
}
|
|
|
|
if (m_Passe.progDomain.m_SubPrograms.Length > 0)
|
|
{
|
|
sb.Append("Program \"dp\" {\n");
|
|
sb.Append(ConvertSerializedSubPrograms(m_Passe.progDomain.m_SubPrograms, platforms, shaderPrograms));
|
|
sb.Append("}\n");
|
|
}
|
|
}
|
|
sb.Append("}\n");
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedSubPrograms(SerializedSubProgram[] m_SubPrograms, ShaderCompilerPlatform[] platforms, ShaderProgram[] shaderPrograms)
|
|
{
|
|
var sb = new StringBuilder();
|
|
var groups = m_SubPrograms.GroupBy(x => x.m_BlobIndex);
|
|
foreach (var group in groups)
|
|
{
|
|
var programs = group.GroupBy(x => x.m_GpuProgramType);
|
|
foreach (var program in programs)
|
|
{
|
|
for (int i = 0; i < platforms.Length; i++)
|
|
{
|
|
var platform = platforms[i];
|
|
if (CheckGpuProgramUsable(platform, program.Key))
|
|
{
|
|
var subPrograms = program.ToList();
|
|
var isTier = subPrograms.Count > 1;
|
|
foreach (var subProgram in subPrograms)
|
|
{
|
|
sb.Append($"SubProgram \"{GetPlatformString(platform)} ");
|
|
if (isTier)
|
|
{
|
|
sb.Append($"hw_tier{subProgram.m_ShaderHardwareTier:00} ");
|
|
}
|
|
sb.Append("\" {\n");
|
|
sb.Append(shaderPrograms[i].m_SubPrograms[subProgram.m_BlobIndex].Export());
|
|
sb.Append("\n}\n");
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedShaderState(SerializedShaderState m_State)
|
|
{
|
|
var sb = new StringBuilder();
|
|
if (!string.IsNullOrEmpty(m_State.m_Name))
|
|
{
|
|
sb.Append($" Name \"{m_State.m_Name}\"\n");
|
|
}
|
|
if (m_State.m_LOD != 0)
|
|
{
|
|
sb.Append($" LOD {m_State.m_LOD}\n");
|
|
}
|
|
|
|
sb.Append(ConvertSerializedTagMap(m_State.m_Tags, 2));
|
|
|
|
sb.Append(ConvertSerializedShaderRTBlendState(m_State.rtBlend));
|
|
|
|
if (m_State.alphaToMask.val > 0f)
|
|
{
|
|
sb.Append(" AlphaToMask On\n");
|
|
}
|
|
|
|
if (m_State.zClip?.val != 1f) //ZClip On
|
|
{
|
|
sb.Append(" ZClip Off\n");
|
|
}
|
|
|
|
if (m_State.zTest.val != 4f) //ZTest LEqual
|
|
{
|
|
sb.Append(" ZTest ");
|
|
switch (m_State.zTest.val) //enum CompareFunction
|
|
{
|
|
case 0f: //kFuncDisabled
|
|
sb.Append("Off");
|
|
break;
|
|
case 1f: //kFuncNever
|
|
sb.Append("Never");
|
|
break;
|
|
case 2f: //kFuncLess
|
|
sb.Append("Less");
|
|
break;
|
|
case 3f: //kFuncEqual
|
|
sb.Append("Equal");
|
|
break;
|
|
case 5f: //kFuncGreater
|
|
sb.Append("Greater");
|
|
break;
|
|
case 6f: //kFuncNotEqual
|
|
sb.Append("NotEqual");
|
|
break;
|
|
case 7f: //kFuncGEqual
|
|
sb.Append("GEqual");
|
|
break;
|
|
case 8f: //kFuncAlways
|
|
sb.Append("Always");
|
|
break;
|
|
}
|
|
|
|
sb.Append("\n");
|
|
}
|
|
|
|
if (m_State.zWrite.val != 1f) //ZWrite On
|
|
{
|
|
sb.Append(" ZWrite Off\n");
|
|
}
|
|
|
|
if (m_State.culling.val != 2f) //Cull Back
|
|
{
|
|
sb.Append(" Cull ");
|
|
switch (m_State.culling.val) //enum CullMode
|
|
{
|
|
case 0f: //kCullOff
|
|
sb.Append("Off");
|
|
break;
|
|
case 1f: //kCullFront
|
|
sb.Append("Front");
|
|
break;
|
|
}
|
|
sb.Append("\n");
|
|
}
|
|
|
|
if (m_State.offsetFactor.val != 0f || m_State.offsetUnits.val != 0f)
|
|
{
|
|
sb.Append($" Offset {m_State.offsetFactor.val}, {m_State.offsetUnits.val}\n");
|
|
}
|
|
|
|
//TODO Stencil
|
|
|
|
//TODO Fog
|
|
|
|
if (m_State.lighting)
|
|
{
|
|
sb.Append($" Lighting {(m_State.lighting ? "On" : "Off")}\n");
|
|
}
|
|
|
|
sb.Append($" GpuProgramID {m_State.gpuProgramID}\n");
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedShaderRTBlendState(SerializedShaderRTBlendState[] rtBlend)
|
|
{
|
|
//TODO Blend
|
|
var sb = new StringBuilder();
|
|
/*for (var i = 0; i < rtBlend.Length; i++)
|
|
{
|
|
var blend = rtBlend[i];
|
|
if (!blend.srcBlend.val.Equals(1f) ||
|
|
!blend.destBlend.val.Equals(0f) ||
|
|
!blend.srcBlendAlpha.val.Equals(1f) ||
|
|
!blend.destBlendAlpha.val.Equals(0f))
|
|
{
|
|
sb.Append(" Blend ");
|
|
sb.Append($"{i} ");
|
|
sb.Append('\n');
|
|
}
|
|
}*/
|
|
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedTagMap(SerializedTagMap m_Tags, int intent)
|
|
{
|
|
var sb = new StringBuilder();
|
|
if (m_Tags.tags.Length > 0)
|
|
{
|
|
sb.Append(new string(' ', intent));
|
|
sb.Append("Tags { ");
|
|
foreach (var pair in m_Tags.tags)
|
|
{
|
|
sb.Append($"\"{pair.Key}\" = \"{pair.Value}\" ");
|
|
}
|
|
sb.Append("}\n");
|
|
}
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedProperties(SerializedProperties m_PropInfo)
|
|
{
|
|
var sb = new StringBuilder();
|
|
sb.Append("Properties {\n");
|
|
foreach (var m_Prop in m_PropInfo.m_Props)
|
|
{
|
|
sb.Append(ConvertSerializedProperty(m_Prop));
|
|
}
|
|
sb.Append("}\n");
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static string ConvertSerializedProperty(SerializedProperty m_Prop)
|
|
{
|
|
var sb = new StringBuilder();
|
|
foreach (var m_Attribute in m_Prop.m_Attributes)
|
|
{
|
|
sb.Append($"[{m_Attribute}] ");
|
|
}
|
|
//TODO Flag
|
|
sb.Append($"{m_Prop.m_Name} (\"{m_Prop.m_Description}\", ");
|
|
switch (m_Prop.m_Type)
|
|
{
|
|
case SerializedPropertyType.kColor:
|
|
sb.Append("Color");
|
|
break;
|
|
case SerializedPropertyType.kVector:
|
|
sb.Append("Vector");
|
|
break;
|
|
case SerializedPropertyType.kFloat:
|
|
sb.Append("Float");
|
|
break;
|
|
case SerializedPropertyType.kRange:
|
|
sb.Append($"Range({m_Prop.m_DefValue[1]}, {m_Prop.m_DefValue[2]})");
|
|
break;
|
|
case SerializedPropertyType.kTexture:
|
|
switch (m_Prop.m_DefTexture.m_TexDim)
|
|
{
|
|
case TextureDimension.kTexDimAny:
|
|
sb.Append("any");
|
|
break;
|
|
case TextureDimension.kTexDim2D:
|
|
sb.Append("2D");
|
|
break;
|
|
case TextureDimension.kTexDim3D:
|
|
sb.Append("3D");
|
|
break;
|
|
case TextureDimension.kTexDimCUBE:
|
|
sb.Append("Cube");
|
|
break;
|
|
case TextureDimension.kTexDim2DArray:
|
|
sb.Append("2DArray");
|
|
break;
|
|
case TextureDimension.kTexDimCubeArray:
|
|
sb.Append("CubeArray");
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
sb.Append(") = ");
|
|
switch (m_Prop.m_Type)
|
|
{
|
|
case SerializedPropertyType.kColor:
|
|
case SerializedPropertyType.kVector:
|
|
sb.Append($"({m_Prop.m_DefValue[0]},{m_Prop.m_DefValue[1]},{m_Prop.m_DefValue[2]},{m_Prop.m_DefValue[3]})");
|
|
break;
|
|
case SerializedPropertyType.kFloat:
|
|
case SerializedPropertyType.kRange:
|
|
sb.Append(m_Prop.m_DefValue[0]);
|
|
break;
|
|
case SerializedPropertyType.kTexture:
|
|
sb.Append($"\"{m_Prop.m_DefTexture.m_DefaultName}\" {{ }}");
|
|
break;
|
|
default:
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
sb.Append("\n");
|
|
return sb.ToString();
|
|
}
|
|
|
|
private static bool CheckGpuProgramUsable(ShaderCompilerPlatform platform, ShaderGpuProgramType programType)
|
|
{
|
|
switch (platform)
|
|
{
|
|
case ShaderCompilerPlatform.kShaderCompPlatformGL:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramGLLegacy;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformD3D9:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformXbox360:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPS3:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformD3D11:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformGLES20:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformNaCl: //Obsolete
|
|
throw new NotSupportedException();
|
|
case ShaderCompilerPlatform.kShaderCompPlatformFlash: //Obsolete
|
|
throw new NotSupportedException();
|
|
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramGLES31AEP
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES31
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLES3;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPSP2:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPS4:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPSM: //Unknown
|
|
throw new NotSupportedException();
|
|
case ShaderCompilerPlatform.kShaderCompPlatformMetal:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramMetalVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramMetalFS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramGLCore32
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore41
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramGLCore43;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformN3DS:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformWiiU:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformVulkan:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramSPIRV;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformSwitch:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
|
|
return programType == ShaderGpuProgramType.kShaderGpuProgramConsoleVS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleFS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleHS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleDS
|
|
|| programType == ShaderGpuProgramType.kShaderGpuProgramConsoleGS;
|
|
default:
|
|
throw new NotSupportedException();
|
|
}
|
|
}
|
|
|
|
public static string GetPlatformString(ShaderCompilerPlatform platform)
|
|
{
|
|
switch (platform)
|
|
{
|
|
case ShaderCompilerPlatform.kShaderCompPlatformGL:
|
|
return "openGL";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformD3D9:
|
|
return "d3d9";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformXbox360:
|
|
return "xbox360";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPS3:
|
|
return "ps3";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformD3D11:
|
|
return "d3d11";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformGLES20:
|
|
return "gles";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformNaCl:
|
|
return "glesdesktop";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformFlash:
|
|
return "flash";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformD3D11_9x:
|
|
return "d3d11_9x";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformGLES3Plus:
|
|
return "gles3";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPSP2:
|
|
return "psp2";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPS4:
|
|
return "ps4";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformXboxOne:
|
|
return "xboxone";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformPSM:
|
|
return "psm";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformMetal:
|
|
return "metal";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformOpenGLCore:
|
|
return "glcore";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformN3DS:
|
|
return "n3ds";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformWiiU:
|
|
return "wiiu";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformVulkan:
|
|
return "vulkan";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformSwitch:
|
|
return "switch";
|
|
case ShaderCompilerPlatform.kShaderCompPlatformXboxOneD3D12:
|
|
return "xboxone_d3d12";
|
|
default:
|
|
return "unknown";
|
|
}
|
|
}
|
|
|
|
private static string header = "//////////////////////////////////////////\n" +
|
|
"//\n" +
|
|
"// NOTE: This is *not* a valid shader file\n" +
|
|
"//\n" +
|
|
"///////////////////////////////////////////\n";
|
|
}
|
|
|
|
public class ShaderProgram
|
|
{
|
|
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;
|
|
}
|
|
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);
|
|
}
|
|
}
|
|
|
|
public string Export(string shader)
|
|
{
|
|
var evaluator = new MatchEvaluator(match =>
|
|
{
|
|
var index = int.Parse(match.Groups[1].Value);
|
|
return m_SubPrograms[index].Export();
|
|
});
|
|
shader = Regex.Replace(shader, "GpuProgramIndex (.+)", evaluator);
|
|
return shader;
|
|
}
|
|
}
|
|
|
|
public class ShaderSubProgram
|
|
{
|
|
private int m_Version;
|
|
public ShaderGpuProgramType m_ProgramType;
|
|
public string[] m_Keywords;
|
|
public string[] m_LocalKeywords;
|
|
public byte[] m_ProgramCode;
|
|
|
|
public ShaderSubProgram(BinaryReader reader)
|
|
{
|
|
//LoadGpuProgramFromData
|
|
//201509030 - Unity 5.3
|
|
//201510240 - Unity 5.4
|
|
//201608170 - Unity 5.5
|
|
//201609010 - Unity 5.6, 2017.1 & 2017.2
|
|
//201708220 - Unity 2017.3, Unity 2017.4 & Unity 2018.1
|
|
//201802150 - Unity 2018.2 & Unity 2018.3
|
|
//201806140 - Unity 2019.1~2020.1
|
|
m_Version = reader.ReadInt32();
|
|
m_ProgramType = (ShaderGpuProgramType)reader.ReadInt32();
|
|
reader.BaseStream.Position += 12;
|
|
if (m_Version >= 201608170)
|
|
{
|
|
reader.BaseStream.Position += 4;
|
|
}
|
|
var m_KeywordsSize = reader.ReadInt32();
|
|
m_Keywords = new string[m_KeywordsSize];
|
|
for (int i = 0; i < m_KeywordsSize; i++)
|
|
{
|
|
m_Keywords[i] = reader.ReadAlignedString();
|
|
}
|
|
if (m_Version >= 201806140)
|
|
{
|
|
var m_LocalKeywordsSize = reader.ReadInt32();
|
|
m_LocalKeywords = new string[m_LocalKeywordsSize];
|
|
for (int i = 0; i < m_LocalKeywordsSize; i++)
|
|
{
|
|
m_LocalKeywords[i] = reader.ReadAlignedString();
|
|
}
|
|
}
|
|
m_ProgramCode = reader.ReadUInt8Array();
|
|
reader.AlignStream();
|
|
|
|
//TODO
|
|
}
|
|
|
|
public string Export()
|
|
{
|
|
var sb = new StringBuilder();
|
|
if (m_Keywords.Length > 0)
|
|
{
|
|
sb.Append("Keywords { ");
|
|
foreach (string keyword in m_Keywords)
|
|
{
|
|
sb.Append($"\"{keyword}\" ");
|
|
}
|
|
sb.Append("}\n");
|
|
}
|
|
if (m_LocalKeywords != null && m_LocalKeywords.Length > 0)
|
|
{
|
|
sb.Append("Local Keywords { ");
|
|
foreach (string keyword in m_LocalKeywords)
|
|
{
|
|
sb.Append($"\"{keyword}\" ");
|
|
}
|
|
sb.Append("}\n");
|
|
}
|
|
|
|
sb.Append("\"");
|
|
if (m_ProgramCode.Length > 0)
|
|
{
|
|
switch (m_ProgramType)
|
|
{
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLLegacy:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLES31AEP:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLES31:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLES3:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLES:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLCore32:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLCore41:
|
|
case ShaderGpuProgramType.kShaderGpuProgramGLCore43:
|
|
sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
|
|
break;
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM20:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX9VertexSM30:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM20:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX9PixelSM30:
|
|
{
|
|
/*var shaderBytecode = new ShaderBytecode(m_ProgramCode);
|
|
sb.Append(shaderBytecode.Disassemble());*/
|
|
sb.Append("// shader disassembly not supported on DXBC");
|
|
break;
|
|
}
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Vertex:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX10Level9Pixel:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM40:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11VertexSM50:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM40:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11PixelSM50:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM40:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11GeometrySM50:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11HullSM50:
|
|
case ShaderGpuProgramType.kShaderGpuProgramDX11DomainSM50:
|
|
{
|
|
/*int start = 6;
|
|
if (m_Version == 201509030) // 5.3
|
|
{
|
|
start = 5;
|
|
}
|
|
var buff = new byte[m_ProgramCode.Length - start];
|
|
Buffer.BlockCopy(m_ProgramCode, start, buff, 0, buff.Length);
|
|
var shaderBytecode = new ShaderBytecode(buff);
|
|
sb.Append(shaderBytecode.Disassemble());*/
|
|
sb.Append("// shader disassembly not supported on DXBC");
|
|
break;
|
|
}
|
|
case ShaderGpuProgramType.kShaderGpuProgramMetalVS:
|
|
case ShaderGpuProgramType.kShaderGpuProgramMetalFS:
|
|
using (var reader = new BinaryReader(new MemoryStream(m_ProgramCode)))
|
|
{
|
|
var fourCC = reader.ReadUInt32();
|
|
if (fourCC == 0xf00dcafe)
|
|
{
|
|
int offset = reader.ReadInt32();
|
|
reader.BaseStream.Position = offset;
|
|
}
|
|
var entryName = reader.ReadStringToNull();
|
|
var buff = reader.ReadBytes((int)(reader.BaseStream.Length - reader.BaseStream.Position));
|
|
sb.Append(Encoding.UTF8.GetString(buff));
|
|
}
|
|
break;
|
|
case ShaderGpuProgramType.kShaderGpuProgramSPIRV:
|
|
try
|
|
{
|
|
sb.Append(SpirVShaderConverter.Convert(m_ProgramCode));
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
sb.Append($"// disassembly error {e.Message}\n");
|
|
}
|
|
break;
|
|
case ShaderGpuProgramType.kShaderGpuProgramConsoleVS:
|
|
case ShaderGpuProgramType.kShaderGpuProgramConsoleFS:
|
|
case ShaderGpuProgramType.kShaderGpuProgramConsoleHS:
|
|
case ShaderGpuProgramType.kShaderGpuProgramConsoleDS:
|
|
case ShaderGpuProgramType.kShaderGpuProgramConsoleGS:
|
|
sb.Append(Encoding.UTF8.GetString(m_ProgramCode));
|
|
break;
|
|
default:
|
|
sb.Append($"//shader disassembly not supported on {m_ProgramType}");
|
|
break;
|
|
}
|
|
}
|
|
sb.Append('"');
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
}
|