Make the shader translator more error resilient (part 2)

This commit is contained in:
gdk 2019-11-15 20:41:06 -03:00 committed by Thog
parent 04102e5c9d
commit 8eb773d81f
5 changed files with 67 additions and 31 deletions

View file

@ -60,6 +60,13 @@ namespace Ryujinx.Graphics.Shader.Instructions
IntegerType intType = (IntegerType)op.RawOpCode.Extract(8, 2); IntegerType intType = (IntegerType)op.RawOpCode.Extract(8, 2);
if (intType == IntegerType.U64)
{
// TODO: Warning. This instruction supports 64-bits integers, but it is not implemented.
return;
}
bool isSmallInt = intType <= IntegerType.U16; bool isSmallInt = intType <= IntegerType.U16;
FPType floatType = (FPType)op.RawOpCode.Extract(10, 2); FPType floatType = (FPType)op.RawOpCode.Extract(10, 2);
@ -118,6 +125,8 @@ namespace Ryujinx.Graphics.Shader.Instructions
IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2); IntegerType srcType = (IntegerType)op.RawOpCode.Extract(10, 2);
// TODO: Handle S/U64.
bool isSmallInt = srcType <= IntegerType.U16; bool isSmallInt = srcType <= IntegerType.U16;
bool isSignedInt = op.RawOpCode.Extract(13); bool isSignedInt = op.RawOpCode.Extract(13);
@ -153,7 +162,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (srcType == IntegerType.U64 || dstType == IntegerType.U64) if (srcType == IntegerType.U64 || dstType == IntegerType.U64)
{ {
// TODO: Warning. This instruction doesn't support 64-bits integers // TODO: Warning. This instruction doesn't support 64-bits integers.
return;
} }
bool srcIsSmallInt = srcType <= IntegerType.U16; bool srcIsSmallInt = srcType <= IntegerType.U16;

View file

@ -56,7 +56,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
// TODO. // TODO.
} }
throw new ArgumentException($"Invalid floating point type \"{floatType}\"."); // TODO: Warn about invalid floating point type.
return Const(0);
} }
public static Operand GetSrcB(EmitterContext context) public static Operand GetSrcB(EmitterContext context)

View file

