aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2019-04-17 20:57:08 -0300
committerjduncanator <1518948+jduncanator@users.noreply.github.com>2019-04-18 09:57:08 +1000
commit6b23a2c125b9c48b5ebea92716004ef68698bb0f (patch)
tree69332df6fbbd8e2bddc522ba682fcc5c7a69e101 /Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs
parentb2e88b04a85b41cc60af3485d88c90429e84a218 (diff)
New shader translator implementation (#654)
* Start implementing a new shader translator * Fix shift instructions and a typo * Small refactoring on StructuredProgram, move RemovePhis method to a separate class * Initial geometry shader support * Implement TLD4 * Fix -- There's no negation on FMUL32I * Add constant folding and algebraic simplification optimizations, nits * Some leftovers from constant folding * Avoid cast for constant assignments * Add a branch elimination pass, and misc small fixes * Remove redundant branches, add expression propagation and other improvements on the code * Small leftovers -- add missing break and continue, remove unused properties, other improvements * Add null check to handle empty block cases on block visitor * Add HADD2 and HMUL2 half float shader instructions * Optimize pack/unpack sequences, some fixes related to half float instructions * Add TXQ, TLD, TLDS and TLD4S shader texture instructions, and some support for bindless textures, some refactoring on codegen * Fix copy paste mistake that caused RZ to be ignored on the AST instruction * Add workaround for conditional exit, and fix half float instruction with constant buffer * Add missing 0.0 source for TLDS.LZ variants * Simplify the switch for TLDS.LZ * Texture instructions related fixes * Implement the HFMA instruction, and some misc. fixes * Enable constant folding on UnpackHalf2x16 instructions * Refactor HFMA to use OpCode* for opcode decoding rather than on the helper methods * Remove the old shader translator * Remove ShaderDeclInfo and other unused things * Add dual vertex shader support * Add ShaderConfig, used to pass shader type and maximum cbuffer size * Move and rename some instruction enums * Move texture instructions into a separate file * Move operand GetExpression and locals management to OperandManager * Optimize opcode decoding using a simple list and binary search * Add missing condition for do-while on goto elimination * Misc. fixes on texture instructions * Simplify TLDS switch * Address PR feedback, and a nit
Diffstat (limited to 'Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs')
-rw-r--r--Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs133
1 files changed, 133 insertions, 0 deletions
diff --git a/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs
new file mode 100644
index 00000000..4edbda8b
--- /dev/null
+++ b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs
@@ -0,0 +1,133 @@
+using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Shader.CodeGen.Glsl.Instructions;
+using Ryujinx.Graphics.Shader.IntermediateRepresentation;
+using Ryujinx.Graphics.Shader.StructuredIr;
+using System;
+
+using static Ryujinx.Graphics.Shader.CodeGen.Glsl.TypeConversion;
+
+namespace Ryujinx.Graphics.Shader.CodeGen.Glsl
+{
+ static class GlslGenerator
+ {
+ public static GlslProgram Generate(StructuredProgramInfo info, ShaderConfig config)
+ {
+ CodeGenContext context = new CodeGenContext(config);
+
+ Declarations.Declare(context, info);
+
+ PrintMainBlock(context, info);
+
+ return new GlslProgram(
+ context.CBufferDescriptors.ToArray(),
+ context.TextureDescriptors.ToArray(),
+ context.GetCode());
+ }
+
+ private static void PrintMainBlock(CodeGenContext context, StructuredProgramInfo info)
+ {
+ context.AppendLine("void main()");
+
+ context.EnterScope();
+
+ Declarations.DeclareLocals(context, info);
+
+ PrintBlock(context, info.MainBlock);
+
+ context.LeaveScope();
+ }
+
+ private static void PrintBlock(CodeGenContext context, AstBlock block)
+ {
+ AstBlockVisitor visitor = new AstBlockVisitor(block);
+
+ visitor.BlockEntered += (sender, e) =>
+ {
+ switch (e.Block.Type)
+ {
+ case AstBlockType.DoWhile:
+ context.AppendLine("do");
+ break;
+
+ case AstBlockType.Else:
+ context.AppendLine("else");
+ break;
+
+ case AstBlockType.ElseIf:
+ context.AppendLine($"else if ({GetCondExpr(context, e.Block.Condition)})");
+ break;
+
+ case AstBlockType.If:
+ context.AppendLine($"if ({GetCondExpr(context, e.Block.Condition)})");
+ break;
+
+ default: throw new InvalidOperationException($"Found unexpected block type \"{e.Block.Type}\".");
+ }
+
+ context.EnterScope();
+ };
+
+ visitor.BlockLeft += (sender, e) =>
+ {
+ context.LeaveScope();
+
+ if (e.Block.Type == AstBlockType.DoWhile)
+ {
+ context.AppendLine($"while ({GetCondExpr(context, e.Block.Condition)});");
+ }
+ };
+
+ foreach (IAstNode node in visitor.Visit())
+ {
+ if (node is AstOperation operation)
+ {
+ if (operation.Inst == Instruction.Return)
+ {
+ PrepareForReturn(context);
+ }
+
+ context.AppendLine(InstGen.GetExpression(context, operation) + ";");
+ }
+ else if (node is AstAssignment assignment)
+ {
+ VariableType srcType = OperandManager.GetNodeDestType(assignment.Source);
+ VariableType dstType = OperandManager.GetNodeDestType(assignment.Destination);
+
+ string dest;
+
+ if (assignment.Destination is AstOperand operand && operand.Type == OperandType.Attribute)
+ {
+ dest = OperandManager.GetOutAttributeName(operand, context.Config.Type);
+ }
+ else
+ {
+ dest = InstGen.GetExpression(context, assignment.Destination);
+ }
+
+ string src = ReinterpretCast(context, assignment.Source, srcType, dstType);
+
+ context.AppendLine(dest + " = " + src + ";");
+ }
+ else
+ {
+ throw new InvalidOperationException($"Found unexpected node type \"{node?.GetType().Name ?? "null"}\".");
+ }
+ }
+ }
+
+ private static string GetCondExpr(CodeGenContext context, IAstNode cond)
+ {
+ VariableType srcType = OperandManager.GetNodeDestType(cond);
+
+ return ReinterpretCast(context, cond, srcType, VariableType.Bool);
+ }
+
+ private static void PrepareForReturn(CodeGenContext context)
+ {
+ if (context.Config.Type == GalShaderType.Vertex)
+ {
+ context.AppendLine("gl_Position.xy *= flip;");
+ }
+ }
+ }
+} \ No newline at end of file