aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Shader/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Shader/CodeGen')
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs32
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs7
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs12
-rw-r--r--src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs2
4 files changed, 46 insertions, 7 deletions
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
index 751d0350..fe0d275b 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Glsl/GlslGenerator.cs
@@ -28,18 +28,18 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
for (int i = 1; i < info.Functions.Count; i++)
{
- PrintFunction(context, info, info.Functions[i]);
+ PrintFunction(context, info.Functions[i]);
context.AppendLine();
}
}
- PrintFunction(context, info, info.Functions[0], MainFunctionName);
+ PrintFunction(context, info.Functions[0], MainFunctionName);
return context.GetCode();
}
- private static void PrintFunction(CodeGenContext context, StructuredProgramInfo info, StructuredFunction function, string funcName = null)
+ private static void PrintFunction(CodeGenContext context, StructuredFunction function, string funcName = null)
{
context.CurrentFunction = function;
@@ -48,7 +48,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
Declarations.DeclareLocals(context, function);
- PrintBlock(context, function.MainBlock);
+ PrintBlock(context, function.MainBlock, funcName == MainFunctionName);
context.LeaveScope();
}
@@ -72,7 +72,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
return $"{Declarations.GetVarTypeName(context, function.ReturnType)} {funcName ?? function.Name}({string.Join(", ", args)})";
}
- private static void PrintBlock(CodeGenContext context, AstBlock block)
+ private static void PrintBlock(CodeGenContext context, AstBlock block, bool isMainFunction)
{
AstBlockVisitor visitor = new AstBlockVisitor(block);
@@ -112,10 +112,32 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
}
};
+ bool supportsBarrierDivergence = context.Config.GpuAccessor.QueryHostSupportsShaderBarrierDivergence();
+ bool mayHaveReturned = false;
+
foreach (IAstNode node in visitor.Visit())
{
if (node is AstOperation operation)
{
+ if (!supportsBarrierDivergence)
+ {
+ if (operation.Inst == IntermediateRepresentation.Instruction.Barrier)
+ {
+ // Barrier on divergent control flow paths may cause the GPU to hang,
+ // so skip emitting the barrier for those cases.
+ if (visitor.Block.Type != AstBlockType.Main || mayHaveReturned || !isMainFunction)
+ {
+ context.Config.GpuAccessor.Log($"Shader has barrier on potentially divergent block, the barrier will be removed.");
+
+ continue;
+ }
+ }
+ else if (operation.Inst == IntermediateRepresentation.Instruction.Return)
+ {
+ mayHaveReturned = true;
+ }
+ }
+
string expr = InstGen.GetExpression(context, operation);
if (expr != null)
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
index c1bfa088..1f5167e6 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/CodeGenContext.cs
@@ -76,6 +76,9 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
public SpirvDelegates Delegates { get; }
+ public bool IsMainFunction { get; private set; }
+ public bool MayHaveReturned { get; set; }
+
public CodeGenContext(
StructuredProgramInfo info,
ShaderConfig config,
@@ -108,8 +111,10 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
Delegates = new SpirvDelegates(this);
}
- public void StartFunction()
+ public void StartFunction(bool isMainFunction)
{
+ IsMainFunction = isMainFunction;
+ MayHaveReturned = false;
_locals.Clear();
_localForArgs.Clear();
_funcArgs.Clear();
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
index 4be0c62b..6c115752 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/Instructions.cs
@@ -242,6 +242,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static OperationResult GenerateBarrier(CodeGenContext context, AstOperation operation)
{
+ // Barrier on divergent control flow paths may cause the GPU to hang,
+ // so skip emitting the barrier for those cases.
+ if (!context.Config.GpuAccessor.QueryHostSupportsShaderBarrierDivergence() &&
+ (context.CurrentBlock.Type != AstBlockType.Main || context.MayHaveReturned || !context.IsMainFunction))
+ {
+ context.Config.GpuAccessor.Log($"Shader has barrier on potentially divergent block, the barrier will be removed.");
+
+ return OperationResult.Invalid;
+ }
+
context.ControlBarrier(
context.Constant(context.TypeU32(), Scope.Workgroup),
context.Constant(context.TypeU32(), Scope.Workgroup),
@@ -1092,6 +1102,8 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
private static OperationResult GenerateReturn(CodeGenContext context, AstOperation operation)
{
+ context.MayHaveReturned = true;
+
if (operation.SourcesCount != 0)
{
context.ReturnValue(context.Get(context.CurrentFunction.ReturnType, operation.GetSource(0)));
diff --git a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
index a55e09fd..5c736b60 100644
--- a/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
+++ b/src/Ryujinx.Graphics.Shader/CodeGen/Spirv/SpirvGenerator.cs
@@ -148,7 +148,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Spirv
context.CurrentFunction = function;
context.AddFunction(spvFunc);
- context.StartFunction();
+ context.StartFunction(isMainFunction: funcIndex == 0);
Declarations.DeclareParameters(context, function);