Make the shader translator more error resilient
This commit is contained in:
parent
eea73bc421
commit
04102e5c9d
3 changed files with 49 additions and 19 deletions
|
@ -29,6 +29,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
|
|
||||||
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
Dictionary<ulong, Block> visited = new Dictionary<ulong, Block>();
|
||||||
|
|
||||||
|
ulong maxAddress = (ulong)code.Length - headerSize;
|
||||||
|
|
||||||
Block GetBlock(ulong blkAddress)
|
Block GetBlock(ulong blkAddress)
|
||||||
{
|
{
|
||||||
if (!visited.TryGetValue(blkAddress, out Block block))
|
if (!visited.TryGetValue(blkAddress, out Block block))
|
||||||
|
@ -45,8 +47,6 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
|
|
||||||
GetBlock(0);
|
GetBlock(0);
|
||||||
|
|
||||||
ulong maxAddress = (ulong)code.Length - headerSize;
|
|
||||||
|
|
||||||
while (workQueue.TryDequeue(out Block currBlock))
|
while (workQueue.TryDequeue(out Block currBlock))
|
||||||
{
|
{
|
||||||
// Check if the current block is inside another block.
|
// Check if the current block is inside another block.
|
||||||
|
@ -93,6 +93,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
// including those from SSY/PBK instructions.
|
// including those from SSY/PBK instructions.
|
||||||
foreach (OpCodePush pushOp in currBlock.PushOpCodes)
|
foreach (OpCodePush pushOp in currBlock.PushOpCodes)
|
||||||
{
|
{
|
||||||
|
if (pushOp.GetAbsoluteAddress() >= maxAddress)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
GetBlock(pushOp.GetAbsoluteAddress());
|
GetBlock(pushOp.GetAbsoluteAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -104,6 +109,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
|
|
||||||
if (lastOp is OpCodeBranch opBr)
|
if (lastOp is OpCodeBranch opBr)
|
||||||
{
|
{
|
||||||
|
if (opBr.GetAbsoluteAddress() >= maxAddress)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
currBlock.Branch = GetBlock(opBr.GetAbsoluteAddress());
|
currBlock.Branch = GetBlock(opBr.GetAbsoluteAddress());
|
||||||
}
|
}
|
||||||
else if (lastOp is OpCodeBranchIndir opBrIndir)
|
else if (lastOp is OpCodeBranchIndir opBrIndir)
|
||||||
|
@ -431,11 +441,11 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
}
|
}
|
||||||
else if (current.GetLastOp() is OpCodeBranchPop op)
|
else if (current.GetLastOp() is OpCodeBranchPop op)
|
||||||
{
|
{
|
||||||
ulong syncAddress = branchStack.Pop();
|
ulong targetAddress = branchStack.Pop();
|
||||||
|
|
||||||
if (branchStack.Count == 0)
|
if (branchStack.Count == 0)
|
||||||
{
|
{
|
||||||
branchStack.Push(syncAddress);
|
branchStack.Push(targetAddress);
|
||||||
|
|
||||||
op.Targets.Add(pushOp, op.Targets.Count);
|
op.Targets.Add(pushOp, op.Targets.Count);
|
||||||
|
|
||||||
|
@ -443,8 +453,8 @@ namespace Ryujinx.Graphics.Shader.Decoders
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Push(new PathBlockState(syncAddress));
|
Push(new PathBlockState(targetAddress));
|
||||||
Push(new PathBlockState(blocks[syncAddress]));
|
Push(new PathBlockState(blocks[targetAddress]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
if (op is OpCodeTexs texsOp)
|
if (op is OpCodeTexs texsOp)
|
||||||
{
|
{
|
||||||
type = GetSamplerType (texsOp.Target);
|
type = GetSamplerType (texsOp.Target);
|
||||||
flags = GetSamplerFlags(texsOp.Target);
|
flags = GetTextureFlags(texsOp.Target);
|
||||||
|
|
||||||
if ((type & SamplerType.Array) != 0)
|
if ((type & SamplerType.Array) != 0)
|
||||||
{
|
{
|
||||||
|
@ -240,7 +240,7 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
else if (op is OpCodeTlds tldsOp)
|
else if (op is OpCodeTlds tldsOp)
|
||||||
{
|
{
|
||||||
type = GetSamplerType (tldsOp.Target);
|
type = GetSamplerType (tldsOp.Target);
|
||||||
flags = GetSamplerFlags(tldsOp.Target) | TextureFlags.IntCoords;
|
flags = GetTextureFlags(tldsOp.Target) | TextureFlags.IntCoords;
|
||||||
|
|
||||||
switch (tldsOp.Target)
|
switch (tldsOp.Target)
|
||||||
{
|
{
|
||||||
|
@ -874,7 +874,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return SamplerType.Texture3D;
|
return SamplerType.Texture3D;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Invalid image target \"{target}\".");
|
// TODO: Error.
|
||||||
|
|
||||||
|
return SamplerType.Texture2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SamplerType GetSamplerType(TextureDimensions dimensions)
|
private static SamplerType GetSamplerType(TextureDimensions dimensions)
|
||||||
|
@ -923,7 +925,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return SamplerType.TextureCube;
|
return SamplerType.TextureCube;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Invalid texture type \"{type}\".");
|
// TODO: Error.
|
||||||
|
|
||||||
|
return SamplerType.Texture2D;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static SamplerType GetSamplerType(TexelLoadTarget type)
|
private static SamplerType GetSamplerType(TexelLoadTarget type)
|
||||||
|
@ -950,10 +954,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return SamplerType.Texture2D | SamplerType.Array;
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -976,10 +982,12 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return TextureFlags.None;
|
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)
|
switch (type)
|
||||||
{
|
{
|
||||||
|
@ -997,7 +1005,9 @@ namespace Ryujinx.Graphics.Shader.Instructions
|
||||||
return TextureFlags.LodLevel | TextureFlags.Offset;
|
return TextureFlags.LodLevel | TextureFlags.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException($"Invalid texture type \"{type}\".");
|
// TODO: Error.
|
||||||
|
|
||||||
|
return TextureFlags.None;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -105,13 +105,16 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
{
|
{
|
||||||
BasicBlock[] irBlocks = ControlFlowGraph.MakeCfg(ops);
|
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);
|
StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(irBlocks, config);
|
||||||
|
|
||||||
|
@ -158,6 +161,13 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
context = new EmitterContext(header.Stage, header);
|
context = new EmitterContext(header.Stage, header);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (cfg == null)
|
||||||
|
{
|
||||||
|
size = 0;
|
||||||
|
|
||||||
|
return new Operation[0];
|
||||||
|
}
|
||||||
|
|
||||||
ulong maxEndAddress = 0;
|
ulong maxEndAddress = 0;
|
||||||
|
|
||||||
for (int blkIndex = 0; blkIndex < cfg.Length; blkIndex++)
|
for (int blkIndex = 0; blkIndex < cfg.Length; blkIndex++)
|
||||||
|
|
Loading…
Reference in a new issue