Example #1
0
        internal static ShaderFunctionAndMethodDeclarationSyntax GetShaderFunction(
            MethodDeclarationSyntax node,
            Compilation compilation,
            bool generateOrderedFunctionList)
        {
            string functionName = node.Identifier.ToFullString();
            List <ParameterDefinition> parameters = new List <ParameterDefinition>();

            foreach (ParameterSyntax ps in node.ParameterList.Parameters)
            {
                parameters.Add(ParameterDefinition.GetParameterDefinition(compilation, ps));
            }

            SemanticModel semanticModel = compilation.GetSemanticModel(node.SyntaxTree);

            TypeReference returnType = new TypeReference(semanticModel.GetFullTypeName(node.ReturnType));

            UInt3 computeGroupCounts = new UInt3();
            bool  isFragmentShader = false, isComputeShader = false;
            bool  isVertexShader = GetMethodAttributes(node, "VertexShader").Any();

            if (!isVertexShader)
            {
                isFragmentShader = GetMethodAttributes(node, "FragmentShader").Any();
            }
            if (!isVertexShader && !isFragmentShader)
            {
                AttributeSyntax computeShaderAttr = GetMethodAttributes(node, "ComputeShader").FirstOrDefault();
                if (computeShaderAttr != null)
                {
                    isComputeShader      = true;
                    computeGroupCounts.X = GetAttributeArgumentUIntValue(computeShaderAttr, 0);
                    computeGroupCounts.Y = GetAttributeArgumentUIntValue(computeShaderAttr, 1);
                    computeGroupCounts.Z = GetAttributeArgumentUIntValue(computeShaderAttr, 2);
                }
            }

            ShaderFunctionType type = isVertexShader
                ? ShaderFunctionType.VertexEntryPoint
                : isFragmentShader
                    ? ShaderFunctionType.FragmentEntryPoint
                    : isComputeShader
                        ? ShaderFunctionType.ComputeEntryPoint
                        : ShaderFunctionType.Normal;

            string         nestedTypePrefix = GetFullNestedTypePrefix(node, out bool nested);
            ShaderFunction sf = new ShaderFunction(
                nestedTypePrefix,
                functionName,
                returnType,
                parameters.ToArray(),
                type,
                computeGroupCounts);

            ShaderFunctionAndMethodDeclarationSyntax[] orderedFunctionList;
            if (type != ShaderFunctionType.Normal && generateOrderedFunctionList)
            {
                FunctionCallGraphDiscoverer fcgd = new FunctionCallGraphDiscoverer(
                    compilation,
                    new TypeAndMethodName {
                    TypeName = sf.DeclaringType, MethodName = sf.Name
                });
                fcgd.GenerateFullGraph();
                orderedFunctionList = fcgd.GetOrderedCallList();
            }
            else
            {
                orderedFunctionList = new ShaderFunctionAndMethodDeclarationSyntax[0];
            }

            return(new ShaderFunctionAndMethodDeclarationSyntax(sf, node, orderedFunctionList));
        }
