コード例 #1
0
        protected override MethodProcessResult GenerateFullTextCore(string setName, ShaderFunction function)
        {
            BackendContext context = GetContext(setName);
            StringBuilder  sb      = new StringBuilder();
            HashSet <ResourceDefinition> resourcesUsed = new HashSet <ResourceDefinition>();

            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[] 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.Texture2DMS:
                    WriteTexture2DMS(sb, rd);
                    break;

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

                case ShaderResourceKind.StructuredBuffer:
                case ShaderResourceKind.RWStructuredBuffer:
                    WriteStructuredBuffer(sb, rd, rd.ResourceKind == ShaderResourceKind.StructuredBuffer);
                    break;

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

            foreach (ShaderFunctionAndBlockSyntax f in entryPoint.OrderedFunctionList)
            {
                if (!f.Function.IsEntryPoint)
                {
                    MethodProcessResult processResult = new ShaderMethodVisitor(Compilation, setName, f.Function, this).VisitFunction(f.Block);
                    foreach (ResourceDefinition rd in processResult.ResourcesUsed)
                    {
                        resourcesUsed.Add(rd);
                    }
                    sb.AppendLine(processResult.FullText);
                }
            }

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

            foreach (ResourceDefinition rd in result.ResourcesUsed)
            {
                resourcesUsed.Add(rd);
            }
            sb.AppendLine(result.FullText);

            WriteMainFunction(setName, sb, entryPoint.Function);

            // Append version last because it relies on information from parsing the shader.
            StringBuilder versionSB = new StringBuilder();

            WriteVersionHeader(function, versionSB);

            sb.Insert(0, versionSB.ToString());

            return(new MethodProcessResult(sb.ToString(), resourcesUsed));
        }
コード例 #2
0
        protected override MethodProcessResult GenerateFullTextCore(string setName, ShaderFunction function)
        {
            Debug.Assert(function.IsEntryPoint);

            StringBuilder sb = new StringBuilder();
            HashSet <ResourceDefinition> resourcesUsed = new HashSet <ResourceDefinition>();

            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);
            }

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

            StringBuilder functionsSB = new StringBuilder();

            foreach (ShaderFunctionAndBlockSyntax f in entryPoint.OrderedFunctionList)
            {
                if (!f.Function.IsEntryPoint)
                {
                    MethodProcessResult processResult = new HlslMethodVisitor(Compilation, setName, f.Function, this).VisitFunction(f.Block);
                    foreach (ResourceDefinition rd in processResult.ResourcesUsed)
                    {
                        resourcesUsed.Add(rd);
                    }
                    functionsSB.AppendLine(processResult.FullText);
                }
            }

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

            foreach (ResourceDefinition rd in result.ResourcesUsed)
            {
                resourcesUsed.Add(rd);
            }

            // Emit all of the resources now, because we've learned which ones are actually used by this function.
            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:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteUniform(sb, rd, uniformBinding);
                        }
                        uniformBinding++;
                        break;

                    case ShaderResourceKind.Texture2D:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteTexture2D(sb, rd, textureBinding);
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.TextureCube:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteTextureCube(sb, rd, textureBinding);
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.Texture2DMS:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteTexture2DMS(sb, rd, textureBinding);
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.Sampler:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteSampler(sb, rd, samplerBinding);
                        }
                        samplerBinding++;
                        break;

                    case ShaderResourceKind.StructuredBuffer:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteStructuredBuffer(sb, rd, textureBinding);
                        }
                        textureBinding++;
                        break;

                    case ShaderResourceKind.RWStructuredBuffer:
                        if (resourcesUsed.Contains(rd))
                        {
                            WriteRWStructuredBuffer(sb, rd, uavBinding);
                        }
                        uavBinding++;
                        break;

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

            // Resources need to be defined before the function that uses them -- so append this after the resources.
            sb.Append(functionsSB.ToString());
            sb.AppendLine(result.FullText);

            return(new MethodProcessResult(sb.ToString(), resourcesUsed));
        }
