From 8eb773d81f0b580851b840f3abc222b784523fbc Mon Sep 17 00:00:00 2001 From: gdk Date: Fri, 15 Nov 2019 20:41:06 -0300 Subject: [PATCH] Make the shader translator more error resilient (part 2) --- .../Instructions/InstEmitConversion.cs | 13 +++- .../Instructions/InstEmitHelper.cs | 4 +- .../Instructions/InstEmitTexture.cs | 69 +++++++++++-------- Ryujinx.Graphics.Shader/SamplerType.cs | 3 +- .../Translation/Translator.cs | 9 +++ 5 files changed, 67 insertions(+), 31 deletions(-) diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs index 95e9a20a70..5aa925d9c9 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitConversion.cs @@ -60,6 +60,13 @@ namespace Ryujinx.Graphics.Shader.Instructions 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; 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); + // TODO: Handle S/U64. + bool isSmallInt = srcType <= IntegerType.U16; bool isSignedInt = op.RawOpCode.Extract(13); @@ -153,7 +162,9 @@ namespace Ryujinx.Graphics.Shader.Instructions 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; diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs index ddacc15188..4b85e96fdc 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitHelper.cs @@ -56,7 +56,9 @@ namespace Ryujinx.Graphics.Shader.Instructions // 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) diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs index 4a05b43b1e..41ba740e7d 100644 --- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs +++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs @@ -14,6 +14,15 @@ namespace Ryujinx.Graphics.Shader.Instructions { 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 rbIndex = op.Rb.Index; @@ -49,8 +58,6 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(context.Copy(Register(op.Rc))); } - SamplerType type = GetSamplerType(op.Dimensions); - int coordsCount = type.GetDimensions(); for (int index = 0; index < coordsCount; index++) @@ -169,8 +176,16 @@ namespace Ryujinx.Graphics.Shader.Instructions if (op is OpCodeTexs texsOp) { - type = GetSamplerType (texsOp.Target); - flags = GetTextureFlags(texsOp.Target); + type = ConvertSamplerType(texsOp.Target); + + if (type == SamplerType.None) + { + // TODO: Error, encoding is invalid. + + return; + } + + flags = ConvertTextureFlags(texsOp.Target); if ((type & SamplerType.Array) != 0) { @@ -239,8 +254,16 @@ namespace Ryujinx.Graphics.Shader.Instructions } else if (op is OpCodeTlds tldsOp) { - type = GetSamplerType (tldsOp.Target); - flags = GetTextureFlags(tldsOp.Target) | TextureFlags.IntCoords; + type = ConvertSamplerType (tldsOp.Target); + + if (type == SamplerType.None) + { + // TODO: Error, encoding is invalid. + + return; + } + + flags = ConvertTextureFlags(tldsOp.Target) | TextureFlags.IntCoords; switch (tldsOp.Target) { @@ -428,7 +451,7 @@ namespace Ryujinx.Graphics.Shader.Instructions List sourcesList = new List(); - SamplerType type = GetSamplerType(op.Dimensions); + SamplerType type = ConvertSamplerType(op.Dimensions); TextureFlags flags = TextureFlags.Gather; @@ -553,7 +576,7 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Ra()); } - SamplerType type = GetSamplerType(op.Dimensions); + SamplerType type = ConvertSamplerType(op.Dimensions); int coordsCount = type.GetDimensions(); @@ -752,7 +775,7 @@ namespace Ryujinx.Graphics.Shader.Instructions sourcesList.Add(Rb()); } - SamplerType type = GetSamplerType(op.Dimensions); + SamplerType type = ConvertSamplerType(op.Dimensions); 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) { @@ -874,12 +897,10 @@ namespace Ryujinx.Graphics.Shader.Instructions return SamplerType.Texture3D; } - // TODO: Error. - - return SamplerType.Texture2D; + return SamplerType.None; } - private static SamplerType GetSamplerType(TextureDimensions dimensions) + private static SamplerType ConvertSamplerType(TextureDimensions dimensions) { switch (dimensions) { @@ -892,7 +913,7 @@ namespace Ryujinx.Graphics.Shader.Instructions throw new ArgumentException($"Invalid texture dimensions \"{dimensions}\"."); } - private static SamplerType GetSamplerType(Decoders.TextureTarget type) + private static SamplerType ConvertSamplerType(Decoders.TextureTarget type) { switch (type) { @@ -925,12 +946,10 @@ namespace Ryujinx.Graphics.Shader.Instructions return SamplerType.TextureCube; } - // TODO: Error. - - return SamplerType.Texture2D; + return SamplerType.None; } - private static SamplerType GetSamplerType(TexelLoadTarget type) + private static SamplerType ConvertSamplerType(TexelLoadTarget type) { switch (type) { @@ -954,12 +973,10 @@ namespace Ryujinx.Graphics.Shader.Instructions return SamplerType.Texture2D | SamplerType.Array; } - // TODO: Error. - - return SamplerType.Texture2D; + return SamplerType.None; } - private static TextureFlags GetTextureFlags(Decoders.TextureTarget type) + private static TextureFlags ConvertTextureFlags(Decoders.TextureTarget type) { switch (type) { @@ -982,12 +999,10 @@ namespace Ryujinx.Graphics.Shader.Instructions return TextureFlags.None; } - // TODO: Error. - return TextureFlags.None; } - private static TextureFlags GetTextureFlags(TexelLoadTarget type) + private static TextureFlags ConvertTextureFlags(TexelLoadTarget type) { switch (type) { @@ -1005,8 +1020,6 @@ namespace Ryujinx.Graphics.Shader.Instructions return TextureFlags.LodLevel | TextureFlags.Offset; } - // TODO: Error. - return TextureFlags.None; } } diff --git a/Ryujinx.Graphics.Shader/SamplerType.cs b/Ryujinx.Graphics.Shader/SamplerType.cs index 5e0b776c3d..9546efe494 100644 --- a/Ryujinx.Graphics.Shader/SamplerType.cs +++ b/Ryujinx.Graphics.Shader/SamplerType.cs @@ -5,6 +5,7 @@ namespace Ryujinx.Graphics.Shader [Flags] public enum SamplerType { + None = 0, Texture1D, TextureBuffer, Texture2D, @@ -32,7 +33,7 @@ namespace Ryujinx.Graphics.Shader case SamplerType.TextureCube: return 3; } - throw new ArgumentException($"Invalid texture type \"{type}\"."); + throw new ArgumentException($"Invalid sampler type \"{type}\"."); } } } \ No newline at end of file diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs index 3e5cb4a89b..2f33997cb1 100644 --- a/Ryujinx.Graphics.Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs @@ -28,6 +28,13 @@ namespace Ryujinx.Graphics.Shader.Translation Block[] cfg = Decoder.Decode(code, (ulong)headerSize); + if (cfg == null) + { + // TODO: Error. + + return code; + } + ulong endAddress = 0; foreach (Block block in cfg) @@ -163,6 +170,8 @@ namespace Ryujinx.Graphics.Shader.Translation if (cfg == null) { + // TODO: Error. + size = 0; return new Operation[0];