Example #2
0
        protected override string GenerateFullTextCore(string setName, ShaderFunction function)
        {
            BackendContext context = GetContext(setName);
            StringBuilder  sb      = new StringBuilder();

            ShaderFunctionAndBlockSyntax entryPoint = context.Functions.SingleOrDefault(
                sfabs => sfabs.Function.Name == function.Name);

            if (entryPoint == null)
            {
                throw new ShaderGenerationException("Couldn't find given function: " + function.Name);
            }

            ValidateRequiredSemantics(setName, entryPoint.Function, function.Type);

            StructureDefinition input = GetRequiredStructureType(setName, entryPoint.Function.Parameters[0].Type);

            WriteVersionHeader(sb);

            StructureDefinition[] orderedStructures
                = StructureDependencyGraph.GetOrderedStructureList(Compilation, context.Structures);

            foreach (StructureDefinition sd in orderedStructures)
            {
                WriteStructure(sb, sd);
            }

            foreach (ResourceDefinition rd in context.Resources)
            {
                switch (rd.ResourceKind)
                {
                case ShaderResourceKind.Uniform:
                    WriteUniform(sb, rd);
                    break;

                case ShaderResourceKind.Texture2D:
                    WriteTexture2D(sb, rd);
                    break;

                case ShaderResourceKind.TextureCube:
                    WriteTextureCube(sb, rd);
                    break;

                case ShaderResourceKind.Sampler:
                    WriteSampler(sb, rd);
                    break;

                default: throw new ShaderGenerationException("Illegal resource kind: " + rd.ResourceKind);
                }
            }

            FunctionCallGraphDiscoverer fcgd = new FunctionCallGraphDiscoverer(
                Compilation,
                new TypeAndMethodName {
                TypeName = function.DeclaringType, MethodName = function.Name
            });

            fcgd.GenerateFullGraph();
            TypeAndMethodName[] orderedFunctionList = fcgd.GetOrderedCallList();

            foreach (TypeAndMethodName name in orderedFunctionList)
            {
                ShaderFunctionAndBlockSyntax f = context.Functions.Single(
                    sfabs => sfabs.Function.DeclaringType == name.TypeName && sfabs.Function.Name == name.MethodName);
                if (!f.Function.IsEntryPoint)
                {
                    sb.AppendLine(new ShaderMethodVisitor(Compilation, setName, f.Function, this).VisitFunction(f.Block));
                }
            }

            string result = new ShaderMethodVisitor(Compilation, setName, entryPoint.Function, this)
                            .VisitFunction(entryPoint.Block);

            sb.AppendLine(result);

            WriteMainFunction(setName, sb, entryPoint.Function);

            return(sb.ToString());
        }
        protected override string GenerateFullTextCore(string setName, ShaderFunction function)
        {
            Debug.Assert(function.IsEntryPoint);

            StringBuilder  sb         = new StringBuilder();
            BackendContext setContext = GetContext(setName);
            ShaderFunctionAndBlockSyntax entryPoint = setContext.Functions.SingleOrDefault(
                sfabs => sfabs.Function.Name == function.Name);

            if (entryPoint == null)
            {
                throw new ShaderGenerationException("Couldn't find given function: " + function.Name);
            }

            ValidateRequiredSemantics(setName, entryPoint.Function, function.Type);

            StructureDefinition[] orderedStructures
                = StructureDependencyGraph.GetOrderedStructureList(Compilation, setContext.Structures);
            foreach (StructureDefinition sd in orderedStructures)
            {
                WriteStructure(sb, sd);
            }

            FunctionCallGraphDiscoverer fcgd = new FunctionCallGraphDiscoverer(
                Compilation,
                new TypeAndMethodName {
                TypeName = function.DeclaringType, MethodName = function.Name
            });

            fcgd.GenerateFullGraph();
            TypeAndMethodName[] orderedFunctionList = fcgd.GetOrderedCallList();

            List <ResourceDefinition[]> resourcesBySet = setContext.Resources.GroupBy(rd => rd.Set)
                                                         .Select(g => g.ToArray()).ToList();

            int uniformBinding = 0, textureBinding = 0, samplerBinding = 0, uavBinding = function.ColorOutputCount;
            int setIndex = 0;

            foreach (ResourceDefinition[] set in resourcesBySet)
            {
                Debug.Assert(set[0].Set == setIndex);
                setIndex += 1;

                foreach (ResourceDefinition rd in set)
                {
                    switch (rd.ResourceKind)
                    {
                    case ShaderResourceKind.Uniform:
                        WriteUniform(sb, rd, uniformBinding++);
                        break;

                    case ShaderResourceKind.Texture2D:
                        WriteTexture2D(sb, rd, textureBinding++);
                        break;

                    case ShaderResourceKind.TextureCube:
                        WriteTextureCube(sb, rd, textureBinding++);
                        break;

                    case ShaderResourceKind.Texture2DMS:
                        WriteTexture2DMS(sb, rd, textureBinding++);
                        break;

                    case ShaderResourceKind.Sampler:
                        WriteSampler(sb, rd, samplerBinding++);
                        break;

                    case ShaderResourceKind.StructuredBuffer:
                        WriteStructuredBuffer(sb, rd, textureBinding++);
                        break;

                    case ShaderResourceKind.RWStructuredBuffer:
                        WriteRWStructuredBuffer(sb, rd, uavBinding++);
                        break;

                    default: throw new ShaderGenerationException("Illegal resource kind: " + rd.ResourceKind);
                    }
                }
            }

            foreach (TypeAndMethodName name in orderedFunctionList)
            {
                ShaderFunctionAndBlockSyntax f = setContext.Functions.Single(
                    sfabs => sfabs.Function.DeclaringType == name.TypeName && sfabs.Function.Name == name.MethodName);
                if (!f.Function.IsEntryPoint)
                {
                    sb.AppendLine(new HlslMethodVisitor(Compilation, setName, f.Function, this).VisitFunction(f.Block));
                }
            }

            string result = new HlslMethodVisitor(Compilation, setName, entryPoint.Function, this)
                            .VisitFunction(entryPoint.Block);

            sb.AppendLine(result);

            return(sb.ToString());
        }
