From 33390035c44c755d5c19777c6562b65d6bdb77f9 Mon Sep 17 00:00:00 2001 From: gdkchan Date: Thu, 11 Apr 2019 21:03:17 -0300 Subject: [PATCH] Remove the old shader translator --- Ryujinx.Graphics/Gal/IGalShader.cs | 5 +- Ryujinx.Graphics/Gal/OpenGL/OglPipeline.cs | 5 +- Ryujinx.Graphics/Gal/OpenGL/OglShader.cs | 39 +- .../Gal/OpenGL/OglShaderProgram.cs | 13 +- Ryujinx.Graphics/Gal/Shader/GlslDecl.cs | 420 ---- Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs | 1684 ----------------- Ryujinx.Graphics/Gal/Shader/GlslProgram.cs | 22 - .../Gal/Shader/ShaderDecodeAlu.cs | 1299 ------------- .../Gal/Shader/ShaderDecodeFlow.cs | 57 - .../Gal/Shader/ShaderDecodeFunc.cs | 4 - .../Gal/Shader/ShaderDecodeHelper.cs | 78 - .../Gal/Shader/ShaderDecodeMem.cs | 878 --------- .../Gal/Shader/ShaderDecodeMove.cs | 431 ----- .../Gal/Shader/ShaderDecodeOpCode.cs | 313 --- .../Gal/Shader/ShaderDecodeSpecial.cs | 25 - Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs | 218 --- Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs | 146 -- Ryujinx.Graphics/Gal/Shader/ShaderIpaMode.cs | 10 - Ryujinx.Graphics/Gal/Shader/ShaderIrAsg.cs | 14 - Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs | 46 - Ryujinx.Graphics/Gal/Shader/ShaderIrCmnt.cs | 12 - Ryujinx.Graphics/Gal/Shader/ShaderIrCond.cs | 17 - Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs | 94 - Ryujinx.Graphics/Gal/Shader/ShaderIrMeta.cs | 4 - .../Gal/Shader/ShaderIrMetaIpa.cs | 12 - .../Gal/Shader/ShaderIrMetaTex.cs | 24 - .../Gal/Shader/ShaderIrMetaTexq.cs | 15 - Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs | 4 - Ryujinx.Graphics/Gal/Shader/ShaderIrOp.cs | 25 - .../Gal/Shader/ShaderIrOperAbuf.cs | 15 - .../Gal/Shader/ShaderIrOperCbuf.cs | 17 - .../Gal/Shader/ShaderIrOperGpr.cs | 36 - .../Gal/Shader/ShaderIrOperImm.cs | 12 - .../Gal/Shader/ShaderIrOperImmf.cs | 12 - .../Gal/Shader/ShaderIrOperPred.cs | 17 - .../Gal/Shader/ShaderOpCodeTable.cs | 190 -- Ryujinx.Graphics/Gal/Shader/ShaderOper.cs | 11 - .../Gal/Shader/ShaderRegisterSize.cs | 9 - Ryujinx.Graphics/Gal/Shader/ShaderTexqInfo.cs | 13 - Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs | 23 +- Ryujinx.Graphics/Shader/CBufferDescriptor.cs | 15 + .../Shader/CodeGen/Glsl/CodeGenContext.cs | 11 +- .../Shader/CodeGen/Glsl/Declarations.cs | 66 +- .../Shader/CodeGen/Glsl/GlslGenerator.cs | 15 +- .../Shader/CodeGen/Glsl/GlslProgram.cs | 20 + Ryujinx.Graphics/Shader/ShaderProgram.cs | 15 + Ryujinx.Graphics/Shader/ShaderProgramInfo.cs | 17 + .../Shader/StructuredIr/StructuredProgram.cs | 2 +- .../StructuredIr/StructuredProgramContext.cs | 2 +- .../StructuredIr/StructuredProgramInfo.cs | 6 +- Ryujinx.Graphics/Shader/TextureDescriptor.cs | 36 + .../Shader/Translation/Translator.cs | 12 +- Ryujinx.ShaderTools/Memory.cs | 2 +- Ryujinx.ShaderTools/Program.cs | 28 +- 54 files changed, 234 insertions(+), 6282 deletions(-) delete mode 100644 Ryujinx.Graphics/Gal/Shader/GlslDecl.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/GlslProgram.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIpaMode.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrAsg.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrCmnt.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrCond.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrMeta.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrMetaIpa.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOp.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOperAbuf.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOperCbuf.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderIrOperPred.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderOper.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderRegisterSize.cs delete mode 100644 Ryujinx.Graphics/Gal/Shader/ShaderTexqInfo.cs create mode 100644 Ryujinx.Graphics/Shader/CBufferDescriptor.cs create mode 100644 Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslProgram.cs create mode 100644 Ryujinx.Graphics/Shader/ShaderProgram.cs create mode 100644 Ryujinx.Graphics/Shader/ShaderProgramInfo.cs create mode 100644 Ryujinx.Graphics/Shader/TextureDescriptor.cs diff --git a/Ryujinx.Graphics/Gal/IGalShader.cs b/Ryujinx.Graphics/Gal/IGalShader.cs index 99cd4d7624..6a9abe75bc 100644 --- a/Ryujinx.Graphics/Gal/IGalShader.cs +++ b/Ryujinx.Graphics/Gal/IGalShader.cs @@ -1,3 +1,4 @@ +using Ryujinx.Graphics.Shader; using System.Collections.Generic; namespace Ryujinx.Graphics.Gal @@ -8,8 +9,8 @@ namespace Ryujinx.Graphics.Gal void Create(IGalMemory memory, long vpAPos, long key, GalShaderType type); - IEnumerable GetConstBufferUsage(long key); - IEnumerable GetTextureUsage(long key); + IEnumerable GetConstBufferUsage(long key); + IEnumerable GetTextureUsage(long key); void Bind(long key); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OglPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OglPipeline.cs index 3c8ada3ea6..64768e285b 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OglPipeline.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OglPipeline.cs @@ -1,4 +1,5 @@ using OpenTK.Graphics.OpenGL; +using Ryujinx.Graphics.Shader; using System; using System.Collections.Generic; @@ -529,9 +530,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { if (stage != null) { - foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage) + foreach (CBufferDescriptor desc in stage.ConstBufferUsage) { - long key = New.ConstBufferKeys[(int)stage.Type][declInfo.Cbuf]; + long key = New.ConstBufferKeys[(int)stage.Type][desc.Slot]; if (key != 0 && _buffer.TryGetUbo(key, out int uboHandle)) { diff --git a/Ryujinx.Graphics/Gal/OpenGL/OglShader.cs b/Ryujinx.Graphics/Gal/OpenGL/OglShader.cs index addc930217..9df341e895 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OglShader.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OglShader.cs @@ -1,5 +1,6 @@ using OpenTK.Graphics.OpenGL; -using Ryujinx.Graphics.Gal.Shader; +using Ryujinx.Graphics.Shader; +using Ryujinx.Graphics.Shader.Translation; using System; using System.Collections.Concurrent; using System.Collections.Generic; @@ -51,9 +52,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL bool isDualVp, GalShaderType type) { - GlslProgram program; - - GlslDecompiler decompiler = new GlslDecompiler(OglLimit.MaxUboSize, OglExtension.NvidiaDriver); + ShaderProgram program; int shaderDumpIndex = ShaderDumper.DumpIndex; @@ -62,13 +61,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL ShaderDumper.Dump(memory, position, type, "a"); ShaderDumper.Dump(memory, positionB, type, "b"); - program = decompiler.Decompile(memory, position, positionB, type); + //TODO: Dual vertex programs support. + program = Translator.Translate(memory, (ulong)position, type); } else { ShaderDumper.Dump(memory, position, type); - program = decompiler.Decompile(memory, position, type); + program = Translator.Translate(memory, (ulong)position, type); } string code = program.Code; @@ -78,27 +78,27 @@ namespace Ryujinx.Graphics.Gal.OpenGL code = "//Shader " + shaderDumpIndex + Environment.NewLine + code; } - return new OglShaderStage(type, code, program.Uniforms, program.Textures); + return new OglShaderStage(type, code, program.Info.CBuffers, program.Info.Textures); } - public IEnumerable GetConstBufferUsage(long key) + public IEnumerable GetConstBufferUsage(long key) { if (_stages.TryGetValue(key, out OglShaderStage stage)) { return stage.ConstBufferUsage; } - return Enumerable.Empty(); + return Enumerable.Empty(); } - public IEnumerable GetTextureUsage(long key) + public IEnumerable GetTextureUsage(long key) { if (_stages.TryGetValue(key, out OglShaderStage stage)) { return stage.TextureUsage; } - return Enumerable.Empty(); + return Enumerable.Empty(); } public unsafe void SetExtraData(float flipX, float flipY, int instance) @@ -211,7 +211,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL private void BindUniformBlocks(int programHandle) { - int extraBlockindex = GL.GetUniformBlockIndex(programHandle, GlslDecl.ExtraUniformBlockName); + int extraBlockindex = GL.GetUniformBlockIndex(programHandle, "Extra"); GL.UniformBlockBinding(programHandle, extraBlockindex, 0); @@ -221,14 +221,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL { if (stage != null) { - foreach (ShaderDeclInfo declInfo in stage.ConstBufferUsage) + foreach (CBufferDescriptor desc in stage.ConstBufferUsage) { - int blockIndex = GL.GetUniformBlockIndex(programHandle, declInfo.Name); + int blockIndex = GL.GetUniformBlockIndex(programHandle, desc.Name); if (blockIndex < 0) { + //This may be fine, the compiler may optimize away unused uniform buffers, + //and in this case the above call would return -1 as the buffer has been + //optimized away. + continue; + //It is expected that its found, if it's not then driver might be in a malfunction - throw new InvalidOperationException(); + //throw new InvalidOperationException(); } GL.UniformBlockBinding(programHandle, blockIndex, freeBinding); @@ -253,9 +258,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL { if (stage != null) { - foreach (ShaderDeclInfo decl in stage.TextureUsage) + foreach (TextureDescriptor desc in stage.TextureUsage) { - int location = GL.GetUniformLocation(programHandle, decl.Name); + int location = GL.GetUniformLocation(programHandle, desc.Name); GL.Uniform1(location, index); diff --git a/Ryujinx.Graphics/Gal/OpenGL/OglShaderProgram.cs b/Ryujinx.Graphics/Gal/OpenGL/OglShaderProgram.cs index 9e68a8e6dc..86126bca4d 100644 --- a/Ryujinx.Graphics/Gal/OpenGL/OglShaderProgram.cs +++ b/Ryujinx.Graphics/Gal/OpenGL/OglShaderProgram.cs @@ -1,4 +1,5 @@ using OpenTK.Graphics.OpenGL; +using Ryujinx.Graphics.Shader; using System; using System.Collections.Generic; @@ -23,14 +24,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL public string Code { get; private set; } - public IEnumerable ConstBufferUsage { get; private set; } - public IEnumerable TextureUsage { get; private set; } + public IEnumerable ConstBufferUsage { get; private set; } + public IEnumerable TextureUsage { get; private set; } public OglShaderStage( - GalShaderType type, - string code, - IEnumerable constBufferUsage, - IEnumerable textureUsage) + GalShaderType type, + string code, + IEnumerable constBufferUsage, + IEnumerable textureUsage) { Type = type; Code = code; diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs deleted file mode 100644 index 734267625c..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs +++ /dev/null @@ -1,420 +0,0 @@ -using Ryujinx.Graphics.Texture; -using System; -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gal.Shader -{ - class GlslDecl - { - public const int LayerAttr = 0x064; - public const int PointSizeAttr = 0x06c; - public const int PointCoordAttrX = 0x2e0; - public const int PointCoordAttrY = 0x2e4; - public const int TessCoordAttrX = 0x2f0; - public const int TessCoordAttrY = 0x2f4; - public const int TessCoordAttrZ = 0x2f8; - public const int InstanceIdAttr = 0x2f8; - public const int VertexIdAttr = 0x2fc; - public const int FaceAttr = 0x3fc; - - public const int GlPositionVec4Index = 7; - - public const int PositionOutAttrLocation = 15; - - private const int AttrStartIndex = 8; - private const int TexStartIndex = 8; - - public const string PositionOutAttrName = "position"; - - private const string TextureName = "tex"; - private const string UniformName = "c"; - - private const string AttrName = "attr"; - private const string InAttrName = "in_" + AttrName; - private const string OutAttrName = "out_" + AttrName; - - private const string GprName = "gpr"; - private const string PredName = "pred"; - - public const string FragmentOutputName = "FragColor"; - - public const string ExtraUniformBlockName = "Extra"; - public const string FlipUniformName = "flip"; - public const string InstanceUniformName = "instance"; - - public const string BasicBlockName = "bb"; - public const string BasicBlockAName = BasicBlockName + "_a"; - public const string BasicBlockBName = BasicBlockName + "_b"; - - public const int SsyStackSize = 16; - public const string SsyStackName = "ssy_stack"; - public const string SsyCursorName = "ssy_cursor"; - - private string[] _stagePrefixes = new string[] { "vp", "tcp", "tep", "gp", "fp" }; - - private string _stagePrefix; - - private Dictionary m_CbTextures; - - private Dictionary m_Textures; - private Dictionary m_Uniforms; - - private Dictionary m_Attributes; - private Dictionary m_InAttributes; - private Dictionary m_OutAttributes; - - private Dictionary m_Gprs; - private Dictionary m_GprsHalf; - private Dictionary m_Preds; - - public IReadOnlyDictionary CbTextures => m_CbTextures; - - public IReadOnlyDictionary Textures => m_Textures; - public IReadOnlyDictionary Uniforms => m_Uniforms; - - public IReadOnlyDictionary Attributes => m_Attributes; - public IReadOnlyDictionary InAttributes => m_InAttributes; - public IReadOnlyDictionary OutAttributes => m_OutAttributes; - - public IReadOnlyDictionary Gprs => m_Gprs; - public IReadOnlyDictionary GprsHalf => m_GprsHalf; - public IReadOnlyDictionary Preds => m_Preds; - - public GalShaderType ShaderType { get; private set; } - - private GlslDecl(GalShaderType shaderType) - { - ShaderType = shaderType; - - m_CbTextures = new Dictionary(); - - m_Textures = new Dictionary(); - m_Uniforms = new Dictionary(); - - m_Attributes = new Dictionary(); - m_InAttributes = new Dictionary(); - m_OutAttributes = new Dictionary(); - - m_Gprs = new Dictionary(); - m_GprsHalf = new Dictionary(); - m_Preds = new Dictionary(); - } - - public GlslDecl(ShaderIrBlock[] blocks, GalShaderType shaderType, ShaderHeader header) : this(shaderType) - { - _stagePrefix = _stagePrefixes[(int)shaderType] + "_"; - - if (shaderType == GalShaderType.Fragment) - { - int index = 0; - - for (int attachment = 0; attachment < 8; attachment++) - { - for (int component = 0; component < 4; component++) - { - if (header.OmapTargets[attachment].ComponentEnabled(component)) - { - m_Gprs.TryAdd(index, new ShaderDeclInfo(GetGprName(index), index)); - - index++; - } - } - } - - if (header.OmapDepth) - { - index = header.DepthRegister; - - m_Gprs.TryAdd(index, new ShaderDeclInfo(GetGprName(index), index)); - } - } - - foreach (ShaderIrBlock block in blocks) - { - ShaderIrNode[] nodes = block.GetNodes(); - - foreach (ShaderIrNode node in nodes) - { - Traverse(nodes, null, node); - } - } - } - - public static GlslDecl Merge(GlslDecl vpA, GlslDecl vpB) - { - GlslDecl combined = new GlslDecl(GalShaderType.Vertex); - - Merge(combined.m_Textures, vpA.m_Textures, vpB.m_Textures); - Merge(combined.m_Uniforms, vpA.m_Uniforms, vpB.m_Uniforms); - - Merge(combined.m_Attributes, vpA.m_Attributes, vpB.m_Attributes); - Merge(combined.m_OutAttributes, vpA.m_OutAttributes, vpB.m_OutAttributes); - - Merge(combined.m_Gprs, vpA.m_Gprs, vpB.m_Gprs); - Merge(combined.m_GprsHalf, vpA.m_GprsHalf, vpB.m_GprsHalf); - Merge(combined.m_Preds, vpA.m_Preds, vpB.m_Preds); - - //Merge input attributes. - foreach (KeyValuePair kv in vpA.m_InAttributes) - { - combined.m_InAttributes.TryAdd(kv.Key, kv.Value); - } - - foreach (KeyValuePair kv in vpB.m_InAttributes) - { - //If Vertex Program A already writes to this attribute, - //then we don't need to add it as an input attribute since - //Vertex Program A will already have written to it anyway, - //and there's no guarantee that there is an input attribute - //for this slot. - if (!vpA.m_OutAttributes.ContainsKey(kv.Key)) - { - combined.m_InAttributes.TryAdd(kv.Key, kv.Value); - } - } - - return combined; - } - - public static string GetGprName(int index) - { - return GprName + index; - } - - private static void Merge( - Dictionary c, - Dictionary a, - Dictionary b) - { - foreach (KeyValuePair kv in a) - { - c.TryAdd(kv.Key, kv.Value); - } - - foreach (KeyValuePair kv in b) - { - c.TryAdd(kv.Key, kv.Value); - } - } - - private void Traverse(ShaderIrNode[] nodes, ShaderIrNode parent, ShaderIrNode node) - { - switch (node) - { - case ShaderIrAsg asg: - { - Traverse(nodes, asg, asg.Dst); - Traverse(nodes, asg, asg.Src); - - break; - } - - case ShaderIrCond cond: - { - Traverse(nodes, cond, cond.Pred); - Traverse(nodes, cond, cond.Child); - - break; - } - - case ShaderIrOp op: - { - Traverse(nodes, op, op.OperandA); - Traverse(nodes, op, op.OperandB); - Traverse(nodes, op, op.OperandC); - - if (op.Inst == ShaderIrInst.Texq || - op.Inst == ShaderIrInst.Texs || - op.Inst == ShaderIrInst.Tld4 || - op.Inst == ShaderIrInst.Txlf) - { - int handle = ((ShaderIrOperImm)op.OperandC).Value; - - int index = handle - TexStartIndex; - - string name = _stagePrefix + TextureName + index; - - GalTextureTarget textureTarget; - - TextureInstructionSuffix textureInstructionSuffix; - - // TODO: Non 2D texture type for TEXQ? - if (op.Inst == ShaderIrInst.Texq) - { - textureTarget = GalTextureTarget.TwoD; - textureInstructionSuffix = TextureInstructionSuffix.None; - } - else - { - ShaderIrMetaTex meta = ((ShaderIrMetaTex)op.MetaData); - - textureTarget = meta.TextureTarget; - textureInstructionSuffix = meta.TextureInstructionSuffix; - } - - m_Textures.TryAdd(handle, new ShaderDeclInfo(name, handle, false, 0, 1, textureTarget, textureInstructionSuffix)); - } - else if (op.Inst == ShaderIrInst.Texb) - { - ShaderIrNode handleSrc = null; - - int index = Array.IndexOf(nodes, parent) - 1; - - for (; index >= 0; index--) - { - ShaderIrNode curr = nodes[index]; - - if (curr is ShaderIrAsg asg && asg.Dst is ShaderIrOperGpr gpr) - { - if (gpr.Index == ((ShaderIrOperGpr)op.OperandC).Index) - { - handleSrc = asg.Src; - - break; - } - } - } - - if (handleSrc != null && handleSrc is ShaderIrOperCbuf cbuf) - { - ShaderIrMetaTex meta = ((ShaderIrMetaTex)op.MetaData); - string name = _stagePrefix + TextureName + "_cb" + cbuf.Index + "_" + cbuf.Pos; - - m_CbTextures.Add(op, new ShaderDeclInfo(name, cbuf.Pos, true, cbuf.Index, 1, meta.TextureTarget, meta.TextureInstructionSuffix)); - } - else - { - throw new NotImplementedException("Shader TEX.B instruction is not fully supported!"); - } - } - break; - } - - case ShaderIrOperCbuf cbuf: - { - if (!m_Uniforms.ContainsKey(cbuf.Index)) - { - string name = _stagePrefix + UniformName + cbuf.Index; - - ShaderDeclInfo declInfo = new ShaderDeclInfo(name, cbuf.Pos, true, cbuf.Index); - - m_Uniforms.Add(cbuf.Index, declInfo); - } - break; - } - - case ShaderIrOperAbuf abuf: - { - //This is a built-in variable. - if (abuf.Offs == LayerAttr || - abuf.Offs == PointSizeAttr || - abuf.Offs == PointCoordAttrX || - abuf.Offs == PointCoordAttrY || - abuf.Offs == VertexIdAttr || - abuf.Offs == InstanceIdAttr || - abuf.Offs == FaceAttr) - { - break; - } - - int index = abuf.Offs >> 4; - int elem = (abuf.Offs >> 2) & 3; - - int glslIndex = index - AttrStartIndex; - - if (glslIndex < 0) - { - return; - } - - ShaderDeclInfo declInfo; - - if (parent is ShaderIrAsg asg && asg.Dst == node) - { - if (!m_OutAttributes.TryGetValue(index, out declInfo)) - { - declInfo = new ShaderDeclInfo(OutAttrName + glslIndex, glslIndex); - - m_OutAttributes.Add(index, declInfo); - } - } - else - { - if (!m_InAttributes.TryGetValue(index, out declInfo)) - { - declInfo = new ShaderDeclInfo(InAttrName + glslIndex, glslIndex); - - m_InAttributes.Add(index, declInfo); - } - } - - declInfo.Enlarge(elem + 1); - - if (!m_Attributes.ContainsKey(index)) - { - declInfo = new ShaderDeclInfo(AttrName + glslIndex, glslIndex, false, 0, 4); - - m_Attributes.Add(index, declInfo); - } - - Traverse(nodes, abuf, abuf.Vertex); - - break; - } - - case ShaderIrOperGpr gpr: - { - if (!gpr.IsConst) - { - string name = GetGprName(gpr.Index); - - if (gpr.RegisterSize == ShaderRegisterSize.Single) - { - m_Gprs.TryAdd(gpr.Index, new ShaderDeclInfo(name, gpr.Index)); - } - else if (gpr.RegisterSize == ShaderRegisterSize.Half) - { - name += "_h" + gpr.HalfPart; - - m_GprsHalf.TryAdd((gpr.Index << 1) | gpr.HalfPart, new ShaderDeclInfo(name, gpr.Index)); - } - else /* if (Gpr.RegisterSize == ShaderRegisterSize.Double) */ - { - throw new NotImplementedException("Double types are not supported."); - } - } - break; - } - - case ShaderIrOperPred pred: - { - if (!pred.IsConst && !HasName(m_Preds, pred.Index)) - { - string name = PredName + pred.Index; - - m_Preds.TryAdd(pred.Index, new ShaderDeclInfo(name, pred.Index)); - } - break; - } - } - } - - private bool HasName(Dictionary decls, int index) - { - //This is used to check if the dictionary already contains - //a entry for a vector at a given index position. - //Used to enable turning gprs into vectors. - int vecIndex = index & ~3; - - if (decls.TryGetValue(vecIndex, out ShaderDeclInfo declInfo)) - { - if (declInfo.Size > 1 && index < vecIndex + declInfo.Size) - { - return true; - } - } - - return decls.ContainsKey(index); - } - } -} diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs deleted file mode 100644 index d98363112c..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs +++ /dev/null @@ -1,1684 +0,0 @@ -using OpenTK.Graphics.OpenGL; -using Ryujinx.Graphics.Shader.Translation; -using Ryujinx.Graphics.Texture; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Linq; -using System.Text; - -namespace Ryujinx.Graphics.Gal.Shader -{ - public class GlslDecompiler - { - private delegate string GetInstExpr(ShaderIrOp op); - - private Dictionary _instsExpr; - - private enum OperType - { - Bool, - F32, - I32 - } - - private const string IdentationStr = " "; - - private const int MaxVertexInput = 3; - - private GlslDecl _decl; - - private ShaderHeader _header, _headerB; - - private ShaderIrBlock[] _blocks, _blocksB; - - private StringBuilder _sb; - - public int MaxUboSize { get; } - - private bool _isNvidiaDriver; - - public GlslDecompiler(int maxUboSize, bool isNvidiaDriver) - { - _instsExpr = new Dictionary() - { - { ShaderIrInst.Abs, GetAbsExpr }, - { ShaderIrInst.Add, GetAddExpr }, - { ShaderIrInst.And, GetAndExpr }, - { ShaderIrInst.Asr, GetAsrExpr }, - { ShaderIrInst.Band, GetBandExpr }, - { ShaderIrInst.Bnot, GetBnotExpr }, - { ShaderIrInst.Bor, GetBorExpr }, - { ShaderIrInst.Bxor, GetBxorExpr }, - { ShaderIrInst.Ceil, GetCeilExpr }, - { ShaderIrInst.Ceq, GetCeqExpr }, - { ShaderIrInst.Cge, GetCgeExpr }, - { ShaderIrInst.Cgt, GetCgtExpr }, - { ShaderIrInst.Clamps, GetClampsExpr }, - { ShaderIrInst.Clampu, GetClampuExpr }, - { ShaderIrInst.Cle, GetCleExpr }, - { ShaderIrInst.Clt, GetCltExpr }, - { ShaderIrInst.Cne, GetCneExpr }, - { ShaderIrInst.Cut, GetCutExpr }, - { ShaderIrInst.Exit, GetExitExpr }, - { ShaderIrInst.Fabs, GetAbsExpr }, - { ShaderIrInst.Fadd, GetAddExpr }, - { ShaderIrInst.Fceq, GetCeqExpr }, - { ShaderIrInst.Fcequ, GetCequExpr }, - { ShaderIrInst.Fcge, GetCgeExpr }, - { ShaderIrInst.Fcgeu, GetCgeuExpr }, - { ShaderIrInst.Fcgt, GetCgtExpr }, - { ShaderIrInst.Fcgtu, GetCgtuExpr }, - { ShaderIrInst.Fclamp, GetFclampExpr }, - { ShaderIrInst.Fcle, GetCleExpr }, - { ShaderIrInst.Fcleu, GetCleuExpr }, - { ShaderIrInst.Fclt, GetCltExpr }, - { ShaderIrInst.Fcltu, GetCltuExpr }, - { ShaderIrInst.Fcnan, GetCnanExpr }, - { ShaderIrInst.Fcne, GetCneExpr }, - { ShaderIrInst.Fcneu, GetCneuExpr }, - { ShaderIrInst.Fcnum, GetCnumExpr }, - { ShaderIrInst.Fcos, GetFcosExpr }, - { ShaderIrInst.Fex2, GetFex2Expr }, - { ShaderIrInst.Ffma, GetFfmaExpr }, - { ShaderIrInst.Flg2, GetFlg2Expr }, - { ShaderIrInst.Floor, GetFloorExpr }, - { ShaderIrInst.Fmax, GetMaxExpr }, - { ShaderIrInst.Fmin, GetMinExpr }, - { ShaderIrInst.Fmul, GetMulExpr }, - { ShaderIrInst.Fneg, GetNegExpr }, - { ShaderIrInst.Frcp, GetFrcpExpr }, - { ShaderIrInst.Frsq, GetFrsqExpr }, - { ShaderIrInst.Fsin, GetFsinExpr }, - { ShaderIrInst.Fsqrt, GetFsqrtExpr }, - { ShaderIrInst.Ftos, GetFtosExpr }, - { ShaderIrInst.Ftou, GetFtouExpr }, - { ShaderIrInst.Ipa, GetIpaExpr }, - { ShaderIrInst.Kil, GetKilExpr }, - { ShaderIrInst.Lsl, GetLslExpr }, - { ShaderIrInst.Lsr, GetLsrExpr }, - { ShaderIrInst.Max, GetMaxExpr }, - { ShaderIrInst.Min, GetMinExpr }, - { ShaderIrInst.Mul, GetMulExpr }, - { ShaderIrInst.Neg, GetNegExpr }, - { ShaderIrInst.Not, GetNotExpr }, - { ShaderIrInst.Or, GetOrExpr }, - { ShaderIrInst.Stof, GetStofExpr }, - { ShaderIrInst.Sub, GetSubExpr }, - { ShaderIrInst.Texb, GetTexbExpr }, - { ShaderIrInst.Texq, GetTexqExpr }, - { ShaderIrInst.Texs, GetTexsExpr }, - { ShaderIrInst.Tld4, GetTld4Expr }, - { ShaderIrInst.Trunc, GetTruncExpr }, - { ShaderIrInst.Txlf, GetTxlfExpr }, - { ShaderIrInst.Utof, GetUtofExpr }, - { ShaderIrInst.Xor, GetXorExpr } - }; - - MaxUboSize = maxUboSize / 16; - _isNvidiaDriver = isNvidiaDriver; - } - - public GlslProgram Decompile( - IGalMemory memory, - long vpAPosition, - long vpBPosition, - GalShaderType shaderType) - { - _header = new ShaderHeader(memory, vpAPosition); - _headerB = new ShaderHeader(memory, vpBPosition); - - _blocks = ShaderDecoder.Decode(memory, vpAPosition); - _blocksB = ShaderDecoder.Decode(memory, vpBPosition); - - GlslDecl declVpA = new GlslDecl(_blocks, shaderType, _header); - GlslDecl declVpB = new GlslDecl(_blocksB, shaderType, _headerB); - - _decl = GlslDecl.Merge(declVpA, declVpB); - - return Decompile(); - } - - private string _newCode; - - public GlslProgram Decompile(IGalMemory memory, long position, GalShaderType shaderType) - { - _header = new ShaderHeader(memory, position); - _headerB = null; - - _blocks = ShaderDecoder.Decode(memory, position); - _blocksB = null; - - _decl = new GlslDecl(_blocks, shaderType, _header); - - _newCode = Translator.Translate(memory, (ulong)position, shaderType); - - return Decompile(); - } - - private GlslProgram Decompile() - { - _sb = new StringBuilder(); - - _sb.AppendLine("#version 410 core"); - - PrintDeclHeader(); - PrintDeclTextures(); - PrintDeclUniforms(); - PrintDeclAttributes(); - PrintDeclInAttributes(); - PrintDeclOutAttributes(); - PrintDeclGprs(); - PrintDeclPreds(); - PrintDeclSsy(); - - if (_blocksB != null) - { - PrintBlockScope(_blocks, GlslDecl.BasicBlockAName); - - _sb.AppendLine(); - - PrintBlockScope(_blocksB, GlslDecl.BasicBlockBName); - } - else - { - PrintBlockScope(_blocks, GlslDecl.BasicBlockName); - } - - _sb.AppendLine(); - - PrintMain(); - - string glslCode = _newCode; //_sb.ToString(); - - List textureInfo = new List(); - - textureInfo.AddRange(_decl.Textures.Values); - textureInfo.AddRange(IterateCbTextures()); - - return new GlslProgram(glslCode, textureInfo, _decl.Uniforms.Values); - } - - private void PrintDeclHeader() - { - if (_decl.ShaderType == GalShaderType.Geometry) - { - int maxVertices = _header.MaxOutputVertexCount; - - string outputTopology; - - switch (_header.OutputTopology) - { - case ShaderHeader.PointList: outputTopology = "points"; break; - case ShaderHeader.LineStrip: outputTopology = "line_strip"; break; - case ShaderHeader.TriangleStrip: outputTopology = "triangle_strip"; break; - - default: throw new InvalidOperationException(); - } - - _sb.AppendLine("#extension GL_ARB_enhanced_layouts : require"); - - _sb.AppendLine(); - - _sb.AppendLine("// Stubbed. Maxwell geometry shaders don't inform input geometry type"); - - _sb.AppendLine("layout(triangles) in;" + Environment.NewLine); - - _sb.AppendLine($"layout({outputTopology}, max_vertices = {maxVertices}) out;"); - - _sb.AppendLine(); - } - } - - private string GetSamplerType(TextureTarget textureTarget, bool hasShadow) - { - string result; - - switch (textureTarget) - { - case TextureTarget.Texture1D: - result = "sampler1D"; - break; - case TextureTarget.Texture2D: - result = "sampler2D"; - break; - case TextureTarget.Texture3D: - result = "sampler3D"; - break; - case TextureTarget.TextureCubeMap: - result = "samplerCube"; - break; - case TextureTarget.TextureRectangle: - result = "sampler2DRect"; - break; - case TextureTarget.Texture1DArray: - result = "sampler1DArray"; - break; - case TextureTarget.Texture2DArray: - result = "sampler2DArray"; - break; - case TextureTarget.TextureCubeMapArray: - result = "samplerCubeArray"; - break; - case TextureTarget.TextureBuffer: - result = "samplerBuffer"; - break; - case TextureTarget.Texture2DMultisample: - result = "sampler2DMS"; - break; - case TextureTarget.Texture2DMultisampleArray: - result = "sampler2DMSArray"; - break; - default: - throw new NotSupportedException(); - } - - if (hasShadow) - result += "Shadow"; - - return result; - } - - private void PrintDeclTextures() - { - foreach (ShaderDeclInfo declInfo in IterateCbTextures()) - { - TextureTarget target = ImageUtils.GetTextureTarget(declInfo.TextureTarget); - _sb.AppendLine($"// {declInfo.TextureSuffix}"); - _sb.AppendLine("uniform " + GetSamplerType(target, (declInfo.TextureSuffix & TextureInstructionSuffix.Dc) != 0) + " " + declInfo.Name + ";"); - } - - foreach (ShaderDeclInfo declInfo in _decl.Textures.Values.OrderBy(DeclKeySelector)) - { - TextureTarget target = ImageUtils.GetTextureTarget(declInfo.TextureTarget); - _sb.AppendLine($"// {declInfo.TextureSuffix}"); - _sb.AppendLine("uniform " + GetSamplerType(target, (declInfo.TextureSuffix & TextureInstructionSuffix.Dc) != 0) + " " + declInfo.Name + ";"); - } - } - - private IEnumerable IterateCbTextures() - { - HashSet names = new HashSet(); - - foreach (ShaderDeclInfo declInfo in _decl.CbTextures.Values.OrderBy(DeclKeySelector)) - { - if (names.Add(declInfo.Name)) - { - yield return declInfo; - } - } - } - - private void PrintDeclUniforms() - { - if (_decl.ShaderType == GalShaderType.Vertex) - { - //Memory layout here is [flip_x, flip_y, instance, unused] - //It's using 4 bytes, not 8 - - _sb.AppendLine("layout (std140) uniform " + GlslDecl.ExtraUniformBlockName + " {"); - - _sb.AppendLine(IdentationStr + "vec2 " + GlslDecl.FlipUniformName + ";"); - - _sb.AppendLine(IdentationStr + "int " + GlslDecl.InstanceUniformName + ";"); - - _sb.AppendLine("};"); - _sb.AppendLine(); - } - - foreach (ShaderDeclInfo declInfo in _decl.Uniforms.Values.OrderBy(DeclKeySelector)) - { - _sb.AppendLine($"layout (std140) uniform {declInfo.Name} {{"); - - _sb.AppendLine($"{IdentationStr}vec4 {declInfo.Name}_data[{MaxUboSize}];"); - - _sb.AppendLine("};"); - } - - if (_decl.Uniforms.Count > 0) - { - _sb.AppendLine(); - } - } - - private void PrintDeclAttributes() - { - string geometryArray = (_decl.ShaderType == GalShaderType.Geometry) ? "[" + MaxVertexInput + "]" : ""; - - PrintDecls(_decl.Attributes, suffix: geometryArray); - } - - private void PrintDeclInAttributes() - { - if (_decl.ShaderType == GalShaderType.Fragment) - { - _sb.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") in vec4 " + GlslDecl.PositionOutAttrName + ";"); - } - - if (_decl.ShaderType == GalShaderType.Geometry) - { - if (_decl.InAttributes.Count > 0) - { - _sb.AppendLine("in Vertex {"); - - foreach (ShaderDeclInfo declInfo in _decl.InAttributes.Values.OrderBy(DeclKeySelector)) - { - if (declInfo.Index >= 0) - { - _sb.AppendLine(IdentationStr + "layout (location = " + declInfo.Index + ") vec4 " + declInfo.Name + "; "); - } - } - - _sb.AppendLine("} block_in[];" + Environment.NewLine); - } - } - else - { - PrintDeclAttributes(_decl.InAttributes.Values, "in"); - } - } - - private void PrintDeclOutAttributes() - { - if (_decl.ShaderType == GalShaderType.Fragment) - { - int count = 0; - - for (int attachment = 0; attachment < 8; attachment++) - { - if (_header.OmapTargets[attachment].Enabled) - { - _sb.AppendLine("layout (location = " + attachment + ") out vec4 " + GlslDecl.FragmentOutputName + attachment + ";"); - - count++; - } - } - - if (count > 0) - { - _sb.AppendLine(); - } - } - else - { - _sb.AppendLine("layout (location = " + GlslDecl.PositionOutAttrLocation + ") out vec4 " + GlslDecl.PositionOutAttrName + ";"); - _sb.AppendLine(); - } - - PrintDeclAttributes(_decl.OutAttributes.Values, "out"); - } - - private void PrintDeclAttributes(IEnumerable decls, string inOut) - { - int count = 0; - - foreach (ShaderDeclInfo declInfo in decls.OrderBy(DeclKeySelector)) - { - if (declInfo.Index >= 0) - { - _sb.AppendLine("layout (location = " + declInfo.Index + ") " + inOut + " vec4 " + declInfo.Name + ";"); - - count++; - } - } - - if (count > 0) - { - _sb.AppendLine(); - } - } - - private void PrintDeclGprs() - { - PrintDecls(_decl.Gprs); - PrintDecls(_decl.GprsHalf); - } - - private void PrintDeclPreds() - { - PrintDecls(_decl.Preds, "bool"); - } - - private void PrintDeclSsy() - { - _sb.AppendLine("uint " + GlslDecl.SsyCursorName + " = 0;"); - - _sb.AppendLine("uint " + GlslDecl.SsyStackName + "[" + GlslDecl.SsyStackSize + "];" + Environment.NewLine); - } - - private void PrintDecls(IReadOnlyDictionary dict, string customType = null, string suffix = "") - { - foreach (ShaderDeclInfo declInfo in dict.Values.OrderBy(DeclKeySelector)) - { - string name; - - if (customType != null) - { - name = customType + " " + declInfo.Name + suffix + ";"; - } - else if (declInfo.Name.Contains(GlslDecl.FragmentOutputName)) - { - name = "layout (location = " + declInfo.Index / 4 + ") out vec4 " + declInfo.Name + suffix + ";"; - } - else - { - name = GetDecl(declInfo) + suffix + ";"; - } - - _sb.AppendLine(name); - } - - if (dict.Count > 0) - { - _sb.AppendLine(); - } - } - - private int DeclKeySelector(ShaderDeclInfo declInfo) - { - return declInfo.Cbuf << 24 | declInfo.Index; - } - - private string GetDecl(ShaderDeclInfo declInfo) - { - if (declInfo.Size == 4) - { - return "vec4 " + declInfo.Name; - } - else - { - return "float " + declInfo.Name; - } - } - - private void PrintMain() - { - _sb.AppendLine("void main() {"); - - foreach (KeyValuePair kv in _decl.InAttributes) - { - if (!_decl.Attributes.TryGetValue(kv.Key, out ShaderDeclInfo attr)) - { - continue; - } - - ShaderDeclInfo declInfo = kv.Value; - - if (_decl.ShaderType == GalShaderType.Geometry) - { - for (int vertex = 0; vertex < MaxVertexInput; vertex++) - { - string dst = attr.Name + "[" + vertex + "]"; - - string src = "block_in[" + vertex + "]." + declInfo.Name; - - _sb.AppendLine(IdentationStr + dst + " = " + src + ";"); - } - } - else - { - _sb.AppendLine(IdentationStr + attr.Name + " = " + declInfo.Name + ";"); - } - } - - _sb.AppendLine(IdentationStr + "uint pc;"); - - if (_blocksB != null) - { - PrintProgram(_blocks, GlslDecl.BasicBlockAName); - PrintProgram(_blocksB, GlslDecl.BasicBlockBName); - } - else - { - PrintProgram(_blocks, GlslDecl.BasicBlockName); - } - - if (_decl.ShaderType != GalShaderType.Geometry) - { - PrintAttrToOutput(); - } - - if (_decl.ShaderType == GalShaderType.Fragment) - { - if (_header.OmapDepth) - { - _sb.AppendLine(IdentationStr + "gl_FragDepth = " + GlslDecl.GetGprName(_header.DepthRegister) + ";"); - } - - int gprIndex = 0; - - for (int attachment = 0; attachment < 8; attachment++) - { - string output = GlslDecl.FragmentOutputName + attachment; - - OmapTarget target = _header.OmapTargets[attachment]; - - for (int component = 0; component < 4; component++) - { - if (target.ComponentEnabled(component)) - { - _sb.AppendLine(IdentationStr + output + "[" + component + "] = " + GlslDecl.GetGprName(gprIndex) + ";"); - - gprIndex++; - } - } - } - } - - _sb.AppendLine("}"); - } - - private void PrintProgram(ShaderIrBlock[] blocks, string name) - { - const string ident1 = IdentationStr; - const string ident2 = ident1 + IdentationStr; - const string ident3 = ident2 + IdentationStr; - const string ident4 = ident3 + IdentationStr; - - _sb.AppendLine(ident1 + "pc = " + GetBlockPosition(blocks[0]) + ";"); - _sb.AppendLine(ident1 + "do {"); - _sb.AppendLine(ident2 + "switch (pc) {"); - - foreach (ShaderIrBlock block in blocks) - { - string functionName = block.Position.ToString("x8"); - - _sb.AppendLine(ident3 + "case 0x" + functionName + ": pc = " + name + "_" + functionName + "(); break;"); - } - - _sb.AppendLine(ident3 + "default:"); - _sb.AppendLine(ident4 + "pc = 0;"); - _sb.AppendLine(ident4 + "break;"); - - _sb.AppendLine(ident2 + "}"); - _sb.AppendLine(ident1 + "} while (pc != 0);"); - } - - private void PrintAttrToOutput(string identation = IdentationStr) - { - foreach (KeyValuePair kv in _decl.OutAttributes) - { - if (!_decl.Attributes.TryGetValue(kv.Key, out ShaderDeclInfo attr)) - { - continue; - } - - ShaderDeclInfo declInfo = kv.Value; - - string name = attr.Name; - - if (_decl.ShaderType == GalShaderType.Geometry) - { - name += "[0]"; - } - - _sb.AppendLine(identation + declInfo.Name + " = " + name + ";"); - } - - if (_decl.ShaderType == GalShaderType.Vertex) - { - _sb.AppendLine(identation + "gl_Position.xy *= " + GlslDecl.FlipUniformName + ";"); - } - - if (_decl.ShaderType != GalShaderType.Fragment) - { - _sb.AppendLine(identation + GlslDecl.PositionOutAttrName + " = gl_Position;"); - _sb.AppendLine(identation + GlslDecl.PositionOutAttrName + ".w = 1;"); - } - } - - private void PrintBlockScope(ShaderIrBlock[] blocks, string name) - { - foreach (ShaderIrBlock block in blocks) - { - _sb.AppendLine("uint " + name + "_" + block.Position.ToString("x8") + "() {"); - - PrintNodes(block, block.GetNodes()); - - _sb.AppendLine("}" + Environment.NewLine); - } - } - - private void PrintNodes(ShaderIrBlock block, ShaderIrNode[] nodes) - { - foreach (ShaderIrNode node in nodes) - { - PrintNode(block, node, IdentationStr); - } - - if (nodes.Length == 0) - { - _sb.AppendLine(IdentationStr + "return 0u;"); - - return; - } - - ShaderIrNode last = nodes[nodes.Length - 1]; - - bool unconditionalFlowChange = false; - - if (last is ShaderIrOp op) - { - switch (op.Inst) - { - case ShaderIrInst.Bra: - case ShaderIrInst.Exit: - case ShaderIrInst.Sync: - unconditionalFlowChange = true; - break; - } - } - - if (!unconditionalFlowChange) - { - if (block.Next != null) - { - _sb.AppendLine(IdentationStr + "return " + GetBlockPosition(block.Next) + ";"); - } - else - { - _sb.AppendLine(IdentationStr + "return 0u;"); - } - } - } - - private void PrintNode(ShaderIrBlock block, ShaderIrNode node, string identation) - { - if (node is ShaderIrCond cond) - { - string ifExpr = GetSrcExpr(cond.Pred, true); - - if (cond.Not) - { - ifExpr = "!(" + ifExpr + ")"; - } - - _sb.AppendLine(identation + "if (" + ifExpr + ") {"); - - PrintNode(block, cond.Child, identation + IdentationStr); - - _sb.AppendLine(identation + "}"); - } - else if (node is ShaderIrAsg asg) - { - if (IsValidOutOper(asg.Dst)) - { - string expr = GetSrcExpr(asg.Src, true); - - expr = GetExprWithCast(asg.Dst, asg.Src, expr); - - _sb.AppendLine(identation + GetDstOperName(asg.Dst) + " = " + expr + ";"); - } - } - else if (node is ShaderIrOp op) - { - switch (op.Inst) - { - case ShaderIrInst.Bra: - { - _sb.AppendLine(identation + "return " + GetBlockPosition(block.Branch) + ";"); - - break; - } - - case ShaderIrInst.Emit: - { - PrintAttrToOutput(identation); - - _sb.AppendLine(identation + "EmitVertex();"); - - break; - } - - case ShaderIrInst.Ssy: - { - string stackIndex = GlslDecl.SsyStackName + "[" + GlslDecl.SsyCursorName + "]"; - - int targetPosition = (op.OperandA as ShaderIrOperImm).Value; - - string target = "0x" + targetPosition.ToString("x8") + "u"; - - _sb.AppendLine(identation + stackIndex + " = " + target + ";"); - - _sb.AppendLine(identation + GlslDecl.SsyCursorName + "++;"); - - break; - } - - case ShaderIrInst.Sync: - { - _sb.AppendLine(identation + GlslDecl.SsyCursorName + "--;"); - - string target = GlslDecl.SsyStackName + "[" + GlslDecl.SsyCursorName + "]"; - - _sb.AppendLine(identation + "return " + target + ";"); - - break; - } - - default: - _sb.AppendLine(identation + GetSrcExpr(op, true) + ";"); - - break; - } - } - else if (node is ShaderIrCmnt cmnt) - { - _sb.AppendLine(identation + "// " + cmnt.Comment); - } - else - { - throw new InvalidOperationException(); - } - } - - private bool IsValidOutOper(ShaderIrNode node) - { - if (node is ShaderIrOperGpr gpr && gpr.IsConst) - { - return false; - } - else if (node is ShaderIrOperPred pred && pred.IsConst) - { - return false; - } - - return true; - } - - private string GetDstOperName(ShaderIrNode node) - { - if (node is ShaderIrOperAbuf abuf) - { - return GetOutAbufName(abuf); - } - else if (node is ShaderIrOperGpr gpr) - { - return GetName(gpr); - } - else if (node is ShaderIrOperPred pred) - { - return GetName(pred); - } - - throw new ArgumentException(nameof(node)); - } - - private string GetSrcExpr(ShaderIrNode node, bool entry = false) - { - switch (node) - { - case ShaderIrOperAbuf abuf: return GetName (abuf); - case ShaderIrOperCbuf cbuf: return GetName (cbuf); - case ShaderIrOperGpr gpr: return GetName (gpr); - case ShaderIrOperImm imm: return GetValue(imm); - case ShaderIrOperImmf immf: return GetValue(immf); - case ShaderIrOperPred pred: return GetName (pred); - - case ShaderIrOp op: - string expr; - - if (_instsExpr.TryGetValue(op.Inst, out GetInstExpr getExpr)) - { - expr = getExpr(op); - } - else - { - throw new NotImplementedException(op.Inst.ToString()); - } - - if (!entry && NeedsParentheses(op)) - { - expr = "(" + expr + ")"; - } - - return expr; - - default: throw new ArgumentException(nameof(node)); - } - } - - private static bool NeedsParentheses(ShaderIrOp op) - { - switch (op.Inst) - { - case ShaderIrInst.Ipa: - case ShaderIrInst.Texq: - case ShaderIrInst.Texs: - case ShaderIrInst.Tld4: - case ShaderIrInst.Txlf: - return false; - } - - return true; - } - - private string GetName(ShaderIrOperCbuf cbuf) - { - if (!_decl.Uniforms.TryGetValue(cbuf.Index, out ShaderDeclInfo declInfo)) - { - throw new InvalidOperationException(); - } - - if (cbuf.Offs != null) - { - string offset = "floatBitsToInt(" + GetSrcExpr(cbuf.Offs) + ")"; - - string index = "(" + cbuf.Pos * 4 + " + " + offset + ")"; - - return $"{declInfo.Name}_data[{index} / 16][({index} / 4) % 4]"; - } - else - { - return $"{declInfo.Name}_data[{cbuf.Pos / 4}][{cbuf.Pos % 4}]"; - } - } - - private string GetOutAbufName(ShaderIrOperAbuf abuf) - { - if (_decl.ShaderType == GalShaderType.Geometry) - { - switch (abuf.Offs) - { - case GlslDecl.LayerAttr: return "gl_Layer"; - } - } - - return GetAttrTempName(abuf); - } - - private string GetName(ShaderIrOperAbuf abuf) - { - //Handle special scalar read-only attributes here. - if (_decl.ShaderType == GalShaderType.Vertex) - { - switch (abuf.Offs) - { - case GlslDecl.VertexIdAttr: return "gl_VertexID"; - case GlslDecl.InstanceIdAttr: return GlslDecl.InstanceUniformName; - } - } - else if (_decl.ShaderType == GalShaderType.TessEvaluation) - { - switch (abuf.Offs) - { - case GlslDecl.TessCoordAttrX: return "gl_TessCoord.x"; - case GlslDecl.TessCoordAttrY: return "gl_TessCoord.y"; - case GlslDecl.TessCoordAttrZ: return "gl_TessCoord.z"; - } - } - else if (_decl.ShaderType == GalShaderType.Fragment) - { - switch (abuf.Offs) - { - case GlslDecl.PointCoordAttrX: return "gl_PointCoord.x"; - case GlslDecl.PointCoordAttrY: return "gl_PointCoord.y"; - case GlslDecl.FaceAttr: return "(gl_FrontFacing ? -1 : 0)"; - } - } - - return GetAttrTempName(abuf); - } - - private string GetAttrTempName(ShaderIrOperAbuf abuf) - { - int index = abuf.Offs >> 4; - int elem = (abuf.Offs >> 2) & 3; - - string swizzle = "." + GetAttrSwizzle(elem); - - if (!_decl.Attributes.TryGetValue(index, out ShaderDeclInfo declInfo)) - { - //Handle special vec4 attributes here - //(for example, index 7 is always gl_Position). - if (index == GlslDecl.GlPositionVec4Index) - { - string name = - _decl.ShaderType != GalShaderType.Vertex && - _decl.ShaderType != GalShaderType.Geometry ? GlslDecl.PositionOutAttrName : "gl_Position"; - - return name + swizzle; - } - else if (abuf.Offs == GlslDecl.PointSizeAttr) - { - return "gl_PointSize"; - } - } - - if (declInfo.Index >= 32) - { - throw new InvalidOperationException($"Shader attribute offset {abuf.Offs} is invalid."); - } - - if (_decl.ShaderType == GalShaderType.Geometry) - { - string vertex = "floatBitsToInt(" + GetSrcExpr(abuf.Vertex) + ")"; - - return declInfo.Name + "[" + vertex + "]" + swizzle; - } - else - { - return declInfo.Name + swizzle; - } - } - - private string GetName(ShaderIrOperGpr gpr) - { - if (gpr.IsConst) - { - return "0"; - } - - if (gpr.RegisterSize == ShaderRegisterSize.Single) - { - return GetNameWithSwizzle(_decl.Gprs, gpr.Index); - } - else if (gpr.RegisterSize == ShaderRegisterSize.Half) - { - return GetNameWithSwizzle(_decl.GprsHalf, (gpr.Index << 1) | gpr.HalfPart); - } - else /* if (Gpr.RegisterSize == ShaderRegisterSize.Double) */ - { - throw new NotImplementedException("Double types are not supported."); - } - } - - private string GetValue(ShaderIrOperImm imm) - { - //Only use hex is the value is too big and would likely be hard to read as int. - if (imm.Value > 0xfff || - imm.Value < -0xfff) - { - return "0x" + imm.Value.ToString("x8", CultureInfo.InvariantCulture); - } - else - { - return GetIntConst(imm.Value); - } - } - - private string GetValue(ShaderIrOperImmf immf) - { - return GetFloatConst(immf.Value); - } - - private string GetName(ShaderIrOperPred pred) - { - return pred.IsConst ? "true" : GetNameWithSwizzle(_decl.Preds, pred.Index); - } - - private string GetNameWithSwizzle(IReadOnlyDictionary dict, int index) - { - int vecIndex = index & ~3; - - if (dict.TryGetValue(vecIndex, out ShaderDeclInfo declInfo)) - { - if (declInfo.Size > 1 && index < vecIndex + declInfo.Size) - { - return declInfo.Name + "." + GetAttrSwizzle(index & 3); - } - } - - if (!dict.TryGetValue(index, out declInfo)) - { - throw new InvalidOperationException(); - } - - return declInfo.Name; - } - - private string GetAttrSwizzle(int elem) - { - return "xyzw".Substring(elem, 1); - } - - private string GetAbsExpr(ShaderIrOp op) => GetUnaryCall(op, "abs"); - - private string GetAddExpr(ShaderIrOp op) => GetBinaryExpr(op, "+"); - - private string GetAndExpr(ShaderIrOp op) => GetBinaryExpr(op, "&"); - - private string GetAsrExpr(ShaderIrOp op) => GetBinaryExpr(op, ">>"); - - private string GetBandExpr(ShaderIrOp op) => GetBinaryExpr(op, "&&"); - - private string GetBnotExpr(ShaderIrOp op) => GetUnaryExpr(op, "!"); - - private string GetBorExpr(ShaderIrOp op) => GetBinaryExpr(op, "||"); - - private string GetBxorExpr(ShaderIrOp op) => GetBinaryExpr(op, "^^"); - - private string GetCeilExpr(ShaderIrOp op) => GetUnaryCall(op, "ceil"); - - private string GetClampsExpr(ShaderIrOp op) - { - return "clamp(" + GetOperExpr(op, op.OperandA) + ", " + - GetOperExpr(op, op.OperandB) + ", " + - GetOperExpr(op, op.OperandC) + ")"; - } - - private string GetClampuExpr(ShaderIrOp op) - { - return "int(clamp(uint(" + GetOperExpr(op, op.OperandA) + "), " + - "uint(" + GetOperExpr(op, op.OperandB) + "), " + - "uint(" + GetOperExpr(op, op.OperandC) + ")))"; - } - - private string GetCeqExpr(ShaderIrOp op) => GetBinaryExpr(op, "=="); - - private string GetCequExpr(ShaderIrOp op) => GetBinaryExprWithNaN(op, "=="); - - private string GetCgeExpr(ShaderIrOp op) => GetBinaryExpr(op, ">="); - - private string GetCgeuExpr(ShaderIrOp op) => GetBinaryExprWithNaN(op, ">="); - - private string GetCgtExpr(ShaderIrOp op) => GetBinaryExpr(op, ">"); - - private string GetCgtuExpr(ShaderIrOp op) => GetBinaryExprWithNaN(op, ">"); - - private string GetCleExpr(ShaderIrOp op) => GetBinaryExpr(op, "<="); - - private string GetCleuExpr(ShaderIrOp op) => GetBinaryExprWithNaN(op, "<="); - - private string GetCltExpr(ShaderIrOp op) => GetBinaryExpr(op, "<"); - - private string GetCltuExpr(ShaderIrOp op) => GetBinaryExprWithNaN(op, "<"); - - private string GetCnanExpr(ShaderIrOp op) => GetUnaryCall(op, "isnan"); - - private string GetCneExpr(ShaderIrOp op) => GetBinaryExpr(op, "!="); - - private string GetCutExpr(ShaderIrOp op) => "EndPrimitive()"; - - private string GetCneuExpr(ShaderIrOp op) => GetBinaryExprWithNaN(op, "!="); - - private string GetCnumExpr(ShaderIrOp op) => GetUnaryCall(op, "!isnan"); - - private string GetExitExpr(ShaderIrOp op) => "return 0u"; - - private string GetFcosExpr(ShaderIrOp op) => GetUnaryCall(op, "cos"); - - private string GetFex2Expr(ShaderIrOp op) => GetUnaryCall(op, "exp2"); - - private string GetFfmaExpr(ShaderIrOp op) => GetTernaryExpr(op, "*", "+"); - - private string GetFclampExpr(ShaderIrOp op) => GetTernaryCall(op, "clamp"); - - private string GetFlg2Expr(ShaderIrOp op) => GetUnaryCall(op, "log2"); - - private string GetFloorExpr(ShaderIrOp op) => GetUnaryCall(op, "floor"); - - private string GetFrcpExpr(ShaderIrOp op) => GetUnaryExpr(op, "1 / "); - - private string GetFrsqExpr(ShaderIrOp op) => GetUnaryCall(op, "inversesqrt"); - - private string GetFsinExpr(ShaderIrOp op) => GetUnaryCall(op, "sin"); - - private string GetFsqrtExpr(ShaderIrOp op) => GetUnaryCall(op, "sqrt"); - - private string GetFtosExpr(ShaderIrOp op) - { - return "int(" + GetOperExpr(op, op.OperandA) + ")"; - } - - private string GetFtouExpr(ShaderIrOp op) - { - return "int(uint(" + GetOperExpr(op, op.OperandA) + "))"; - } - - private string GetIpaExpr(ShaderIrOp op) - { - ShaderIrMetaIpa meta = (ShaderIrMetaIpa)op.MetaData; - - ShaderIrOperAbuf abuf = (ShaderIrOperAbuf)op.OperandA; - - if (meta.Mode == ShaderIpaMode.Pass) - { - int index = abuf.Offs >> 4; - int elem = (abuf.Offs >> 2) & 3; - - if (_decl.ShaderType == GalShaderType.Fragment && index == GlslDecl.GlPositionVec4Index) - { - switch (elem) - { - case 0: return "gl_FragCoord.x"; - case 1: return "gl_FragCoord.y"; - case 2: return "gl_FragCoord.z"; - case 3: return "1"; - } - } - } - - return GetSrcExpr(op.OperandA); - } - - private string GetKilExpr(ShaderIrOp op) => "discard"; - - private string GetLslExpr(ShaderIrOp op) => GetBinaryExpr(op, "<<"); - private string GetLsrExpr(ShaderIrOp op) - { - return "int(uint(" + GetOperExpr(op, op.OperandA) + ") >> " + - GetOperExpr(op, op.OperandB) + ")"; - } - - private string GetMaxExpr(ShaderIrOp op) => GetBinaryCall(op, "max"); - private string GetMinExpr(ShaderIrOp op) => GetBinaryCall(op, "min"); - - private string GetMulExpr(ShaderIrOp op) => GetBinaryExpr(op, "*"); - - private string GetNegExpr(ShaderIrOp op) => GetUnaryExpr(op, "-"); - - private string GetNotExpr(ShaderIrOp op) => GetUnaryExpr(op, "~"); - - private string GetOrExpr(ShaderIrOp op) => GetBinaryExpr(op, "|"); - - private string GetStofExpr(ShaderIrOp op) - { - return "float(" + GetOperExpr(op, op.OperandA) + ")"; - } - - private string GetSubExpr(ShaderIrOp op) => GetBinaryExpr(op, "-"); - - private string GetTexbExpr(ShaderIrOp op) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - if (!_decl.CbTextures.TryGetValue(op, out ShaderDeclInfo declInfo)) - { - throw new InvalidOperationException(); - } - - string coords = GetTexSamplerCoords(op); - - string ch = "rgba".Substring(meta.Elem, 1); - - return GetTextureOperation(op, declInfo.Name, coords, ch); - } - - private string GetTexqExpr(ShaderIrOp op) - { - ShaderIrMetaTexq meta = (ShaderIrMetaTexq)op.MetaData; - - string ch = "xyzw".Substring(meta.Elem, 1); - - if (meta.Info == ShaderTexqInfo.Dimension) - { - string sampler = GetTexSamplerName(op); - - string lod = GetOperExpr(op, op.OperandA); //??? - - return "textureSize(" + sampler + ", " + lod + ")." + ch; - } - else - { - throw new NotImplementedException(meta.Info.ToString()); - } - } - - private string GetTexsExpr(ShaderIrOp op) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - string sampler = GetTexSamplerName(op); - - string coords = GetTexSamplerCoords(op); - - string ch = "rgba".Substring(meta.Elem, 1); - - return GetTextureOperation(op, sampler, coords, ch); - } - - private string GetTld4Expr(ShaderIrOp op) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - string sampler = GetTexSamplerName(op); - - string coords = GetTexSamplerCoords(op); - - string ch = "rgba".Substring(meta.Elem, 1); - - return GetTextureGatherOperation(op, sampler, coords, ch); - } - - // TODO: support AOFFI on non nvidia drivers - private string GetTxlfExpr(ShaderIrOp op) - { - // TODO: Support all suffixes - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - TextureInstructionSuffix suffix = meta.TextureInstructionSuffix; - - string sampler = GetTexSamplerName(op); - - string coords = GetITexSamplerCoords(op); - - string ch = "rgba".Substring(meta.Elem, 1); - - string lod = "0"; - - if (meta.LevelOfDetail != null) - { - lod = GetOperExpr(op, meta.LevelOfDetail); - } - - if ((suffix & TextureInstructionSuffix.AOffI) != 0 && _isNvidiaDriver) - { - string offset = GetTextureOffset(meta, GetOperExpr(op, meta.Offset)); - return "texelFetchOffset(" + sampler + ", " + coords + ", " + lod + ", " + offset + ")." + ch; - } - - return "texelFetch(" + sampler + ", " + coords + ", " + lod + ")." + ch; - } - - private string GetTruncExpr(ShaderIrOp op) => GetUnaryCall(op, "trunc"); - - private string GetUtofExpr(ShaderIrOp op) - { - return "float(uint(" + GetOperExpr(op, op.OperandA) + "))"; - } - - private string GetXorExpr(ShaderIrOp op) => GetBinaryExpr(op, "^"); - - private string GetUnaryCall(ShaderIrOp op, string funcName) - { - return funcName + "(" + GetOperExpr(op, op.OperandA) + ")"; - } - - private string GetBinaryCall(ShaderIrOp op, string funcName) - { - return funcName + "(" + GetOperExpr(op, op.OperandA) + ", " + - GetOperExpr(op, op.OperandB) + ")"; - } - - private string GetTernaryCall(ShaderIrOp op, string funcName) - { - return funcName + "(" + GetOperExpr(op, op.OperandA) + ", " + - GetOperExpr(op, op.OperandB) + ", " + - GetOperExpr(op, op.OperandC) + ")"; - } - - private string GetUnaryExpr(ShaderIrOp op, string opr) - { - return opr + GetOperExpr(op, op.OperandA); - } - - private string GetBinaryExpr(ShaderIrOp op, string opr) - { - return GetOperExpr(op, op.OperandA) + " " + opr + " " + - GetOperExpr(op, op.OperandB); - } - - private string GetBinaryExprWithNaN(ShaderIrOp op, string opr) - { - string a = GetOperExpr(op, op.OperandA); - string b = GetOperExpr(op, op.OperandB); - - string nanCheck = - " || isnan(" + a + ")" + - " || isnan(" + b + ")"; - - return a + " " + opr + " " + b + nanCheck; - } - - private string GetTernaryExpr(ShaderIrOp op, string opr1, string opr2) - { - return GetOperExpr(op, op.OperandA) + " " + opr1 + " " + - GetOperExpr(op, op.OperandB) + " " + opr2 + " " + - GetOperExpr(op, op.OperandC); - } - - private string GetTexSamplerName(ShaderIrOp op) - { - ShaderIrOperImm node = (ShaderIrOperImm)op.OperandC; - - int handle = ((ShaderIrOperImm)op.OperandC).Value; - - if (!_decl.Textures.TryGetValue(handle, out ShaderDeclInfo declInfo)) - { - throw new InvalidOperationException(); - } - - return declInfo.Name; - } - - private string GetTexSamplerCoords(ShaderIrOp op) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - bool hasDepth = (meta.TextureInstructionSuffix & TextureInstructionSuffix.Dc) != 0; - - int coords = ImageUtils.GetCoordsCountTextureTarget(meta.TextureTarget); - - bool isArray = ImageUtils.IsArray(meta.TextureTarget); - - - string GetLastArgument(ShaderIrNode node) - { - string result = GetOperExpr(op, node); - - // array index is actually an integer so we need to pass it correctly - if (isArray) - { - result = "float(floatBitsToInt(" + result + "))"; - } - - return result; - } - - string lastArgument; - string depthArgument = ""; - - int vecSize = coords; - if (hasDepth && op.Inst != ShaderIrInst.Tld4) - { - vecSize++; - depthArgument = $", {GetOperExpr(op, meta.DepthCompare)}"; - } - - switch (coords) - { - case 1: - if (hasDepth) - { - return $"vec3({GetOperExpr(op, meta.Coordinates[0])}, 0.0{depthArgument})"; - } - - return GetOperExpr(op, meta.Coordinates[0]); - case 2: - lastArgument = GetLastArgument(meta.Coordinates[1]); - - return $"vec{vecSize}({GetOperExpr(op, meta.Coordinates[0])}, {lastArgument}{depthArgument})"; - case 3: - lastArgument = GetLastArgument(meta.Coordinates[2]); - - return $"vec{vecSize}({GetOperExpr(op, meta.Coordinates[0])}, {GetOperExpr(op, meta.Coordinates[1])}, {lastArgument}{depthArgument})"; - case 4: - lastArgument = GetLastArgument(meta.Coordinates[3]); - - return $"vec4({GetOperExpr(op, meta.Coordinates[0])}, {GetOperExpr(op, meta.Coordinates[1])}, {GetOperExpr(op, meta.Coordinates[2])}, {lastArgument}){depthArgument}"; - default: - throw new InvalidOperationException(); - } - - } - - private string GetTextureOffset(ShaderIrMetaTex meta, string oper, int shift = 4, int mask = 0xF) - { - string GetOffset(string operation, int index) - { - return $"({operation} >> {index * shift}) & 0x{mask:x}"; - } - - int coords = ImageUtils.GetCoordsCountTextureTarget(meta.TextureTarget); - - if (ImageUtils.IsArray(meta.TextureTarget)) - coords -= 1; - - switch (coords) - { - case 1: - return GetOffset(oper, 0); - case 2: - return "ivec2(" + GetOffset(oper, 0) + ", " + GetOffset(oper, 1) + ")"; - case 3: - return "ivec3(" + GetOffset(oper, 0) + ", " + GetOffset(oper, 1) + ", " + GetOffset(oper, 2) + ")"; - case 4: - return "ivec4(" + GetOffset(oper, 0) + ", " + GetOffset(oper, 1) + ", " + GetOffset(oper, 2) + ", " + GetOffset(oper, 3) + ")"; - default: - throw new InvalidOperationException(); - } - } - - // TODO: support AOFFI on non nvidia drivers - private string GetTextureGatherOperation(ShaderIrOp op, string sampler, string coords, string ch) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - TextureInstructionSuffix suffix = meta.TextureInstructionSuffix; - - string chString = "." + ch; - - string comp = meta.Component.ToString(); - - if ((suffix & TextureInstructionSuffix.Dc) != 0) - { - comp = GetOperExpr(op, meta.DepthCompare); - } - - if ((suffix & TextureInstructionSuffix.AOffI) != 0 && _isNvidiaDriver) - { - string offset = GetTextureOffset(meta, "floatBitsToInt((" + GetOperExpr(op, meta.Offset) + "))", 8, 0x3F); - - if ((suffix & TextureInstructionSuffix.Dc) != 0) - { - return "textureGatherOffset(" + sampler + ", " + coords + ", " + comp + ", " + offset + ")" + chString; - } - - return "textureGatherOffset(" + sampler + ", " + coords + ", " + offset + ", " + comp + ")" + chString; - } - // TODO: Support PTP - else if ((suffix & TextureInstructionSuffix.Ptp) != 0) - { - //throw new NotImplementedException(); - } - - return "textureGather(" + sampler + ", " + coords + ", " + comp + ")" + chString; - } - - // TODO: support AOFFI on non nvidia drivers - private string GetTextureOperation(ShaderIrOp op, string sampler, string coords, string ch) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - TextureInstructionSuffix suffix = meta.TextureInstructionSuffix; - - string chString = "." + ch; - - if ((suffix & TextureInstructionSuffix.Dc) != 0) - { - chString = ""; - } - - // TODO: Support LBA and LLA - if ((suffix & TextureInstructionSuffix.Lz) != 0) - { - if ((suffix & TextureInstructionSuffix.AOffI) != 0 && _isNvidiaDriver) - { - string offset = GetTextureOffset(meta, "floatBitsToInt((" + GetOperExpr(op, meta.Offset) + "))"); - - return "textureLodOffset(" + sampler + ", " + coords + ", 0.0, " + offset + ")" + chString; - } - - return "textureLod(" + sampler + ", " + coords + ", 0.0)" + chString; - } - else if ((suffix & TextureInstructionSuffix.Lb) != 0) - { - if ((suffix & TextureInstructionSuffix.AOffI) != 0 && _isNvidiaDriver) - { - string offset = GetTextureOffset(meta, "floatBitsToInt((" + GetOperExpr(op, meta.Offset) + "))"); - - return "textureOffset(" + sampler + ", " + coords + ", " + offset + ", " + GetOperExpr(op, meta.LevelOfDetail) + ")" + chString; - } - - return "texture(" + sampler + ", " + coords + ", " + GetOperExpr(op, meta.LevelOfDetail) + ")" + chString; - } - else if ((suffix & TextureInstructionSuffix.Ll) != 0) - { - if ((suffix & TextureInstructionSuffix.AOffI) != 0 && _isNvidiaDriver) - { - string offset = GetTextureOffset(meta, "floatBitsToInt((" + GetOperExpr(op, meta.Offset) + "))"); - - return "textureLodOffset(" + sampler + ", " + coords + ", " + GetOperExpr(op, meta.LevelOfDetail) + ", " + offset + ")" + chString; - } - - return "textureLod(" + sampler + ", " + coords + ", " + GetOperExpr(op, meta.LevelOfDetail) + ")" + chString; - } - else if ((suffix & TextureInstructionSuffix.AOffI) != 0 && _isNvidiaDriver) - { - string offset = GetTextureOffset(meta, "floatBitsToInt((" + GetOperExpr(op, meta.Offset) + "))"); - - return "textureOffset(" + sampler + ", " + coords + ", " + offset + ")" + chString; - } - else - { - return "texture(" + sampler + ", " + coords + ")" + chString; - } - throw new NotImplementedException($"Texture Suffix {meta.TextureInstructionSuffix} is not implemented"); - - } - - private string GetITexSamplerCoords(ShaderIrOp op) - { - ShaderIrMetaTex meta = (ShaderIrMetaTex)op.MetaData; - - switch (ImageUtils.GetCoordsCountTextureTarget(meta.TextureTarget)) - { - case 1: - return GetOperExpr(op, meta.Coordinates[0]); - case 2: - return "ivec2(" + GetOperExpr(op, meta.Coordinates[0]) + ", " + GetOperExpr(op, meta.Coordinates[1]) + ")"; - case 3: - return "ivec3(" + GetOperExpr(op, meta.Coordinates[0]) + ", " + GetOperExpr(op, meta.Coordinates[1]) + ", " + GetOperExpr(op, meta.Coordinates[2]) + ")"; - default: - throw new InvalidOperationException(); - } - } - - private string GetOperExpr(ShaderIrOp op, ShaderIrNode oper) - { - return GetExprWithCast(op, oper, GetSrcExpr(oper)); - } - - private static string GetExprWithCast(ShaderIrNode dst, ShaderIrNode src, string expr) - { - //Note: The "DstType" (of the cast) is the type that the operation - //uses on the source operands, while the "SrcType" is the destination - //type of the operand result (if it is a operation) or just the type - //of the variable for registers/uniforms/attributes. - OperType dstType = GetSrcNodeType(dst); - OperType srcType = GetDstNodeType(src); - - if (dstType != srcType) - { - //Check for invalid casts - //(like bool to int/float and others). - if (srcType != OperType.F32 && - srcType != OperType.I32) - { - throw new InvalidOperationException(); - } - - switch (src) - { - case ShaderIrOperGpr gpr: - { - //When the Gpr is ZR, just return the 0 value directly, - //since the float encoding for 0 is 0. - if (gpr.IsConst) - { - return "0"; - } - break; - } - } - - switch (dstType) - { - case OperType.F32: expr = "intBitsToFloat(" + expr + ")"; break; - case OperType.I32: expr = "floatBitsToInt(" + expr + ")"; break; - } - } - - return expr; - } - - private static string GetIntConst(int value) - { - string expr = value.ToString(CultureInfo.InvariantCulture); - - return value < 0 ? "(" + expr + ")" : expr; - } - - private static string GetFloatConst(float value) - { - string expr = value.ToString(CultureInfo.InvariantCulture); - - return value < 0 ? "(" + expr + ")" : expr; - } - - private static OperType GetDstNodeType(ShaderIrNode node) - { - //Special case instructions with the result type different - //from the input types (like integer <-> float conversion) here. - if (node is ShaderIrOp op) - { - switch (op.Inst) - { - case ShaderIrInst.Stof: - case ShaderIrInst.Txlf: - case ShaderIrInst.Utof: - return OperType.F32; - - case ShaderIrInst.Ftos: - case ShaderIrInst.Ftou: - return OperType.I32; - } - } - - return GetSrcNodeType(node); - } - - private static OperType GetSrcNodeType(ShaderIrNode node) - { - switch (node) - { - case ShaderIrOperAbuf abuf: - return abuf.Offs == GlslDecl.LayerAttr || - abuf.Offs == GlslDecl.InstanceIdAttr || - abuf.Offs == GlslDecl.VertexIdAttr || - abuf.Offs == GlslDecl.FaceAttr - ? OperType.I32 - : OperType.F32; - - case ShaderIrOperCbuf cbuf: return OperType.F32; - case ShaderIrOperGpr gpr: return OperType.F32; - case ShaderIrOperImm imm: return OperType.I32; - case ShaderIrOperImmf immf: return OperType.F32; - case ShaderIrOperPred pred: return OperType.Bool; - - case ShaderIrOp op: - if (op.Inst > ShaderIrInst.B_Start && - op.Inst < ShaderIrInst.B_End) - { - return OperType.Bool; - } - else if (op.Inst > ShaderIrInst.F_Start && - op.Inst < ShaderIrInst.F_End) - { - return OperType.F32; - } - else if (op.Inst > ShaderIrInst.I_Start && - op.Inst < ShaderIrInst.I_End) - { - return OperType.I32; - } - break; - } - - throw new ArgumentException(nameof(node)); - } - - private static string GetBlockPosition(ShaderIrBlock block) - { - if (block != null) - { - return "0x" + block.Position.ToString("x8") + "u"; - } - else - { - return "0u"; - } - } - } -} diff --git a/Ryujinx.Graphics/Gal/Shader/GlslProgram.cs b/Ryujinx.Graphics/Gal/Shader/GlslProgram.cs deleted file mode 100644 index be8555d572..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/GlslProgram.cs +++ /dev/null @@ -1,22 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gal.Shader -{ - public struct GlslProgram - { - public string Code { get; private set; } - - public IEnumerable Textures { get; private set; } - public IEnumerable Uniforms { get; private set; } - - public GlslProgram( - string code, - IEnumerable textures, - IEnumerable uniforms) - { - Code = code; - Textures = textures; - Uniforms = uniforms; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs deleted file mode 100644 index f935be74ff..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs +++ /dev/null @@ -1,1299 +0,0 @@ -using System; - -using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static partial class ShaderDecode - { - private enum HalfOutputType - { - PackedFp16, - Fp32, - MergeH0, - MergeH1 - } - - public static void Bfe_C(ShaderIrBlock block, long opCode, int position) - { - EmitBfe(block, opCode, ShaderOper.Cr); - } - - public static void Bfe_I(ShaderIrBlock block, long opCode, int position) - { - EmitBfe(block, opCode, ShaderOper.Imm); - } - - public static void Bfe_R(ShaderIrBlock block, long opCode, int position) - { - EmitBfe(block, opCode, ShaderOper.Rr); - } - - public static void Fadd_C(ShaderIrBlock block, long opCode, int position) - { - EmitFadd(block, opCode, ShaderOper.Cr); - } - - public static void Fadd_I(ShaderIrBlock block, long opCode, int position) - { - EmitFadd(block, opCode, ShaderOper.Immf); - } - - public static void Fadd_I32(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode operA = opCode.Gpr8(); - ShaderIrNode operB = opCode.Immf32_20(); - - bool negB = opCode.Read(53); - bool absA = opCode.Read(54); - bool negA = opCode.Read(56); - bool absB = opCode.Read(57); - - operA = GetAluFabsFneg(operA, absA, negA); - operB = GetAluFabsFneg(operB, absB, negB); - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Fadd, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - public static void Fadd_R(ShaderIrBlock block, long opCode, int position) - { - EmitFadd(block, opCode, ShaderOper.Rr); - } - - public static void Ffma_CR(ShaderIrBlock block, long opCode, int position) - { - EmitFfma(block, opCode, ShaderOper.Cr); - } - - public static void Ffma_I(ShaderIrBlock block, long opCode, int position) - { - EmitFfma(block, opCode, ShaderOper.Immf); - } - - public static void Ffma_RC(ShaderIrBlock block, long opCode, int position) - { - EmitFfma(block, opCode, ShaderOper.Rc); - } - - public static void Ffma_RR(ShaderIrBlock block, long opCode, int position) - { - EmitFfma(block, opCode, ShaderOper.Rr); - } - - public static void Fmnmx_C(ShaderIrBlock block, long opCode, int position) - { - EmitFmnmx(block, opCode, ShaderOper.Cr); - } - - public static void Fmnmx_I(ShaderIrBlock block, long opCode, int position) - { - EmitFmnmx(block, opCode, ShaderOper.Immf); - } - - public static void Fmnmx_R(ShaderIrBlock block, long opCode, int position) - { - EmitFmnmx(block, opCode, ShaderOper.Rr); - } - - public static void Fmul_I32(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode operA = opCode.Gpr8(); - ShaderIrNode operB = opCode.Immf32_20(); - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Fmul, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - public static void Fmul_C(ShaderIrBlock block, long opCode, int position) - { - EmitFmul(block, opCode, ShaderOper.Cr); - } - - public static void Fmul_I(ShaderIrBlock block, long opCode, int position) - { - EmitFmul(block, opCode, ShaderOper.Immf); - } - - public static void Fmul_R(ShaderIrBlock block, long opCode, int position) - { - EmitFmul(block, opCode, ShaderOper.Rr); - } - - public static void Fset_C(ShaderIrBlock block, long opCode, int position) - { - EmitFset(block, opCode, ShaderOper.Cr); - } - - public static void Fset_I(ShaderIrBlock block, long opCode, int position) - { - EmitFset(block, opCode, ShaderOper.Immf); - } - - public static void Fset_R(ShaderIrBlock block, long opCode, int position) - { - EmitFset(block, opCode, ShaderOper.Rr); - } - - public static void Fsetp_C(ShaderIrBlock block, long opCode, int position) - { - EmitFsetp(block, opCode, ShaderOper.Cr); - } - - public static void Fsetp_I(ShaderIrBlock block, long opCode, int position) - { - EmitFsetp(block, opCode, ShaderOper.Immf); - } - - public static void Fsetp_R(ShaderIrBlock block, long opCode, int position) - { - EmitFsetp(block, opCode, ShaderOper.Rr); - } - - public static void Hadd2_R(ShaderIrBlock block, long opCode, int position) - { - EmitBinaryHalfOp(block, opCode, ShaderIrInst.Fadd); - } - - public static void Hmul2_R(ShaderIrBlock block, long opCode, int position) - { - EmitBinaryHalfOp(block, opCode, ShaderIrInst.Fmul); - } - - public static void Iadd_C(ShaderIrBlock block, long opCode, int position) - { - EmitIadd(block, opCode, ShaderOper.Cr); - } - - public static void Iadd_I(ShaderIrBlock block, long opCode, int position) - { - EmitIadd(block, opCode, ShaderOper.Imm); - } - - public static void Iadd_I32(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode operA = opCode.Gpr8(); - ShaderIrNode operB = opCode.Imm32_20(); - - bool negA = opCode.Read(56); - - operA = GetAluIneg(operA, negA); - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Add, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - public static void Iadd_R(ShaderIrBlock block, long opCode, int position) - { - EmitIadd(block, opCode, ShaderOper.Rr); - } - - public static void Iadd3_C(ShaderIrBlock block, long opCode, int position) - { - EmitIadd3(block, opCode, ShaderOper.Cr); - } - - public static void Iadd3_I(ShaderIrBlock block, long opCode, int position) - { - EmitIadd3(block, opCode, ShaderOper.Imm); - } - - public static void Iadd3_R(ShaderIrBlock block, long opCode, int position) - { - EmitIadd3(block, opCode, ShaderOper.Rr); - } - - public static void Imnmx_C(ShaderIrBlock block, long opCode, int position) - { - EmitImnmx(block, opCode, ShaderOper.Cr); - } - - public static void Imnmx_I(ShaderIrBlock block, long opCode, int position) - { - EmitImnmx(block, opCode, ShaderOper.Imm); - } - - public static void Imnmx_R(ShaderIrBlock block, long opCode, int position) - { - EmitImnmx(block, opCode, ShaderOper.Rr); - } - - public static void Ipa(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode operA = opCode.Abuf28(); - ShaderIrNode operB = opCode.Gpr20(); - - ShaderIpaMode mode = (ShaderIpaMode)(opCode.Read(54, 3)); - - ShaderIrMetaIpa meta = new ShaderIrMetaIpa(mode); - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Ipa, operA, operB, null, meta); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - public static void Iscadd_C(ShaderIrBlock block, long opCode, int position) - { - EmitIscadd(block, opCode, ShaderOper.Cr); - } - - public static void Iscadd_I(ShaderIrBlock block, long opCode, int position) - { - EmitIscadd(block, opCode, ShaderOper.Imm); - } - - public static void Iscadd_R(ShaderIrBlock block, long opCode, int position) - { - EmitIscadd(block, opCode, ShaderOper.Rr); - } - - public static void Iset_C(ShaderIrBlock block, long opCode, int position) - { - EmitIset(block, opCode, ShaderOper.Cr); - } - - public static void Iset_I(ShaderIrBlock block, long opCode, int position) - { - EmitIset(block, opCode, ShaderOper.Imm); - } - - public static void Iset_R(ShaderIrBlock block, long opCode, int position) - { - EmitIset(block, opCode, ShaderOper.Rr); - } - - public static void Isetp_C(ShaderIrBlock block, long opCode, int position) - { - EmitIsetp(block, opCode, ShaderOper.Cr); - } - - public static void Isetp_I(ShaderIrBlock block, long opCode, int position) - { - EmitIsetp(block, opCode, ShaderOper.Imm); - } - - public static void Isetp_R(ShaderIrBlock block, long opCode, int position) - { - EmitIsetp(block, opCode, ShaderOper.Rr); - } - - public static void Lop_I32(ShaderIrBlock block, long opCode, int position) - { - int subOp = opCode.Read(53, 3); - - bool invA = opCode.Read(55); - bool invB = opCode.Read(56); - - ShaderIrInst inst = 0; - - switch (subOp) - { - case 0: inst = ShaderIrInst.And; break; - case 1: inst = ShaderIrInst.Or; break; - case 2: inst = ShaderIrInst.Xor; break; - } - - ShaderIrNode operB = GetAluNot(opCode.Imm32_20(), invB); - - //SubOp == 3 is pass, used by the not instruction - //which just moves the inverted register value. - if (subOp < 3) - { - ShaderIrNode operA = GetAluNot(opCode.Gpr8(), invA); - - ShaderIrOp op = new ShaderIrOp(inst, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - else - { - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operB))); - } - } - - public static void Lop_C(ShaderIrBlock block, long opCode, int position) - { - EmitLop(block, opCode, ShaderOper.Cr); - } - - public static void Lop_I(ShaderIrBlock block, long opCode, int position) - { - EmitLop(block, opCode, ShaderOper.Imm); - } - - public static void Lop_R(ShaderIrBlock block, long opCode, int position) - { - EmitLop(block, opCode, ShaderOper.Rr); - } - - public static void Mufu(ShaderIrBlock block, long opCode, int position) - { - int subOp = opCode.Read(20, 0xf); - - bool absA = opCode.Read(46); - bool negA = opCode.Read(48); - - ShaderIrInst inst = 0; - - switch (subOp) - { - case 0: inst = ShaderIrInst.Fcos; break; - case 1: inst = ShaderIrInst.Fsin; break; - case 2: inst = ShaderIrInst.Fex2; break; - case 3: inst = ShaderIrInst.Flg2; break; - case 4: inst = ShaderIrInst.Frcp; break; - case 5: inst = ShaderIrInst.Frsq; break; - case 8: inst = ShaderIrInst.Fsqrt; break; - - default: throw new NotImplementedException(subOp.ToString()); - } - - ShaderIrNode operA = opCode.Gpr8(); - - ShaderIrOp op = new ShaderIrOp(inst, GetAluFabsFneg(operA, absA, negA)); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - public static void Psetp(ShaderIrBlock block, long opCode, int position) - { - bool negA = opCode.Read(15); - bool negB = opCode.Read(32); - bool negP = opCode.Read(42); - - ShaderIrInst lopInst = opCode.BLop24(); - - ShaderIrNode operA = opCode.Pred12(); - ShaderIrNode operB = opCode.Pred29(); - - if (negA) - { - operA = new ShaderIrOp(ShaderIrInst.Bnot, operA); - } - - if (negB) - { - operB = new ShaderIrOp(ShaderIrInst.Bnot, operB); - } - - ShaderIrOp op = new ShaderIrOp(lopInst, operA, operB); - - ShaderIrOperPred p0Node = opCode.Pred3(); - ShaderIrOperPred p1Node = opCode.Pred0(); - ShaderIrOperPred p2Node = opCode.Pred39(); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(p0Node, op))); - - lopInst = opCode.BLop45(); - - if (lopInst == ShaderIrInst.Band && p1Node.IsConst && p2Node.IsConst) - { - return; - } - - ShaderIrNode p2NNode = p2Node; - - if (negP) - { - p2NNode = new ShaderIrOp(ShaderIrInst.Bnot, p2NNode); - } - - op = new ShaderIrOp(ShaderIrInst.Bnot, p0Node); - - op = new ShaderIrOp(lopInst, op, p2NNode); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(p1Node, op))); - - op = new ShaderIrOp(lopInst, p0Node, p2NNode); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(p0Node, op))); - } - - public static void Rro_C(ShaderIrBlock block, long opCode, int position) - { - EmitRro(block, opCode, ShaderOper.Cr); - } - - public static void Rro_I(ShaderIrBlock block, long opCode, int position) - { - EmitRro(block, opCode, ShaderOper.Immf); - } - - public static void Rro_R(ShaderIrBlock block, long opCode, int position) - { - EmitRro(block, opCode, ShaderOper.Rr); - } - - public static void Shl_C(ShaderIrBlock block, long opCode, int position) - { - EmitAluBinary(block, opCode, ShaderOper.Cr, ShaderIrInst.Lsl); - } - - public static void Shl_I(ShaderIrBlock block, long opCode, int position) - { - EmitAluBinary(block, opCode, ShaderOper.Imm, ShaderIrInst.Lsl); - } - - public static void Shl_R(ShaderIrBlock block, long opCode, int position) - { - EmitAluBinary(block, opCode, ShaderOper.Rr, ShaderIrInst.Lsl); - } - - public static void Shr_C(ShaderIrBlock block, long opCode, int position) - { - EmitAluBinary(block, opCode, ShaderOper.Cr, GetShrInst(opCode)); - } - - public static void Shr_I(ShaderIrBlock block, long opCode, int position) - { - EmitAluBinary(block, opCode, ShaderOper.Imm, GetShrInst(opCode)); - } - - public static void Shr_R(ShaderIrBlock block, long opCode, int position) - { - EmitAluBinary(block, opCode, ShaderOper.Rr, GetShrInst(opCode)); - } - - private static ShaderIrInst GetShrInst(long opCode) - { - bool signed = opCode.Read(48); - - return signed ? ShaderIrInst.Asr : ShaderIrInst.Lsr; - } - - public static void Vmad(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode operA = opCode.Gpr8(); - - ShaderIrNode operB; - - if (opCode.Read(50)) - { - operB = opCode.Gpr20(); - } - else - { - operB = opCode.Imm19_20(); - } - - ShaderIrOperGpr operC = opCode.Gpr39(); - - ShaderIrNode tmp = new ShaderIrOp(ShaderIrInst.Mul, operA, operB); - - ShaderIrNode final = new ShaderIrOp(ShaderIrInst.Add, tmp, operC); - - int shr = opCode.Read(51, 3); - - if (shr != 0) - { - int shift = (shr == 2) ? 15 : 7; - - final = new ShaderIrOp(ShaderIrInst.Lsr, final, new ShaderIrOperImm(shift)); - } - - block.AddNode(new ShaderIrCmnt("Stubbed. Instruction is reduced to a * b + c")); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), final))); - } - - public static void Xmad_CR(ShaderIrBlock block, long opCode, int position) - { - EmitXmad(block, opCode, ShaderOper.Cr); - } - - public static void Xmad_I(ShaderIrBlock block, long opCode, int position) - { - EmitXmad(block, opCode, ShaderOper.Imm); - } - - public static void Xmad_RC(ShaderIrBlock block, long opCode, int position) - { - EmitXmad(block, opCode, ShaderOper.Rc); - } - - public static void Xmad_RR(ShaderIrBlock block, long opCode, int position) - { - EmitXmad(block, opCode, ShaderOper.Rr); - } - - private static void EmitAluBinary( - ShaderIrBlock block, - long opCode, - ShaderOper oper, - ShaderIrInst inst) - { - ShaderIrNode operA = opCode.Gpr8(), operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - ShaderIrNode op = new ShaderIrOp(inst, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - private static void EmitBfe(ShaderIrBlock block, long opCode, ShaderOper oper) - { - //TODO: Handle the case where position + length - //is greater than the word size, in this case the sign bit - //needs to be replicated to fill the remaining space. - bool negB = opCode.Read(48); - bool negA = opCode.Read(49); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - ShaderIrNode op; - - bool signed = opCode.Read(48); //? - - if (operB is ShaderIrOperImm posLen) - { - int position = (posLen.Value >> 0) & 0xff; - int length = (posLen.Value >> 8) & 0xff; - - int lSh = 32 - (position + length); - - ShaderIrInst rightShift = signed - ? ShaderIrInst.Asr - : ShaderIrInst.Lsr; - - op = new ShaderIrOp(ShaderIrInst.Lsl, operA, new ShaderIrOperImm(lSh)); - op = new ShaderIrOp(rightShift, op, new ShaderIrOperImm(lSh + position)); - } - else - { - ShaderIrOperImm shift = new ShaderIrOperImm(8); - ShaderIrOperImm mask = new ShaderIrOperImm(0xff); - - ShaderIrNode opPos, opLen; - - opPos = new ShaderIrOp(ShaderIrInst.And, operB, mask); - opLen = new ShaderIrOp(ShaderIrInst.Lsr, operB, shift); - opLen = new ShaderIrOp(ShaderIrInst.And, opLen, mask); - - op = new ShaderIrOp(ShaderIrInst.Lsr, operA, opPos); - - op = ExtendTo32(op, signed, opLen); - } - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - private static void EmitFadd(ShaderIrBlock block, long opCode, ShaderOper oper) - { - bool negB = opCode.Read(45); - bool absA = opCode.Read(46); - bool negA = opCode.Read(48); - bool absB = opCode.Read(49); - bool sat = opCode.Read(50); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - operA = GetAluFabsFneg(operA, absA, negA); - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Immf: operB = opCode.Immf19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operB = GetAluFabsFneg(operB, absB, negB); - - ShaderIrNode op = new ShaderIrOp(ShaderIrInst.Fadd, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), GetAluFsat(op, sat)))); - } - - private static void EmitFmul(ShaderIrBlock block, long opCode, ShaderOper oper) - { - bool negB = opCode.Read(48); - bool sat = opCode.Read(50); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Immf: operB = opCode.Immf19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operB = GetAluFneg(operB, negB); - - ShaderIrNode op = new ShaderIrOp(ShaderIrInst.Fmul, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), GetAluFsat(op, sat)))); - } - - private static void EmitFfma(ShaderIrBlock block, long opCode, ShaderOper oper) - { - bool negB = opCode.Read(48); - bool negC = opCode.Read(49); - bool sat = opCode.Read(50); - - ShaderIrNode operA = opCode.Gpr8(), operB, operC; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Immf: operB = opCode.Immf19_20(); break; - case ShaderOper.Rc: operB = opCode.Gpr39(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operB = GetAluFneg(operB, negB); - - if (oper == ShaderOper.Rc) - { - operC = GetAluFneg(opCode.Cbuf34(), negC); - } - else - { - operC = GetAluFneg(opCode.Gpr39(), negC); - } - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Ffma, operA, operB, operC); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), GetAluFsat(op, sat)))); - } - - private static void EmitIadd(ShaderIrBlock block, long opCode, ShaderOper oper) - { - ShaderIrNode operA = opCode.Gpr8(); - ShaderIrNode operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - bool negA = opCode.Read(49); - bool negB = opCode.Read(48); - - operA = GetAluIneg(operA, negA); - operB = GetAluIneg(operB, negB); - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Add, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - private static void EmitIadd3(ShaderIrBlock block, long opCode, ShaderOper oper) - { - int mode = opCode.Read(37, 3); - - bool neg1 = opCode.Read(51); - bool neg2 = opCode.Read(50); - bool neg3 = opCode.Read(49); - - int height1 = opCode.Read(35, 3); - int height2 = opCode.Read(33, 3); - int height3 = opCode.Read(31, 3); - - ShaderIrNode operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - ShaderIrNode ApplyHeight(ShaderIrNode src, int height) - { - if (oper != ShaderOper.Rr) - { - return src; - } - - switch (height) - { - case 0: return src; - case 1: return new ShaderIrOp(ShaderIrInst.And, src, new ShaderIrOperImm(0xffff)); - case 2: return new ShaderIrOp(ShaderIrInst.Lsr, src, new ShaderIrOperImm(16)); - - default: throw new InvalidOperationException(); - } - } - - ShaderIrNode src1 = GetAluIneg(ApplyHeight(opCode.Gpr8(), height1), neg1); - ShaderIrNode src2 = GetAluIneg(ApplyHeight(operB, height2), neg2); - ShaderIrNode src3 = GetAluIneg(ApplyHeight(opCode.Gpr39(), height3), neg3); - - ShaderIrOp sum = new ShaderIrOp(ShaderIrInst.Add, src1, src2); - - if (oper == ShaderOper.Rr) - { - switch (mode) - { - case 1: sum = new ShaderIrOp(ShaderIrInst.Lsr, sum, new ShaderIrOperImm(16)); break; - case 2: sum = new ShaderIrOp(ShaderIrInst.Lsl, sum, new ShaderIrOperImm(16)); break; - } - } - - //Note: Here there should be a "+ 1" when carry flag is set - //but since carry is mostly ignored by other instructions, it's excluded for now - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), new ShaderIrOp(ShaderIrInst.Add, sum, src3)))); - } - - private static void EmitIscadd(ShaderIrBlock block, long opCode, ShaderOper oper) - { - bool negB = opCode.Read(48); - bool negA = opCode.Read(49); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - ShaderIrOperImm scale = opCode.Imm5_39(); - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operA = GetAluIneg(operA, negA); - operB = GetAluIneg(operB, negB); - - ShaderIrOp scaleOp = new ShaderIrOp(ShaderIrInst.Lsl, operA, scale); - ShaderIrOp addOp = new ShaderIrOp(ShaderIrInst.Add, operB, scaleOp); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), addOp))); - } - - private static void EmitFmnmx(ShaderIrBlock block, long opCode, ShaderOper oper) - { - EmitMnmx(block, opCode, true, oper); - } - - private static void EmitImnmx(ShaderIrBlock block, long opCode, ShaderOper oper) - { - EmitMnmx(block, opCode, false, oper); - } - - private static void EmitMnmx(ShaderIrBlock block, long opCode, bool isFloat, ShaderOper oper) - { - bool negB = opCode.Read(45); - bool absA = opCode.Read(46); - bool negA = opCode.Read(48); - bool absB = opCode.Read(49); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - if (isFloat) - { - operA = GetAluFabsFneg(operA, absA, negA); - } - else - { - operA = GetAluIabsIneg(operA, absA, negA); - } - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Immf: operB = opCode.Immf19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - if (isFloat) - { - operB = GetAluFabsFneg(operB, absB, negB); - } - else - { - operB = GetAluIabsIneg(operB, absB, negB); - } - - ShaderIrOperPred pred = opCode.Pred39(); - - ShaderIrOp op; - - ShaderIrInst maxInst = isFloat ? ShaderIrInst.Fmax : ShaderIrInst.Max; - ShaderIrInst minInst = isFloat ? ShaderIrInst.Fmin : ShaderIrInst.Min; - - if (pred.IsConst) - { - bool isMax = opCode.Read(42); - - op = new ShaderIrOp(isMax - ? maxInst - : minInst, operA, operB); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - else - { - ShaderIrNode predN = opCode.Pred39N(); - - ShaderIrOp opMax = new ShaderIrOp(maxInst, operA, operB); - ShaderIrOp opMin = new ShaderIrOp(minInst, operA, operB); - - ShaderIrAsg asgMax = new ShaderIrAsg(opCode.Gpr0(), opMax); - ShaderIrAsg asgMin = new ShaderIrAsg(opCode.Gpr0(), opMin); - - block.AddNode(opCode.PredNode(new ShaderIrCond(predN, asgMax, not: true))); - block.AddNode(opCode.PredNode(new ShaderIrCond(predN, asgMin, not: false))); - } - } - - private static void EmitRro(ShaderIrBlock block, long opCode, ShaderOper oper) - { - //Note: this is a range reduction instruction and is supposed to - //be used with Mufu, here it just moves the value and ignores the operation. - bool negA = opCode.Read(45); - bool absA = opCode.Read(49); - - ShaderIrNode operA; - - switch (oper) - { - case ShaderOper.Cr: operA = opCode.Cbuf34(); break; - case ShaderOper.Immf: operA = opCode.Immf19_20(); break; - case ShaderOper.Rr: operA = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operA = GetAluFabsFneg(operA, absA, negA); - - block.AddNode(new ShaderIrCmnt("Stubbed.")); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA))); - } - - private static void EmitFset(ShaderIrBlock block, long opCode, ShaderOper oper) - { - EmitSet(block, opCode, true, oper); - } - - private static void EmitIset(ShaderIrBlock block, long opCode, ShaderOper oper) - { - EmitSet(block, opCode, false, oper); - } - - private static void EmitSet(ShaderIrBlock block, long opCode, bool isFloat, ShaderOper oper) - { - bool negA = opCode.Read(43); - bool absB = opCode.Read(44); - bool negB = opCode.Read(53); - bool absA = opCode.Read(54); - - bool boolFloat = opCode.Read(isFloat ? 52 : 44); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Immf: operB = opCode.Immf19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - ShaderIrInst cmpInst; - - if (isFloat) - { - operA = GetAluFabsFneg(operA, absA, negA); - operB = GetAluFabsFneg(operB, absB, negB); - - cmpInst = opCode.CmpF(); - } - else - { - cmpInst = opCode.Cmp(); - } - - ShaderIrOp op = new ShaderIrOp(cmpInst, operA, operB); - - ShaderIrInst lopInst = opCode.BLop45(); - - ShaderIrOperPred pNode = opCode.Pred39(); - - ShaderIrNode imm0, imm1; - - if (boolFloat) - { - imm0 = new ShaderIrOperImmf(0); - imm1 = new ShaderIrOperImmf(1); - } - else - { - imm0 = new ShaderIrOperImm(0); - imm1 = new ShaderIrOperImm(-1); - } - - ShaderIrNode asg0 = new ShaderIrAsg(opCode.Gpr0(), imm0); - ShaderIrNode asg1 = new ShaderIrAsg(opCode.Gpr0(), imm1); - - if (lopInst != ShaderIrInst.Band || !pNode.IsConst) - { - ShaderIrOp op2 = new ShaderIrOp(lopInst, op, pNode); - - asg0 = new ShaderIrCond(op2, asg0, not: true); - asg1 = new ShaderIrCond(op2, asg1, not: false); - } - else - { - asg0 = new ShaderIrCond(op, asg0, not: true); - asg1 = new ShaderIrCond(op, asg1, not: false); - } - - block.AddNode(opCode.PredNode(asg0)); - block.AddNode(opCode.PredNode(asg1)); - } - - private static void EmitFsetp(ShaderIrBlock block, long opCode, ShaderOper oper) - { - EmitSetp(block, opCode, true, oper); - } - - private static void EmitIsetp(ShaderIrBlock block, long opCode, ShaderOper oper) - { - EmitSetp(block, opCode, false, oper); - } - - private static void EmitSetp(ShaderIrBlock block, long opCode, bool isFloat, ShaderOper oper) - { - bool absA = opCode.Read(7); - bool negP = opCode.Read(42); - bool negA = opCode.Read(43); - bool absB = opCode.Read(44); - - ShaderIrNode operA = opCode.Gpr8(), operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Immf: operB = opCode.Immf19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - ShaderIrInst cmpInst; - - if (isFloat) - { - operA = GetAluFabsFneg(operA, absA, negA); - operB = GetAluFabs (operB, absB); - - cmpInst = opCode.CmpF(); - } - else - { - cmpInst = opCode.Cmp(); - } - - ShaderIrOp op = new ShaderIrOp(cmpInst, operA, operB); - - ShaderIrOperPred p0Node = opCode.Pred3(); - ShaderIrOperPred p1Node = opCode.Pred0(); - ShaderIrOperPred p2Node = opCode.Pred39(); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(p0Node, op))); - - ShaderIrInst lopInst = opCode.BLop45(); - - if (lopInst == ShaderIrInst.Band && p1Node.IsConst && p2Node.IsConst) - { - return; - } - - ShaderIrNode p2NNode = p2Node; - - if (negP) - { - p2NNode = new ShaderIrOp(ShaderIrInst.Bnot, p2NNode); - } - - op = new ShaderIrOp(ShaderIrInst.Bnot, p0Node); - - op = new ShaderIrOp(lopInst, op, p2NNode); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(p1Node, op))); - - op = new ShaderIrOp(lopInst, p0Node, p2NNode); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(p0Node, op))); - } - - private static void EmitBinaryHalfOp(ShaderIrBlock block, long opCode, ShaderIrInst inst) - { - bool absB = opCode.Read(30); - bool negB = opCode.Read(31); - bool sat = opCode.Read(32); - bool absA = opCode.Read(44); - - ShaderIrOperGpr[] vecA = opCode.GprHalfVec8(); - ShaderIrOperGpr[] vecB = opCode.GprHalfVec20(); - - HalfOutputType outputType = (HalfOutputType)opCode.Read(49, 3); - - int elems = outputType == HalfOutputType.PackedFp16 ? 2 : 1; - int first = outputType == HalfOutputType.MergeH1 ? 1 : 0; - - for (int index = first; index < elems; index++) - { - ShaderIrNode operA = GetAluFabs (vecA[index], absA); - ShaderIrNode operB = GetAluFabsFneg(vecB[index], absB, negB); - - ShaderIrNode op = new ShaderIrOp(inst, operA, operB); - - ShaderIrOperGpr dst = GetHalfDst(opCode, outputType, index); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, GetAluFsat(op, sat)))); - } - } - - private static ShaderIrOperGpr GetHalfDst(long opCode, HalfOutputType outputType, int index) - { - switch (outputType) - { - case HalfOutputType.PackedFp16: return opCode.GprHalf0(index); - case HalfOutputType.Fp32: return opCode.Gpr0(); - case HalfOutputType.MergeH0: return opCode.GprHalf0(0); - case HalfOutputType.MergeH1: return opCode.GprHalf0(1); - } - - throw new ArgumentException(nameof(outputType)); - } - - private static void EmitLop(ShaderIrBlock block, long opCode, ShaderOper oper) - { - int subOp = opCode.Read(41, 3); - - bool invA = opCode.Read(39); - bool invB = opCode.Read(40); - - ShaderIrInst inst = 0; - - switch (subOp) - { - case 0: inst = ShaderIrInst.And; break; - case 1: inst = ShaderIrInst.Or; break; - case 2: inst = ShaderIrInst.Xor; break; - } - - ShaderIrNode operA = GetAluNot(opCode.Gpr8(), invA); - ShaderIrNode operB; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.Imm19_20(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operB = GetAluNot(operB, invB); - - ShaderIrNode op; - - if (subOp < 3) - { - op = new ShaderIrOp(inst, operA, operB); - } - else - { - op = operB; - } - - ShaderIrNode compare = new ShaderIrOp(ShaderIrInst.Cne, op, new ShaderIrOperImm(0)); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Pred48(), compare))); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - private enum XmadMode - { - Cfull = 0, - Clo = 1, - Chi = 2, - Csfu = 3, - Cbcc = 4 - } - - private static void EmitXmad(ShaderIrBlock block, long opCode, ShaderOper oper) - { - bool signedA = opCode.Read(48); - bool signedB = opCode.Read(49); - bool highB = opCode.Read(52); - bool highA = opCode.Read(53); - - int mode = opCode.Read(50, 7); - - ShaderIrNode operA = opCode.Gpr8(), operB, operC; - - switch (oper) - { - case ShaderOper.Cr: operB = opCode.Cbuf34(); break; - case ShaderOper.Imm: operB = opCode.ImmU16_20(); break; - case ShaderOper.Rc: operB = opCode.Gpr39(); break; - case ShaderOper.Rr: operB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - ShaderIrNode operB2 = operB; - - if (oper == ShaderOper.Imm) - { - int imm = ((ShaderIrOperImm)operB2).Value; - - if (!highB) - { - imm <<= 16; - } - - if (signedB) - { - imm >>= 16; - } - else - { - imm = (int)((uint)imm >> 16); - } - - operB2 = new ShaderIrOperImm(imm); - } - - ShaderIrOperImm imm16 = new ShaderIrOperImm(16); - - //If we are working with the lower 16-bits of the A/B operands, - //we need to shift the lower 16-bits to the top 16-bits. Later, - //they will be right shifted. For U16 types, this will be a logical - //right shift, and for S16 types, a arithmetic right shift. - if (!highA) - { - operA = new ShaderIrOp(ShaderIrInst.Lsl, operA, imm16); - } - - if (!highB && oper != ShaderOper.Imm) - { - operB2 = new ShaderIrOp(ShaderIrInst.Lsl, operB2, imm16); - } - - ShaderIrInst shiftA = signedA ? ShaderIrInst.Asr : ShaderIrInst.Lsr; - ShaderIrInst shiftB = signedB ? ShaderIrInst.Asr : ShaderIrInst.Lsr; - - operA = new ShaderIrOp(shiftA, operA, imm16); - - if (oper != ShaderOper.Imm) - { - operB2 = new ShaderIrOp(shiftB, operB2, imm16); - } - - bool productShiftLeft = false; - bool merge = false; - - if (oper == ShaderOper.Rc) - { - operC = opCode.Cbuf34(); - } - else - { - operC = opCode.Gpr39(); - - productShiftLeft = opCode.Read(36); - merge = opCode.Read(37); - } - - ShaderIrOp mulOp = new ShaderIrOp(ShaderIrInst.Mul, operA, operB2); - - if (productShiftLeft) - { - mulOp = new ShaderIrOp(ShaderIrInst.Lsl, mulOp, imm16); - } - - switch ((XmadMode)mode) - { - case XmadMode.Clo: operC = ExtendTo32(operC, signed: false, size: 16); break; - - case XmadMode.Chi: operC = new ShaderIrOp(ShaderIrInst.Lsr, operC, imm16); break; - - case XmadMode.Cbcc: - { - ShaderIrOp operBLsh16 = new ShaderIrOp(ShaderIrInst.Lsl, operB, imm16); - - operC = new ShaderIrOp(ShaderIrInst.Add, operC, operBLsh16); - - break; - } - - case XmadMode.Csfu: - { - ShaderIrOperImm imm31 = new ShaderIrOperImm(31); - - ShaderIrOp signAdjustA = new ShaderIrOp(ShaderIrInst.Lsr, operA, imm31); - ShaderIrOp signAdjustB = new ShaderIrOp(ShaderIrInst.Lsr, operB2, imm31); - - signAdjustA = new ShaderIrOp(ShaderIrInst.Lsl, signAdjustA, imm16); - signAdjustB = new ShaderIrOp(ShaderIrInst.Lsl, signAdjustB, imm16); - - ShaderIrOp signAdjust = new ShaderIrOp(ShaderIrInst.Add, signAdjustA, signAdjustB); - - operC = new ShaderIrOp(ShaderIrInst.Sub, operC, signAdjust); - - break; - } - } - - ShaderIrOp addOp = new ShaderIrOp(ShaderIrInst.Add, mulOp, operC); - - if (merge) - { - ShaderIrOperImm imm16Mask = new ShaderIrOperImm(0xffff); - - addOp = new ShaderIrOp(ShaderIrInst.And, addOp, imm16Mask); - operB = new ShaderIrOp(ShaderIrInst.Lsl, operB, imm16); - addOp = new ShaderIrOp(ShaderIrInst.Or, addOp, operB); - } - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), addOp))); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs deleted file mode 100644 index fc9926934d..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static partial class ShaderDecode - { - public static void Bra(ShaderIrBlock block, long opCode, int position) - { - if ((opCode & 0x20) != 0) - { - //This reads the target offset from the constant buffer. - //Almost impossible to support with GLSL. - throw new NotImplementedException(); - } - - ShaderIrOperImm imm = new ShaderIrOperImm(position + opCode.Branch()); - - block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Bra, imm))); - } - - public static void Exit(ShaderIrBlock block, long opCode, int position) - { - int cCode = (int)opCode & 0x1f; - - //TODO: Figure out what the other condition codes mean... - if (cCode == 0xf) - { - block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Exit))); - } - } - - public static void Kil(ShaderIrBlock block, long opCode, int position) - { - block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Kil))); - } - - public static void Ssy(ShaderIrBlock block, long opCode, int position) - { - if ((opCode & 0x20) != 0) - { - //This reads the target offset from the constant buffer. - //Almost impossible to support with GLSL. - throw new NotImplementedException(); - } - - ShaderIrOperImm imm = new ShaderIrOperImm(position + opCode.Branch()); - - block.AddNode(new ShaderIrOp(ShaderIrInst.Ssy, imm)); - } - - public static void Sync(ShaderIrBlock block, long opCode, int position) - { - //TODO: Implement Sync condition codes - block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Sync))); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs deleted file mode 100644 index cc385aa4ea..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - delegate void ShaderDecodeFunc(ShaderIrBlock block, long opCode, int position); -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs deleted file mode 100644 index 9a84e6129c..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs +++ /dev/null @@ -1,78 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - static class ShaderDecodeHelper - { - private static readonly ShaderIrOperImmf ImmfZero = new ShaderIrOperImmf(0); - private static readonly ShaderIrOperImmf ImmfOne = new ShaderIrOperImmf(1); - - public static ShaderIrNode GetAluFabsFneg(ShaderIrNode node, bool abs, bool neg) - { - return GetAluFneg(GetAluFabs(node, abs), neg); - } - - public static ShaderIrNode GetAluFabs(ShaderIrNode node, bool abs) - { - return abs ? new ShaderIrOp(ShaderIrInst.Fabs, node) : node; - } - - public static ShaderIrNode GetAluFneg(ShaderIrNode node, bool neg) - { - return neg ? new ShaderIrOp(ShaderIrInst.Fneg, node) : node; - } - - public static ShaderIrNode GetAluFsat(ShaderIrNode node, bool sat) - { - return sat ? new ShaderIrOp(ShaderIrInst.Fclamp, node, ImmfZero, ImmfOne) : node; - } - - public static ShaderIrNode GetAluIabsIneg(ShaderIrNode node, bool abs, bool neg) - { - return GetAluIneg(GetAluIabs(node, abs), neg); - } - - public static ShaderIrNode GetAluIabs(ShaderIrNode node, bool abs) - { - return abs ? new ShaderIrOp(ShaderIrInst.Abs, node) : node; - } - - public static ShaderIrNode GetAluIneg(ShaderIrNode node, bool neg) - { - return neg ? new ShaderIrOp(ShaderIrInst.Neg, node) : node; - } - - public static ShaderIrNode GetAluNot(ShaderIrNode node, bool not) - { - return not ? new ShaderIrOp(ShaderIrInst.Not, node) : node; - } - - public static ShaderIrNode ExtendTo32(ShaderIrNode node, bool signed, int size) - { - int shift = 32 - size; - - ShaderIrInst rightShift = signed - ? ShaderIrInst.Asr - : ShaderIrInst.Lsr; - - node = new ShaderIrOp(ShaderIrInst.Lsl, node, new ShaderIrOperImm(shift)); - node = new ShaderIrOp(rightShift, node, new ShaderIrOperImm(shift)); - - return node; - } - - public static ShaderIrNode ExtendTo32(ShaderIrNode node, bool signed, ShaderIrNode size) - { - ShaderIrOperImm wordSize = new ShaderIrOperImm(32); - - ShaderIrOp shift = new ShaderIrOp(ShaderIrInst.Sub, wordSize, size); - - ShaderIrInst rightShift = signed - ? ShaderIrInst.Asr - : ShaderIrInst.Lsr; - - node = new ShaderIrOp(ShaderIrInst.Lsl, node, shift); - node = new ShaderIrOp(rightShift, node, shift); - - return node; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs deleted file mode 100644 index 7ce126b0c4..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs +++ /dev/null @@ -1,878 +0,0 @@ -using Ryujinx.Graphics.Texture; -using System; - -using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static partial class ShaderDecode - { - // ReSharper disable InconsistentNaming - private const int ____ = 0x0; - private const int R___ = 0x1; - private const int _G__ = 0x2; - private const int RG__ = 0x3; - private const int __B_ = 0x4; - private const int RGB_ = 0x7; - private const int ___A = 0x8; - private const int R__A = 0x9; - private const int _G_A = 0xa; - private const int RG_A = 0xb; - private const int __BA = 0xc; - private const int R_BA = 0xd; - private const int _GBA = 0xe; - private const int RGBA = 0xf; - // ReSharper restore InconsistentNaming - - private static int[,] _maskLut = new int[,] - { - { ____, ____, ____, ____, ____, ____, ____, ____ }, - { R___, _G__, __B_, ___A, RG__, R__A, _G_A, __BA }, - { R___, _G__, __B_, ___A, RG__, ____, ____, ____ }, - { RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ } - }; - - private static GalTextureTarget TexToTextureTarget(int texType, bool isArray) - { - switch (texType) - { - case 0: - return isArray ? GalTextureTarget.OneDArray : GalTextureTarget.OneD; - case 2: - return isArray ? GalTextureTarget.TwoDArray : GalTextureTarget.TwoD; - case 4: - if (isArray) - throw new InvalidOperationException("ARRAY bit set on a TEX with 3D texture!"); - return GalTextureTarget.ThreeD; - case 6: - return isArray ? GalTextureTarget.CubeArray : GalTextureTarget.CubeMap; - default: - throw new InvalidOperationException(); - } - } - - private static GalTextureTarget TexsToTextureTarget(int texType) - { - switch (texType) - { - case 0: - return GalTextureTarget.OneD; - case 2: - case 4: - case 6: - case 8: - case 0xa: - case 0xc: - return GalTextureTarget.TwoD; - case 0xe: - case 0x10: - case 0x12: - return GalTextureTarget.TwoDArray; - case 0x14: - case 0x16: - return GalTextureTarget.ThreeD; - case 0x18: - case 0x1a: - return GalTextureTarget.CubeMap; - default: - throw new InvalidOperationException(); - } - } - - public static GalTextureTarget TldsToTextureTarget(int texType) - { - switch (texType) - { - case 0: - case 2: - return GalTextureTarget.OneD; - case 4: - case 8: - case 0xa: - case 0xc: - case 0x18: - return GalTextureTarget.TwoD; - case 0x10: - return GalTextureTarget.TwoDArray; - case 0xe: - return GalTextureTarget.ThreeD; - default: - throw new InvalidOperationException(); - } - } - - public static void Ld_A(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode[] opers = opCode.Abuf20(); - - //Used by GS - ShaderIrOperGpr vertex = opCode.Gpr39(); - - int index = 0; - - foreach (ShaderIrNode operA in opers) - { - ShaderIrOperGpr operD = opCode.Gpr0(); - - operD.Index += index++; - - block.AddNode(opCode.PredNode(new ShaderIrAsg(operD, operA))); - } - } - - public static void Ld_C(ShaderIrBlock block, long opCode, int position) - { - int cbufPos = opCode.Read(22, 0x3fff); - int cbufIndex = opCode.Read(36, 0x1f); - int type = opCode.Read(48, 7); - - if (type > 5) - { - throw new InvalidOperationException(); - } - - ShaderIrOperGpr temp = ShaderIrOperGpr.MakeTemporary(); - - block.AddNode(new ShaderIrAsg(temp, opCode.Gpr8())); - - int count = type == 5 ? 2 : 1; - - for (int index = 0; index < count; index++) - { - ShaderIrOperCbuf operA = new ShaderIrOperCbuf(cbufIndex, cbufPos, temp); - - ShaderIrOperGpr operD = opCode.Gpr0(); - - operA.Pos += index; - operD.Index += index; - - if (!operD.IsValidRegister) - { - break; - } - - ShaderIrNode node = operA; - - if (type < 4) - { - //This is a 8 or 16 bits type. - bool signed = (type & 1) != 0; - - int size = 8 << (type >> 1); - - node = ExtendTo32(node, signed, size); - } - - block.AddNode(opCode.PredNode(new ShaderIrAsg(operD, node))); - } - } - - public static void St_A(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode[] opers = opCode.Abuf20(); - - int index = 0; - - foreach (ShaderIrNode operA in opers) - { - ShaderIrOperGpr operD = opCode.Gpr0(); - - operD.Index += index++; - - block.AddNode(opCode.PredNode(new ShaderIrAsg(operA, operD))); - } - } - - public static void Texq(ShaderIrBlock block, long opCode, int position) - { - ShaderIrNode operD = opCode.Gpr0(); - ShaderIrNode operA = opCode.Gpr8(); - - ShaderTexqInfo info = (ShaderTexqInfo)(opCode.Read(22, 0x1f)); - - ShaderIrMetaTexq meta0 = new ShaderIrMetaTexq(info, 0); - ShaderIrMetaTexq meta1 = new ShaderIrMetaTexq(info, 1); - - ShaderIrNode operC = opCode.Imm13_36(); - - ShaderIrOp op0 = new ShaderIrOp(ShaderIrInst.Texq, operA, null, operC, meta0); - ShaderIrOp op1 = new ShaderIrOp(ShaderIrInst.Texq, operA, null, operC, meta1); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(operD, op0))); - block.AddNode(opCode.PredNode(new ShaderIrAsg(operA, op1))); //Is this right? - } - - public static void Tex(ShaderIrBlock block, long opCode, int position) - { - TextureInstructionSuffix suffix; - - int rawSuffix = opCode.Read(0x34, 0x38); - - switch (rawSuffix) - { - case 0: - suffix = TextureInstructionSuffix.None; - break; - case 0x8: - suffix = TextureInstructionSuffix.Lz; - break; - case 0x10: - suffix = TextureInstructionSuffix.Lb; - break; - case 0x18: - suffix = TextureInstructionSuffix.Ll; - break; - case 0x30: - suffix = TextureInstructionSuffix.Lba; - break; - case 0x38: - suffix = TextureInstructionSuffix.Lla; - break; - default: - throw new InvalidOperationException($"Invalid Suffix for TEX instruction {rawSuffix}"); - } - - bool isOffset = opCode.Read(0x36); - - if (isOffset) - suffix |= TextureInstructionSuffix.AOffI; - - EmitTex(block, opCode, suffix, gprHandle: false); - } - - public static void Tex_B(ShaderIrBlock block, long opCode, int position) - { - TextureInstructionSuffix suffix; - - int rawSuffix = opCode.Read(0x24, 0xe); - - switch (rawSuffix) - { - case 0: - suffix = TextureInstructionSuffix.None; - break; - case 0x2: - suffix = TextureInstructionSuffix.Lz; - break; - case 0x4: - suffix = TextureInstructionSuffix.Lb; - break; - case 0x6: - suffix = TextureInstructionSuffix.Ll; - break; - case 0xc: - suffix = TextureInstructionSuffix.Lba; - break; - case 0xe: - suffix = TextureInstructionSuffix.Lla; - break; - default: - throw new InvalidOperationException($"Invalid Suffix for TEX.B instruction {rawSuffix}"); - } - - bool isOffset = opCode.Read(0x23); - - if (isOffset) - suffix |= TextureInstructionSuffix.AOffI; - - EmitTex(block, opCode, suffix, gprHandle: true); - } - - private static void EmitTex(ShaderIrBlock block, long opCode, TextureInstructionSuffix textureInstructionSuffix, bool gprHandle) - { - bool isArray = opCode.HasArray(); - - GalTextureTarget textureTarget = TexToTextureTarget(opCode.Read(28, 6), isArray); - - bool hasDepthCompare = opCode.Read(0x32); - - if (hasDepthCompare) - { - textureInstructionSuffix |= TextureInstructionSuffix.Dc; - } - - ShaderIrOperGpr[] coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureTarget(textureTarget)]; - - int indexExtraCoord = 0; - - if (isArray) - { - indexExtraCoord++; - - coords[coords.Length - 1] = opCode.Gpr8(); - } - - - for (int index = 0; index < coords.Length - indexExtraCoord; index++) - { - ShaderIrOperGpr coordReg = opCode.Gpr8(); - - coordReg.Index += index; - - coordReg.Index += indexExtraCoord; - - if (!coordReg.IsValidRegister) - { - coordReg.Index = ShaderIrOperGpr.ZrIndex; - } - - coords[index] = coordReg; - } - - int chMask = opCode.Read(31, 0xf); - - ShaderIrOperGpr levelOfDetail = null; - ShaderIrOperGpr offset = null; - ShaderIrOperGpr depthCompare = null; - - // TODO: determine first argument when TEX.B is used - int operBIndex = gprHandle ? 1 : 0; - - if ((textureInstructionSuffix & TextureInstructionSuffix.Ll) != 0 || - (textureInstructionSuffix & TextureInstructionSuffix.Lb) != 0 || - (textureInstructionSuffix & TextureInstructionSuffix.Lba) != 0 || - (textureInstructionSuffix & TextureInstructionSuffix.Lla) != 0) - { - levelOfDetail = opCode.Gpr20(); - levelOfDetail.Index += operBIndex; - - operBIndex++; - } - - if ((textureInstructionSuffix & TextureInstructionSuffix.AOffI) != 0) - { - offset = opCode.Gpr20(); - offset.Index += operBIndex; - - operBIndex++; - } - - if ((textureInstructionSuffix & TextureInstructionSuffix.Dc) != 0) - { - depthCompare = opCode.Gpr20(); - depthCompare.Index += operBIndex; - - operBIndex++; - } - - // ??? - ShaderIrNode operC = gprHandle - ? (ShaderIrNode)opCode.Gpr20() - : (ShaderIrNode)opCode.Imm13_36(); - - ShaderIrInst inst = gprHandle ? ShaderIrInst.Texb : ShaderIrInst.Texs; - - coords = CoordsRegistersToTempRegisters(block, coords); - - int regInc = 0; - - for (int ch = 0; ch < 4; ch++) - { - if (!IsChannelUsed(chMask, ch)) - { - continue; - } - - ShaderIrOperGpr dst = opCode.Gpr0(); - - dst.Index += regInc++; - - if (!dst.IsValidRegister || dst.IsConst) - { - continue; - } - - ShaderIrMetaTex meta = new ShaderIrMetaTex(ch, textureTarget, textureInstructionSuffix, coords) - { - LevelOfDetail = levelOfDetail, - Offset = offset, - DepthCompare = depthCompare - }; - - ShaderIrOp op = new ShaderIrOp(inst, coords[0], coords.Length > 1 ? coords[1] : null, operC, meta); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, op))); - } - } - - public static void Texs(ShaderIrBlock block, long opCode, int position) - { - TextureInstructionSuffix suffix; - - int rawSuffix = opCode.Read(0x34, 0x1e); - - switch (rawSuffix) - { - case 0: - case 0x4: - case 0x10: - case 0x16: - suffix = TextureInstructionSuffix.Lz; - break; - case 0x6: - case 0x1a: - suffix = TextureInstructionSuffix.Ll; - break; - case 0x8: - suffix = TextureInstructionSuffix.Dc; - break; - case 0x2: - case 0xe: - case 0x14: - case 0x18: - suffix = TextureInstructionSuffix.None; - break; - case 0xa: - suffix = TextureInstructionSuffix.Ll | TextureInstructionSuffix.Dc; - break; - case 0xc: - case 0x12: - suffix = TextureInstructionSuffix.Lz | TextureInstructionSuffix.Dc; - break; - default: - throw new InvalidOperationException($"Invalid Suffix for TEXS instruction {rawSuffix}"); - } - - GalTextureTarget textureTarget = TexsToTextureTarget(opCode.Read(52, 0x1e)); - - EmitTexs(block, opCode, ShaderIrInst.Texs, textureTarget, suffix); - } - - public static void Tlds(ShaderIrBlock block, long opCode, int position) - { - TextureInstructionSuffix suffix; - - int rawSuffix = opCode.Read(0x34, 0x1e); - - switch (rawSuffix) - { - case 0: - case 0x4: - case 0x8: - suffix = TextureInstructionSuffix.Lz | TextureInstructionSuffix.AOffI; - break; - case 0xc: - suffix = TextureInstructionSuffix.Lz | TextureInstructionSuffix.Mz; - break; - case 0xe: - case 0x10: - suffix = TextureInstructionSuffix.Lz; - break; - case 0x2: - case 0xa: - suffix = TextureInstructionSuffix.Ll; - break; - case 0x18: - suffix = TextureInstructionSuffix.Ll | TextureInstructionSuffix.AOffI; - break; - default: - throw new InvalidOperationException($"Invalid Suffix for TLDS instruction {rawSuffix}"); - } - - GalTextureTarget textureTarget = TldsToTextureTarget(opCode.Read(52, 0x1e)); - - EmitTexs(block, opCode, ShaderIrInst.Txlf, textureTarget, suffix); - } - - public static void Tld4(ShaderIrBlock block, long opCode, int position) - { - TextureInstructionSuffix suffix; - - int rawSuffix = opCode.Read(0x34, 0xc); - - switch (rawSuffix) - { - case 0: - suffix = TextureInstructionSuffix.None; - break; - case 0x4: - suffix = TextureInstructionSuffix.AOffI; - break; - case 0x8: - suffix = TextureInstructionSuffix.Ptp; - break; - default: - throw new InvalidOperationException($"Invalid Suffix for TLD4 instruction {rawSuffix}"); - } - - bool isShadow = opCode.Read(0x32); - - bool isArray = opCode.HasArray(); - int chMask = opCode.Read(31, 0xf); - - GalTextureTarget textureTarget = TexToTextureTarget(opCode.Read(28, 6), isArray); - - if (isShadow) - { - suffix |= TextureInstructionSuffix.Dc; - } - - EmitTld4(block, opCode, textureTarget, suffix, chMask, opCode.Read(0x38, 0x3), false); - } - - public static void Tld4S(ShaderIrBlock block, long opCode, int position) - { - TextureInstructionSuffix suffix = TextureInstructionSuffix.None; - - bool isOffset = opCode.Read(0x33); - bool isShadow = opCode.Read(0x32); - - if (isOffset) - { - suffix |= TextureInstructionSuffix.AOffI; - } - - if (isShadow) - { - suffix |= TextureInstructionSuffix.Dc; - } - - // TLD4S seems to only support 2D textures with RGBA mask? - EmitTld4(block, opCode, GalTextureTarget.TwoD, suffix, RGBA, opCode.Read(0x34, 0x3), true); - } - - private static void EmitTexs(ShaderIrBlock block, - long opCode, - ShaderIrInst inst, - GalTextureTarget textureTarget, - TextureInstructionSuffix textureInstructionSuffix) - { - if (inst == ShaderIrInst.Txlf && textureTarget == GalTextureTarget.CubeArray) - { - throw new InvalidOperationException("TLDS instructions cannot use CUBE modifier!"); - } - - bool isArray = ImageUtils.IsArray(textureTarget); - - ShaderIrOperGpr[] coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureTarget(textureTarget)]; - - ShaderIrOperGpr operA = opCode.Gpr8(); - ShaderIrOperGpr operB = opCode.Gpr20(); - - ShaderIrOperGpr suffixExtra = opCode.Gpr20(); - suffixExtra.Index += 1; - - int coordStartIndex = 0; - - if (isArray) - { - coordStartIndex++; - coords[coords.Length - 1] = opCode.Gpr8(); - } - - switch (coords.Length - coordStartIndex) - { - case 1: - coords[0] = opCode.Gpr8(); - - break; - case 2: - coords[0] = opCode.Gpr8(); - coords[0].Index += coordStartIndex; - - break; - case 3: - coords[0] = opCode.Gpr8(); - coords[0].Index += coordStartIndex; - - coords[1] = opCode.Gpr8(); - coords[1].Index += 1 + coordStartIndex; - - break; - default: - throw new NotSupportedException($"{coords.Length - coordStartIndex} coords textures aren't supported in TEXS"); - } - - int operBIndex = 0; - - ShaderIrOperGpr levelOfDetail = null; - ShaderIrOperGpr offset = null; - ShaderIrOperGpr depthCompare = null; - - // OperB is always the last value - // Not applicable to 1d textures - if (coords.Length - coordStartIndex != 1) - { - coords[coords.Length - coordStartIndex - 1] = operB; - operBIndex++; - } - - // Encoding of TEXS/TLDS is a bit special and change for 2d textures - // NOTE: OperA seems to hold at best two args. - // On 2D textures, if no suffix need an additional values, Y is stored in OperB, otherwise coords are in OperA and the additional values is in OperB. - if (textureInstructionSuffix != TextureInstructionSuffix.None && textureInstructionSuffix != TextureInstructionSuffix.Lz && textureTarget == GalTextureTarget.TwoD) - { - coords[coords.Length - coordStartIndex - 1] = opCode.Gpr8(); - coords[coords.Length - coordStartIndex - 1].Index += coords.Length - coordStartIndex - 1; - operBIndex--; - } - - // TODO: Find what MZ does and what changes about the encoding (Maybe Multisample?) - if ((textureInstructionSuffix & TextureInstructionSuffix.Ll) != 0) - { - levelOfDetail = opCode.Gpr20(); - levelOfDetail.Index += operBIndex; - operBIndex++; - } - - if ((textureInstructionSuffix & TextureInstructionSuffix.AOffI) != 0) - { - offset = opCode.Gpr20(); - offset.Index += operBIndex; - operBIndex++; - } - - if ((textureInstructionSuffix & TextureInstructionSuffix.Dc) != 0) - { - depthCompare = opCode.Gpr20(); - depthCompare.Index += operBIndex; - operBIndex++; - } - - int lutIndex; - - lutIndex = !opCode.Gpr0().IsConst ? 1 : 0; - lutIndex |= !opCode.Gpr28().IsConst ? 2 : 0; - - if (lutIndex == 0) - { - //Both destination registers are RZ, do nothing. - return; - } - - bool fp16 = !opCode.Read(59); - - int dstIncrement = 0; - - ShaderIrOperGpr GetDst() - { - ShaderIrOperGpr dst; - - if (fp16) - { - //FP16 mode, two components are packed on the two - //halfs of a 32-bits register, as two half-float values. - int halfPart = dstIncrement & 1; - - switch (lutIndex) - { - case 1: dst = opCode.GprHalf0(halfPart); break; - case 2: dst = opCode.GprHalf28(halfPart); break; - case 3: dst = (dstIncrement >> 1) != 0 - ? opCode.GprHalf28(halfPart) - : opCode.GprHalf0(halfPart); break; - - default: throw new InvalidOperationException(); - } - } - else - { - //32-bits mode, each component uses one register. - //Two components uses two consecutive registers. - switch (lutIndex) - { - case 1: dst = opCode.Gpr0(); break; - case 2: dst = opCode.Gpr28(); break; - case 3: dst = (dstIncrement >> 1) != 0 - ? opCode.Gpr28() - : opCode.Gpr0(); break; - - default: throw new InvalidOperationException(); - } - - dst.Index += dstIncrement & 1; - } - - dstIncrement++; - - return dst; - } - - int chMask = _maskLut[lutIndex, opCode.Read(50, 7)]; - - if (chMask == 0) - { - //All channels are disabled, do nothing. - return; - } - - ShaderIrNode operC = opCode.Imm13_36(); - coords = CoordsRegistersToTempRegisters(block, coords); - - for (int ch = 0; ch < 4; ch++) - { - if (!IsChannelUsed(chMask, ch)) - { - continue; - } - - ShaderIrMetaTex meta = new ShaderIrMetaTex(ch, textureTarget, textureInstructionSuffix, coords) - { - LevelOfDetail = levelOfDetail, - Offset = offset, - DepthCompare = depthCompare - }; - ShaderIrOp op = new ShaderIrOp(inst, operA, operB, operC, meta); - - ShaderIrOperGpr dst = GetDst(); - - if (dst.IsValidRegister && !dst.IsConst) - { - block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, op))); - } - } - } - - private static void EmitTld4(ShaderIrBlock block, long opCode, GalTextureTarget textureType, TextureInstructionSuffix textureInstructionSuffix, int chMask, int component, bool scalar) - { - ShaderIrOperGpr operA = opCode.Gpr8(); - ShaderIrOperGpr operB = opCode.Gpr20(); - ShaderIrOperImm operC = opCode.Imm13_36(); - - ShaderIrOperGpr[] coords = new ShaderIrOperGpr[ImageUtils.GetCoordsCountTextureTarget(textureType)]; - - ShaderIrOperGpr offset = null; - ShaderIrOperGpr depthCompare = null; - - bool isArray = ImageUtils.IsArray(textureType); - - int operBIndex = 0; - - if (scalar) - { - int coordStartIndex = 0; - - if (isArray) - { - coordStartIndex++; - coords[coords.Length - 1] = operB; - } - - switch (coords.Length - coordStartIndex) - { - case 1: - coords[0] = opCode.Gpr8(); - - break; - case 2: - coords[0] = opCode.Gpr8(); - coords[0].Index += coordStartIndex; - - break; - case 3: - coords[0] = opCode.Gpr8(); - coords[0].Index += coordStartIndex; - - coords[1] = opCode.Gpr8(); - coords[1].Index += 1 + coordStartIndex; - - break; - default: - throw new NotSupportedException($"{coords.Length - coordStartIndex} coords textures aren't supported in TLD4S"); - } - - if (coords.Length - coordStartIndex != 1) - { - coords[coords.Length - coordStartIndex - 1] = operB; - operBIndex++; - } - - if (textureInstructionSuffix != TextureInstructionSuffix.None && textureType == GalTextureTarget.TwoD) - { - coords[coords.Length - coordStartIndex - 1] = opCode.Gpr8(); - coords[coords.Length - coordStartIndex - 1].Index += coords.Length - coordStartIndex - 1; - operBIndex--; - } - } - else - { - int indexExtraCoord = 0; - - if (isArray) - { - indexExtraCoord++; - - coords[coords.Length - 1] = opCode.Gpr8(); - } - - for (int index = 0; index < coords.Length - indexExtraCoord; index++) - { - coords[index] = opCode.Gpr8(); - - coords[index].Index += index; - - coords[index].Index += indexExtraCoord; - - if (coords[index].Index > ShaderIrOperGpr.ZrIndex) - { - coords[index].Index = ShaderIrOperGpr.ZrIndex; - } - } - } - - if ((textureInstructionSuffix & TextureInstructionSuffix.AOffI) != 0) - { - offset = opCode.Gpr20(); - offset.Index += operBIndex; - operBIndex++; - } - - if ((textureInstructionSuffix & TextureInstructionSuffix.Dc) != 0) - { - depthCompare = opCode.Gpr20(); - depthCompare.Index += operBIndex; - operBIndex++; - } - - coords = CoordsRegistersToTempRegisters(block, coords); - - int regInc = 0; - - for (int ch = 0; ch < 4; ch++) - { - if (!IsChannelUsed(chMask, ch)) - { - continue; - } - - ShaderIrOperGpr dst = opCode.Gpr0(); - - dst.Index += regInc++; - - if (!dst.IsValidRegister || dst.IsConst) - { - continue; - } - - ShaderIrMetaTex meta = new ShaderIrMetaTex(ch, textureType, textureInstructionSuffix, coords) - { - Component = component, - Offset = offset, - DepthCompare = depthCompare - }; - - ShaderIrOp op = new ShaderIrOp(ShaderIrInst.Tld4, operA, operB, operC, meta); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(dst, op))); - } - } - - private static bool IsChannelUsed(int chMask, int ch) - { - return (chMask & (1 << ch)) != 0; - } - - private static ShaderIrOperGpr[] CoordsRegistersToTempRegisters(ShaderIrBlock block, params ShaderIrOperGpr[] registers) - { - ShaderIrOperGpr[] res = new ShaderIrOperGpr[registers.Length]; - - for (int index = 0; index < res.Length; index++) - { - res[index] = ShaderIrOperGpr.MakeTemporary(index); - block.AddNode(new ShaderIrAsg(res[index], registers[index])); - } - - return res; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs deleted file mode 100644 index 0a2b4232bb..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs +++ /dev/null @@ -1,431 +0,0 @@ -using System; - -using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static partial class ShaderDecode - { - private enum IntType - { - U8 = 0, - U16 = 1, - U32 = 2, - U64 = 3, - S8 = 4, - S16 = 5, - S32 = 6, - S64 = 7 - } - - private enum FloatType - { - F16 = 1, - F32 = 2, - F64 = 3 - } - - public static void F2f_C(ShaderIrBlock block, long opCode, int position) - { - EmitF2F(block, opCode, ShaderOper.Cr); - } - - public static void F2f_I(ShaderIrBlock block, long opCode, int position) - { - EmitF2F(block, opCode, ShaderOper.Immf); - } - - public static void F2f_R(ShaderIrBlock block, long opCode, int position) - { - EmitF2F(block, opCode, ShaderOper.Rr); - } - - public static void F2i_C(ShaderIrBlock block, long opCode, int position) - { - EmitF2I(block, opCode, ShaderOper.Cr); - } - - public static void F2i_I(ShaderIrBlock block, long opCode, int position) - { - EmitF2I(block, opCode, ShaderOper.Immf); - } - - public static void F2i_R(ShaderIrBlock block, long opCode, int position) - { - EmitF2I(block, opCode, ShaderOper.Rr); - } - - public static void I2f_C(ShaderIrBlock block, long opCode, int position) - { - EmitI2F(block, opCode, ShaderOper.Cr); - } - - public static void I2f_I(ShaderIrBlock block, long opCode, int position) - { - EmitI2F(block, opCode, ShaderOper.Imm); - } - - public static void I2f_R(ShaderIrBlock block, long opCode, int position) - { - EmitI2F(block, opCode, ShaderOper.Rr); - } - - public static void I2i_C(ShaderIrBlock block, long opCode, int position) - { - EmitI2I(block, opCode, ShaderOper.Cr); - } - - public static void I2i_I(ShaderIrBlock block, long opCode, int position) - { - EmitI2I(block, opCode, ShaderOper.Imm); - } - - public static void I2i_R(ShaderIrBlock block, long opCode, int position) - { - EmitI2I(block, opCode, ShaderOper.Rr); - } - - public static void Isberd(ShaderIrBlock block, long opCode, int position) - { - //This instruction seems to be used to translate from an address to a vertex index in a GS - //Stub it as such - - block.AddNode(new ShaderIrCmnt("Stubbed.")); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), opCode.Gpr8()))); - } - - public static void Mov_C(ShaderIrBlock block, long opCode, int position) - { - ShaderIrOperCbuf cbuf = opCode.Cbuf34(); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), cbuf))); - } - - public static void Mov_I(ShaderIrBlock block, long opCode, int position) - { - ShaderIrOperImm imm = opCode.Imm19_20(); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), imm))); - } - - public static void Mov_I32(ShaderIrBlock block, long opCode, int position) - { - ShaderIrOperImm imm = opCode.Imm32_20(); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), imm))); - } - - public static void Mov_R(ShaderIrBlock block, long opCode, int position) - { - ShaderIrOperGpr gpr = opCode.Gpr20(); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), gpr))); - } - - public static void Sel_C(ShaderIrBlock block, long opCode, int position) - { - EmitSel(block, opCode, ShaderOper.Cr); - } - - public static void Sel_I(ShaderIrBlock block, long opCode, int position) - { - EmitSel(block, opCode, ShaderOper.Imm); - } - - public static void Sel_R(ShaderIrBlock block, long opCode, int position) - { - EmitSel(block, opCode, ShaderOper.Rr); - } - - public static void Mov_S(ShaderIrBlock block, long opCode, int position) - { - block.AddNode(new ShaderIrCmnt("Stubbed.")); - - //Zero is used as a special number to get a valid "0 * 0 + VertexIndex" in a GS - ShaderIrNode source = new ShaderIrOperImm(0); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), source))); - } - - private static void EmitF2F(ShaderIrBlock block, long opCode, ShaderOper oper) - { - bool negA = opCode.Read(45); - bool absA = opCode.Read(49); - - ShaderIrNode operA; - - switch (oper) - { - case ShaderOper.Cr: operA = opCode.Cbuf34(); break; - case ShaderOper.Immf: operA = opCode.Immf19_20(); break; - case ShaderOper.Rr: operA = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operA = GetAluFabsFneg(operA, absA, negA); - - ShaderIrInst roundInst = GetRoundInst(opCode); - - if (roundInst != ShaderIrInst.Invalid) - { - operA = new ShaderIrOp(roundInst, operA); - } - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA))); - } - - private static void EmitF2I(ShaderIrBlock block, long opCode, ShaderOper oper) - { - IntType type = GetIntType(opCode); - - if (type == IntType.U64 || - type == IntType.S64) - { - //TODO: 64-bits support. - //Note: GLSL doesn't support 64-bits integers. - throw new NotImplementedException(); - } - - bool negA = opCode.Read(45); - bool absA = opCode.Read(49); - - ShaderIrNode operA; - - switch (oper) - { - case ShaderOper.Cr: operA = opCode.Cbuf34(); break; - case ShaderOper.Immf: operA = opCode.Immf19_20(); break; - case ShaderOper.Rr: operA = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operA = GetAluFabsFneg(operA, absA, negA); - - ShaderIrInst roundInst = GetRoundInst(opCode); - - if (roundInst != ShaderIrInst.Invalid) - { - operA = new ShaderIrOp(roundInst, operA); - } - - bool signed = type >= IntType.S8; - - int size = 8 << ((int)type & 3); - - if (size < 32) - { - uint mask = uint.MaxValue >> (32 - size); - - float cMin = 0; - float cMax = mask; - - if (signed) - { - uint halfMask = mask >> 1; - - cMin -= halfMask + 1; - cMax = halfMask; - } - - ShaderIrOperImmf min = new ShaderIrOperImmf(cMin); - ShaderIrOperImmf max = new ShaderIrOperImmf(cMax); - - operA = new ShaderIrOp(ShaderIrInst.Fclamp, operA, min, max); - } - - ShaderIrInst inst = signed - ? ShaderIrInst.Ftos - : ShaderIrInst.Ftou; - - ShaderIrNode op = new ShaderIrOp(inst, operA); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - private static void EmitI2F(ShaderIrBlock block, long opCode, ShaderOper oper) - { - IntType type = GetIntType(opCode); - - if (type == IntType.U64 || - type == IntType.S64) - { - //TODO: 64-bits support. - //Note: GLSL doesn't support 64-bits integers. - throw new NotImplementedException(); - } - - int sel = opCode.Read(41, 3); - - bool negA = opCode.Read(45); - bool absA = opCode.Read(49); - - ShaderIrNode operA; - - switch (oper) - { - case ShaderOper.Cr: operA = opCode.Cbuf34(); break; - case ShaderOper.Imm: operA = opCode.Imm19_20(); break; - case ShaderOper.Rr: operA = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operA = GetAluIabsIneg(operA, absA, negA); - - bool signed = type >= IntType.S8; - - int shift = sel * 8; - - int size = 8 << ((int)type & 3); - - if (shift != 0) - { - operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift)); - } - - if (size < 32) - { - operA = ExtendTo32(operA, signed, size); - } - - ShaderIrInst inst = signed - ? ShaderIrInst.Stof - : ShaderIrInst.Utof; - - ShaderIrNode op = new ShaderIrOp(inst, operA); - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), op))); - } - - private static void EmitI2I(ShaderIrBlock block, long opCode, ShaderOper oper) - { - IntType type = GetIntType(opCode); - - if (type == IntType.U64 || - type == IntType.S64) - { - //TODO: 64-bits support. - //Note: GLSL doesn't support 64-bits integers. - throw new NotImplementedException(); - } - - int sel = opCode.Read(41, 3); - - bool negA = opCode.Read(45); - bool absA = opCode.Read(49); - bool satA = opCode.Read(50); - - ShaderIrNode operA; - - switch (oper) - { - case ShaderOper.Cr: operA = opCode.Cbuf34(); break; - case ShaderOper.Immf: operA = opCode.Immf19_20(); break; - case ShaderOper.Rr: operA = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - operA = GetAluIabsIneg(operA, absA, negA); - - bool signed = type >= IntType.S8; - - int shift = sel * 8; - - int size = 8 << ((int)type & 3); - - if (shift != 0) - { - operA = new ShaderIrOp(ShaderIrInst.Asr, operA, new ShaderIrOperImm(shift)); - } - - if (size < 32) - { - uint mask = uint.MaxValue >> (32 - size); - - if (satA) - { - uint cMin = 0; - uint cMax = mask; - - if (signed) - { - uint halfMask = mask >> 1; - - cMin -= halfMask + 1; - cMax = halfMask; - } - - ShaderIrOperImm min = new ShaderIrOperImm((int)cMin); - ShaderIrOperImm max = new ShaderIrOperImm((int)cMax); - - operA = new ShaderIrOp(signed - ? ShaderIrInst.Clamps - : ShaderIrInst.Clampu, operA, min, max); - } - else - { - operA = ExtendTo32(operA, signed, size); - } - } - - block.AddNode(opCode.PredNode(new ShaderIrAsg(opCode.Gpr0(), operA))); - } - - private static void EmitSel(ShaderIrBlock block, long opCode, ShaderOper oper) - { - ShaderIrOperGpr dst = opCode.Gpr0(); - ShaderIrNode pred = opCode.Pred39N(); - - ShaderIrNode resultA = opCode.Gpr8(); - ShaderIrNode resultB; - - switch (oper) - { - case ShaderOper.Cr: resultB = opCode.Cbuf34(); break; - case ShaderOper.Imm: resultB = opCode.Imm19_20(); break; - case ShaderOper.Rr: resultB = opCode.Gpr20(); break; - - default: throw new ArgumentException(nameof(oper)); - } - - block.AddNode(opCode.PredNode(new ShaderIrCond(pred, new ShaderIrAsg(dst, resultA), false))); - - block.AddNode(opCode.PredNode(new ShaderIrCond(pred, new ShaderIrAsg(dst, resultB), true))); - } - - private static IntType GetIntType(long opCode) - { - bool signed = opCode.Read(13); - - IntType type = (IntType)(opCode.Read(10, 3)); - - if (signed) - { - type += (int)IntType.S8; - } - - return type; - } - - private static FloatType GetFloatType(long opCode) - { - return (FloatType)(opCode.Read(8, 3)); - } - - private static ShaderIrInst GetRoundInst(long opCode) - { - switch (opCode.Read(39, 3)) - { - case 1: return ShaderIrInst.Floor; - case 2: return ShaderIrInst.Ceil; - case 3: return ShaderIrInst.Trunc; - } - - return ShaderIrInst.Invalid; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs deleted file mode 100644 index 4b1e404692..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeOpCode.cs +++ /dev/null @@ -1,313 +0,0 @@ -using System; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static partial class ShaderDecode - { - private static int Read(this long opCode, int position, int mask) - { - return (int)(opCode >> position) & mask; - } - - private static bool Read(this long opCode, int position) - { - return ((opCode >> position) & 1) != 0; - } - - private static int Branch(this long opCode) - { - return ((int)(opCode >> 20) << 8) >> 8; - } - - private static bool HasArray(this long opCode) - { - return opCode.Read(0x1c); - } - - private static ShaderIrOperAbuf[] Abuf20(this long opCode) - { - int abuf = opCode.Read(20, 0x3ff); - int size = opCode.Read(47, 3); - - ShaderIrOperGpr vertex = opCode.Gpr39(); - - ShaderIrOperAbuf[] opers = new ShaderIrOperAbuf[size + 1]; - - for (int index = 0; index <= size; index++) - { - opers[index] = new ShaderIrOperAbuf(abuf + index * 4, vertex); - } - - return opers; - } - - private static ShaderIrOperAbuf Abuf28(this long opCode) - { - int abuf = opCode.Read(28, 0x3ff); - - return new ShaderIrOperAbuf(abuf, opCode.Gpr39()); - } - - private static ShaderIrOperCbuf Cbuf34(this long opCode) - { - return new ShaderIrOperCbuf( - opCode.Read(34, 0x1f), - opCode.Read(20, 0x3fff)); - } - - private static ShaderIrOperGpr Gpr8(this long opCode) - { - return new ShaderIrOperGpr(opCode.Read(8, 0xff)); - } - - private static ShaderIrOperGpr Gpr20(this long opCode) - { - return new ShaderIrOperGpr(opCode.Read(20, 0xff)); - } - - private static ShaderIrOperGpr Gpr39(this long opCode) - { - return new ShaderIrOperGpr(opCode.Read(39, 0xff)); - } - - private static ShaderIrOperGpr Gpr0(this long opCode) - { - return new ShaderIrOperGpr(opCode.Read(0, 0xff)); - } - - private static ShaderIrOperGpr Gpr28(this long opCode) - { - return new ShaderIrOperGpr(opCode.Read(28, 0xff)); - } - - private static ShaderIrOperGpr[] GprHalfVec8(this long opCode) - { - return GetGprHalfVec2(opCode.Read(8, 0xff), opCode.Read(47, 3)); - } - - private static ShaderIrOperGpr[] GprHalfVec20(this long opCode) - { - return GetGprHalfVec2(opCode.Read(20, 0xff), opCode.Read(28, 3)); - } - - private static ShaderIrOperGpr[] GetGprHalfVec2(int gpr, int mask) - { - if (mask == 1) - { - //This value is used for FP32, the whole 32-bits register - //is used as each element on the vector. - return new ShaderIrOperGpr[] - { - new ShaderIrOperGpr(gpr), - new ShaderIrOperGpr(gpr) - }; - } - - ShaderIrOperGpr low = new ShaderIrOperGpr(gpr, 0); - ShaderIrOperGpr high = new ShaderIrOperGpr(gpr, 1); - - return new ShaderIrOperGpr[] - { - (mask & 1) != 0 ? high : low, - (mask & 2) != 0 ? high : low - }; - } - - private static ShaderIrOperGpr GprHalf0(this long opCode, int halfPart) - { - return new ShaderIrOperGpr(opCode.Read(0, 0xff), halfPart); - } - - private static ShaderIrOperGpr GprHalf28(this long opCode, int halfPart) - { - return new ShaderIrOperGpr(opCode.Read(28, 0xff), halfPart); - } - - private static ShaderIrOperImm Imm5_39(this long opCode) - { - return new ShaderIrOperImm(opCode.Read(39, 0x1f)); - } - - private static ShaderIrOperImm Imm13_36(this long opCode) - { - return new ShaderIrOperImm(opCode.Read(36, 0x1fff)); - } - - private static ShaderIrOperImm Imm32_20(this long opCode) - { - return new ShaderIrOperImm((int)(opCode >> 20)); - } - - private static ShaderIrOperImmf Immf32_20(this long opCode) - { - return new ShaderIrOperImmf(BitConverter.Int32BitsToSingle((int)(opCode >> 20))); - } - - private static ShaderIrOperImm ImmU16_20(this long opCode) - { - return new ShaderIrOperImm(opCode.Read(20, 0xffff)); - } - - private static ShaderIrOperImm Imm19_20(this long opCode) - { - int value = opCode.Read(20, 0x7ffff); - - bool neg = opCode.Read(56); - - if (neg) - { - value = -value; - } - - return new ShaderIrOperImm(value); - } - - private static ShaderIrOperImmf Immf19_20(this long opCode) - { - uint imm = (uint)(opCode >> 20) & 0x7ffff; - - bool neg = opCode.Read(56); - - imm <<= 12; - - if (neg) - { - imm |= 0x80000000; - } - - float value = BitConverter.Int32BitsToSingle((int)imm); - - return new ShaderIrOperImmf(value); - } - - private static ShaderIrOperPred Pred0(this long opCode) - { - return new ShaderIrOperPred(opCode.Read(0, 7)); - } - - private static ShaderIrOperPred Pred3(this long opCode) - { - return new ShaderIrOperPred(opCode.Read(3, 7)); - } - - private static ShaderIrOperPred Pred12(this long opCode) - { - return new ShaderIrOperPred(opCode.Read(12, 7)); - } - - private static ShaderIrOperPred Pred29(this long opCode) - { - return new ShaderIrOperPred(opCode.Read(29, 7)); - } - - private static ShaderIrNode Pred39N(this long opCode) - { - ShaderIrNode node = opCode.Pred39(); - - if (opCode.Read(42)) - { - node = new ShaderIrOp(ShaderIrInst.Bnot, node); - } - - return node; - } - - private static ShaderIrOperPred Pred39(this long opCode) - { - return new ShaderIrOperPred(opCode.Read(39, 7)); - } - - private static ShaderIrOperPred Pred48(this long opCode) - { - return new ShaderIrOperPred(opCode.Read(48, 7)); - } - - private static ShaderIrInst Cmp(this long opCode) - { - switch (opCode.Read(49, 7)) - { - case 1: return ShaderIrInst.Clt; - case 2: return ShaderIrInst.Ceq; - case 3: return ShaderIrInst.Cle; - case 4: return ShaderIrInst.Cgt; - case 5: return ShaderIrInst.Cne; - case 6: return ShaderIrInst.Cge; - } - - throw new ArgumentException(nameof(opCode)); - } - - private static ShaderIrInst CmpF(this long opCode) - { - switch (opCode.Read(48, 0xf)) - { - case 0x1: return ShaderIrInst.Fclt; - case 0x2: return ShaderIrInst.Fceq; - case 0x3: return ShaderIrInst.Fcle; - case 0x4: return ShaderIrInst.Fcgt; - case 0x5: return ShaderIrInst.Fcne; - case 0x6: return ShaderIrInst.Fcge; - case 0x7: return ShaderIrInst.Fcnum; - case 0x8: return ShaderIrInst.Fcnan; - case 0x9: return ShaderIrInst.Fcltu; - case 0xa: return ShaderIrInst.Fcequ; - case 0xb: return ShaderIrInst.Fcleu; - case 0xc: return ShaderIrInst.Fcgtu; - case 0xd: return ShaderIrInst.Fcneu; - case 0xe: return ShaderIrInst.Fcgeu; - } - - throw new ArgumentException(nameof(opCode)); - } - - private static ShaderIrInst BLop45(this long opCode) - { - switch (opCode.Read(45, 3)) - { - case 0: return ShaderIrInst.Band; - case 1: return ShaderIrInst.Bor; - case 2: return ShaderIrInst.Bxor; - } - - throw new ArgumentException(nameof(opCode)); - } - - private static ShaderIrInst BLop24(this long opCode) - { - switch (opCode.Read(24, 3)) - { - case 0: return ShaderIrInst.Band; - case 1: return ShaderIrInst.Bor; - case 2: return ShaderIrInst.Bxor; - } - - throw new ArgumentException(nameof(opCode)); - } - - private static ShaderIrNode PredNode(this long opCode, ShaderIrNode node) - { - ShaderIrOperPred pred = opCode.PredNode(); - - if (pred.Index != ShaderIrOperPred.UnusedIndex) - { - bool inv = opCode.Read(19); - - node = new ShaderIrCond(pred, node, inv); - } - - return node; - } - - private static ShaderIrOperPred PredNode(this long opCode) - { - int pred = opCode.Read(16, 0xf); - - if (pred != 0xf) - { - pred &= 7; - } - - return new ShaderIrOperPred(pred); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs deleted file mode 100644 index 9098ca5e55..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - static partial class ShaderDecode - { - public static void Out_R(ShaderIrBlock block, long opCode, int position) - { - //TODO: Those registers have to be used for something - ShaderIrOperGpr gpr0 = opCode.Gpr0(); - ShaderIrOperGpr gpr8 = opCode.Gpr8(); - ShaderIrOperGpr gpr20 = opCode.Gpr20(); - - int type = opCode.Read(39, 3); - - if ((type & 1) != 0) - { - block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Emit))); - } - - if ((type & 2) != 0) - { - block.AddNode(opCode.PredNode(new ShaderIrOp(ShaderIrInst.Cut))); - } - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs deleted file mode 100644 index 4b23f8d0fa..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs +++ /dev/null @@ -1,218 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static class ShaderDecoder - { - private const long HeaderSize = 0x50; - - private const bool AddDbgComments = true; - - public static ShaderIrBlock[] Decode(IGalMemory memory, long start) - { - Dictionary visited = new Dictionary(); - Dictionary visitedEnd = new Dictionary(); - - Queue blocks = new Queue(); - - long beginning = start + HeaderSize; - - ShaderIrBlock Enqueue(int position, ShaderIrBlock source = null) - { - if (!visited.TryGetValue(position, out ShaderIrBlock output)) - { - output = new ShaderIrBlock(position); - - blocks.Enqueue(output); - - visited.Add(position, output); - } - - if (source != null) - { - output.Sources.Add(source); - } - - return output; - } - - ShaderIrBlock entry = Enqueue(0); - - while (blocks.Count > 0) - { - ShaderIrBlock current = blocks.Dequeue(); - - FillBlock(memory, current, beginning); - - //Set child blocks. "Branch" is the block the branch instruction - //points to (when taken), "Next" is the block at the next address, - //executed when the branch is not taken. For Unconditional Branches - //or end of shader, Next is null. - if (current.Nodes.Count > 0) - { - ShaderIrNode lastNode = current.GetLastNode(); - - ShaderIrOp innerOp = GetInnermostOp(lastNode); - - if (innerOp?.Inst == ShaderIrInst.Bra) - { - int target = ((ShaderIrOperImm)innerOp.OperandA).Value; - - current.Branch = Enqueue(target, current); - } - - foreach (ShaderIrNode node in current.Nodes) - { - innerOp = GetInnermostOp(node); - - if (innerOp is ShaderIrOp currOp && currOp.Inst == ShaderIrInst.Ssy) - { - int target = ((ShaderIrOperImm)currOp.OperandA).Value; - - Enqueue(target, current); - } - } - - if (NodeHasNext(lastNode)) - { - current.Next = Enqueue(current.EndPosition); - } - } - - //If we have on the graph two blocks with the same end position, - //then we need to split the bigger block and have two small blocks, - //the end position of the bigger "Current" block should then be == to - //the position of the "Smaller" block. - while (visitedEnd.TryGetValue(current.EndPosition, out ShaderIrBlock smaller)) - { - if (current.Position > smaller.Position) - { - ShaderIrBlock temp = smaller; - - smaller = current; - current = temp; - } - - current.EndPosition = smaller.Position; - current.Next = smaller; - current.Branch = null; - - current.Nodes.RemoveRange( - current.Nodes.Count - smaller.Nodes.Count, - smaller.Nodes.Count); - - visitedEnd[smaller.EndPosition] = smaller; - } - - visitedEnd.Add(current.EndPosition, current); - } - - //Make and sort Graph blocks array by position. - ShaderIrBlock[] graph = new ShaderIrBlock[visited.Count]; - - while (visited.Count > 0) - { - uint firstPos = uint.MaxValue; - - foreach (ShaderIrBlock block in visited.Values) - { - if (firstPos > (uint)block.Position) - firstPos = (uint)block.Position; - } - - ShaderIrBlock current = visited[(int)firstPos]; - - do - { - graph[graph.Length - visited.Count] = current; - - visited.Remove(current.Position); - - current = current.Next; - } - while (current != null); - } - - return graph; - } - - private static void FillBlock(IGalMemory memory, ShaderIrBlock block, long beginning) - { - int position = block.Position; - - do - { - //Ignore scheduling instructions, which are written every 32 bytes. - if ((position & 0x1f) == 0) - { - position += 8; - - continue; - } - - uint word0 = (uint)memory.ReadInt32(position + beginning + 0); - uint word1 = (uint)memory.ReadInt32(position + beginning + 4); - - position += 8; - - long opCode = word0 | (long)word1 << 32; - - ShaderDecodeFunc decode = ShaderOpCodeTable.GetDecoder(opCode); - - if (AddDbgComments) - { - string dbgOpCode = $"0x{(position - 8):x16}: 0x{opCode:x16} "; - - dbgOpCode += (decode?.Method.Name ?? "???"); - - if (decode == ShaderDecode.Bra || decode == ShaderDecode.Ssy) - { - int offset = ((int)(opCode >> 20) << 8) >> 8; - - long target = position + offset; - - dbgOpCode += " (0x" + target.ToString("x16") + ")"; - } - - block.AddNode(new ShaderIrCmnt(dbgOpCode)); - } - - if (decode == null) - { - continue; - } - - decode(block, opCode, position); - } - while (!IsFlowChange(block.GetLastNode())); - - block.EndPosition = position; - } - - private static bool IsFlowChange(ShaderIrNode node) - { - return !NodeHasNext(GetInnermostOp(node)); - } - - private static ShaderIrOp GetInnermostOp(ShaderIrNode node) - { - if (node is ShaderIrCond cond) - { - node = cond.Child; - } - - return node is ShaderIrOp op ? op : null; - } - - private static bool NodeHasNext(ShaderIrNode node) - { - if (!(node is ShaderIrOp op)) - { - return true; - } - - return op.Inst != ShaderIrInst.Exit && - op.Inst != ShaderIrInst.Bra; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs b/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs deleted file mode 100644 index 2f9326e121..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderHeader.cs +++ /dev/null @@ -1,146 +0,0 @@ -using System; - -namespace Ryujinx.Graphics.Gal.Shader -{ - struct OmapTarget - { - public bool Red; - public bool Green; - public bool Blue; - public bool Alpha; - - public bool Enabled => Red || Green || Blue || Alpha; - - public bool ComponentEnabled(int component) - { - switch (component) - { - case 0: return Red; - case 1: return Green; - case 2: return Blue; - case 3: return Alpha; - } - - throw new ArgumentException(nameof(component)); - } - } - - class ShaderHeader - { - public const int PointList = 1; - public const int LineStrip = 6; - public const int TriangleStrip = 7; - - public int SphType { get; private set; } - public int Version { get; private set; } - public int ShaderType { get; private set; } - public bool MrtEnable { get; private set; } - public bool KillsPixels { get; private set; } - public bool DoesGlobalStore { get; private set; } - public int SassVersion { get; private set; } - public bool DoesLoadOrStore { get; private set; } - public bool DoesFp64 { get; private set; } - public int StreamOutMask { get; private set; } - - public int ShaderLocalMemoryLowSize { get; private set; } - public int PerPatchAttributeCount { get; private set; } - - public int ShaderLocalMemoryHighSize { get; private set; } - public int ThreadsPerInputPrimitive { get; private set; } - - public int ShaderLocalMemoryCrsSize { get; private set; } - public int OutputTopology { get; private set; } - - public int MaxOutputVertexCount { get; private set; } - public int StoreReqStart { get; private set; } - public int StoreReqEnd { get; private set; } - - public OmapTarget[] OmapTargets { get; private set; } - public bool OmapSampleMask { get; private set; } - public bool OmapDepth { get; private set; } - - public ShaderHeader(IGalMemory memory, long position) - { - uint commonWord0 = (uint)memory.ReadInt32(position + 0); - uint commonWord1 = (uint)memory.ReadInt32(position + 4); - uint commonWord2 = (uint)memory.ReadInt32(position + 8); - uint commonWord3 = (uint)memory.ReadInt32(position + 12); - uint commonWord4 = (uint)memory.ReadInt32(position + 16); - - SphType = ReadBits(commonWord0, 0, 5); - Version = ReadBits(commonWord0, 5, 5); - ShaderType = ReadBits(commonWord0, 10, 4); - MrtEnable = ReadBits(commonWord0, 14, 1) != 0; - KillsPixels = ReadBits(commonWord0, 15, 1) != 0; - DoesGlobalStore = ReadBits(commonWord0, 16, 1) != 0; - SassVersion = ReadBits(commonWord0, 17, 4); - DoesLoadOrStore = ReadBits(commonWord0, 26, 1) != 0; - DoesFp64 = ReadBits(commonWord0, 27, 1) != 0; - StreamOutMask = ReadBits(commonWord0, 28, 4); - - ShaderLocalMemoryLowSize = ReadBits(commonWord1, 0, 24); - PerPatchAttributeCount = ReadBits(commonWord1, 24, 8); - - ShaderLocalMemoryHighSize = ReadBits(commonWord2, 0, 24); - ThreadsPerInputPrimitive = ReadBits(commonWord2, 24, 8); - - ShaderLocalMemoryCrsSize = ReadBits(commonWord3, 0, 24); - OutputTopology = ReadBits(commonWord3, 24, 4); - - MaxOutputVertexCount = ReadBits(commonWord4, 0, 12); - StoreReqStart = ReadBits(commonWord4, 12, 8); - StoreReqEnd = ReadBits(commonWord4, 24, 8); - - //Type 2 (fragment?) reading - uint type2OmapTarget = (uint)memory.ReadInt32(position + 72); - uint type2Omap = (uint)memory.ReadInt32(position + 76); - - OmapTargets = new OmapTarget[8]; - - for (int i = 0; i < OmapTargets.Length; i++) - { - int offset = i * 4; - - OmapTargets[i] = new OmapTarget - { - Red = ReadBits(type2OmapTarget, offset + 0, 1) != 0, - Green = ReadBits(type2OmapTarget, offset + 1, 1) != 0, - Blue = ReadBits(type2OmapTarget, offset + 2, 1) != 0, - Alpha = ReadBits(type2OmapTarget, offset + 3, 1) != 0 - }; - } - - OmapSampleMask = ReadBits(type2Omap, 0, 1) != 0; - OmapDepth = ReadBits(type2Omap, 1, 1) != 0; - } - - public int DepthRegister - { - get - { - int count = 0; - - for (int index = 0; index < OmapTargets.Length; index++) - { - for (int component = 0; component < 4; component++) - { - if (OmapTargets[index].ComponentEnabled(component)) - { - count++; - } - } - } - - // Depth register is always two registers after the last color output - return count + 1; - } - } - - private static int ReadBits(uint word, int offset, int bitWidth) - { - uint mask = (1u << bitWidth) - 1u; - - return (int)((word >> offset) & mask); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIpaMode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIpaMode.cs deleted file mode 100644 index b3713fa483..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIpaMode.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - enum ShaderIpaMode - { - Pass = 0, - None = 1, - Constant = 2, - Sc = 3 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrAsg.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrAsg.cs deleted file mode 100644 index 53871a1451..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrAsg.cs +++ /dev/null @@ -1,14 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrAsg : ShaderIrNode - { - public ShaderIrNode Dst { get; set; } - public ShaderIrNode Src { get; set; } - - public ShaderIrAsg(ShaderIrNode dst, ShaderIrNode src) - { - Dst = dst; - Src = src; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs deleted file mode 100644 index 49257d2834..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Collections.Generic; - -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrBlock - { - public int Position { get; set; } - public int EndPosition { get; set; } - - public ShaderIrBlock Next { get; set; } - public ShaderIrBlock Branch { get; set; } - - public List Sources { get; private set; } - - public List Nodes { get; private set; } - - public ShaderIrBlock(int position) - { - Position = position; - - Sources = new List(); - - Nodes = new List(); - } - - public void AddNode(ShaderIrNode node) - { - Nodes.Add(node); - } - - public ShaderIrNode[] GetNodes() - { - return Nodes.ToArray(); - } - - public ShaderIrNode GetLastNode() - { - if (Nodes.Count > 0) - { - return Nodes[Nodes.Count - 1]; - } - - return null; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrCmnt.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrCmnt.cs deleted file mode 100644 index 5da04e5ee2..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrCmnt.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrCmnt : ShaderIrNode - { - public string Comment { get; private set; } - - public ShaderIrCmnt(string comment) - { - Comment = comment; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrCond.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrCond.cs deleted file mode 100644 index 34acf90d7e..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrCond.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrCond : ShaderIrNode - { - public ShaderIrNode Pred { get; set; } - public ShaderIrNode Child { get; set; } - - public bool Not { get; private set; } - - public ShaderIrCond(ShaderIrNode pred, ShaderIrNode child, bool not) - { - Pred = pred; - Child = child; - Not = not; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs deleted file mode 100644 index 68ff214e4e..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrInst.cs +++ /dev/null @@ -1,94 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - enum ShaderIrInst - { - Invalid, - - B_Start, - Band, - Bnot, - Bor, - Bxor, - B_End, - - F_Start, - Ceil, - - Fabs, - Fadd, - Fceq, - Fcequ, - Fcge, - Fcgeu, - Fcgt, - Fcgtu, - Fclamp, - Fcle, - Fcleu, - Fclt, - Fcltu, - Fcnan, - Fcne, - Fcneu, - Fcnum, - Fcos, - Fex2, - Ffma, - Flg2, - Floor, - Fmax, - Fmin, - Fmul, - Fneg, - Frcp, - Frsq, - Fsin, - Fsqrt, - Ftos, - Ftou, - Ipa, - Texb, - Texs, - Tld4, - Trunc, - F_End, - - I_Start, - Abs, - Add, - And, - Asr, - Ceq, - Cge, - Cgt, - Clamps, - Clampu, - Cle, - Clt, - Cne, - Lsl, - Lsr, - Max, - Min, - Mul, - Neg, - Not, - Or, - Stof, - Sub, - Texq, - Txlf, - Utof, - Xor, - I_End, - - Bra, - Exit, - Kil, - Ssy, - Sync, - - Emit, - Cut - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMeta.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMeta.cs deleted file mode 100644 index afb7503be8..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMeta.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrMeta { } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaIpa.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaIpa.cs deleted file mode 100644 index 07db646757..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaIpa.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrMetaIpa : ShaderIrMeta - { - public ShaderIpaMode Mode { get; private set; } - - public ShaderIrMetaIpa(ShaderIpaMode mode) - { - Mode = mode; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs deleted file mode 100644 index e0265138c8..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTex.cs +++ /dev/null @@ -1,24 +0,0 @@ -using Ryujinx.Graphics.Texture; - -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrMetaTex : ShaderIrMeta - { - public int Elem { get; private set; } - public GalTextureTarget TextureTarget { get; private set; } - public ShaderIrNode[] Coordinates { get; private set; } - public TextureInstructionSuffix TextureInstructionSuffix { get; private set; } - public ShaderIrOperGpr LevelOfDetail; - public ShaderIrOperGpr Offset; - public ShaderIrOperGpr DepthCompare; - public int Component; // for TLD4(S) - - public ShaderIrMetaTex(int elem, GalTextureTarget textureTarget, TextureInstructionSuffix textureInstructionSuffix, params ShaderIrNode[] coordinates) - { - Elem = elem; - TextureTarget = textureTarget; - TextureInstructionSuffix = textureInstructionSuffix; - Coordinates = coordinates; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs deleted file mode 100644 index c925ea4e1a..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrMetaTexq.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrMetaTexq : ShaderIrMeta - { - public ShaderTexqInfo Info { get; private set; } - - public int Elem { get; private set; } - - public ShaderIrMetaTexq(ShaderTexqInfo info, int elem) - { - Info = info; - Elem = elem; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs deleted file mode 100644 index 2648164a11..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrNode.cs +++ /dev/null @@ -1,4 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrNode { } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOp.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOp.cs deleted file mode 100644 index c91c392653..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOp.cs +++ /dev/null @@ -1,25 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOp : ShaderIrNode - { - public ShaderIrInst Inst { get; private set; } - public ShaderIrNode OperandA { get; set; } - public ShaderIrNode OperandB { get; set; } - public ShaderIrNode OperandC { get; set; } - public ShaderIrMeta MetaData { get; set; } - - public ShaderIrOp( - ShaderIrInst inst, - ShaderIrNode operandA = null, - ShaderIrNode operandB = null, - ShaderIrNode operandC = null, - ShaderIrMeta metaData = null) - { - Inst = inst; - OperandA = operandA; - OperandB = operandB; - OperandC = operandC; - MetaData = metaData; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperAbuf.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperAbuf.cs deleted file mode 100644 index 1f339e8051..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperAbuf.cs +++ /dev/null @@ -1,15 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOperAbuf : ShaderIrNode - { - public int Offs { get; private set; } - - public ShaderIrNode Vertex { get; private set; } - - public ShaderIrOperAbuf(int offs, ShaderIrNode vertex) - { - Offs = offs; - Vertex = vertex; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperCbuf.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperCbuf.cs deleted file mode 100644 index 9f419bbbec..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperCbuf.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOperCbuf : ShaderIrNode - { - public int Index { get; private set; } - public int Pos { get; set; } - - public ShaderIrNode Offs { get; private set; } - - public ShaderIrOperCbuf(int index, int pos, ShaderIrNode offs = null) - { - Index = index; - Pos = pos; - Offs = offs; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs deleted file mode 100644 index 0d102d8978..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperGpr.cs +++ /dev/null @@ -1,36 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOperGpr : ShaderIrNode - { - public const int ZrIndex = 0xff; - - public bool IsConst => Index == ZrIndex; - - public bool IsValidRegister => (uint)Index <= ZrIndex; - - public int Index { get; set; } - public int HalfPart { get; set; } - - public ShaderRegisterSize RegisterSize { get; private set; } - - public ShaderIrOperGpr(int index) - { - Index = index; - - RegisterSize = ShaderRegisterSize.Single; - } - - public ShaderIrOperGpr(int index, int halfPart) - { - Index = index; - HalfPart = halfPart; - - RegisterSize = ShaderRegisterSize.Half; - } - - public static ShaderIrOperGpr MakeTemporary(int index = 0) - { - return new ShaderIrOperGpr(0x100 + index); - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs deleted file mode 100644 index 6b23b36574..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImm.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOperImm : ShaderIrNode - { - public int Value { get; private set; } - - public ShaderIrOperImm(int value) - { - Value = value; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs deleted file mode 100644 index 5b08c5b1c9..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperImmf.cs +++ /dev/null @@ -1,12 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOperImmf : ShaderIrNode - { - public float Value { get; private set; } - - public ShaderIrOperImmf(float value) - { - Value = value; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperPred.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrOperPred.cs deleted file mode 100644 index 6c16a145d9..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderIrOperPred.cs +++ /dev/null @@ -1,17 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - class ShaderIrOperPred : ShaderIrNode - { - public const int UnusedIndex = 0x7; - public const int NeverExecute = 0xf; - - public bool IsConst => Index >= UnusedIndex; - - public int Index { get; set; } - - public ShaderIrOperPred(int index) - { - Index = index; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs deleted file mode 100644 index 1edf91a015..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderOpCodeTable.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; - -namespace Ryujinx.Graphics.Gal.Shader -{ - static class ShaderOpCodeTable - { - private const int EncodingBits = 14; - - private class ShaderDecodeEntry - { - public ShaderDecodeFunc Func; - - public int XBits; - - public ShaderDecodeEntry(ShaderDecodeFunc func, int xBits) - { - Func = func; - XBits = xBits; - } - } - - private static ShaderDecodeEntry[] _opCodes; - - static ShaderOpCodeTable() - { - _opCodes = new ShaderDecodeEntry[1 << EncodingBits]; - -#region Instructions - Set("0100110000000x", ShaderDecode.Bfe_C); - Set("0011100x00000x", ShaderDecode.Bfe_I); - Set("0101110000000x", ShaderDecode.Bfe_R); - Set("111000100100xx", ShaderDecode.Bra); - Set("111000110000xx", ShaderDecode.Exit); - Set("0100110010101x", ShaderDecode.F2f_C); - Set("0011100x10101x", ShaderDecode.F2f_I); - Set("0101110010101x", ShaderDecode.F2f_R); - Set("0100110010110x", ShaderDecode.F2i_C); - Set("0011100x10110x", ShaderDecode.F2i_I); - Set("0101110010110x", ShaderDecode.F2i_R); - Set("0100110001011x", ShaderDecode.Fadd_C); - Set("0011100x01011x", ShaderDecode.Fadd_I); - Set("000010xxxxxxxx", ShaderDecode.Fadd_I32); - Set("0101110001011x", ShaderDecode.Fadd_R); - Set("010010011xxxxx", ShaderDecode.Ffma_CR); - Set("0011001x1xxxxx", ShaderDecode.Ffma_I); - Set("010100011xxxxx", ShaderDecode.Ffma_RC); - Set("010110011xxxxx", ShaderDecode.Ffma_RR); - Set("0100110001101x", ShaderDecode.Fmul_C); - Set("0011100x01101x", ShaderDecode.Fmul_I); - Set("00011110xxxxxx", ShaderDecode.Fmul_I32); - Set("0101110001101x", ShaderDecode.Fmul_R); - Set("0100110001100x", ShaderDecode.Fmnmx_C); - Set("0011100x01100x", ShaderDecode.Fmnmx_I); - Set("0101110001100x", ShaderDecode.Fmnmx_R); - Set("0100100xxxxxxx", ShaderDecode.Fset_C); - Set("0011000xxxxxxx", ShaderDecode.Fset_I); - Set("01011000xxxxxx", ShaderDecode.Fset_R); - Set("010010111011xx", ShaderDecode.Fsetp_C); - Set("0011011x1011xx", ShaderDecode.Fsetp_I); - Set("010110111011xx", ShaderDecode.Fsetp_R); - Set("0101110100010x", ShaderDecode.Hadd2_R); - Set("0101110100001x", ShaderDecode.Hmul2_R); - Set("0100110010111x", ShaderDecode.I2f_C); - Set("0011100x10111x", ShaderDecode.I2f_I); - Set("0101110010111x", ShaderDecode.I2f_R); - Set("0100110011100x", ShaderDecode.I2i_C); - Set("0011100x11100x", ShaderDecode.I2i_I); - Set("0101110011100x", ShaderDecode.I2i_R); - Set("0100110000010x", ShaderDecode.Iadd_C); - Set("0011100000010x", ShaderDecode.Iadd_I); - Set("0001110x0xxxxx", ShaderDecode.Iadd_I32); - Set("0101110000010x", ShaderDecode.Iadd_R); - Set("010011001100xx", ShaderDecode.Iadd3_C); - Set("001110001100xx", ShaderDecode.Iadd3_I); - Set("010111001100xx", ShaderDecode.Iadd3_R); - Set("0100110000100x", ShaderDecode.Imnmx_C); - Set("0011100x00100x", ShaderDecode.Imnmx_I); - Set("0101110000100x", ShaderDecode.Imnmx_R); - Set("1110111111010x", ShaderDecode.Isberd); - Set("11100000xxxxxx", ShaderDecode.Ipa); - Set("0100110000011x", ShaderDecode.Iscadd_C); - Set("0011100x00011x", ShaderDecode.Iscadd_I); - Set("0101110000011x", ShaderDecode.Iscadd_R); - Set("010010110101xx", ShaderDecode.Iset_C); - Set("001101100101xx", ShaderDecode.Iset_I); - Set("010110110101xx", ShaderDecode.Iset_R); - Set("010010110110xx", ShaderDecode.Isetp_C); - Set("0011011x0110xx", ShaderDecode.Isetp_I); - Set("010110110110xx", ShaderDecode.Isetp_R); - Set("111000110011xx", ShaderDecode.Kil); - Set("1110111111011x", ShaderDecode.Ld_A); - Set("1110111110010x", ShaderDecode.Ld_C); - Set("0100110001000x", ShaderDecode.Lop_C); - Set("0011100001000x", ShaderDecode.Lop_I); - Set("000001xxxxxxxx", ShaderDecode.Lop_I32); - Set("0101110001000x", ShaderDecode.Lop_R); - Set("0100110010011x", ShaderDecode.Mov_C); - Set("0011100x10011x", ShaderDecode.Mov_I); - Set("000000010000xx", ShaderDecode.Mov_I32); - Set("0101110010011x", ShaderDecode.Mov_R); - Set("1111000011001x", ShaderDecode.Mov_S); - Set("0101000010000x", ShaderDecode.Mufu); - Set("1111101111100x", ShaderDecode.Out_R); - Set("0101000010010x", ShaderDecode.Psetp); - Set("0100110010010x", ShaderDecode.Rro_C); - Set("0011100x10010x", ShaderDecode.Rro_I); - Set("0101110010010x", ShaderDecode.Rro_R); - Set("0100110010100x", ShaderDecode.Sel_C); - Set("0011100010100x", ShaderDecode.Sel_I); - Set("0101110010100x", ShaderDecode.Sel_R); - Set("0100110001001x", ShaderDecode.Shl_C); - Set("0011100x01001x", ShaderDecode.Shl_I); - Set("0101110001001x", ShaderDecode.Shl_R); - Set("0100110000101x", ShaderDecode.Shr_C); - Set("0011100x00101x", ShaderDecode.Shr_I); - Set("0101110000101x", ShaderDecode.Shr_R); - Set("111000101001xx", ShaderDecode.Ssy); - Set("1110111111110x", ShaderDecode.St_A); - Set("1111000011111x", ShaderDecode.Sync); - Set("110000xxxx111x", ShaderDecode.Tex); - Set("1101111010111x", ShaderDecode.Tex_B); - Set("1101111101001x", ShaderDecode.Texq); - Set("1101x00xxxxxxx", ShaderDecode.Texs); - Set("1101101xxxxxxx", ShaderDecode.Tlds); - Set("110010xxxx111x", ShaderDecode.Tld4); - Set("1101111100xxxx", ShaderDecode.Tld4S); - Set("01011111xxxxxx", ShaderDecode.Vmad); - Set("0100111xxxxxxx", ShaderDecode.Xmad_CR); - Set("0011011x00xxxx", ShaderDecode.Xmad_I); - Set("010100010xxxxx", ShaderDecode.Xmad_RC); - Set("0101101100xxxx", ShaderDecode.Xmad_RR); -#endregion - } - - private static void Set(string encoding, ShaderDecodeFunc func) - { - if (encoding.Length != EncodingBits) - { - throw new ArgumentException(nameof(encoding)); - } - - int bit = encoding.Length - 1; - int value = 0; - int xMask = 0; - int xBits = 0; - - int[] xPos = new int[encoding.Length]; - - for (int index = 0; index < encoding.Length; index++, bit--) - { - char chr = encoding[index]; - - if (chr == '1') - { - value |= 1 << bit; - } - else if (chr == 'x') - { - xMask |= 1 << bit; - - xPos[xBits++] = bit; - } - } - - xMask = ~xMask; - - ShaderDecodeEntry entry = new ShaderDecodeEntry(func, xBits); - - for (int index = 0; index < (1 << xBits); index++) - { - value &= xMask; - - for (int x = 0; x < xBits; x++) - { - value |= ((index >> x) & 1) << xPos[x]; - } - - if (_opCodes[value] == null || _opCodes[value].XBits > xBits) - { - _opCodes[value] = entry; - } - } - } - - public static ShaderDecodeFunc GetDecoder(long opCode) - { - return _opCodes[(ulong)opCode >> (64 - EncodingBits)]?.Func; - } - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderOper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderOper.cs deleted file mode 100644 index 22a2ab85cd..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderOper.cs +++ /dev/null @@ -1,11 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - enum ShaderOper - { - Cr, - Imm, - Immf, - Rc, - Rr - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderRegisterSize.cs b/Ryujinx.Graphics/Gal/Shader/ShaderRegisterSize.cs deleted file mode 100644 index eb37359bf4..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderRegisterSize.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - enum ShaderRegisterSize - { - Half, - Single, - Double - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderTexqInfo.cs b/Ryujinx.Graphics/Gal/Shader/ShaderTexqInfo.cs deleted file mode 100644 index 9158662ccd..0000000000 --- a/Ryujinx.Graphics/Gal/Shader/ShaderTexqInfo.cs +++ /dev/null @@ -1,13 +0,0 @@ -namespace Ryujinx.Graphics.Gal.Shader -{ - enum ShaderTexqInfo - { - Dimension = 1, - TextureType = 2, - SamplePos = 5, - Filter = 16, - Lod = 18, - Wrap = 20, - BorderColor = 22 - } -} \ No newline at end of file diff --git a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs index ecc5894508..bbed642b82 100644 --- a/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/Graphics3d/NvGpuEngine3d.cs @@ -1,6 +1,7 @@ using Ryujinx.Common; using Ryujinx.Graphics.Gal; using Ryujinx.Graphics.Memory; +using Ryujinx.Graphics.Shader; using Ryujinx.Graphics.Texture; using System; using System.Collections.Generic; @@ -626,20 +627,22 @@ namespace Ryujinx.Graphics.Graphics3d for (int index = 0; index < keys.Length; index++) { - foreach (ShaderDeclInfo declInfo in _gpu.Renderer.Shader.GetTextureUsage(keys[index])) + foreach (TextureDescriptor desc in _gpu.Renderer.Shader.GetTextureUsage(keys[index])) { - long position; + int textureHandle; - if (declInfo.IsCb) + if (desc.IsBindless) { - position = _constBuffers[index][declInfo.Cbuf].Position; + long position = _constBuffers[index][desc.CbufSlot].Position; + + textureHandle = vmm.ReadInt32(position + desc.CbufOffset * 4); } else { - position = _constBuffers[index][textureCbIndex].Position; - } + long position = _constBuffers[index][textureCbIndex].Position; - int textureHandle = vmm.ReadInt32(position + declInfo.Index * 4); + textureHandle = vmm.ReadInt32(position + desc.HandleIndex * 4); + } unboundTextures.Add(UploadTexture(vmm, textureHandle)); } @@ -712,9 +715,9 @@ namespace Ryujinx.Graphics.Graphics3d { for (int stage = 0; stage < keys.Length; stage++) { - foreach (ShaderDeclInfo declInfo in _gpu.Renderer.Shader.GetConstBufferUsage(keys[stage])) + foreach (CBufferDescriptor desc in _gpu.Renderer.Shader.GetConstBufferUsage(keys[stage])) { - ConstBuffer cb = _constBuffers[stage][declInfo.Cbuf]; + ConstBuffer cb = _constBuffers[stage][desc.Slot]; if (!cb.Enabled) { @@ -735,7 +738,7 @@ namespace Ryujinx.Graphics.Graphics3d } } - state.ConstBufferKeys[stage][declInfo.Cbuf] = key; + state.ConstBufferKeys[stage][desc.Slot] = key; } } } diff --git a/Ryujinx.Graphics/Shader/CBufferDescriptor.cs b/Ryujinx.Graphics/Shader/CBufferDescriptor.cs new file mode 100644 index 0000000000..f99665e162 --- /dev/null +++ b/Ryujinx.Graphics/Shader/CBufferDescriptor.cs @@ -0,0 +1,15 @@ +namespace Ryujinx.Graphics.Shader +{ + public struct CBufferDescriptor + { + public string Name { get; } + + public int Slot { get; } + + public CBufferDescriptor(string name, int slot) + { + Name = name; + Slot = slot; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/CodeGen/Glsl/CodeGenContext.cs b/Ryujinx.Graphics/Shader/CodeGen/Glsl/CodeGenContext.cs index 8c095b772b..9e849bccee 100644 --- a/Ryujinx.Graphics/Shader/CodeGen/Glsl/CodeGenContext.cs +++ b/Ryujinx.Graphics/Shader/CodeGen/Glsl/CodeGenContext.cs @@ -9,10 +9,11 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { private const string Tab = " "; - public StructuredProgramInfo Info { get; } - public GalShaderType ShaderType { get; } + public List CBufferDescriptors { get; } + public List TextureDescriptors { get; } + private StringBuilder _sb; private Dictionary _locals; @@ -21,11 +22,13 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl private string _identation; - public CodeGenContext(StructuredProgramInfo info, GalShaderType shaderType) + public CodeGenContext(GalShaderType shaderType) { - Info = info; ShaderType = shaderType; + CBufferDescriptors = new List(); + TextureDescriptors = new List(); + _sb = new StringBuilder(); _locals = new Dictionary(); diff --git a/Ryujinx.Graphics/Shader/CodeGen/Glsl/Declarations.cs b/Ryujinx.Graphics/Shader/CodeGen/Glsl/Declarations.cs index 85df7384e6..e80da36bb7 100644 --- a/Ryujinx.Graphics/Shader/CodeGen/Glsl/Declarations.cs +++ b/Ryujinx.Graphics/Shader/CodeGen/Glsl/Declarations.cs @@ -9,7 +9,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { static class Declarations { - public static void Declare(CodeGenContext context, StructuredProgramInfo prgInfo) + public static void Declare(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("#version 420 core"); @@ -38,38 +38,38 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine(); - if (prgInfo.ConstantBuffers.Count != 0) + if (info.CBuffers.Count != 0) { - DeclareUniforms(context, prgInfo); + DeclareUniforms(context, info); context.AppendLine(); } - if (prgInfo.Samplers.Count != 0) + if (info.Samplers.Count != 0) { - DeclareSamplers(context, prgInfo); + DeclareSamplers(context, info); context.AppendLine(); } - if (prgInfo.IAttributes.Count != 0) + if (info.IAttributes.Count != 0) { - DeclareInputAttributes(context, prgInfo); + DeclareInputAttributes(context, info); context.AppendLine(); } - if (prgInfo.OAttributes.Count != 0) + if (info.OAttributes.Count != 0) { - DeclareOutputAttributes(context, prgInfo); + DeclareOutputAttributes(context, info); context.AppendLine(); } } - public static void DeclareLocals(CodeGenContext context, StructuredProgramInfo prgInfo) + public static void DeclareLocals(CodeGenContext context, StructuredProgramInfo info) { - foreach (AstOperand decl in prgInfo.Locals) + foreach (AstOperand decl in info.Locals) { string name = context.DeclareLocal(decl); @@ -90,14 +90,16 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl throw new ArgumentException($"Invalid variable type \"{type}\"."); } - private static void DeclareUniforms(CodeGenContext context, StructuredProgramInfo prgInfo) + private static void DeclareUniforms(CodeGenContext context, StructuredProgramInfo info) { - foreach (int cbufSlot in prgInfo.ConstantBuffers.OrderBy(x => x)) + foreach (int cbufSlot in info.CBuffers.OrderBy(x => x)) { string ubName = OperandManager.GetShaderStagePrefix(context.ShaderType); ubName += "_" + DefaultNames.UniformNamePrefix + cbufSlot; + context.CBufferDescriptors.Add(new CBufferDescriptor(ubName, cbufSlot)); + context.AppendLine("layout (std140) uniform " + ubName); context.EnterScope(); @@ -108,15 +110,15 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl } } - private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo prgInfo) + private static void DeclareSamplers(CodeGenContext context, StructuredProgramInfo info) { - HashSet samplerNames = new HashSet(); + Dictionary samplers = new Dictionary(); - foreach (AstTextureOperation texOp in prgInfo.Samplers.OrderBy(x => x.Handle)) + foreach (AstTextureOperation texOp in info.Samplers.OrderBy(x => x.Handle)) { string samplerName = OperandManager.GetSamplerName(context.ShaderType, texOp); - if (!samplerNames.Add(samplerName)) + if (!samplers.TryAdd(samplerName, texOp)) { continue; } @@ -125,21 +127,43 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.AppendLine("uniform " + samplerTypeName + " " + samplerName + ";"); } + + foreach (KeyValuePair kv in samplers) + { + string samplerName = kv.Key; + + AstTextureOperation texOp = kv.Value; + + TextureDescriptor desc; + + if ((texOp.Flags & TextureFlags.Bindless) != 0) + { + AstOperand operand = texOp.GetSource(0) as AstOperand; + + desc = new TextureDescriptor(samplerName, operand.CbufSlot, operand.CbufOffset); + } + else + { + desc = new TextureDescriptor(samplerName, texOp.Handle); + } + + context.TextureDescriptors.Add(desc); + } } - private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo prgInfo) + private static void DeclareInputAttributes(CodeGenContext context, StructuredProgramInfo info) { string suffix = context.ShaderType == GalShaderType.Geometry ? "[]" : string.Empty; - foreach (int attr in prgInfo.IAttributes.OrderBy(x => x)) + foreach (int attr in info.IAttributes.OrderBy(x => x)) { context.AppendLine($"layout (location = {attr}) in vec4 {DefaultNames.IAttributePrefix}{attr}{suffix};"); } } - private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo prgInfo) + private static void DeclareOutputAttributes(CodeGenContext context, StructuredProgramInfo info) { - foreach (int attr in prgInfo.OAttributes.OrderBy(x => x)) + foreach (int attr in info.OAttributes.OrderBy(x => x)) { context.AppendLine($"layout (location = {attr}) out vec4 {DefaultNames.OAttributePrefix}{attr};"); } diff --git a/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs index e19f674b00..89672f6cfe 100644 --- a/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs +++ b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslGenerator.cs @@ -8,20 +8,23 @@ using static Ryujinx.Graphics.Shader.CodeGen.Glsl.TypeConversion; namespace Ryujinx.Graphics.Shader.CodeGen.Glsl { - class GlslGenerator + static class GlslGenerator { - public string Generate(StructuredProgramInfo info, GalShaderType shaderType) + public static GlslProgram Generate(StructuredProgramInfo info, GalShaderType shaderType) { - CodeGenContext context = new CodeGenContext(info, shaderType); + CodeGenContext context = new CodeGenContext(shaderType); Declarations.Declare(context, info); PrintMainBlock(context, info); - return context.GetCode(); + return new GlslProgram( + context.CBufferDescriptors.ToArray(), + context.TextureDescriptors.ToArray(), + context.GetCode()); } - private void PrintMainBlock(CodeGenContext context, StructuredProgramInfo info) + private static void PrintMainBlock(CodeGenContext context, StructuredProgramInfo info) { context.AppendLine("void main()"); @@ -34,7 +37,7 @@ namespace Ryujinx.Graphics.Shader.CodeGen.Glsl context.LeaveScope(); } - private void PrintBlock(CodeGenContext context, AstBlock block) + private static void PrintBlock(CodeGenContext context, AstBlock block) { AstBlockVisitor visitor = new AstBlockVisitor(block); diff --git a/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslProgram.cs b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslProgram.cs new file mode 100644 index 0000000000..e616aa1f81 --- /dev/null +++ b/Ryujinx.Graphics/Shader/CodeGen/Glsl/GlslProgram.cs @@ -0,0 +1,20 @@ +namespace Ryujinx.Graphics.Shader.CodeGen.Glsl +{ + class GlslProgram + { + public CBufferDescriptor[] CBufferDescriptors { get; } + public TextureDescriptor[] TextureDescriptors { get; } + + public string Code { get; } + + public GlslProgram( + CBufferDescriptor[] cBufferDescs, + TextureDescriptor[] textureDescs, + string code) + { + CBufferDescriptors = cBufferDescs; + TextureDescriptors = textureDescs; + Code = code; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/ShaderProgram.cs b/Ryujinx.Graphics/Shader/ShaderProgram.cs new file mode 100644 index 0000000000..9257fd262d --- /dev/null +++ b/Ryujinx.Graphics/Shader/ShaderProgram.cs @@ -0,0 +1,15 @@ +namespace Ryujinx.Graphics.Shader +{ + public class ShaderProgram + { + public ShaderProgramInfo Info { get; } + + public string Code { get; } + + internal ShaderProgram(ShaderProgramInfo info, string code) + { + Info = info; + Code = code; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/ShaderProgramInfo.cs b/Ryujinx.Graphics/Shader/ShaderProgramInfo.cs new file mode 100644 index 0000000000..c529a3536f --- /dev/null +++ b/Ryujinx.Graphics/Shader/ShaderProgramInfo.cs @@ -0,0 +1,17 @@ +using System; +using System.Collections.ObjectModel; + +namespace Ryujinx.Graphics.Shader +{ + public class ShaderProgramInfo + { + public ReadOnlyCollection CBuffers { get; } + public ReadOnlyCollection Textures { get; } + + internal ShaderProgramInfo(CBufferDescriptor[] cBuffers, TextureDescriptor[] textures) + { + CBuffers = Array.AsReadOnly(cBuffers); + Textures = Array.AsReadOnly(textures); + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs index 7a5bdac0c9..f65631be7c 100644 --- a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs +++ b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgram.cs @@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr throw new InvalidOperationException("Found LDC with non-constant constant buffer slot."); } - context.Info.ConstantBuffers.Add(ldcSource.Value); + context.Info.CBuffers.Add(ldcSource.Value); } AstAssignment assignment; diff --git a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs index 0cf438c396..e1f0503a57 100644 --- a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs +++ b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramContext.cs @@ -234,7 +234,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr } else if (operand.Type == OperandType.ConstantBuffer) { - Info.ConstantBuffers.Add(operand.GetCbufSlot()); + Info.CBuffers.Add(operand.GetCbufSlot()); } return GetOperand(operand); diff --git a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs index 203d39ea6b..d368ef0058 100644 --- a/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs +++ b/Ryujinx.Graphics/Shader/StructuredIr/StructuredProgramInfo.cs @@ -8,13 +8,11 @@ namespace Ryujinx.Graphics.Shader.StructuredIr public HashSet Locals { get; } - public HashSet ConstantBuffers { get; } + public HashSet CBuffers { get; } public HashSet IAttributes { get; } public HashSet OAttributes { get; } - private HashSet _textureHandles; - public HashSet Samplers { get; } public StructuredProgramInfo(AstBlock mainBlock) @@ -23,7 +21,7 @@ namespace Ryujinx.Graphics.Shader.StructuredIr Locals = new HashSet(); - ConstantBuffers = new HashSet(); + CBuffers = new HashSet(); IAttributes = new HashSet(); OAttributes = new HashSet(); diff --git a/Ryujinx.Graphics/Shader/TextureDescriptor.cs b/Ryujinx.Graphics/Shader/TextureDescriptor.cs new file mode 100644 index 0000000000..96f0f5b16d --- /dev/null +++ b/Ryujinx.Graphics/Shader/TextureDescriptor.cs @@ -0,0 +1,36 @@ +namespace Ryujinx.Graphics.Shader +{ + public struct TextureDescriptor + { + public string Name { get; } + + public int HandleIndex { get; } + + public bool IsBindless { get; } + + public int CbufSlot { get; } + public int CbufOffset { get; } + + public TextureDescriptor(string name, int hIndex) + { + Name = name; + HandleIndex = hIndex; + + IsBindless = false; + + CbufSlot = 0; + CbufOffset = 0; + } + + public TextureDescriptor(string name, int cbufSlot, int cbufOffset) + { + Name = name; + HandleIndex = 0; + + IsBindless = true; + + CbufSlot = cbufSlot; + CbufOffset = cbufOffset; + } + } +} \ No newline at end of file diff --git a/Ryujinx.Graphics/Shader/Translation/Translator.cs b/Ryujinx.Graphics/Shader/Translation/Translator.cs index c73c93f0e4..ca20ca2be0 100644 --- a/Ryujinx.Graphics/Shader/Translation/Translator.cs +++ b/Ryujinx.Graphics/Shader/Translation/Translator.cs @@ -12,7 +12,7 @@ namespace Ryujinx.Graphics.Shader.Translation { public static class Translator { - public static string Translate(IGalMemory memory, ulong address, GalShaderType shaderType) + public static ShaderProgram Translate(IGalMemory memory, ulong address, GalShaderType shaderType) { ShaderHeader header = new ShaderHeader(memory, address); @@ -98,13 +98,15 @@ namespace Ryujinx.Graphics.Shader.Translation Optimizer.Optimize(irBlocks); - StructuredProgramInfo prgInfo = StructuredProgram.MakeStructuredProgram(irBlocks); + StructuredProgramInfo sInfo = StructuredProgram.MakeStructuredProgram(irBlocks); - GlslGenerator generator = new GlslGenerator(); + GlslProgram program = GlslGenerator.Generate(sInfo, shaderType); - string glslProgram = generator.Generate(prgInfo, shaderType); + ShaderProgramInfo spInfo = new ShaderProgramInfo( + program.CBufferDescriptors, + program.TextureDescriptors); - return glslProgram; + return new ShaderProgram(spInfo, program.Code); } } } \ No newline at end of file diff --git a/Ryujinx.ShaderTools/Memory.cs b/Ryujinx.ShaderTools/Memory.cs index f801ab39a9..c99224b5ed 100644 --- a/Ryujinx.ShaderTools/Memory.cs +++ b/Ryujinx.ShaderTools/Memory.cs @@ -23,4 +23,4 @@ namespace Ryujinx.ShaderTools return Reader.ReadInt32(); } } -} +} \ No newline at end of file diff --git a/Ryujinx.ShaderTools/Program.cs b/Ryujinx.ShaderTools/Program.cs index 1b10613d81..56b647b10c 100644 --- a/Ryujinx.ShaderTools/Program.cs +++ b/Ryujinx.ShaderTools/Program.cs @@ -7,36 +7,28 @@ namespace Ryujinx.ShaderTools { class Program { - private static readonly int MaxUboSize = 65536; - static void Main(string[] args) { if (args.Length == 2) { - //GlslDecompiler Decompiler = new GlslDecompiler(MaxUboSize); - - GalShaderType ShaderType = GalShaderType.Vertex; + GalShaderType type = GalShaderType.Vertex; switch (args[0].ToLower()) { - case "v": ShaderType = GalShaderType.Vertex; break; - case "tc": ShaderType = GalShaderType.TessControl; break; - case "te": ShaderType = GalShaderType.TessEvaluation; break; - case "g": ShaderType = GalShaderType.Geometry; break; - case "f": ShaderType = GalShaderType.Fragment; break; + case "v": type = GalShaderType.Vertex; break; + case "tc": type = GalShaderType.TessControl; break; + case "te": type = GalShaderType.TessEvaluation; break; + case "g": type = GalShaderType.Geometry; break; + case "f": type = GalShaderType.Fragment; break; } - using (FileStream FS = new FileStream(args[1], FileMode.Open, FileAccess.Read)) + using (FileStream fs = new FileStream(args[1], FileMode.Open, FileAccess.Read)) { - Memory Mem = new Memory(FS); + Memory mem = new Memory(fs); - string code = Translator.Translate(Mem, 0, ShaderType); + string code = Translator.Translate(mem, 0, type).Code; Console.WriteLine(code); - - //GlslProgram Program = Decompiler.Decompile(Mem, 0, ShaderType); - - //Console.WriteLine(Program.Code); } } else @@ -45,4 +37,4 @@ namespace Ryujinx.ShaderTools } } } -} +} \ No newline at end of file