diff options
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs')
-rw-r--r-- | Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs | 97 |
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()) + }; + } } } |