aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Shader/Translation
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Shader/Translation')
-rw-r--r--Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs38
-rw-r--r--Ryujinx.Graphics.Shader/Translation/Translator.cs12
-rw-r--r--Ryujinx.Graphics.Shader/Translation/TranslatorContext.cs97
3 files changed, 135 insertions, 12 deletions
diff --git a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
index fcf35ce2..ae4107e8 100644
--- a/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
+++ b/Ryujinx.Graphics.Shader/Translation/ShaderConfig.cs
@@ -48,6 +48,9 @@ namespace Ryujinx.Graphics.Shader.Translation
public int Cb1DataSize { get; private set; }
+ public bool LayerOutputWritten { get; private set; }
+ public int LayerOutputAttribute { get; private set; }
+
public bool NextUsesFixedFuncAttributes { get; private set; }
public int UsedInputAttributes { get; private set; }
public int UsedOutputAttributes { get; private set; }
@@ -131,6 +134,20 @@ namespace Ryujinx.Graphics.Shader.Translation
_usedImages = new Dictionary<TextureInfo, TextureMeta>();
}
+ public ShaderConfig(
+ ShaderStage stage,
+ OutputTopology outputTopology,
+ int maxOutputVertices,
+ IGpuAccessor gpuAccessor,
+ TranslationOptions options) : this(gpuAccessor, options)
+ {
+ Stage = stage;
+ ThreadsPerInputPrimitive = 1;
+ OutputTopology = outputTopology;
+ MaxOutputVertices = maxOutputVertices;
+ TransformFeedbackEnabled = gpuAccessor.QueryTransformFeedbackEnabled();
+ }
+
public ShaderConfig(ShaderHeader header, IGpuAccessor gpuAccessor, TranslationOptions options) : this(gpuAccessor, options)
{
Stage = header.Stage;
@@ -240,6 +257,12 @@ namespace Ryujinx.Graphics.Shader.Translation
}
}
+ public void SetLayerOutputAttribute(int attr)
+ {
+ LayerOutputWritten = true;
+ LayerOutputAttribute = attr;
+ }
+
public void SetInputUserAttributeFixedFunc(int index)
{
UsedInputAttributes |= 1 << index;
@@ -694,5 +717,20 @@ namespace Ryujinx.Graphics.Shader.Translation
{
return FindDescriptorIndex(GetImageDescriptors(), texOp);
}
+
+ public ShaderProgramInfo CreateProgramInfo()
+ {
+ return new ShaderProgramInfo(
+ GetConstantBufferDescriptors(),
+ GetStorageBufferDescriptors(),
+ GetTextureDescriptors(),
+ GetImageDescriptors(),
+ Stage,
+ UsedFeatures.HasFlag(FeatureFlags.InstanceId),
+ UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
+ UsedFeatures.HasFlag(FeatureFlags.RtLayer),
+ ClipDistancesWritten,
+ OmapTargets);
+ }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics.Shader/Translation/Translator.cs b/Ryujinx.Graphics.Shader/Translation/Translator.cs
index 82539196..f8795c0f 100644
--- a/Ryujinx.Graphics.Shader/Translation/Translator.cs
+++ b/Ryujinx.Graphics.Shader/Translation/Translator.cs
@@ -79,17 +79,7 @@ namespace Ryujinx.Graphics.Shader.Translation
var sInfo = StructuredProgram.MakeStructuredProgram(funcs, config);
- var info = new ShaderProgramInfo(
- config.GetConstantBufferDescriptors(),
- config.GetStorageBufferDescriptors(),
- config.GetTextureDescriptors(),
- config.GetImageDescriptors(),
- config.Stage,
- config.UsedFeatures.HasFlag(FeatureFlags.InstanceId),
- config.UsedFeatures.HasFlag(FeatureFlags.DrawParameters),
- config.UsedFeatures.HasFlag(FeatureFlags.RtLayer),
- config.ClipDistancesWritten,
- config.OmapTargets);
+ var info = config.CreateProgramInfo();
return config.Options.TargetLanguage switch
{
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())
+ };
+ }
}
}