aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs97
1 files changed, 96 insertions, 1 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
index 7d820f03..127f84a6 100644
--- a/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
+++ b/Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs
@@ -1,7 +1,12 @@
-using Ryujinx.Graphics.Shader.Decoders;
+using Ryujinx.Graphics.Shader.CodeGen.Glsl;
+using Ryujinx.Graphics.Shader.CodeGen.Spirv;
+using Ryujinx.Graphics.Shader.Decoders;
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
+using Ryujinx.Graphics.Shader.StructuredIr;
+using System;
using System.Collections.Generic;
using System.Linq;
+using System.Numerics;
using static Ryujinx.Graphics.Shader.IntermediateRepresentation.OperandHelper;
using static Ryujinx.Graphics.Shader.Translation.Translator;
@@ -18,6 +23,7 @@ namespace Ryujinx.Graphics.Shader.Translation
public ShaderStage Stage => _config.Stage;
public int Size => _config.Size;
public int Cb1DataSize => _config.Cb1DataSize;
+ public bool LayerOutputWritten => _config.LayerOutputWritten;
public IGpuAccessor GpuAccessor => _config.GpuAccessor;
@@ -149,5 +155,94 @@ namespace Ryujinx.Graphics.Shader.Translation
return Translator.Translate(code, _config);
}
+
+ public ShaderProgram GenerateGeometryPassthrough()
+ {
+ int outputAttributesMask = _config.UsedOutputAttributes;
+ int layerOutputAttr = _config.LayerOutputAttribute;
+
+ OutputTopology outputTopology;
+ int maxOutputVertices;
+
+ switch (GpuAccessor.QueryPrimitiveTopology())
+ {
+ case InputTopology.Points:
+ outputTopology = OutputTopology.PointList;
+ maxOutputVertices = 1;
+ break;
+ case InputTopology.Lines:
+ case InputTopology.LinesAdjacency:
+ outputTopology = OutputTopology.LineStrip;
+ maxOutputVertices = 2;
+ break;
+ default:
+ outputTopology = OutputTopology.TriangleStrip;
+ maxOutputVertices = 3;
+ break;
+ }
+
+ ShaderConfig config = new ShaderConfig(ShaderStage.Geometry, outputTopology, maxOutputVertices, GpuAccessor, _config.Options);
+
+ EmitterContext context = new EmitterContext(default, config, false);
+
+ for (int v = 0; v < maxOutputVertices; v++)
+ {
+ int outAttrsMask = outputAttributesMask;
+
+ while (outAttrsMask != 0)
+ {
+ int attrIndex = BitOperations.TrailingZeroCount(outAttrsMask);
+
+ outAttrsMask &= ~(1 << attrIndex);
+
+ for (int c = 0; c < 4; c++)
+ {
+ int attr = AttributeConsts.UserAttributeBase + attrIndex * 16 + c * 4;
+
+ Operand value = context.LoadAttribute(Const(attr), Const(0), Const(v));
+
+ if (attr == layerOutputAttr)
+ {
+ context.Copy(Attribute(AttributeConsts.Layer), value);
+ }
+ else
+ {
+ context.Copy(Attribute(attr), value);
+ config.SetOutputUserAttribute(attrIndex);
+ }
+
+ config.SetInputUserAttribute(attrIndex, c);
+ }
+ }
+
+ for (int c = 0; c < 4; c++)
+ {
+ int attr = AttributeConsts.PositionX + c * 4;
+
+ Operand value = context.LoadAttribute(Const(attr), Const(0), Const(v));
+
+ context.Copy(Attribute(attr), value);
+ }
+
+ context.EmitVertex();
+ }
+
+ context.EndPrimitive();
+
+ var operations = context.GetOperations();
+ var cfg = ControlFlowGraph.Create(operations);
+ var function = new Function(cfg.Blocks, "main", false, 0, 0);
+
+ var sInfo = StructuredProgram.MakeStructuredProgram(new[] { function }, config);
+
+ var info = config.CreateProgramInfo();
+
+ return config.Options.TargetLanguage switch
+ {
+ TargetLanguage.Glsl => new ShaderProgram(info, TargetLanguage.Glsl, GlslGenerator.Generate(sInfo, config)),
+ TargetLanguage.Spirv => new ShaderProgram(info, TargetLanguage.Spirv, SpirvGenerator.Generate(sInfo, config)),
+ _ => throw new NotImplementedException(config.Options.TargetLanguage.ToString())
+ };
+ }
}
}