aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdk <gab.dark.100@gmail.com>2019-11-15 00:01:54 -0300
committerThog <thog@protonmail.com>2020-01-09 02:13:00 +0100
commit04102e5c9db600d4ea4ffc0b514bda6f5e300bca (patch)
tree0ac17582778c118b98fc6d1a7f26f17b441374fc
parenteea73bc421d359f0df60f377d2f921357a217416 (diff)
Make the shader translator more error resilient
-rw-r--r--Ryujinx.Graphics.Shader/Decoders/Decoder.cs22
-rw-r--r--Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs28
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Translator.cs18
3 files changed, 49 insertions, 19 deletions
diff --git a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
index 9f039b94..5cee5b3a 100644
--- a/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
+++ b/Ryujinx.Graphics.Shader/Decoders/Decoder.cs
@@ -29,6 +29,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
+ ulong maxAddress = (ulong)code.Length - headerSize;
+
Block GetBlock(ulong blkAddress)
{
if (!visited.TryGetValue(blkAddress, out Block block))
@@ -45,8 +47,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
GetBlock(0);
- ulong maxAddress = (ulong)code.Length - headerSize;
-
while (workQueue.TryDequeue(out Block currBlock))
{
// Check if the current block is inside another block.
@@ -93,6 +93,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
// including those from SSY/PBK instructions.
foreach (OpCodePush pushOp in currBlock.PushOpCodes)
{
+ if (pushOp.GetAbsoluteAddress() >= maxAddress)
+ {
+ return null;
+ }
+
GetBlock(pushOp.GetAbsoluteAddress());
}
@@ -104,6 +109,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
if (lastOp is OpCodeBranch opBr)
{
+ if (opBr.GetAbsoluteAddress() >= maxAddress)
+ {
+ return null;
+ }
+
currBlock.Branch = GetBlock(opBr.GetAbsoluteAddress());
}
else if (lastOp is OpCodeBranchIndir opBrIndir)
@@ -431,11 +441,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
else if (current.GetLastOp() is OpCodeBranchPop op)
{
- ulong syncAddress = branchStack.Pop();
+ ulong targetAddress = branchStack.Pop();
if (branchStack.Count == 0)
{
- branchStack.Push(syncAddress);
+ branchStack.Push(targetAddress);
op.Targets.Add(pushOp, op.Targets.Count);
@@ -443,8 +453,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
}
else
{
- Push(new PathBlockState(syncAddress));
- Push(new PathBlockState(blocks[syncAddress]));
+ Push(new PathBlockState(targetAddress));
+ Push(new PathBlockState(blocks[targetAddress]));
}
}
}
diff --git a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
index 2654a05b..4a05b43b 100644
--- a/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
+++ b/Ryujinx.Graphics.Shader/Instructions/InstEmitTexture.cs
@@ -170,7 +170,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
if (op is OpCodeTexs texsOp)
{
type = GetSamplerType (texsOp.Target);
- flags = GetSamplerFlags(texsOp.Target);
+ flags = GetTextureFlags(texsOp.Target);
if ((type & SamplerType.Array) != 0)
{
@@ -240,7 +240,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
else if (op is OpCodeTlds tldsOp)
{
type = GetSamplerType (tldsOp.Target);
- flags = GetSamplerFlags(tldsOp.Target) | TextureFlags.IntCoords;
+ flags = GetTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;
switch (tldsOp.Target)
{
@@ -874,7 +874,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
return SamplerType.Texture3D;
}
- throw new ArgumentException($"Invalid image target \"{target}\".");
+ // TODO: Error.
+
+ return SamplerType.Texture2D;
}
private static SamplerType GetSamplerType(TextureDimensions dimensions)
@@ -923,7 +925,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
return SamplerType.TextureCube;
}
- throw new ArgumentException($"Invalid texture type \"{type}\".");
+ // TODO: Error.
+
+ return SamplerType.Texture2D;
}
private static SamplerType GetSamplerType(TexelLoadTarget type)
@@ -950,10 +954,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
return SamplerType.Texture2D | SamplerType.Array;
}
- throw new ArgumentException($"Invalid texture type \"{type}\".");
+ // TODO: Error.
+
+ return SamplerType.Texture2D;
}
- private static TextureFlags GetSamplerFlags(Decoders.TextureTarget type)
+ private static TextureFlags GetTextureFlags(Decoders.TextureTarget type)
{
switch (type)
{
@@ -976,10 +982,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
return TextureFlags.None;
}
- throw new ArgumentException($"Invalid texture type \"{type}\".");
+ // TODO: Error.
+
+ return TextureFlags.None;
}
- private static TextureFlags GetSamplerFlags(TexelLoadTarget type)
+ private static TextureFlags GetTextureFlags(TexelLoadTarget type)
{
switch (type)
{
@@ -997,7 +1005,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
return TextureFlags.LodLevel | TextureFlags.Offset;
}
- throw new ArgumentException($"Invalid texture type \"{type}\".");
+ // TODO: Error.
+
+ return TextureFlags.None;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 55617b24..3e5cb4a8 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -105,13 +105,16 @@ namespace Ryujinx.Graphics.Shader.Translation
{
BasicBlock[] irBlocks = ControlFlowGraph.MakeCfg(ops);
- Dominance.FindDominators(irBlocks[0], irBlocks.Length);
+ if (irBlocks.Length > 0)
+ {
+ Dominance.FindDominators(irBlocks[0], irBlocks.Length);
- Dominance.FindDominanceFrontiers(irBlocks);
+ Dominance.FindDominanceFrontiers(irBlocks);
- Ssa.Rename(irBlocks);
+ Ssa.Rename(irBlocks);
- Optimizer.Optimize(irBlocks, config.Stage);
+ Optimizer.Optimize(irBlocks, config.Stage);
+ }
StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(irBlocks, config);
@@ -158,6 +161,13 @@ namespace Ryujinx.Graphics.Shader.Translation
context = new EmitterContext(header.Stage, header);
}
+ if (cfg == null)
+ {
+ size = 0;
+
+ return new Operation[0];
+ }
+
ulong maxEndAddress = 0;
for (int blkIndex = 0; blkIndex < cfg.Length; blkIndex++)