Example #4
0
        internal static ShaderFunctionAndMethodDeclarationSyntax GetShaderFunction(
            BaseMethodDeclarationSyntax node,
            Compilation compilation,
            bool generateOrderedFunctionList)
        {
            SemanticModel semanticModel = compilation.GetSemanticModel(node.SyntaxTree);

            string        functionName;
            TypeReference returnTypeReference;

            if (node is MethodDeclarationSyntax mds)
            {
                functionName        = mds.Identifier.ToFullString();
                returnTypeReference = new TypeReference(semanticModel.GetFullTypeName(mds.ReturnType), semanticModel.GetTypeInfo(mds.ReturnType).Type);
            }
            else if (node is ConstructorDeclarationSyntax cds)
            {
                functionName = ".ctor";
                ITypeSymbol typeSymbol = semanticModel.GetDeclaredSymbol(cds).ContainingType;
                returnTypeReference = new TypeReference(GetFullTypeName(typeSymbol, out _), typeSymbol);
            }
            else
            {
                throw new ArgumentOutOfRangeException(nameof(node), "Unsupported BaseMethodDeclarationSyntax type.");
            }

            UInt3 computeGroupCounts = new UInt3();
            bool  isFragmentShader = false, isComputeShader = false;
            bool  isVertexShader   = GetMethodAttributes(node, "VertexShader").Any();
            bool  isGeometryShader = GetMethodAttributes(node, "GeometryShader").Any();

            if (!isVertexShader)
            {
                isFragmentShader = GetMethodAttributes(node, "FragmentShader").Any();
            }
            if (!isVertexShader && !isFragmentShader && !isGeometryShader)
            {
                AttributeSyntax computeShaderAttr = GetMethodAttributes(node, "ComputeShader").FirstOrDefault();
                if (computeShaderAttr != null)
                {
                    isComputeShader      = true;
                    computeGroupCounts.X = GetAttributeArgumentUIntValue(computeShaderAttr, 0);
                    computeGroupCounts.Y = GetAttributeArgumentUIntValue(computeShaderAttr, 1);
                    computeGroupCounts.Z = GetAttributeArgumentUIntValue(computeShaderAttr, 2);
                }
            }

            ShaderFunctionType type = isVertexShader
                ? ShaderFunctionType.VertexEntryPoint
                : isFragmentShader
                    ? ShaderFunctionType.FragmentEntryPoint
                    : isComputeShader
                        ? ShaderFunctionType.ComputeEntryPoint
                        : isGeometryShader
                            ? ShaderFunctionType.GeometryEntryPoint
                            : ShaderFunctionType.Normal;

            string nestedTypePrefix = GetFullNestedTypePrefix(node, out bool nested);

            List <ParameterDefinition> parameters = new List <ParameterDefinition>();

            foreach (ParameterSyntax ps in node.ParameterList.Parameters)
            {
                parameters.Add(ParameterDefinition.GetParameterDefinition(compilation, ps));
            }

            ShaderFunction sf = new ShaderFunction(
                nestedTypePrefix,
                functionName,
                returnTypeReference,
                parameters.ToArray(),
                type,
                computeGroupCounts);

            if (isGeometryShader)
            {
                AttributeSyntax geometryShaderAttr = GetMethodAttributes(node, "GeometryShader").FirstOrDefault();
                var             geometryArgs       = geometryShaderAttr.ArgumentList.Arguments;
                if (geometryArgs.Count == 3)
                {
                    sf.InputPrimitive  = (PrimitiveType)Enum.ToObject(typeof(PrimitiveType), semanticModel.GetConstantValue(geometryArgs[0].Expression).Value);
                    sf.OutputPrimitive = (PrimitiveType)Enum.ToObject(typeof(PrimitiveType), semanticModel.GetConstantValue(geometryArgs[1].Expression).Value);
                    sf.MaxVertices     = (int)semanticModel.GetConstantValue(geometryArgs[2].Expression).Value;
                }
            }

            ShaderFunctionAndMethodDeclarationSyntax[] orderedFunctionList;
            if (type != ShaderFunctionType.Normal && generateOrderedFunctionList)
            {
                FunctionCallGraphDiscoverer fcgd = new FunctionCallGraphDiscoverer(
                    compilation,
                    new TypeAndMethodName {
                    TypeName = sf.DeclaringType, MethodName = sf.Name
                });
                fcgd.GenerateFullGraph();
                orderedFunctionList = fcgd.GetOrderedCallList();
            }
            else
            {
                orderedFunctionList = new ShaderFunctionAndMethodDeclarationSyntax[0];
            }

            return(new ShaderFunctionAndMethodDeclarationSyntax(sf, node, orderedFunctionList));
        }
