mirror of
https://github.com/AssetRipper/AssetRipper.git
synced 2025-12-11 20:15:29 +01:00
371 lines
8.0 KiB
C#
371 lines
8.0 KiB
C#
using AssetRipper.Export.Modules.Shaders.UltraShaderConverter.UShader.DirectX;
|
|
using System.Globalization;
|
|
|
|
namespace AssetRipper.Export.Modules.Shaders.UltraShaderConverter.USIL;
|
|
|
|
public class USILOperand
|
|
{
|
|
public USILOperandType operandType;
|
|
|
|
public int[] immValueInt = Array.Empty<int>();
|
|
public float[] immValueFloat = Array.Empty<float>();
|
|
public bool immIsInt; // useless
|
|
|
|
public bool absoluteValue;
|
|
public bool negative;
|
|
public bool transposeMatrix;
|
|
|
|
public int registerIndex;
|
|
public int arrayIndex;
|
|
public USILOperand? arrayRelative;
|
|
|
|
public string? metadataName;
|
|
public bool metadataNameAssigned;
|
|
public bool metadataNameWithArray;
|
|
|
|
public string comment = string.Empty;
|
|
|
|
public USILOperand[] children = Array.Empty<USILOperand>();
|
|
|
|
public int[] mask;
|
|
public bool displayMask;
|
|
|
|
public USILOperand()
|
|
{
|
|
operandType = USILOperandType.None;
|
|
|
|
immIsInt = false;
|
|
|
|
absoluteValue = false;
|
|
negative = false;
|
|
transposeMatrix = false;
|
|
|
|
registerIndex = 0;
|
|
arrayIndex = 0;
|
|
arrayRelative = null;
|
|
|
|
metadataName = null;
|
|
metadataNameAssigned = false;
|
|
metadataNameWithArray = false;
|
|
|
|
mask = Array.Empty<int>();
|
|
displayMask = true;
|
|
}
|
|
|
|
public USILOperand(USILOperand original)
|
|
{
|
|
operandType = original.operandType;
|
|
|
|
immValueInt = original.immValueInt;
|
|
immValueFloat = original.immValueFloat;
|
|
immIsInt = original.immIsInt;
|
|
|
|
absoluteValue = original.absoluteValue;
|
|
negative = original.negative;
|
|
transposeMatrix = original.transposeMatrix;
|
|
|
|
registerIndex = original.registerIndex;
|
|
arrayIndex = original.arrayIndex;
|
|
|
|
if (original.arrayRelative != null)
|
|
{
|
|
arrayRelative = new USILOperand(original.arrayRelative);
|
|
}
|
|
else
|
|
{
|
|
arrayRelative = null;
|
|
}
|
|
|
|
metadataName = original.metadataName;
|
|
metadataNameAssigned = original.metadataNameAssigned;
|
|
metadataNameWithArray = original.metadataNameWithArray;
|
|
|
|
comment = original.comment;
|
|
|
|
children = new USILOperand[original.children.Length];
|
|
for (int i = 0; i < original.children.Length; i++)
|
|
{
|
|
children[i] = new USILOperand(original.children[i]);
|
|
}
|
|
|
|
mask = original.mask.ToArray();
|
|
displayMask = original.displayMask;
|
|
}
|
|
|
|
public USILOperand(int value)
|
|
{
|
|
operandType = USILOperandType.ImmediateInt;
|
|
immValueInt = [value];
|
|
immIsInt = true;
|
|
mask = [0];
|
|
}
|
|
|
|
public USILOperand(float value)
|
|
{
|
|
operandType = USILOperandType.ImmediateFloat;
|
|
immValueFloat = [value];
|
|
immIsInt = false;
|
|
mask = [0];
|
|
}
|
|
|
|
public int GetValueCount()
|
|
{
|
|
switch (operandType)
|
|
{
|
|
case USILOperandType.ImmediateFloat:
|
|
return immValueFloat.Length;
|
|
case USILOperandType.ImmediateInt:
|
|
return immValueInt.Length;
|
|
case USILOperandType.Multiple:
|
|
int multipleSum = 0;
|
|
foreach (USILOperand operand in children)
|
|
{
|
|
multipleSum += operand.GetValueCount();
|
|
}
|
|
return multipleSum;
|
|
default:
|
|
return mask.Length;
|
|
}
|
|
}
|
|
|
|
public override string ToString()
|
|
{
|
|
return ToString(false);
|
|
}
|
|
|
|
public string ToString(bool forceHideMask)
|
|
{
|
|
string prefix = "";
|
|
string body = "";
|
|
string suffix = "";
|
|
|
|
bool displayMaskOverride = displayMask;
|
|
if (forceHideMask)
|
|
{
|
|
displayMaskOverride = false;
|
|
}
|
|
|
|
if (!metadataNameAssigned)
|
|
{
|
|
prefix = GetTypeShortForm(operandType);
|
|
}
|
|
|
|
if (absoluteValue)
|
|
{
|
|
prefix = $"abs({prefix}";
|
|
}
|
|
|
|
if (negative)
|
|
{
|
|
prefix = $"-{prefix}";
|
|
}
|
|
|
|
if (metadataNameAssigned)
|
|
{
|
|
body = metadataName ?? "";
|
|
}
|
|
else
|
|
{
|
|
switch (operandType)
|
|
{
|
|
case USILOperandType.None:
|
|
{
|
|
body = "none";
|
|
break;
|
|
}
|
|
case USILOperandType.Null:
|
|
{
|
|
body = "null";
|
|
break;
|
|
}
|
|
case USILOperandType.Comment:
|
|
{
|
|
body = comment;
|
|
break;
|
|
}
|
|
case USILOperandType.TempRegister:
|
|
case USILOperandType.InputRegister:
|
|
case USILOperandType.OutputRegister:
|
|
case USILOperandType.ResourceRegister:
|
|
case USILOperandType.SamplerRegister:
|
|
case USILOperandType.Sampler2D:
|
|
case USILOperandType.Sampler3D:
|
|
case USILOperandType.SamplerCube:
|
|
{
|
|
body = $"{registerIndex}";
|
|
break;
|
|
}
|
|
case USILOperandType.IndexableTempRegister:
|
|
{
|
|
body = $"{registerIndex}[{arrayIndex}]";
|
|
break;
|
|
}
|
|
case USILOperandType.ConstantBuffer:
|
|
case USILOperandType.Matrix:
|
|
{
|
|
body = $"{registerIndex}";
|
|
break;
|
|
}
|
|
case USILOperandType.ImmediateConstantBuffer:
|
|
{
|
|
body = "";
|
|
break;
|
|
}
|
|
case USILOperandType.ImmediateInt:
|
|
{
|
|
if (immValueInt.Length == 1)
|
|
{
|
|
body = $"{immValueInt[0]}";
|
|
}
|
|
else //if (immValueInt.Length > 1)
|
|
{
|
|
body += $"int{immValueInt.Length}(";
|
|
for (int i = 0; i < immValueInt.Length; i++)
|
|
{
|
|
if (i != immValueInt.Length - 1)
|
|
{
|
|
body += $"{immValueInt[i]}, ";
|
|
}
|
|
else
|
|
{
|
|
body += $"{immValueInt[i]}";
|
|
}
|
|
}
|
|
body += ")";
|
|
}
|
|
break;
|
|
}
|
|
case USILOperandType.ImmediateFloat:
|
|
{
|
|
if (immValueFloat.Length == 1)
|
|
{
|
|
// todo: check if number can't possibly be expressed as float and write in hex.
|
|
// todo: float precision isn't correct atm. add precision check somewhere.
|
|
body = $"{immValueFloat[0].ToString("0.0######", CultureInfo.InvariantCulture)}";
|
|
}
|
|
else //if (immValueFloat.Length > 1)
|
|
{
|
|
// todo: if all numbers are the same and it matches the mask, use it only once
|
|
body += $"float{immValueFloat.Length}(";
|
|
for (int i = 0; i < immValueFloat.Length; i++)
|
|
{
|
|
if (i != immValueFloat.Length - 1)
|
|
{
|
|
body += $"{immValueFloat[i].ToString("0.0######", CultureInfo.InvariantCulture)}, ";
|
|
}
|
|
else
|
|
{
|
|
body += $"{immValueFloat[i].ToString("0.0######", CultureInfo.InvariantCulture)}";
|
|
}
|
|
}
|
|
body += ")";
|
|
}
|
|
break;
|
|
}
|
|
case USILOperandType.Multiple:
|
|
{
|
|
body += $"float{GetValueCount()}({string.Join(", ", children.ToList())})";
|
|
break;
|
|
}
|
|
|
|
default:
|
|
{
|
|
if (DXShaderNamingUtils.HasSpecialInputOutputName(operandType))
|
|
{
|
|
body = DXShaderNamingUtils.GetSpecialInputOutputName(operandType);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!metadataNameAssigned || metadataNameWithArray)
|
|
{
|
|
switch (operandType)
|
|
{
|
|
case USILOperandType.ConstantBuffer:
|
|
case USILOperandType.Matrix:
|
|
{
|
|
if (arrayRelative != null)
|
|
{
|
|
if (arrayIndex == 0)
|
|
{
|
|
body += $"[{arrayRelative}]";
|
|
}
|
|
else
|
|
{
|
|
body += $"[{arrayRelative} + {arrayIndex}]";
|
|
}
|
|
}
|
|
else
|
|
{
|
|
body += $"[{arrayIndex}]";
|
|
}
|
|
break;
|
|
}
|
|
case USILOperandType.ImmediateConstantBuffer:
|
|
{
|
|
body += $"[{arrayRelative} + {arrayIndex}]";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (operandType != USILOperandType.ImmediateFloat &&
|
|
operandType != USILOperandType.ImmediateInt &&
|
|
operandType != USILOperandType.Multiple &&
|
|
!DXShaderNamingUtils.HasSpecialInputOutputName(operandType) &&
|
|
displayMaskOverride)
|
|
{
|
|
if (mask.Length > 0)
|
|
{
|
|
suffix += ".";
|
|
}
|
|
|
|
if (operandType == USILOperandType.Matrix)
|
|
{
|
|
string[] charArray = transposeMatrix ? USILConstants.TMATRIX_MASK_CHARS : USILConstants.MATRIX_MASK_CHARS;
|
|
for (int i = 0; i < mask.Length; i++)
|
|
{
|
|
suffix += charArray[arrayIndex * 4 + mask[i]];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int i = 0; i < mask.Length; i++)
|
|
{
|
|
suffix += USILConstants.MASK_CHARS[mask[i]];
|
|
}
|
|
}
|
|
|
|
if (suffix == ".xyzw")
|
|
{
|
|
suffix = "";
|
|
}
|
|
}
|
|
|
|
if (absoluteValue)
|
|
{
|
|
suffix = $"{suffix})";
|
|
}
|
|
|
|
return $"{prefix}{body}{suffix}";
|
|
}
|
|
|
|
public static string GetTypeShortForm(USILOperandType operandType)
|
|
{
|
|
return operandType switch
|
|
{
|
|
USILOperandType.TempRegister => "tmp",
|
|
USILOperandType.IndexableTempRegister => "xtmp",
|
|
USILOperandType.InputRegister => "in",
|
|
USILOperandType.OutputRegister => "out",
|
|
USILOperandType.ResourceRegister => "rsc",
|
|
USILOperandType.SamplerRegister => "smp",
|
|
USILOperandType.ConstantBuffer => "cb",
|
|
USILOperandType.ImmediateConstantBuffer => "icb",
|
|
_ => ""
|
|
};
|
|
}
|
|
}
|