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); }
internal override void AddResource(string setName, ResourceDefinition rd) { if (rd.ResourceKind == ShaderResourceKind.Uniform) { _uniformNames.Add(rd.Name); } if (rd.ResourceKind == ShaderResourceKind.StructuredBuffer || rd.ResourceKind == ShaderResourceKind.RWStructuredBuffer) { _ssboNames.Add(rd.Name); } base.AddResource(setName, rd); }
public override void VisitVariableDeclaration(VariableDeclarationSyntax node) { if (node.Variables.Count != 1) { throw new ShaderGenerationException("Cannot declare multiple variables together."); } VariableDeclaratorSyntax vds = node.Variables[0]; string resourceName = vds.Identifier.Text; TypeInfo typeInfo = GetModel(node).GetTypeInfo(node.Type); string fullTypeName = GetModel(node).GetFullTypeName(node.Type); TypeReference valueType = new TypeReference(fullTypeName, typeInfo); ShaderResourceKind kind = ClassifyResourceKind(fullTypeName); if (kind == ShaderResourceKind.StructuredBuffer || kind == ShaderResourceKind.RWStructuredBuffer || kind == ShaderResourceKind.RWTexture2D) { valueType = ParseElementType(vds); } int set = 0; // Default value if not otherwise specified. if (GetResourceDecl(node, out AttributeSyntax resourceSetDecl)) { set = GetAttributeArgumentIntValue(resourceSetDecl, 0, GetModel(node)); } int resourceBinding = GetAndIncrementBinding(set); ResourceDefinition rd = new ResourceDefinition(resourceName, set, resourceBinding, valueType, kind); if (kind == ShaderResourceKind.Uniform) { ValidateResourceType(typeInfo); } foreach (LanguageBackend b in _backends) { b.AddResource(_shaderSet.Name, rd); } }
internal virtual void AddResource(string setName, ResourceDefinition rd) { if (rd == null) { throw new ArgumentNullException(nameof(rd)); } if (rd.ResourceKind == ShaderResourceKind.Local) { GetContext(setName).Statics.Add(rd); } else { var context = GetContext(setName); var structure = context.Structures.FirstOrDefault(s => s.Name == rd.ValueType.Name); if (structure == null || structure.Fields.All(f => !f.IsBuiltIn)) { context.Resources.Add(rd); } } }
protected override void WriteTextureCube(StringBuilder sb, ResourceDefinition rd) { sb.AppendLine($"uniform samplerCube {CorrectIdentifier(rd.Name)};"); sb.AppendLine(); }
protected override void WriteSampler(StringBuilder sb, ResourceDefinition rd) { }
protected abstract void WriteTextureCube(StringBuilder sb, ResourceDefinition rd);
protected abstract void WriteSampler(StringBuilder sb, ResourceDefinition rd);
protected abstract void WriteUniform(StringBuilder sb, ResourceDefinition rd);
private string FormatLayoutStr(ResourceDefinition rd) { return($"layout(binding = {rd.Binding})"); }
private void WriteRWStructuredBuffer(StringBuilder sb, ResourceDefinition rd, int binding) { sb.AppendLine($"RWStructuredBuffer<{CSharpToShaderType(rd.ValueType.Name)}> {CorrectIdentifier(rd.Name)}: register(u{binding});"); }
private void WriteTexture2DMS(StringBuilder sb, ResourceDefinition rd, int binding) { sb.AppendLine($"Texture2DMS<float4> {CorrectIdentifier(rd.Name)} : register(t{binding});"); sb.AppendLine(); }
private void WriteSampler(StringBuilder sb, ResourceDefinition rd, int binding) { sb.AppendLine($"SamplerState {CorrectIdentifier(rd.Name)} : register(s{binding});"); sb.AppendLine(); }
public override void VisitVariableDeclaration(VariableDeclarationSyntax node) { if (node.Variables.Count != 1) { throw new ShaderGenerationException("Cannot declare multiple variables together."); } VariableDeclaratorSyntax vds = node.Variables[0]; string resourceName = vds.Identifier.Text; TypeInfo typeInfo = GetModel(node).GetTypeInfo(node.Type); string fullTypeName = GetModel(node).GetFullTypeName(node.Type); TypeReference valueType = new TypeReference(fullTypeName, typeInfo.Type); ShaderResourceKind kind = ClassifyResourceKind(fullTypeName); var structure = _backends.Select(b => b.GetContext(_shaderSet.Name).Structures .FirstOrDefault(s => SymbolEqualityComparer.Default.Equals(s.Type, typeInfo.Type))) .FirstOrDefault(); if (structure != null && structure.Fields.Any(f => f.IsBuiltIn)) { kind = ShaderResourceKind.BuiltIn; } ShaderBuiltin builtin = default; if (kind == ShaderResourceKind.Uniform) { if (node.Parent is FieldDeclarationSyntax field) { if (field.Modifiers.Any(f => f.IsKind(SyntaxKind.PrivateKeyword))) { kind = ShaderResourceKind.Local; } else if (field.AttributeLists.Any(l => l.Attributes.Any(a => a.Name.ToString().Contains("Semantic")))) { kind = ShaderResourceKind.BuiltIn; SemanticType semanticType = GetSemanticType(vds); if (semanticType == SemanticType.None) { var geometrySemantic = GetGeometrySemantic(vds); if (geometrySemantic != GeometrySemantic.None) { builtin = new ShaderBuiltin(geometrySemantic); } } else { builtin = new ShaderBuiltin(semanticType); } } } else if (typeInfo.Type.GetAttributes().Any(a => a.AttributeClass.Name.Contains("Semantic"))) { kind = ShaderResourceKind.BuiltIn; } } if (kind == ShaderResourceKind.StructuredBuffer || kind == ShaderResourceKind.RWStructuredBuffer || kind == ShaderResourceKind.RWTexture2D || valueType.Name.Contains(nameof(UniformBuffer <int>))) { valueType = ParseElementType(vds); } if (node.Parent is FieldDeclarationSyntax) { var arraySize = node.Parent.DescendantNodes().OfType <AttributeSyntax>().FirstOrDefault( attrSyntax => attrSyntax.Name.ToString().EndsWith("ArraySize")); if (arraySize != null) { var fixedSize = (int)GetModel(node).GetConstantValue(arraySize.ArgumentList.Arguments.First().Expression).Value; valueType = new TypeReference(valueType.Name, valueType.TypeInfo, fixedSize); } var emitAttribute = node.Parent.DescendantNodes().OfType <AttributeSyntax>().FirstOrDefault( attrSyntax => attrSyntax.Name.ToString().EndsWith("EmitVertex")); if (emitAttribute != null) { kind = ShaderResourceKind.Emit; } } ResourceDefinition rd; if (kind == ShaderResourceKind.Local) { rd = new ResourceDefinition(resourceName, 0, 0, valueType, kind); } else { int set = 0; // Default value if not otherwise specified. if (GetResourceDecl(node, out AttributeSyntax resourceSetDecl)) { set = GetAttributeArgumentIntValue(resourceSetDecl, 0, GetModel(node)); } int resourceBinding = GetAndIncrementBinding(set); if (kind == ShaderResourceKind.Uniform) { ValidateUniformType(typeInfo); } rd = new ResourceDefinition(resourceName, set, resourceBinding, valueType, kind); } rd.Semantic = builtin.Semantic; foreach (LanguageBackend b in _backends) { b.AddResource(_shaderSet.Name, rd); } }
private string FormatLayoutStr(ResourceDefinition rd, string storageSpec = null) { string storageSpecPart = storageSpec != null ? $"{storageSpec}, " : string.Empty; return($"layout({storageSpecPart}set = {rd.Set}, binding = {rd.Binding})"); }
protected abstract void WriteStructuredBuffer(StringBuilder sb, ResourceDefinition rd, bool isReadOnly);