Пример #1
0
            public string ToDeclarationalGlsl(GlslBuilderContext context, List <ParamEntry> parms)
            {
                var sb = new StringBuilder();



                switch (Instruction)
                {
                case "dcl":
                    if (context.HasBeenSeen(WithoutSwizzle(Arguments[0])))
                    {
                        return(sb.ToString());
                    }

                    var declType = Modifier != null && declarationTypes.ContainsKey(Modifier) ? declarationTypes[Modifier] : "vec4";

                    if (Modifier == "2d" || Modifier == "volume" || Modifier == "cube")
                    {
                        sb.AppendLine($"uniform {declarationTypes[Modifier]} {WithoutSwizzle(Arguments[0])};");
                    }
                    else
                    {
                        sb.AppendLine($"in {declType} {WithoutSwizzle(Arguments[0])};");
                    }

                    context.VariableTypes[WithoutSwizzle(Arguments[0])] = declType;
                    break;

                case "def":
                    if (context.HasBeenSeen(WithoutSwizzle(Arguments[0])))
                    {
                        return(sb.ToString());
                    }

                    sb.AppendLine($"vec4 {Arguments[0]} = vec4({Arguments[1]}, {Arguments[2]}, {Arguments[3]}, {Arguments[4]});");
                    context.VariableTypes[Arguments[0]] = "vec4";
                    break;
                }

                return(sb.ToString());
            }
