forked from Mirror/Ryujinx
Salieri: Detect and avoid caching shaders using bindless textures (#2097)
* Salieri: Add blacklist system and blacklist shaders using bindless Currently the shader cache doesn't have the right format to support bindless textures correctly and may cache shaders that it cannot rebuild after host invalidation. This PR address the issue by blacklisting shaders using bindless textures. THis also support detection of already cached broken shader and handle removal of those. * Move to a feature flags design to avoid intrusive changes in the translator This remove the auto correct behaviour * Reduce diff on TranslationFlags * Reduce comma on last entry of TranslationFlags * Fix inverted logic and remove leftovers * remove debug edits oops
This commit is contained in:
parent
9b7335a63b
commit
aef25980a7
4 changed files with 39 additions and 4 deletions
|
@ -195,7 +195,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
|
|
||||||
if (tfd != null)
|
if (tfd != null)
|
||||||
{
|
{
|
||||||
flags = TranslationFlags.Feedback;
|
flags |= TranslationFlags.Feedback;
|
||||||
}
|
}
|
||||||
|
|
||||||
TranslationCounts counts = new TranslationCounts();
|
TranslationCounts counts = new TranslationCounts();
|
||||||
|
@ -426,6 +426,8 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
// The shader isn't currently cached, translate it and compile it.
|
// The shader isn't currently cached, translate it and compile it.
|
||||||
ShaderCodeHolder shader = TranslateShader(shaderContexts[0]);
|
ShaderCodeHolder shader = TranslateShader(shaderContexts[0]);
|
||||||
|
|
||||||
|
bool isDiskShaderCacheIncompatible = shaderContexts[0].UsedFeatures.HasFlag(FeatureFlags.Bindless);
|
||||||
|
|
||||||
shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code);
|
shader.HostShader = _context.Renderer.CompileShader(ShaderStage.Compute, shader.Program.Code);
|
||||||
|
|
||||||
IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, null);
|
IProgram hostProgram = _context.Renderer.CreateProgram(new IShader[] { shader.HostShader }, null);
|
||||||
|
@ -434,7 +436,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
|
|
||||||
cpShader = new ShaderBundle(hostProgram, shader);
|
cpShader = new ShaderBundle(hostProgram, shader);
|
||||||
|
|
||||||
if (isShaderCacheEnabled)
|
if (isShaderCacheEnabled && !isDiskShaderCacheIncompatible)
|
||||||
{
|
{
|
||||||
_cpProgramsDiskCache.Add(programCodeHash, cpShader);
|
_cpProgramsDiskCache.Add(programCodeHash, cpShader);
|
||||||
|
|
||||||
|
@ -540,6 +542,17 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
shaders[3] = TranslateShader(shaderContexts[4]);
|
shaders[3] = TranslateShader(shaderContexts[4]);
|
||||||
shaders[4] = TranslateShader(shaderContexts[5]);
|
shaders[4] = TranslateShader(shaderContexts[5]);
|
||||||
|
|
||||||
|
bool isDiskShaderCacheIncompatible = false;
|
||||||
|
|
||||||
|
for (int i = 0; i < shaderContexts.Length; i++)
|
||||||
|
{
|
||||||
|
if (shaderContexts[i] != null && shaderContexts[i].UsedFeatures.HasFlag(FeatureFlags.Bindless))
|
||||||
|
{
|
||||||
|
isDiskShaderCacheIncompatible = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
List<IShader> hostShaders = new List<IShader>();
|
List<IShader> hostShaders = new List<IShader>();
|
||||||
|
|
||||||
for (int stage = 0; stage < Constants.ShaderStages; stage++)
|
for (int stage = 0; stage < Constants.ShaderStages; stage++)
|
||||||
|
@ -564,7 +577,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
|
|
||||||
gpShaders = new ShaderBundle(hostProgram, shaders);
|
gpShaders = new ShaderBundle(hostProgram, shaders);
|
||||||
|
|
||||||
if (isShaderCacheEnabled)
|
if (isShaderCacheEnabled && !isDiskShaderCacheIncompatible)
|
||||||
{
|
{
|
||||||
_gpProgramsDiskCache.Add(programCodeHash, gpShaders);
|
_gpProgramsDiskCache.Add(programCodeHash, gpShaders);
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
|
|
||||||
// Affected by resolution scaling.
|
// Affected by resolution scaling.
|
||||||
FragCoordXY = 1 << 1,
|
FragCoordXY = 1 << 1,
|
||||||
IntegerSampling = 1 << 0
|
IntegerSampling = 1 << 0,
|
||||||
|
|
||||||
|
Bindless = 1 << 2,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,6 +36,22 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
return new TranslatorContext(address, cfg, config);
|
return new TranslatorContext(address, cfg, config);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void ScanForBindless(BasicBlock[] blocks, ShaderConfig config)
|
||||||
|
{
|
||||||
|
for (int blkIndex = 0; blkIndex < blocks.Length; blkIndex++)
|
||||||
|
{
|
||||||
|
// Right now the guest shader cache cannot handle bindless textures correctly.
|
||||||
|
for (LinkedListNode<INode> node = blocks[blkIndex].Operations.First; node != null; node = node.Next)
|
||||||
|
{
|
||||||
|
if (node.Value is TextureOperation texOp && (texOp.Flags & TextureFlags.Bindless) != 0)
|
||||||
|
{
|
||||||
|
config.SetUsedFeature(FeatureFlags.Bindless);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo)
|
internal static ShaderProgram Translate(FunctionCode[] functions, ShaderConfig config, out ShaderProgramInfo shaderProgramInfo)
|
||||||
{
|
{
|
||||||
var cfgs = new ControlFlowGraph[functions.Length];
|
var cfgs = new ControlFlowGraph[functions.Length];
|
||||||
|
@ -75,6 +91,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
Dominance.FindDominators(cfg);
|
Dominance.FindDominators(cfg);
|
||||||
Dominance.FindDominanceFrontiers(cfg.Blocks);
|
Dominance.FindDominanceFrontiers(cfg.Blocks);
|
||||||
|
|
||||||
|
ScanForBindless(cfg.Blocks, config);
|
||||||
|
|
||||||
Ssa.Rename(cfg.Blocks);
|
Ssa.Rename(cfg.Blocks);
|
||||||
|
|
||||||
Optimizer.RunPass(cfg.Blocks, config);
|
Optimizer.RunPass(cfg.Blocks, config);
|
||||||
|
|
|
@ -17,6 +17,8 @@ namespace Ryujinx.Graphics.Shader.Translation
|
||||||
public ShaderStage Stage => _config.Stage;
|
public ShaderStage Stage => _config.Stage;
|
||||||
public int Size => _config.Size;
|
public int Size => _config.Size;
|
||||||
|
|
||||||
|
public FeatureFlags UsedFeatures => _config.UsedFeatures;
|
||||||
|
|
||||||
public HashSet<int> TextureHandlesForCache => _config.TextureHandlesForCache;
|
public HashSet<int> TextureHandlesForCache => _config.TextureHandlesForCache;
|
||||||
|
|
||||||
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
|
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
|
||||||
|
|
Loading…
Reference in a new issue