aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs')
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs1679
1 files changed, 0 insertions, 1679 deletions
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
deleted file mode 100644
index 228a9018..00000000
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ /dev/null
@@ -1,1679 +0,0 @@
-using OpenTK.Graphics.OpenGL;
-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<ShaderIrInst, GetInstExpr> _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, GetInstExpr>()
- {
- { 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();
- }
-
- 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);
-
- 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 = _sb.ToString();
-
- List<ShaderDeclInfo> textureInfo = new List<ShaderDeclInfo>();
-
- 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<ShaderDeclInfo> IterateCbTextures()
- {
- HashSet<string> names = new HashSet<string>();
-
- 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<ShaderDeclInfo> 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<int, ShaderDeclInfo> 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<int, ShaderDeclInfo> 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<int, ShaderDeclInfo> 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<int, ShaderDeclInfo> 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";
- }
- }
- }
-}