/// <summary> /// Loads additional static methods used by the shader /// </summary> /// <param name="name">The HLSL name of the new method to load</param> /// <param name="methodInfo">The <see cref="MethodInfo"/> instance for the method to load</param> private void LoadStaticMethodSource(string name, MethodInfo methodInfo) { // Decompile the target method MethodDecompiler.Instance.GetSyntaxTree(methodInfo, MethodType.Static, out MethodDeclarationSyntax root, out SemanticModel semanticModel); // Rewrite the method ShaderSyntaxRewriter syntaxRewriter = new ShaderSyntaxRewriter(semanticModel, methodInfo.DeclaringType); root = (MethodDeclarationSyntax)syntaxRewriter.Visit(root); // Register the captured static members foreach (var member in syntaxRewriter.StaticMembers) { LoadFieldInfo(member.Value, member.Key); } // Register the captured static methods foreach (var method in syntaxRewriter.StaticMethods) { LoadStaticMethodSource(method.Key, method.Value); } // Get the function parameters IReadOnlyList <ParameterInfo> parameters = ( from parameter in root.ParameterList.Parameters.Select((p, i) => (Node: p, Index: i)) let modifiers = parameter.Node.Modifiers let type = parameter.Node.Type.ToFullString() let parameterName = parameter.Node.Identifier.ToFullString() let last = parameter.Index == root.ParameterList.Parameters.Count - 1 select new ParameterInfo(modifiers, type, parameterName, last)).ToArray(); // Get the function body string body = root.Body.ToFullString(); body = Regex.Replace(body, @"(?<=\W)(\d+)[fFdD]", m => m.Groups[1].Value); body = body.TrimEnd('\n', '\r', ' '); body = HlslKnownKeywords.GetMappedText(body); // Get the final function info instance FunctionInfo functionInfo = new FunctionInfo( methodInfo.ReturnType, $"{methodInfo.DeclaringType.FullName}{Type.Delimiter}{methodInfo.Name}", string.Join(", ", methodInfo.GetParameters().Select(p => $"{p.ParameterType.ToFriendlyString()} {p.Name}")), root.ReturnType.ToString(), name, parameters, body); _FunctionsList.Add(functionInfo); }
/// <summary> /// Loads the entry method for the current shader being loaded /// </summary> private void LoadMethodSource() { // Decompile the shader method MethodDecompiler.Instance.GetSyntaxTree(Action.Method, MethodType.Closure, out MethodDeclarationSyntax root, out SemanticModel semanticModel); // Rewrite the shader method (eg. to fix the type declarations) ShaderSyntaxRewriter syntaxRewriter = new ShaderSyntaxRewriter(semanticModel, ShaderType); root = (MethodDeclarationSyntax)syntaxRewriter.Visit(root); // Extract the implicit local functions var locals = root.DescendantNodes().OfType <LocalFunctionStatementSyntax>().ToArray(); root = root.RemoveNodes(locals, SyntaxRemoveOptions.KeepNoTrivia); foreach (var local in locals) { string alignedLocal = local.ToFullString().RemoveLeftPadding().Trim(' ', '\r', '\n'); alignedLocal = Regex.Replace(alignedLocal, @"(?<=\W)(\d+)[fFdD]", m => m.Groups[1].Value); alignedLocal = HlslKnownKeywords.GetMappedText(alignedLocal); _LocalFunctionsList.Add(new LocalFunctionInfo(alignedLocal)); } // Register the captured static members foreach (var member in syntaxRewriter.StaticMembers) { LoadFieldInfo(member.Value, member.Key); } // Register the captured static methods foreach (var method in syntaxRewriter.StaticMethods) { LoadStaticMethodSource(method.Key, method.Value); } // Get the thread ids identifier name and shader method body ThreadsIdsVariableName = root.ParameterList.Parameters.First().Identifier.Text; MethodBody = root.Body.ToFullString(); // Additional preprocessing MethodBody = Regex.Replace(MethodBody, @"(?<=\W)(\d+)[fFdD]", m => m.Groups[1].Value); MethodBody = MethodBody.TrimEnd('\n', '\r', ' '); MethodBody = HlslKnownKeywords.GetMappedText(MethodBody); }