コード例 #3
0
        protected override MethodProcessResult GenerateFullTextCore(string setName, ShaderFunction function)
        {
            Debug.Assert(function.IsEntryPoint);

            StringBuilder sb = new StringBuilder();
            HashSet <ResourceDefinition> resourcesUsed = new HashSet <ResourceDefinition>();
            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);

            // Write header
            sb.AppendLine("#include <metal_stdlib>");
            sb.AppendLine("using namespace metal;");

            // TODO: Necessary for Metal?
            StructureDefinition[] orderedStructures
                = StructureDependencyGraph.GetOrderedStructureList(Compilation, setContext.Structures);
            foreach (StructureDefinition sd in orderedStructures)
            {
                WriteStructure(sb, sd);
            }

            StringBuilder functionsSB = new StringBuilder();

            foreach (ShaderFunctionAndBlockSyntax f in entryPoint.OrderedFunctionList)
            {
                if (!f.Function.IsEntryPoint)
                {
                    MethodProcessResult processResult = new MetalMethodVisitor(Compilation, setName, f.Function, this).VisitFunction(f.Block);
                    foreach (ResourceDefinition rd in processResult.ResourcesUsed)
                    {
                        resourcesUsed.Add(rd);
                    }
                    functionsSB.AppendLine(processResult.FullText);
                }
            }

            MethodProcessResult entryResult = new MetalMethodVisitor(Compilation, setName, entryPoint.Function, this)
                                              .VisitFunction(entryPoint.Block);

            foreach (ResourceDefinition rd in entryResult.ResourcesUsed)
            {
                resourcesUsed.Add(rd);
            }

            StringBuilder containerSB = new StringBuilder();

            containerSB.AppendLine("struct ShaderContainer {");

            List <string> structFields    = new List <string>();
            List <string> ctorParams      = new List <string>();
            List <string> ctorAssignments = new List <string>();

            foreach (ResourceDefinition resource in resourcesUsed)
            {
                structFields.Add(GetResourceField(resource));
                ctorParams.Add(GetResourceCtorParam(resource));
                ctorAssignments.Add($"{resource.Name}({resource.Name}_param)");
            }

            foreach (string sf in structFields)
            {
                containerSB.AppendLine(sf);
            }

            containerSB.AppendLine(functionsSB.ToString());

            // Emit the ctor definition
            containerSB.AppendLine($"ShaderContainer(");
            string ctorParamsStr = string.Join(", ", ctorParams);

            containerSB.AppendLine(ctorParamsStr);
            containerSB.AppendLine($")");
            string allCtorAssignments = string.Join(", ", ctorAssignments);

            if (!string.IsNullOrEmpty(allCtorAssignments))
            {
                containerSB.AppendLine(":");
                containerSB.AppendLine(allCtorAssignments);
            }
            containerSB.AppendLine("{}");

            containerSB.AppendLine(entryResult.FullText);

            containerSB.AppendLine("};"); // Close the global containing struct.
            sb.AppendLine(containerSB.ToString());

            // Emit the out function call which creates the container struct and calls the real shader function.
            string type = entryPoint.Function.Type == ShaderFunctionType.VertexEntryPoint
                ? "vertex"
                : entryPoint.Function.Type == ShaderFunctionType.FragmentEntryPoint
                    ? "fragment"
                    : "kernel";

            ShaderFunction entryFunction         = entryPoint.Function;
            string         returnType            = CSharpToShaderType(entryFunction.ReturnType.Name);
            string         fullDeclType          = CSharpToShaderType(entryFunction.DeclaringType);
            string         funcName              = entryFunction.Name;
            string         baseParameterList     = string.Join(", ", entryFunction.Parameters.Select(FormatParameter));
            string         resourceParameterList = GetResourceParameterList(entryFunction, setName, resourcesUsed);
            string         builtinParameterList  = string.Join(
                ", ",
                GetBuiltinParameterList(entryFunction).Select(b => $"{b.Type} {b.Name} {b.Attribute}"));
            string fullParameterList = string.Join(
                ", ",
                new string[]
            {
                baseParameterList, resourceParameterList, builtinParameterList
            }.Where(s => !string.IsNullOrEmpty(s)));

            string functionDeclStr = $"{type} {returnType} {funcName}({fullParameterList})";

            string containerArgs = string.Join(", ", resourcesUsed.Select(
                                                   rd => rd.Name));

            string entryFuncArgs = string.Join(
                ", ",
                MetalBackend.GetBuiltinParameterList(entryFunction).Select(b => $"{b.Name}"));

            if (entryFunction.Parameters.Length > 0)
            {
                Debug.Assert(entryFunction.Parameters.Length == 1);
                entryFuncArgs = Utilities.JoinIgnoreNull(
                    ", ",
                    new string[] { $"{entryFunction.Parameters[0].Name}", entryFuncArgs });
            }

            sb.AppendLine(functionDeclStr);
            sb.AppendLine("{");
            sb.AppendLine($"return ShaderContainer({containerArgs}).{entryFunction.Name}({entryFuncArgs});");
            sb.AppendLine("}");

            return(new MethodProcessResult(sb.ToString(), resourcesUsed));
        }