protected override string GetFunctionDeclStr() { string returnType = _backend.CSharpToShaderType(_shaderFunction.ReturnType.Name); string fullDeclType = _backend.CSharpToShaderType(_shaderFunction.DeclaringType); string funcName = _shaderFunction.IsEntryPoint ? _shaderFunction.Name : fullDeclType + "_" + _shaderFunction.Name; string baseParameterList = GetParameterDeclList(); string builtinParameterList = string.Join( ", ", MetalBackend.GetBuiltinParameterList(_shaderFunction).Select(b => $"{b.Type} {b.Name}")); string fullParameterList = string.Join( ", ", new string[] { baseParameterList, builtinParameterList }.Where(s => !string.IsNullOrEmpty(s))); string functionDeclStr = $"{returnType} {funcName}({fullParameterList})"; return(functionDeclStr); }
protected override MethodProcessResult GenerateFullTextCore(string setName, ShaderFunction function) { Debug.Assert(function.IsEntryPoint); StringBuilder sb = new StringBuilder(); BackendContext setContext = GetContext(setName); ShaderFunctionAndMethodDeclarationSyntax 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); } HashSet <ResourceDefinition> resourcesUsed = ProcessFunctions(setName, entryPoint, out string funcsStr, out string entryStr); ValidateResourcesUsed(setName, resourcesUsed); 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(funcsStr); // 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(entryStr); 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)); }