private bool GetDeclaration(TypeAndMethodName name, out BaseMethodDeclarationSyntax decl) { bool isConstructor = name.MethodName == ".ctor"; ITypeSymbol symb = Compilation.FindTypeByMetadataName(name.TypeName); foreach (SyntaxReference synRef in symb.DeclaringSyntaxReferences) { SyntaxNode node = synRef.GetSyntax(); foreach (SyntaxNode child in node.ChildNodes()) { if (isConstructor) { if (child is ConstructorDeclarationSyntax cds) { decl = cds; return(true); } } if (child is MethodDeclarationSyntax mds) { if (mds.Identifier.ToFullString() == name.MethodName) { decl = mds; return(true); } } } } decl = null; return(false); }
public override void VisitAttribute(AttributeSyntax node) { // TODO: Only look at assembly-level attributes. if (node.Name.ToFullString().Contains("ComputeShaderSet")) { string name = GetStringParam(node, 0); string cs = GetStringParam(node, 1); if (!TypeAndMethodName.Get(cs, out TypeAndMethodName csName)) { throw new ShaderGenerationException("ComputeShaderSetAttribute has an incomplete or invalid compute shader name."); } _shaderSets.Add(new ShaderSetInfo(name, csName)); } else if (node.Name.ToFullString().Contains("ShaderSet")) { int paramIndex = 0; string name = GetStringParam(node, paramIndex++); TypeAndMethodName vsName = null; string vs = GetStringParam(node, paramIndex++); if (vs != null && !TypeAndMethodName.Get(vs, out vsName)) { throw new ShaderGenerationException("ShaderSetAttribute has an incomplete or invalid vertex shader name."); } TypeAndMethodName gsName = null; if (node.ArgumentList.Arguments.Count > 3) { string gs = GetStringParam(node, paramIndex++); if (gs != null && !TypeAndMethodName.Get(gs, out gsName)) { throw new ShaderGenerationException("ShaderSetAttribute has an incomplete or invalid geometry shader name."); } } TypeAndMethodName fsName = null; string fs = GetStringParam(node, paramIndex++); if (fs != null && !TypeAndMethodName.Get(fs, out fsName)) { throw new ShaderGenerationException("ShaderSetAttribute has an incomplete or invalid fragment shader name."); } if (vsName == null && gsName == null && fsName == null) { throw new ShaderGenerationException("ShaderSetAttribute must specify at least one shader name."); } if (!_discoveredNames.Add(name)) { throw new ShaderGenerationException("Multiple shader sets with the same name were defined: " + name); } _shaderSets.Add(new ShaderSetInfo( name, vsName, gsName, fsName)); } }
public ShaderSetInfo(string name, TypeAndMethodName vs, TypeAndMethodName gs, TypeAndMethodName fs) //: this(name, vs, fs) { Name = name; GeometryShader = gs; VertexShader = vs; FragmentShader = fs; }
public ShaderSetInfo(string name, TypeAndMethodName vs, TypeAndMethodName fs) { if (vs == null && fs == null) { throw new ArgumentException("At least one of vs or fs must be non-null."); } Name = name; VertexShader = vs; FragmentShader = fs; }
public FunctionCallGraphDiscoverer(Compilation compilation, TypeAndMethodName rootMethod) { Compilation = compilation; _rootNode = new CallGraphNode() { Name = rootMethod }; bool foundDecl = GetDeclaration(rootMethod, out _rootNode.Declaration); Debug.Assert(foundDecl); _nodesByName.Add(rootMethod, _rootNode); }
private void GenerateShaders(ShaderSetInfo ss, ShaderGenerationResult result) { TypeAndMethodName vertexFunctionName = ss.VertexShader; TypeAndMethodName fragmentFunctionName = ss.FragmentShader; HashSet <SyntaxTree> treesToVisit = new HashSet <SyntaxTree>(); if (vertexFunctionName != null) { GetTrees(treesToVisit, vertexFunctionName.TypeName); } if (fragmentFunctionName != null) { GetTrees(treesToVisit, fragmentFunctionName.TypeName); } foreach (LanguageBackend language in _languages) { language.InitContext(ss.Name); } ShaderSyntaxWalker walker = new ShaderSyntaxWalker(_compilation, _languages.ToArray(), ss); foreach (SyntaxTree tree in treesToVisit) { walker.Visit(tree.GetRoot()); } foreach (LanguageBackend language in _languages) { ShaderModel model = language.GetShaderModel(ss.Name); ShaderFunction vsFunc = (ss.VertexShader != null) ? model.GetFunction(ss.VertexShader.FullName) : null; ShaderFunction fsFunc = (ss.FragmentShader != null) ? model.GetFunction(ss.FragmentShader.FullName) : null; { string vsCode = null; string fsCode = null; if (vsFunc != null) { vsCode = language.GetCode(ss.Name, vsFunc); } if (fsFunc != null) { fsCode = language.GetCode(ss.Name, fsFunc); } result.AddShaderSet(language, new GeneratedShaderSet(ss.Name, vsCode, fsCode, vsFunc, fsFunc, model)); } } }
private CallGraphNode GetNode(TypeAndMethodName name) { if (!_nodesByName.TryGetValue(name, out CallGraphNode node)) { node = new CallGraphNode() { Name = name }; GetDeclaration(name, out node.Declaration); _nodesByName.Add(name, node); } return(node); }
public override void VisitAttribute(AttributeSyntax node) { if (node.Name.ToFullString().Contains("ShaderSet")) { string name = GetStringParam(node, 0); TypeAndMethodName vsName = null; string vs = GetStringParam(node, 1); if (vs != null && !TypeAndMethodName.Get(vs, out vsName)) { throw new ShaderGenerationException("ShaderSetAttribute has an incomplete or invalid vertex shader name."); } TypeAndMethodName fsName = null; string fs = GetStringParam(node, 2); if (fs != null && !TypeAndMethodName.Get(fs, out fsName)) { throw new ShaderGenerationException("ShaderSetAttribute has an incomplete or invalid fragment shader name."); } if (vsName == null && fsName == null) { throw new ShaderGenerationException("ShaderSetAttribute must specify at least one shader name."); } if (!_discoveredNames.Add(name)) { throw new ShaderGenerationException("Multiple shader sets with the same name were defined: " + name); } _shaderSets.Add(new ShaderSetInfo( name, vsName, fsName)); } }
public ShaderGenerator( Compilation compilation, string vertexFunctionName, string fragmentFunctionName, LanguageBackend[] languages, IShaderSetProcessor[] processors) { if (compilation == null) { throw new ArgumentNullException(nameof(compilation)); } if (vertexFunctionName == null && fragmentFunctionName == null) { throw new ArgumentException( $"One of {nameof(vertexFunctionName)} or {nameof(fragmentFunctionName)} must be non-null."); } if (languages == null) { throw new ArgumentNullException(nameof(languages)); } if (processors == null) { throw new ArgumentNullException(nameof(processors)); } if (languages.Length == 0) { throw new ArgumentException("At least one LanguageBackend must be provided."); } _compilation = compilation; _languages = new List <LanguageBackend>(languages); TypeAndMethodName _vertexFunctionName = null; if (vertexFunctionName != null && !TypeAndMethodName.Get(vertexFunctionName, out _vertexFunctionName)) { throw new ShaderGenerationException( $"The name passed to {nameof(vertexFunctionName)} must be a fully-qualified type and method."); } TypeAndMethodName _fragmentFunctionName = null; if (fragmentFunctionName != null && !TypeAndMethodName.Get(fragmentFunctionName, out _fragmentFunctionName)) { throw new ShaderGenerationException( $"The name passed to {nameof(fragmentFunctionName)} must be a fully-qualified type and method."); } string setName = string.Empty; if (vertexFunctionName != null) { setName = vertexFunctionName; } if (fragmentFunctionName != null) { if (setName == string.Empty) { setName = fragmentFunctionName; } else { setName += "+" + fragmentFunctionName; } } _shaderSets.Add(new ShaderSetInfo( setName, _vertexFunctionName, _fragmentFunctionName)); _processors = processors; }
public ShaderGenerator( Compilation compilation, LanguageBackend[] languages, string vertexFunctionName = null, string fragmentFunctionName = null, string computeFunctionName = null, params IShaderSetProcessor[] processors) { if (languages == null) { throw new ArgumentNullException(nameof(languages)); } if (languages.Length < 1) { throw new ArgumentException("At least one LanguageBackend must be provided."); } _compilation = compilation ?? throw new ArgumentNullException(nameof(compilation)); _languages = languages.ToArray(); _processors = processors; // If we've not specified any names, we're auto-discovering if (string.IsNullOrWhiteSpace(vertexFunctionName) && string.IsNullOrWhiteSpace(fragmentFunctionName) && string.IsNullOrWhiteSpace(computeFunctionName)) { ShaderSetDiscoverer ssd = new ShaderSetDiscoverer(); foreach (SyntaxTree tree in _compilation.SyntaxTrees) { ssd.Visit(tree.GetRoot()); } _shaderSets = ssd.GetShaderSets(); return; } // We've explicitly specified shaders so find them directly. List <ShaderSetInfo> shaderSets = new List <ShaderSetInfo>(); TypeAndMethodName vertex = null; if (!string.IsNullOrWhiteSpace(vertexFunctionName) && !TypeAndMethodName.Get(vertexFunctionName, out vertex)) { throw new ShaderGenerationException( $"The name passed to {nameof(vertexFunctionName)} must be a fully-qualified type and method."); } TypeAndMethodName fragment = null; if (!string.IsNullOrWhiteSpace(fragmentFunctionName) && !TypeAndMethodName.Get(fragmentFunctionName, out fragment)) { throw new ShaderGenerationException( $"The name passed to {nameof(fragmentFunctionName)} must be a fully-qualified type and method."); } if (vertex != null || fragment != null) { // We have either a vertex or fragment, so create a graphics shader set. string setName = string.Empty; if (vertex != null) { setName = vertexFunctionName; } if (fragment != null) { if (setName == string.Empty) { setName = fragmentFunctionName; } else { setName += "+" + fragmentFunctionName; } } shaderSets.Add(new ShaderSetInfo(setName, vertex, fragment)); } TypeAndMethodName compute = null; if (!string.IsNullOrWhiteSpace(computeFunctionName) && !TypeAndMethodName.Get(computeFunctionName, out compute)) { throw new ShaderGenerationException( $"The name passed to {nameof(computeFunctionName)} must be a fully-qualified type and method."); } if (compute != null) { shaderSets.Add(new ShaderSetInfo(computeFunctionName, compute)); } _shaderSets = shaderSets.ToArray(); }
public ShaderSetInfo(string name, TypeAndMethodName cs) { Name = name; ComputeShader = cs; }