mirror of
https://github.com/aelurum/AssetStudio.git
synced 2025-07-16 19:14:15 -04:00
implemented SPIR-V shader export
This commit is contained in:
221
AssetStudioUtility/CSspv/Disassembler.cs
Normal file
221
AssetStudioUtility/CSspv/Disassembler.cs
Normal file
@ -0,0 +1,221 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
|
||||
namespace SpirV
|
||||
{
|
||||
public struct ModuleHeader
|
||||
{
|
||||
public Version Version { get; set; }
|
||||
public string GeneratorVendor { get; set; }
|
||||
public string GeneratorName { get; set; }
|
||||
public int GeneratorVersion { get; set; }
|
||||
public uint Bound { get; set; }
|
||||
public uint Reserved { get; set; }
|
||||
}
|
||||
|
||||
[Flags]
|
||||
public enum DisassemblyOptions
|
||||
{
|
||||
None,
|
||||
ShowTypes,
|
||||
ShowNames,
|
||||
Default = ShowTypes | ShowNames
|
||||
}
|
||||
|
||||
public class Disassembler
|
||||
{
|
||||
public string Disassemble (Module module)
|
||||
{
|
||||
return Disassemble(module, DisassemblyOptions.Default);
|
||||
}
|
||||
|
||||
public string Disassemble(Module module, DisassemblyOptions options)
|
||||
{
|
||||
m_sb.AppendLine("; SPIR-V");
|
||||
m_sb.Append("; Version: ").Append(module.Header.Version).AppendLine();
|
||||
if (module.Header.GeneratorName == null)
|
||||
{
|
||||
m_sb.Append("; Generator: unknown; ").Append(module.Header.GeneratorVersion).AppendLine();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_sb.Append("; Generator: ").Append(module.Header.GeneratorVendor).Append(' ').
|
||||
Append(module.Header.GeneratorName).Append("; ").Append(module.Header.GeneratorVersion).AppendLine();
|
||||
}
|
||||
m_sb.Append("; Bound: ").Append(module.Header.Bound).AppendLine();
|
||||
m_sb.Append("; Schema: ").Append(module.Header.Reserved).AppendLine();
|
||||
|
||||
string[] lines = new string[module.Instructions.Count + 1];
|
||||
lines[0] = m_sb.ToString();
|
||||
m_sb.Clear();
|
||||
|
||||
for (int i = 0; i < module.Instructions.Count; i++)
|
||||
{
|
||||
ParsedInstruction instruction = module.Instructions[i];
|
||||
PrintInstruction(m_sb, instruction, options);
|
||||
lines[i + 1] = m_sb.ToString();
|
||||
m_sb.Clear();
|
||||
}
|
||||
|
||||
int longestPrefix = 0;
|
||||
for (int i = 0; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
longestPrefix = Math.Max(longestPrefix, line.IndexOf('='));
|
||||
if (longestPrefix > 50)
|
||||
{
|
||||
longestPrefix = 50;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_sb.Append(lines[0]);
|
||||
for (int i = 1; i < lines.Length; i++)
|
||||
{
|
||||
string line = lines[i];
|
||||
int index = line.IndexOf('=');
|
||||
if (index == -1)
|
||||
{
|
||||
m_sb.Append(' ', longestPrefix + 4);
|
||||
m_sb.Append(line);
|
||||
}
|
||||
else
|
||||
{
|
||||
int pad = Math.Max(0, longestPrefix - index);
|
||||
m_sb.Append(' ', pad);
|
||||
m_sb.Append(line, 0, index);
|
||||
m_sb.Append('=');
|
||||
m_sb.Append(line, index + 1, line.Length - index - 1);
|
||||
}
|
||||
m_sb.AppendLine();
|
||||
}
|
||||
|
||||
string result = m_sb.ToString();
|
||||
m_sb.Clear();
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void PrintInstruction(StringBuilder sb, ParsedInstruction instruction, DisassemblyOptions options)
|
||||
{
|
||||
if (instruction.Operands.Count == 0)
|
||||
{
|
||||
sb.Append(instruction.Instruction.Name);
|
||||
return;
|
||||
}
|
||||
|
||||
int currentOperand = 0;
|
||||
if (instruction.Instruction.Operands[currentOperand].Type is IdResultType)
|
||||
{
|
||||
if (options.HasFlag(DisassemblyOptions.ShowTypes))
|
||||
{
|
||||
instruction.ResultType.ToString(sb).Append(' ');
|
||||
}
|
||||
++currentOperand;
|
||||
}
|
||||
|
||||
if (currentOperand < instruction.Operands.Count && instruction.Instruction.Operands[currentOperand].Type is IdResult)
|
||||
{
|
||||
if (!options.HasFlag(DisassemblyOptions.ShowNames) || string.IsNullOrWhiteSpace(instruction.Name))
|
||||
{
|
||||
PrintOperandValue(sb, instruction.Operands[currentOperand].Value, options);
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.Append(instruction.Name);
|
||||
}
|
||||
sb.Append(" = ");
|
||||
|
||||
++currentOperand;
|
||||
}
|
||||
|
||||
sb.Append(instruction.Instruction.Name);
|
||||
sb.Append(' ');
|
||||
|
||||
for (; currentOperand < instruction.Operands.Count; ++currentOperand)
|
||||
{
|
||||
PrintOperandValue(sb, instruction.Operands[currentOperand].Value, options);
|
||||
sb.Append(' ');
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintOperandValue(StringBuilder sb, object value, DisassemblyOptions options)
|
||||
{
|
||||
switch (value)
|
||||
{
|
||||
case System.Type t:
|
||||
sb.Append(t.Name);
|
||||
break;
|
||||
|
||||
case string s:
|
||||
{
|
||||
sb.Append('"');
|
||||
sb.Append(s);
|
||||
sb.Append('"');
|
||||
}
|
||||
break;
|
||||
|
||||
case ObjectReference or:
|
||||
{
|
||||
if (options.HasFlag(DisassemblyOptions.ShowNames) && or.Reference != null && !string.IsNullOrWhiteSpace(or.Reference.Name))
|
||||
{
|
||||
sb.Append(or.Reference.Name);
|
||||
}
|
||||
else
|
||||
{
|
||||
or.ToString(sb);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case IBitEnumOperandValue beov:
|
||||
PrintBitEnumValue(sb, beov, options);
|
||||
break;
|
||||
|
||||
case IValueEnumOperandValue veov:
|
||||
PrintValueEnumValue(sb, veov, options);
|
||||
break;
|
||||
|
||||
case VaryingOperandValue varOpVal:
|
||||
varOpVal.ToString(sb);
|
||||
break;
|
||||
|
||||
default:
|
||||
sb.Append(value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintBitEnumValue(StringBuilder sb, IBitEnumOperandValue enumOperandValue, DisassemblyOptions options)
|
||||
{
|
||||
foreach (uint key in enumOperandValue.Values.Keys)
|
||||
{
|
||||
sb.Append(enumOperandValue.EnumerationType.GetEnumName(key));
|
||||
IReadOnlyList<object> value = enumOperandValue.Values[key];
|
||||
if (value.Count != 0)
|
||||
{
|
||||
sb.Append(' ');
|
||||
foreach (object v in value)
|
||||
{
|
||||
PrintOperandValue(sb, v, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void PrintValueEnumValue(StringBuilder sb, IValueEnumOperandValue valueOperandValue, DisassemblyOptions options)
|
||||
{
|
||||
sb.Append(valueOperandValue.Key);
|
||||
if (valueOperandValue.Value is IList<object> valueList && valueList.Count > 0)
|
||||
{
|
||||
sb.Append(' ');
|
||||
foreach (object v in valueList)
|
||||
{
|
||||
PrintOperandValue(sb, v, options);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private readonly StringBuilder m_sb = new StringBuilder();
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user