Example #5
0
        protected override string GenerateFullTextCore(string setName, ShaderFunction function)
        {
            Debug.Assert(function.IsEntryPoint);

            StringBuilder  sb         = new StringBuilder();
            BackendContext setContext = GetContext(setName);
            ShaderFunctionAndBlockSyntax entryPoint = setContext.Functions.SingleOrDefault(
                sfabs => sfabs.Function.Name == function.Name);

            if (entryPoint == null)
            {
                throw new ShaderGenerationException("Couldn't find given function: " + function.Name);
            }

            ValidateRequiredSemantics(setName, entryPoint.Function, function.Type);

            StructureDefinition input = GetRequiredStructureType(setName, entryPoint.Function.Parameters[0].Type);

            if (function.Type == ShaderFunctionType.VertexEntryPoint)
            {
                // HLSL vertex outputs needs to have semantics applied to the structure fields.
                StructureDefinition output = CreateOutputStructure(setName, GetRequiredStructureType(setName, entryPoint.Function.ReturnType));
                setContext.Functions.Remove(entryPoint);
                entryPoint = entryPoint.WithReturnType(new TypeReference(output.Name));
                setContext.Functions.Add(entryPoint);
            }

            if (function.Type == ShaderFunctionType.FragmentEntryPoint)
            {
                // HLSL pixel shader inputs also need these semantics.
                StructureDefinition modifiedInput = CreateOutputStructure(setName, input);
                setContext.Functions.Remove(entryPoint);
                entryPoint = entryPoint.WithParameter(0, new TypeReference(modifiedInput.Name));
                setContext.Functions.Add(entryPoint);
            }

            StructureDefinition[] orderedStructures
                = StructureDependencyGraph.GetOrderedStructureList(Compilation, setContext.Structures);
            foreach (StructureDefinition sd in orderedStructures)
            {
                WriteStructure(sb, sd);
            }
            foreach (StructureDefinition sd in GetSynthesizedStructures(setName))
            {
                WriteStructure(sb, sd);
            }

            FunctionCallGraphDiscoverer fcgd = new FunctionCallGraphDiscoverer(
                Compilation,
                new TypeAndMethodName {
                TypeName = function.DeclaringType, MethodName = function.Name
            });

            fcgd.GenerateFullGraph();
            TypeAndMethodName[] orderedFunctionList = fcgd.GetOrderedCallList();

            List <ResourceDefinition[]> resourcesBySet = setContext.Resources.GroupBy(rd => rd.Set)
                                                         .Select(g => g.ToArray()).ToList();

            int uniformBinding = 0, textureBinding = 0, samplerBinding = 0;
            int setIndex = 0;

            foreach (ResourceDefinition[] set in resourcesBySet)
            {
                Debug.Assert(set[0].Set == setIndex);
                setIndex += 1;

                foreach (ResourceDefinition rd in set)
                {
                    switch (rd.ResourceKind)
                    {
                    case ShaderResourceKind.Uniform:
                        WriteUniform(sb, rd, uniformBinding++);
                        break;

                    case ShaderResourceKind.Texture2D:
                        WriteTexture2D(sb, rd, textureBinding++);
                        break;

                    case ShaderResourceKind.TextureCube:
                        WriteTextureCube(sb, rd, textureBinding++);
                        break;

                    case ShaderResourceKind.Sampler:
                        WriteSampler(sb, rd, samplerBinding++);
                        break;

                    default: throw new ShaderGenerationException("Illegal resource kind: " + rd.ResourceKind);
                    }
                }
            }

            foreach (TypeAndMethodName name in orderedFunctionList)
            {
                ShaderFunctionAndBlockSyntax f = setContext.Functions.Single(
                    sfabs => sfabs.Function.DeclaringType == name.TypeName && sfabs.Function.Name == name.MethodName);
                if (!f.Function.IsEntryPoint)
                {
                    sb.AppendLine(new HlslMethodVisitor(Compilation, setName, f.Function, this).VisitFunction(f.Block));
                }
            }

            string result = new HlslMethodVisitor(Compilation, setName, entryPoint.Function, this)
                            .VisitFunction(entryPoint.Block);

            sb.AppendLine(result);

            return(sb.ToString());
        }