@ -14,6 +14,15 @@ namespace Ryujinx.Graphics.Shader.Instructions
{ {
OpCodeImage op = (OpCodeImage)context.CurrOp; OpCodeImage op = (OpCodeImage)context.CurrOp;
SamplerType type = ConvertSamplerType(op.Dimensions);
if (type == SamplerType.None)
{
// TODO: Error, encoding is invalid.
return;
}
int raIndex = op.Ra.Index; int raIndex = op.Ra.Index;
int rbIndex = op.Rb.Index; int rbIndex = op.Rb.Index;
@ -49,8 +58,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(context.Copy(Register(op.Rc))); sourcesList.Add(context.Copy(Register(op.Rc)));
} }
SamplerType type = GetSamplerType(op.Dimensions);
int coordsCount = type.GetDimensions(); int coordsCount = type.GetDimensions();
for (int index = 0; index < coordsCount; index++) for (int index = 0; index < coordsCount; index++)
@ -169,8 +176,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op is OpCodeTexs texsOp) if (op is OpCodeTexs texsOp)
{ {
type = GetSamplerType (texsOp.Target); type = ConvertSamplerType(texsOp.Target);
flags = GetTextureFlags(texsOp.Target);
if (type == SamplerType.None)
{
// TODO: Error, encoding is invalid.
return;
}
flags = ConvertTextureFlags(texsOp.Target);
if ((type & SamplerType.Array) != 0) if ((type & SamplerType.Array) != 0)
{ {
@ -239,8 +254,16 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
else if (op is OpCodeTlds tldsOp) else if (op is OpCodeTlds tldsOp)
{ {
type = GetSamplerType (tldsOp.Target); type = ConvertSamplerType (tldsOp.Target);
flags = GetTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;
if (type == SamplerType.None)
{
// TODO: Error, encoding is invalid.
return;
}
flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;
switch (tldsOp.Target) switch (tldsOp.Target)
{ {
@ -428,7 +451,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
List<Operand> sourcesList = new List<Operand>(); List<Operand> sourcesList = new List<Operand>();
SamplerType type = GetSamplerType(op.Dimensions); SamplerType type = ConvertSamplerType(op.Dimensions);
TextureFlags flags = TextureFlags.Gather; TextureFlags flags = TextureFlags.Gather;
@ -553,7 +576,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(Ra()); sourcesList.Add(Ra());
} }
SamplerType type = GetSamplerType(op.Dimensions); SamplerType type = ConvertSamplerType(op.Dimensions);
int coordsCount = type.GetDimensions(); int coordsCount = type.GetDimensions();
@ -752,7 +775,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
sourcesList.Add(Rb()); sourcesList.Add(Rb());
} }
SamplerType type = GetSamplerType(op.Dimensions); SamplerType type = ConvertSamplerType(op.Dimensions);
int coordsCount = type.GetDimensions(); int coordsCount = type.GetDimensions();
@ -851,7 +874,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
} }
} }
private static SamplerType GetSamplerType(ImageDimensions target) private static SamplerType ConvertSamplerType(ImageDimensions target)
{ {
switch (target) switch (target)
{ {
@ -874,12 +897,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
return SamplerType.Texture3D; return SamplerType.Texture3D;
} }
// TODO: Error. return SamplerType.None;
return SamplerType.Texture2D;
} }
private static SamplerType GetSamplerType(TextureDimensions dimensions) private static SamplerType ConvertSamplerType(TextureDimensions dimensions)
{ {
switch (dimensions) switch (dimensions)
{ {
@ -892,7 +913,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\"."); throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\".");
} }
private static SamplerType GetSamplerType(Decoders.TextureTarget type) private static SamplerType ConvertSamplerType(Decoders.TextureTarget type)
{ {
switch (type) switch (type)
{ {
@ -925,12 +946,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
return SamplerType.TextureCube; return SamplerType.TextureCube;
} }
// TODO: Error. return SamplerType.None;
return SamplerType.Texture2D;
} }
private static SamplerType GetSamplerType(TexelLoadTarget type) private static SamplerType ConvertSamplerType(TexelLoadTarget type)
{ {
switch (type) switch (type)
{ {
@ -954,12 +973,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
return SamplerType.Texture2D | SamplerType.Array; return SamplerType.Texture2D | SamplerType.Array;
} }
// TODO: Error. return SamplerType.None;
return SamplerType.Texture2D;
} }
private static TextureFlags GetTextureFlags(Decoders.TextureTarget type) private static TextureFlags ConvertTextureFlags(Decoders.TextureTarget type)
{ {
switch (type) switch (type)
{ {
@ -982,12 +999,10 @@ namespace Ryujinx.Graphics.Shader.Instructions
return TextureFlags.None; return TextureFlags.None;
} }
// TODO: Error.
return TextureFlags.None; return TextureFlags.None;
} }
private static TextureFlags GetTextureFlags(TexelLoadTarget type) private static TextureFlags ConvertTextureFlags(TexelLoadTarget type)
{ {
switch (type) switch (type)
{ {
@ -1005,8 +1020,6 @@ namespace Ryujinx.Graphics.Shader.Instructions
return TextureFlags.LodLevel | TextureFlags.Offset; return TextureFlags.LodLevel | TextureFlags.Offset;
} }
// TODO: Error.
return TextureFlags.None; return TextureFlags.None;
} }
} }

View file

@ -5,6 +5,7 @@ namespace Ryujinx.Graphics.Shader
[Flags] [Flags]
public enum SamplerType public enum SamplerType
{ {
None = 0,
Texture1D, Texture1D,
TextureBuffer, TextureBuffer,
Texture2D, Texture2D,
@ -32,7 +33,7 @@ namespace Ryujinx.Graphics.Shader
case SamplerType.TextureCube: return 3; case SamplerType.TextureCube: return 3;
} }
throw new ArgumentException($"Invalid texture type \"{type}\"."); throw new ArgumentException($"Invalid sampler type \"{type}\".");
} }
} }
} }

View file

@ -28,6 +28,13 @@ namespace Ryujinx.Graphics.Shader.Translation
Block[] cfg = Decoder.Decode(code, (ulong)headerSize); Block[] cfg = Decoder.Decode(code, (ulong)headerSize);
if (cfg == null)
{
// TODO: Error.
return code;
}
ulong endAddress = 0; ulong endAddress = 0;
foreach (Block block in cfg) foreach (Block block in cfg)
@ -163,6 +170,8 @@ namespace Ryujinx.Graphics.Shader.Translation
if (cfg == null) if (cfg == null)
{ {
// TODO: Error.
size = 0; size = 0;
return new Operation[0]; return new Operation[0];