示例#1
0
        // Generate bitmask types
        private static void GenerateBitmasks(Vendor vendor)
        {
            if (vendor.Bitmasks.Count == 0)
            {
                return;
            }

            // Make path and file context
            var vpath = vendor.IsCore ? "Bitmasks.cs" : Path.Combine(vendor.Tag, "Bitmasks.cs");

            using var file = new SourceFile(vpath);

            // For each bitmask
            foreach (var type in vendor.Bitmasks.Values)
            {
                // Open block
                file.WriteLine("[Flags]");
                using var block = file.PushBlock($"public enum {type.Name} : uint");

                // Write values
                foreach (var entry in type.Entries)
                {
                    block.WriteLine($"{entry.Name} = {entry.Value},");
                }
            }
        }
示例#2
0
        public SourceBlock PushBlock(string?header)
        {
            if (header is not null)
            {
                File.WriteLine(header);
            }
            File.WriteLine("{");

            File.PushBlock(Depth);
            return(new(File));
        }
示例#3
0
        // Generate struct types
        private static void GenerateStructs(Vendor vendor)
        {
            if (vendor.Structs.Count == 0)
            {
                return;
            }

            // Make path and file context
            var vpath = vendor.IsCore ? "Structs.cs" : Path.Combine(vendor.Tag, "Structs.cs");

            using var file = new SourceFile(vpath);

            // For each struct
            List <string> ctorArgs    = new();
            List <string> ctorAssigns = new();
            List <string> hashes      = new();
            List <string> comparisons = new();

            foreach (var @struct in vendor.Structs.Values)
            {
                // Open block
                file.WriteLine($"[StructLayout(LayoutKind.{(@struct.IsUnion ? "Explicit" : "Sequential")})]");
                using var block = file.PushBlock($"public unsafe partial struct {@struct.Name} : IEquatable<{@struct.Name}>");

                // Typed structs
                if (@struct.IsTyped)
                {
                    block.WriteLine($"public const VkStructureType TYPE = VkStructureType.{@struct.Type!};");
                    block.WriteLine();
                }

                // Fields (and ctor arguments)
                ctorArgs.Clear();
                ctorAssigns.Clear();
                hashes.Clear();
                comparisons.Clear();
                foreach (var field in @struct.Fields)
                {
                    var lower = NameHelper.GetSafeArgName(field.Name);
                    if (field.ArraySize is not null)
                    {
                        if (field.IsFixed)
                        {
                            if (@struct.IsUnion)
                            {
                                block.WriteLine("[FieldOffset(0)]");
                            }
                            block.WriteLine($"public fixed {field.Type} {field.Name}[{field.ArraySize}];");
                            for (uint i = 0; i < field.ArraySize; ++i)
                            {
                                ctorArgs.Add($"{field.Type} {lower}_{i} = default");
                                ctorAssigns.Add($"{field.Name}[{i}] = {lower}_{i};");
                                hashes.Add($"{field.Name}[{i}].GetHashCode()");
                                comparisons.Add($"(l.{field.Name}[{i}] == r.{field.Name}[{i}])");
                            }
                        }
                        else
                        {
                            for (uint i = 0; i < field.ArraySize; ++i)
                            {
                                block.WriteLine($"public {field.Type} {field.Name}_{i};");
                                ctorArgs.Add($"{field.Type} {lower}_{i} = default");
                                ctorAssigns.Add($"{field.Name}_{i} = {lower}_{i};");
                                hashes.Add($"{field.Name}_{i}.GetHashCode()");
                                comparisons.Add($"(l.{field.Name}_{i} == r.{field.Name}_{i})");
                            }
                        }
                    }
                    else
                    {
                        if (@struct.IsUnion)
                        {
                            block.WriteLine("[FieldOffset(0)]");
                        }
                        block.WriteLine($"public {field.Type} {field.Name};");
                        if (field.Name == "sType")
                        {
                            ctorAssigns.Add("sType = TYPE;");
                        }
                        else if (field.Name == "pNext")
                        {
                            ctorAssigns.Add("pNext = null;");
                        }
                        else
                        {
                            ctorArgs.Add($"{field.Type} {lower} = default");
                            ctorAssigns.Add($"{field.Name} = {lower};");
                        }
                        var isPtr = field.Type.Contains('*');
                        hashes.Add(isPtr ? $"((ulong){field.Name}).GetHashCode()" : $"{field.Name}.GetHashCode()");
                        comparisons.Add($"(l.{field.Name} == r.{field.Name})");
                    }
                }
                block.WriteLine();

                // Ctor
                if ([email protected] && ([email protected] || (@struct.Fields.Count > 2)))
                {
                    block.WriteLine($"public {@struct.Name}(");
                    for (int i = 0; i < ctorArgs.Count; ++i)
                    {
                        block.WriteLine($"\t{ctorArgs[i]}{((i == ctorArgs.Count - 1) ? "" : ",")}");
                    }
                    block.WriteLine(") {");
                    foreach (var line in ctorAssigns)
                    {
                        block.WriteLine('\t' + line);
                    }
                    block.WriteLine("}");
                    block.WriteLine();
                }
                else if (@struct.IsUnion)
                {
                    foreach (var field in @struct.Fields)
                    {
                        var fname = NameHelper.GetSafeArgName(field.Name);
                        if (field.ArraySize is not null)
                        {
                            block.WriteLine($"public {@struct.Name}(");
                            for (uint i = 0; i < field.ArraySize; ++i)
                            {
                                block.WriteLine($"\tin {field.Type} {fname}_{i}{((i != field.ArraySize - 1) ? ", " : "")}");
                            }
                            block.WriteLine(") {");
                            for (uint i = 0; i < field.ArraySize; ++i)
                            {
                                block.WriteLine('\t' + (field.IsFixed ? $"{field.Name}[{i}]" : $"{field.Name}_{i}") + $" = {fname}_{i};");
                            }
                            block.WriteLine("}");
                        }
                        else
                        {
                            block.WriteLine($"public {@struct.Name}(in {field.Type} {fname}) : this() => {field.Name} = {fname};");
                        }
                        block.WriteLine();
                    }
                }

                // Equality
                block.WriteLine($"public readonly override bool Equals(object? o) => (o is {@struct.Name} s) && (this == s);");
                block.WriteLine($"readonly bool IEquatable<{@struct.Name}>.Equals({@struct.Name} o) => o == this;");
                block.WriteLine();

                // Hash code
                block.WriteLine("[MethodImpl(MethodImplOptions.AggressiveOptimization)]");
                using (var hash = block.PushBlock("public readonly override int GetHashCode()")) {
                    hash.WriteLine("return");
                    for (int i = 0; i < hashes.Count; i += 4)
                    {
                        hash.WriteLine('\t' + (i != 0 ? "^ " : "") + String.Join(" ^ ", hashes.Skip(i).Take(4)));
                    }
                    hash.WriteLine("\t;");
                }

                // Equality operators
                block.WriteLine("[MethodImpl(MethodImplOptions.AggressiveOptimization)]");
                using (var op = block.PushBlock($"public static bool operator == (in {@struct.Name} l, in {@struct.Name} r)")) {
                    op.WriteLine("return");
                    for (int i = 0; i < comparisons.Count; i += 4)
                    {
                        op.WriteLine('\t' + (i != 0 ? "&& " : "") + String.Join(" && ", comparisons.Skip(i).Take(4)));
                    }
                    op.WriteLine("\t;");
                }
                block.WriteLine("[MethodImpl(MethodImplOptions.AggressiveOptimization)]");
                using (var op = block.PushBlock($"public static bool operator != (in {@struct.Name} l, in {@struct.Name} r)")) {
                    op.WriteLine("return");
                    for (int i = 0; i < comparisons.Count; i += 4)
                    {
                        op.WriteLine('\t' + (i != 0 ? "|| " : "") + String.Join(" || ",
                                                                                comparisons.Skip(i).Take(4).Select(cmp => cmp.Replace("==", "!="))));
                    }
                    op.WriteLine("\t;");
                }

                if ([email protected])
                {
                    // New function
                    block.WriteLine("[MethodImpl(MethodImplOptions.AggressiveInlining)]");
                    if (@struct.IsTyped)
                    {
                        block.WriteLine($"public static void New(out {@struct.Name} s) => s = new() {{ sType = TYPE }};");
                    }
                    else
                    {
                        block.WriteLine($"public static void New(out {@struct.Name} s) => s = new();");
                    }
                }
            }
        }