protected HashSet <ResourceDefinition> ProcessFunctions(string setName, ShaderFunctionAndMethodDeclarationSyntax entryPoint, out string funcs, out string entry) { HashSet <ResourceDefinition> resourcesUsed = new HashSet <ResourceDefinition>(); StringBuilder sb = new StringBuilder(); foreach (ShaderFunctionAndMethodDeclarationSyntax f in entryPoint.OrderedFunctionList) { if (!f.Function.IsEntryPoint) { MethodProcessResult processResult = VisitShaderMethod(setName, f.Function).VisitFunction(f.MethodDeclaration); foreach (ResourceDefinition rd in processResult.ResourcesUsed) { resourcesUsed.Add(rd); } sb.AppendLine(processResult.FullText); } } funcs = sb.ToString(); MethodProcessResult result = VisitShaderMethod(setName, entryPoint.Function).VisitFunction(entryPoint.MethodDeclaration); foreach (ResourceDefinition rd in result.ResourcesUsed) { resourcesUsed.Add(rd); } entry = result.FullText; return(resourcesUsed); }
internal string FormatInvocation(string setName, string type, string method, InvocationParameterInfo[] parameterInfos) { Debug.Assert(setName != null); Debug.Assert(type != null); Debug.Assert(method != null); Debug.Assert(parameterInfos != null); ShaderFunctionAndMethodDeclarationSyntax function = GetContext(setName).Functions .SingleOrDefault( sfabs => sfabs.Function.DeclaringType == type && sfabs.Function.Name == method && parameterInfos.Length == sfabs.Function.Parameters.Length); if (function != null) { ParameterDefinition[] funcParameters = function.Function.Parameters; string[] formattedParams = new string[funcParameters.Length]; for (int i = 0; i < formattedParams.Length; i++) { formattedParams[i] = FormatInvocationParameter(funcParameters[i], parameterInfos[i]); } string invocationList = string.Join(", ", formattedParams); string fullMethodName = CSharpToShaderType(function.Function.DeclaringType) + "_" + function.Function.Name; return($"{fullMethodName}({invocationList})"); } else { return(FormatInvocationCore(setName, type, method, parameterInfos)); } }
public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { ShaderFunctionAndMethodDeclarationSyntax sfab = Utilities.GetShaderFunction(node, _compilation, true); foreach (LanguageBackend b in _backends) { b.AddFunction(_shaderSet.Name, sfab); foreach (var calledFunction in sfab.OrderedFunctionList) { b.AddFunction(_shaderSet.Name, calledFunction); } } }
internal virtual void AddFunction(string setName, ShaderFunctionAndMethodDeclarationSyntax sf) { if (sf == null) { throw new ArgumentNullException(nameof(sf)); } var context = GetContext(setName); if (!context.Functions.Contains(sf)) { context.Functions.Add(sf); } }
protected HashSet <ResourceDefinition> ProcessFunctions(string setName, ShaderFunctionAndMethodDeclarationSyntax entryPoint, out string funcs, out string entry) { HashSet <ResourceDefinition> resourcesUsed = new HashSet <ResourceDefinition>(); StringBuilder sb = new StringBuilder(); foreach (ShaderFunctionAndMethodDeclarationSyntax f in entryPoint.OrderedFunctionList) { if (!f.Function.IsEntryPoint) { MethodProcessResult processResult = VisitShaderMethod(setName, f.Function).VisitFunction(f.MethodDeclaration); foreach (ResourceDefinition rd in processResult.ResourcesUsed) { resourcesUsed.Add(rd); } sb.AppendLine(processResult.FullText); foreach (var param in f.Function.Parameters) { resourcesUsed.Add(new ResourceDefinition(param.Name, 0, 0, param.Type, ShaderResourceKind.Local)); } } } funcs = sb.ToString(); MethodProcessResult result = VisitShaderMethod(setName, entryPoint.Function).VisitFunction(entryPoint.MethodDeclaration); foreach (ResourceDefinition rd in result.ResourcesUsed) { resourcesUsed.Add(rd); } var context = GetContext(setName); foreach (var param in entryPoint.Function.Parameters) { var paramResource = new ResourceDefinition(param.Name, 0, 0, param.Type, ShaderResourceKind.Local); resourcesUsed.Add(paramResource); var sd = context.Structures.FirstOrDefault(paramResource.Matches); if (sd != null) { int fieldIndex = 0; foreach (var field in sd.Fields.Where(f => !f.IsBuiltIn)) { resourcesUsed.Add(new ResourceDefinition(field.Name, 0, fieldIndex++, field.Type, ShaderResourceKind.Emit)); } } } entry = result.FullText; return(resourcesUsed); }
private void TraverseNode(HashSet <ShaderFunctionAndMethodDeclarationSyntax> result, CallGraphNode node) { foreach (ShaderFunctionAndMethodDeclarationSyntax existing in result) { if (node.Parents.Any(cgn => cgn.Name.Equals(existing))) { throw new ShaderGenerationException("There was a cyclical call graph involving " + existing + " and " + node.Name); } } foreach (CallGraphNode child in node.Children) { TraverseNode(result, child); } ShaderFunctionAndMethodDeclarationSyntax sfab = Utilities.GetShaderFunction(node.Declaration, Compilation, false); result.Add(sfab); }
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)); }
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)); }