Пример #2
0
            public string ToExecutableGlsl(GlslBuilderContext context)
            {
                var sb = new StringBuilder();

                switch (Instruction)
                {
                case "def":
                case "dcl":
                    break;

                case "abs":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = abs({Arguments[1]});");
                    break;

                case "add":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} + {Arguments[2]}){ResolveSwizzleForDest(0, 1, 2)};");
                    break;

                case "break":
                    if (Modifier == null)
                    {
                        sb.AppendLine($"{Ind()}break; //" + Original);
                    }
                    else
                    {
                        sb.AppendLine($"{Ind()}if (!({Arguments[0]} {comparisons[Modifier]} {Arguments[1]})) {{ break; }} //" + Original);
                    }
                    break;

                case "breakp":
                    sb.AppendLine($"{Ind()}if ({Arguments[0]}) {{ break; }} //" + Original);
                    break;

                case "call":
                    sb.AppendLine($"{Ind()}{Arguments[0]}();");
                    break;

                case "callnz":
                    sb.AppendLine($"{Ind()}if ({Arguments[1]}) {{ {Arguments[0]}(); }}");
                    break;

                case "cmp":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} > 0) ? {Arguments[2]} : {Arguments[3]};");
                    break;

                case "cnd":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} > 0.5) ? {Arguments[2]} : {Arguments[3]};");
                    break;

                case "crs":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = cross({Arguments[1]}, {Arguments[2]});");
                    break;

                case "dp2add":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = dot({Arguments[1]}, {Arguments[2]}) + {Arguments[3]};");
                    break;

                case "dp3":
                case "dp4":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = dot({Arguments[1]}, {Arguments[2]});");
                    break;

                case "dsx":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = dFdx({Arguments[1]});");
                    break;

                case "dsy":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = dFdy({Arguments[1]});");
                    break;

                case "else":
                    sb.AppendLine($"{Ind()}\r\nelse {{");
                    break;

                case "endloop":
                    sb.AppendLine("aL++;");
                    goto case "endif";

                case "endrep":
                case "endif":
                    context.IndentLevel--;
                    sb.AppendLine($"{Ind()}}}");
                    break;

                case "exp":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = exp({Arguments[1]}){ResolveSwizzleForDest(0, 1)};");
                    break;

                case "frc":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = fract({Arguments[1]}){ResolveSwizzleForDest(0, 1)};");
                    break;

                case "if":
                    if (Modifier == null)
                    {
                        sb.AppendLine($"if ({Arguments[0]}) //" + Original);
                    }
                    else
                    {
                        sb.AppendLine($"if ({Arguments[0]} {comparisons[Modifier]} {Arguments[1]}) //" + Original);
                    }
                    sb.AppendLine("{");
                    context.IndentLevel++;
                    break;

                case "label":
                    sb.AppendLine($"{Ind()}{Arguments[0]}() //" + Original);
                    sb.AppendLine("{");
                    context.IndentLevel++;
                    break;

                case "loop":
                    sb.AppendLine($"{Ind()}while({Arguments[0]} < {Arguments[1]}) //" + Original);
                    sb.AppendLine("{");
                    context.IndentLevel++;
                    break;

                case "log":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = log({Arguments[1]});");
                    break;

                case "lrp":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = mix({Arguments[2]}, {Arguments[3]}, {Arguments[1]});");
                    break;

                case "mul":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} * {Arguments[2]}){ResolveSwizzleForDest(0, 1, 2)};");
                    break;

                case "m3x2":
                case "m3x3":
                case "m3x4":
                case "m4x3":
                case "m4x4":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} * {Arguments[2]});");
                    break;

                case "mad":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} * {Arguments[2]} + {Arguments[3]}){ResolveSwizzleForDest(0, 1, 2, 3)};");
                    break;

                case "max":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = max({Arguments[1]}, {Arguments[2]});");
                    break;

                case "min":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = min({Arguments[1]}, {Arguments[2]});");
                    break;

                case "mov":
                    if (Modifier == "sat")
                    {
                        sb.AppendLine($"{Ind()}{DestArg(0)} = clamp({Arguments[1]}, 0.0, 1.0){ResolveSwizzleForDest(0, 1)};");
                    }
                    else
                    {
                        sb.AppendLine($"{Ind()}{DestArg(0)} = {Arguments[1]}{ResolveSwizzleForDest(0,1)};");
                    }
                    break;

                case "nop":
                    break;

                case "nrm":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = normalize({Arguments[1]});");
                    break;

                case "pow":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = pow({Arguments[1]}, {Arguments[2]});");
                    break;

                case "ps":
                    sb.AppendLine($"//" + Original);
                    break;

                case "rcp":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = (1 / {Arguments[1]}); //" + Original);
                    break;

                case "rep":
                    var lchar = context.GetNewLoopVar();
                    sb.AppendLine($"{Ind()}for(int {lchar} = 0; {lchar} < {Arguments[0]}; {lchar}++) //" + Original);
                    sb.AppendLine("{");
                    context.IndentLevel++;
                    break;

                case "ret":
                    sb.AppendLine($"return;");
                    context.IndentLevel--;
                    sb.AppendLine("}");
                    break;

                case "rsq":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = inversesqrt({Arguments[1]});");
                    break;

                case "sincos":
                    var swiz = GetArgSwizzle(Arguments[0]);

                    if (swiz[0] == 'x')
                    {
                        sb.AppendLine($"{Ind()}{DestArg(0)} = cos({Arguments[1]}); //" + Original);
                    }

                    if (swiz[swiz.Length - 1] == 'y')
                    {
                        sb.AppendLine($"{Ind()}{DestArg(0)} = sin({Arguments[1]}); //" + Original);
                    }

                    break;

                case "sub":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = ({Arguments[1]} - {Arguments[2]}){ResolveSwizzleForDest(0, 1, 2)};");
                    break;

                case "texld":
                case "texldp":
                case "texldb":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = texture({Arguments[2]}, {Arguments[1]}{TexArgSwizzle(2)});");
                    break;

                case "texkill":
                    sb.AppendLine($"{Ind()}if ({Arguments[0]} < 0) {{ discard; }}");
                    break;

                case "texldd":
                    sb.AppendLine($"{Ind()}{DestArg(0)} = texldd({Arguments[1]}); //" + Original);
                    break;

                default:
                    sb.AppendLine("//asm\r\n" + Original + "\r\n");
                    break;
                }

                var code = sb.ToString();

                return(code);

                string TexArgSwizzle(int index)
                {
                    var t = context.VariableTypes[Arguments[index]];

                    switch (t)
                    {
                    case "sampler2D":
                        return(".xy");

                    default:
                        return(".xyz");
                    }
                }

                int GetLargestSwizzle(params int[] indicies)
                {
                    int max = 0;

                    foreach (var i in indicies)
                    {
                        max = Math.Max((GetArgSwizzle(Arguments[i]) ?? "xyzw").Length, max);
                    }

                    return(max);
                }

                string DestArg(int index)
                {
                    var seen = context.HasBeenSeen(WithoutSwizzle(Arguments[index]));

                    if (seen == false)
                    {
                        return($"\r\n{Ind()}vec4 {WithoutSwizzle(Arguments[index])};\r\n{Ind()}{Arguments[index]}");
                    }
                    else
                    {
                        return(Arguments[index]);
                    }
                }

                string ResolveSwizzleForDest(int dest, params int[] args)
                {
                    var destSwizzleLength = (DestArgSwizzle(dest)?.Length ?? 1) - 1;

                    return(GetLargestSwizzle(args) == destSwizzleLength ? "" : DestArgSwizzle(dest));
                }

                string DestArgSwizzle(int index)
                {
                    var sw = GetArgSwizzle(Arguments[index]);

                    if (sw != null)
                    {
                        sw = "." + sw;
                    }

                    return(sw);
                }

                string Ind()
                {
                    return(string.Join("", Enumerable.Repeat(" ", context.IndentLevel * context.IndentSpaces)));
                }
            }
