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