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);
        }
示例#2
0
        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));
            }
        }
示例#3
0
 public ShaderSetInfo(string name, TypeAndMethodName vs, TypeAndMethodName gs, TypeAndMethodName fs)
 //: this(name, vs, fs)
 {
     Name           = name;
     GeometryShader = gs;
     VertexShader   = vs;
     FragmentShader = fs;
 }
示例#4
0
        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;
        }
示例#5
0
        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);
        }
示例#6
0
        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));
                }
            }
        }
示例#7
0
        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);
        }
示例#8
0
        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;
        }
示例#10
0
        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();
        }
示例#11
0
 public ShaderSetInfo(string name, TypeAndMethodName cs)
 {
     Name          = name;
     ComputeShader = cs;
 }