Пример #3
0
        public static string TranslateAsmShaderToPseudocode(string shaderAsm)
        {
            var paramStart     = Math.Max(shaderAsm.IndexOf("//\r\n//\r\n"), 0);
            var registersStart = Math.Max(shaderAsm.IndexOf("//\r\n//\r\n", paramStart + 2), 0);
            var codeStart      = Math.Max(shaderAsm.IndexOf("//\r\n\r\n", registersStart + 2), 0);

            var paramLines    = ParamPattern.Matches(shaderAsm.Substring(paramStart, registersStart - paramStart));
            var registerLines = RegisterPattern.Matches(shaderAsm.Substring(registersStart, codeStart - registersStart));
            var codeLines     = CodeLinePattern.Matches(shaderAsm.Substring(codeStart));

            var parms = new List <ParamEntry>();
            var regs  = new List <RegisterEntry>();
            var ops   = new List <Operation>();

            foreach (Match p in paramLines)
            {
                parms.Add(ParamEntry.CreateFromGroup(p.Groups));
            }

            foreach (Match r in registerLines)
            {
                regs.Add(RegisterEntry.CreateFromGroup(r.Groups));
            }

            foreach (Match r in codeLines)
            {
                ops.Add(Operation.CreateFromString(r.Groups[1].Value));
            }

            //parms.Dump();
            //regs.Dump();
            //ops.Dump();


            // TODO: Decls and defs

            var pseudo  = new StringBuilder();
            var context = new GlslBuilderContext();

            pseudo.AppendLine("#version 450");
            pseudo.AppendLine();

            foreach (var op in ops)
            {
                pseudo.Append(op.ToDeclarationalGlsl(context, parms));
            }

            pseudo.AppendLine();

            foreach (var reg in regs)
            {
                if (context.HasBeenSeen(reg.RegisterId))
                {
                    continue;
                }

                pseudo.AppendLine($"vec4 {reg.RegisterId};");
            }

            pseudo.AppendLine();
            pseudo.AppendLine("void main()");
            pseudo.AppendLine("{");

            foreach (var op in ops)
            {
                pseudo.Append(op.ToExecutableGlsl(context));
            }

            pseudo.AppendLine("}");
            return(pseudo.ToString());
        }