public StructureDefinition(ITypeSymbol type, FieldDefinition[] fields, AlignmentInfo?size = null) { Type = type ?? throw new ArgumentNullException(nameof(type)); Name = type.GetFullMetadataName(); Fields = fields; Alignment = size ?? TypeSizeCache.Get(type); if (Alignment.CSharpSize == Alignment.ShaderSize) { CSharpMatchesShaderAlignment = true; } else { CSharpMatchesShaderAlignment = GetCSharpMatchesShaderAlignment(); } }
public static bool TryGetStructDefinition(SemanticModel model, StructDeclarationSyntax node, out StructureDefinition sd) { string fullNestedTypePrefix = Utilities.GetFullNestedTypePrefix(node, out bool nested); string structName = node.Identifier.ToFullString().Trim(); if (!string.IsNullOrEmpty(fullNestedTypePrefix)) { string joiner = nested ? "+" : "."; structName = fullNestedTypePrefix + joiner + structName; } int structCSharpSize = 0; int structShaderSize = 0; int structCSharpAlignment = 0; int structShaderAlignment = 0; List <FieldDefinition> fields = new List <FieldDefinition>(); foreach (MemberDeclarationSyntax member in node.Members) { if (member is FieldDeclarationSyntax fds && !fds.Modifiers.Any(x => x.IsKind(SyntaxKind.ConstKeyword))) { VariableDeclarationSyntax varDecl = fds.Declaration; foreach (VariableDeclaratorSyntax vds in varDecl.Variables) { string fieldName = vds.Identifier.Text.Trim(); string typeName = model.GetFullTypeName(varDecl.Type, out bool isArray); int arrayElementCount = 0; if (isArray) { arrayElementCount = GetArrayCountValue(vds, model); } TypeInfo typeInfo = model.GetTypeInfo(varDecl.Type); AlignmentInfo fieldSizeAndAlignment; if (typeInfo.Type.Kind == SymbolKind.ArrayType) { ITypeSymbol elementType = ((IArrayTypeSymbol)typeInfo.Type).ElementType; AlignmentInfo elementSizeAndAlignment = TypeSizeCache.Get(elementType); fieldSizeAndAlignment = new AlignmentInfo( elementSizeAndAlignment.CSharpSize * arrayElementCount, elementSizeAndAlignment.ShaderSize * arrayElementCount, elementSizeAndAlignment.CSharpAlignment, elementSizeAndAlignment.ShaderAlignment); } else { fieldSizeAndAlignment = TypeSizeCache.Get(typeInfo.Type); } structCSharpSize += structCSharpSize % fieldSizeAndAlignment.CSharpAlignment; structCSharpSize += fieldSizeAndAlignment.CSharpSize; structCSharpAlignment = Math.Max(structCSharpAlignment, fieldSizeAndAlignment.CSharpAlignment); structShaderSize += structShaderSize % fieldSizeAndAlignment.ShaderAlignment; structShaderSize += fieldSizeAndAlignment.ShaderSize; structShaderAlignment = Math.Max(structShaderAlignment, fieldSizeAndAlignment.ShaderAlignment); TypeReference tr = new TypeReference(typeName, model.GetTypeInfo(varDecl.Type).Type); SemanticType semanticType = GetSemanticType(vds); fields.Add(new FieldDefinition(fieldName, tr, semanticType, arrayElementCount, fieldSizeAndAlignment)); } } } sd = new StructureDefinition( structName.Trim(), fields.ToArray(), new AlignmentInfo(structCSharpSize, structShaderSize, structCSharpAlignment, structShaderAlignment)); return(true); }
public static bool TryGetStructDefinition(SemanticModel model, StructDeclarationSyntax node, out StructureDefinition sd) { //string fullNestedTypePrefix = Utilities.GetFullNestedTypePrefix(node, out bool nested); //string structName = node.Identifier.ToFullString().Trim(); //if (!string.IsNullOrEmpty(fullNestedTypePrefix)) //{ // string joiner = nested ? "+" : "."; // structName = fullNestedTypePrefix + joiner + structName; //} int structCSharpSize = 0; int structShaderSize = 0; int structCSharpAlignment = 0; int structShaderAlignment = 0; List <FieldDefinition> fields = new List <FieldDefinition>(); foreach (MemberDeclarationSyntax member in node.Members) { if (member is FieldDeclarationSyntax fds && !fds.Modifiers.Any(x => x.IsKind(SyntaxKind.ConstKeyword))) { VariableDeclarationSyntax varDecl = fds.Declaration; foreach (VariableDeclaratorSyntax vds in varDecl.Variables) { string fieldName = vds.Identifier.Text.Trim(); string typeName = model.GetFullTypeName(varDecl.Type, out bool isArray); int arrayElementCount = 0; if (isArray) { arrayElementCount = GetArrayCountValue(vds, model); } TypeInfo typeInfo = model.GetTypeInfo(varDecl.Type); AlignmentInfo fieldSizeAndAlignment; int fixedSize = 1; if (typeInfo.Type.Kind == SymbolKind.ArrayType) { var arraySize = fds.DescendantNodes().OfType <AttributeSyntax>().FirstOrDefault( attrSyntax => attrSyntax.Name.ToString().EndsWith("ArraySize")); fixedSize = (int)model.GetConstantValue(arraySize.ArgumentList.Arguments.First().Expression).Value; ITypeSymbol elementType = ((IArrayTypeSymbol)typeInfo.Type).ElementType; AlignmentInfo elementSizeAndAlignment = TypeSizeCache.Get(elementType); fieldSizeAndAlignment = new AlignmentInfo( elementSizeAndAlignment.CSharpSize * arrayElementCount, elementSizeAndAlignment.ShaderSize * arrayElementCount, elementSizeAndAlignment.CSharpAlignment, elementSizeAndAlignment.ShaderAlignment); } else { fieldSizeAndAlignment = TypeSizeCache.Get(typeInfo.Type); } structCSharpSize += structCSharpSize % fieldSizeAndAlignment.CSharpAlignment; structCSharpSize += fieldSizeAndAlignment.CSharpSize; structCSharpAlignment = Math.Max(structCSharpAlignment, fieldSizeAndAlignment.CSharpAlignment); structShaderSize += structShaderSize % fieldSizeAndAlignment.ShaderAlignment; structShaderSize += fieldSizeAndAlignment.ShaderSize; structShaderAlignment = Math.Max(structShaderAlignment, fieldSizeAndAlignment.ShaderAlignment); TypeReference tr = new TypeReference(typeName, model.GetTypeInfo(varDecl.Type).Type, fixedSize); SemanticType semanticType = GetSemanticType(vds); if (semanticType == SemanticType.None) { var geometrySemantic = GetGeometrySemantic(vds); if (geometrySemantic != GeometrySemantic.None) { fields.Add(new FieldDefinition(fieldName, tr, geometrySemantic, arrayElementCount, fieldSizeAndAlignment)); continue; } } fields.Add(new FieldDefinition(fieldName, tr, semanticType, arrayElementCount, fieldSizeAndAlignment)); } } } var type = model.GetDeclaredSymbol(node); sd = new StructureDefinition( type, fields.ToArray(), new AlignmentInfo(structCSharpSize, structShaderSize, structCSharpAlignment, structShaderAlignment)); return(true); }
private FieldDefinition ReflectField(IFieldSymbol field) { int fixedSize; AlignmentInfo fieldSizeAndAlignment; if (field.Type is IArrayTypeSymbol arrayType) { var elementSizeAndAlignment = TypeSizeCache.Get(arrayType.ElementType); var arraySizeAttribute = field.GetAttributes().Single(a => a.AttributeClass.Name == nameof(ArraySizeAttribute)); fixedSize = (int)arraySizeAttribute.ConstructorArguments[0].Value; fieldSizeAndAlignment = new AlignmentInfo( elementSizeAndAlignment.CSharpSize * fixedSize, elementSizeAndAlignment.ShaderSize * fixedSize, elementSizeAndAlignment.CSharpAlignment, elementSizeAndAlignment.ShaderAlignment); } else { fixedSize = 0; fieldSizeAndAlignment = TypeSizeCache.Get(field.Type); } SemanticType semantic = SemanticType.None; var semanticAttribute = field.GetAttributes().SingleOrDefault(a => a.AttributeClass.Name.Contains("Semantic")); if (semanticAttribute != null) { switch (semanticAttribute.AttributeClass.Name) { case nameof(PositionSemanticAttribute): semantic = SemanticType.Position; break; case nameof(SystemPositionSemanticAttribute): semantic = SemanticType.SystemPosition; break; case nameof(ColorSemanticAttribute): semantic = SemanticType.Color; break; case nameof(ColorTargetSemanticAttribute): semantic = SemanticType.ColorTarget; break; case nameof(NormalSemanticAttribute): semantic = SemanticType.Normal; break; case nameof(TangentSemanticAttribute): semantic = SemanticType.Tangent; break; case nameof(TextureCoordinateSemanticAttribute): semantic = SemanticType.TextureCoordinate; break; case nameof(GeometrySemanticAttribute): var geometrySemantic = semanticAttribute.ConstructorArguments.First(); return(new FieldDefinition(field.Name, new TypeReference(field.Type.GetFullMetadataName(), field.Type, fixedSize), (GeometrySemantic)Enum.ToObject(typeof(GeometrySemantic), geometrySemantic.Value), fixedSize, fieldSizeAndAlignment)); default: throw new NotSupportedException(); } } return(new FieldDefinition(field.Name, new TypeReference(field.Type.GetFullMetadataName(), field.Type, fixedSize), semantic, fixedSize, fieldSizeAndAlignment)); }