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); ShaderFunctionAndBlockSyntax 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) { string functionName = node.Identifier.ToFullString(); List <ParameterDefinition> parameters = new List <ParameterDefinition>(); foreach (ParameterSyntax ps in node.ParameterList.Parameters) { parameters.Add(ParameterDefinition.GetParameterDefinition(_compilation, ps)); } TypeReference returnType = new TypeReference(GetModel(node).GetFullTypeName(node.ReturnType)); bool isVertexShader, isFragmentShader = false; isVertexShader = Utilities.GetMethodAttributes(node, "VertexShader").Any(); if (!isVertexShader) { isFragmentShader = Utilities.GetMethodAttributes(node, "FragmentShader").Any(); } ShaderFunctionType type = isVertexShader ? ShaderFunctionType.VertexEntryPoint : isFragmentShader ? ShaderFunctionType.FragmentEntryPoint : ShaderFunctionType.Normal; string nestedTypePrefix = Utilities.GetFullNestedTypePrefix(node, out bool nested); ShaderFunction sf = new ShaderFunction(nestedTypePrefix, functionName, returnType, parameters.ToArray(), type); ShaderFunctionAndBlockSyntax sfab = new ShaderFunctionAndBlockSyntax(sf, node.Body); foreach (LanguageBackend b in _backends) { b.AddFunction(_shaderSet.Name, sfab); } }
internal virtual void AddFunction(string setName, ShaderFunctionAndBlockSyntax sf) { if (sf == null) { throw new ArgumentNullException(nameof(sf)); } GetContext(setName).Functions.Add(sf); }
public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { string functionName = node.Identifier.ToFullString(); List <ParameterDefinition> parameters = new List <ParameterDefinition>(); foreach (ParameterSyntax ps in node.ParameterList.Parameters) { parameters.Add(ParameterDefinition.GetParameterDefinition(_compilation, ps)); } TypeReference returnType = new TypeReference(GetModel(node).GetFullTypeName(node.ReturnType)); UInt3 computeGroupCounts = new UInt3(); bool isFragmentShader = false, isComputeShader = false; bool isVertexShader = Utilities.GetMethodAttributes(node, "VertexShader").Any(); if (!isVertexShader) { isFragmentShader = Utilities.GetMethodAttributes(node, "FragmentShader").Any(); } if (!isVertexShader && !isFragmentShader) { AttributeSyntax computeShaderAttr = Utilities.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 = Utilities.GetFullNestedTypePrefix(node, out bool nested); ShaderFunction sf = new ShaderFunction( nestedTypePrefix, functionName, returnType, parameters.ToArray(), type, computeGroupCounts); ShaderFunctionAndBlockSyntax sfab = new ShaderFunctionAndBlockSyntax(sf, node.Body); foreach (LanguageBackend b in _backends) { b.AddFunction(_shaderSet.Name, sfab); } }
public override void VisitMethodDeclaration(MethodDeclarationSyntax node) { ShaderFunctionAndBlockSyntax 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); } } }
private void TraverseNode(HashSet <ShaderFunctionAndBlockSyntax> result, CallGraphNode node) { foreach (ShaderFunctionAndBlockSyntax 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); } ShaderFunctionAndBlockSyntax sfab = Utilities.GetShaderFunction(node.Declaration, Compilation, false); result.Add(sfab); }
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); ShaderFunctionAndBlockSyntax function = GetContext(setName).Functions .SingleOrDefault(sfabs => sfabs.Function.DeclaringType == type && sfabs.Function.Name == method); if (function != null) { string invocationList = string.Join(", ", parameterInfos.Select(ipi => CSharpToIdentifierNameCore(ipi.FullTypeName, ipi.Identifier))); string fullMethodName = CSharpToShaderType(function.Function.DeclaringType) + "_" + function.Function.Name; return($"{fullMethodName}({invocationList})"); } else { return(FormatInvocationCore(setName, type, method, parameterInfos)); } }
internal static ShaderFunctionAndBlockSyntax 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); ShaderFunctionAndBlockSyntax[] 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 ShaderFunctionAndBlockSyntax[0]; } return(new ShaderFunctionAndBlockSyntax(sf, node.Body, orderedFunctionList)); }
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()); }
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()); }