예제 #1
0
        private Dictionary <string, Function> ConvertFunctions(VulkanSpecification spec, ProfileConverterOptions opts)
        {
            var ret = new Dictionary <string, Function>();

            foreach (var function in spec.Commands)
            {
                ret.Add
                (
                    function.Name, new Function
                {
                    Name       = Naming.Translate(NameTrimmer.Trim(TrimName(function.Name, opts), opts.Prefix), opts.Prefix),
                    Parameters = function.Parameters.Select
                                 (
                        x => new Parameter
                    {
                        Count = x.IsNullTerminated ? null :
                                x.ElementCountSymbolic != null ? new Count(x.ElementCountSymbolic.Split(',')) :
                                new Count(x.ElementCount),
                        Flow = ConvertFlow(x.Modifier), Name = x.Name, Type = ConvertType(x.Type)
                    }
                                 )
                                 .ToList(),
                    NativeName = function.Name,
                    ReturnType = ConvertType(function.ReturnType)
                }
                );
            }

            return(ret);
        }
예제 #2
0
        /*********
        ** Public Methods
        *********/
        /// <summary>The application entry point.</summary>
        public static void Main()
        {
            // ensure vk.xml exists
            var vkXmlPath = Path.Combine(Environment.CurrentDirectory, "vk.xml");

            if (!File.Exists(vkXmlPath))
            {
                throw new FileNotFoundException($"{vkXmlPath} doesn't exist");
            }

            // parse xml file to specification object
            VulkanSpecification specification;

            using (var fileStream = File.OpenRead(vkXmlPath))
            {
                try
                {
                    specification = new VulkanSpecification(XDocument.Load(fileStream));
                }
                catch (Exception ex)
                {
                    Console.WriteLine($"Failed to parse XML file to VulkanSpecification {ex}");
                    return;
                }
            }

            // generate code
            CodeGenerator.GenerateCode(specification);
        }
예제 #3
0
        /*********
        ** Public Methods
        *********/
        /// <summary>Geenrates the C# files for a specification.</summary>
        /// <param name="specification">The specification to generate the code from.</param>
        public static void GenerateCode(VulkanSpecification specification)
        {
            var outputPath = "./Generated/";

            if (!Directory.Exists(outputPath))
            {
                Directory.CreateDirectory(outputPath);
            }

            GenerateVKFile(specification.Constants, specification.Commands, Path.Combine(outputPath, "VK.gen.cs"));
            GenerateEnumsFile(specification.Enums, Path.Combine(outputPath, "Enums.gen.cs"));
            GenerateDelegatesFile(specification.Delegates, Path.Combine(outputPath, "Delegates.gen.cs"));
            GenerateHandlesFile(specification.Handles, Path.Combine(outputPath, "Handles.gen.cs"));
            GenerateStructuresFile(specification.Structures, specification.Constants, Path.Combine(outputPath, "Structures.gen.cs"));
        }
예제 #4
0
        private Dictionary <string, Function> ConvertFunctions(VulkanSpecification spec, BindTask task)
        {
            var ret = new Dictionary <string, Function>();

            foreach (var function in spec.Commands)
            {
                ret.Add
                (
                    function.Name, new Function
                {
                    Name       = Naming.Translate(NameTrimmer.Trim(TrimName(function.Name, task), task.FunctionPrefix), task.FunctionPrefix),
                    Parameters = function.Parameters.Select
                                 (
                        x => new Parameter
                    {
                        Count = x.IsNullTerminated ? null :
                                x.ElementCountSymbolic != null ?
                                function.Parameters.Any(y => y.Name == x.ElementCountSymbolic)
                                            ? new(x.ElementCountSymbolic)
                                            : new(x.ElementCountSymbolic.Split(',')) :
                                new(x.ElementCount),
                        Flow = ConvertFlow(x.Modifier), Name = x.Name, Type = ConvertType(x.Type)
                    }
예제 #5
0
        private Dictionary <string, Struct> ConvertStructs(VulkanSpecification spec, BindTask task)
        {
            var prefix = task.FunctionPrefix;
            var ret    = new Dictionary <string, Struct>();

            // Gets all aliases of a struct, no matter where in an alias chain we start
            // Note this could be simpler if we just assume we only need to check $VKALIASES, but this
            // version is bombproof.
            IReadOnlyList <Struct> GetAllAliasesFromName(string structName)
            {
                var todo = new Queue <string>();

                todo.Enqueue(structName);
                var result = new Dictionary <string, Struct>();

                while (todo.Any())
                {
                    structName = todo.Dequeue();
                    if (!ret.TryGetValue(structName, out var s))
                    {
                        result[structName] = null;
                        continue;
                    }

                    result[structName] = s;

                    // Get any aliases
                    var aliasOf = s.Attributes
                                  .FirstOrDefault
                                  (
                        a => a.Arguments.Count > 1 && a.Name == "BuildToolsIntrinsic" &&
                        a.Arguments[0] == "$VKALIASOF"
                                  )
                                  ?.Arguments[1];
                    if (!string.IsNullOrWhiteSpace(aliasOf) && !result.ContainsKey(aliasOf))
                    {
                        todo.Enqueue(aliasOf);
                    }

                    // Check other way as well
                    foreach (var a in s.Attributes
                             .FirstOrDefault
                             (
                                 a => a.Arguments.Count > 1 && a.Name == "BuildToolsIntrinsic" &&
                                 a.Arguments[0] == "$VKALIASES"
                             )
                             ?.Arguments
                             .Skip(1)
                             .Where(a => !string.IsNullOrWhiteSpace(a) && !result.ContainsKey(a))
                             .ToArray()
                             ?? Array.Empty <string>())
                    {
                        todo.Enqueue(a);
                    }
                }

                return(result.Values.Where(s => s is not null).ToList());
            }

            // Opposite way round lookup of what aliases exist for this key-struct
            // i.e. if VkB is an alias of VkA, and VkC is an alias of VkA, then aliases has [VkA]={VkB,VkC}
            var aliases = new Dictionary <string, List <string> >();
            // Holds any chain starts for chains we haven't seen yet (should rarely be needed).
            var chainExtensions = new List <(Struct, IReadOnlyList <string>)>();

            foreach (var s in spec.Structures)
            {
                // Build aliases dictionary
                if (!string.IsNullOrWhiteSpace(s.Alias))
                {
                    if (!aliases.TryGetValue(s.Alias, out var aList))
                    {
                        aList            = new();
                        aliases[s.Alias] = aList;
                    }

                    aList.Add(s.Name);
                    continue;
                }

                var @struct = new Struct
                {
                    Fields = s.Members.Select
                             (
                        x => new Field
                    {
                        Count = string.IsNullOrEmpty(x.ElementCountSymbolic)
                                    ? x.ElementCount != 1 ? new Count(x.ElementCount) : null
                                    : new Count(x.ElementCountSymbolic, false),
                        Name              = Naming.Translate(TrimName(x.Name, task), prefix),
                        Doc               = $"/// <summary>{x.Comment}</summary>",
                        NativeName        = x.Name,
                        NativeType        = x.Type.ToString(),
                        Type              = ConvertType(x.Type),
                        DefaultAssignment =
                            (x.Type.Name == "VkStructureType" || x.Type.Name == "XrStructureType") &&
                            !string.IsNullOrWhiteSpace(x.LegalValues)
                                        ? "StructureType." + TryTrim
                            (
                                Naming.Translate
                                (
                                    TrimName(x.LegalValues.Split(',').FirstOrDefault(), task),
                                    task.FunctionPrefix
                                ),
                                Naming.TranslateLite(TrimName("VkStructureType", task), task.FunctionPrefix)
                            )
                                        : null,
                        NumBits = x.NumBits
                    }.WithFixedFieldFixup09072020()
                             )
                             .ToList(),
                    Name       = Naming.TranslateLite(TrimName(s.Name, task), prefix),
                    NativeName = s.Name
                };

                // Find the STYpe field (and it's position, which is required for IChainable
                var(sTypeField, sTypeFieldIndex) = @struct.Fields.Select((f, i) => (Field: f, Index: i))
                                                   .FirstOrDefault(f => f.Field.Name == "SType" && f.Field.Type.Name == "VkStructureType");
                if (sTypeField is not null)
                {
                    @struct.Attributes.Add
                    (
                        new()
                    {
                        Name      = "BuildToolsIntrinsic",
                        Arguments = new() { "$VKSTRUCTUREDTYPE", sTypeField.DefaultAssignment ?? string.Empty }
                    }
                    );

                    // Ensure SType was in position 0, and we have a pointer called PNext in position 1.
                    Field pNextField;
                    if (sTypeFieldIndex == 0 &&
                        @struct.Fields.Count > 1 &&
                        (pNextField = @struct.Fields[1]).Name == "PNext" &&
                        pNextField.Type.IsPointer)
                    {
                        // The type is at least chainable.
                        @struct.Attributes.Add
                        (
                            new()
                        {
                            Name      = "BuildToolsIntrinsic",
                            Arguments = new() { "$VKCHAINABLE" }
                        }
                        );

                        if (s.Extends.Any())
                        {
                            chainExtensions.Add((@struct, s.Extends));
                        }
                    }
                }

                ret.Add(s.Name, @struct);
            }

            // Create Aliases
            foreach (var(structName, aList) in aliases)
            {
                if (!ret.TryGetValue(structName, out var @struct))
                {
                    continue;
                }

                foreach (var alias in aList)
                {
                    var aliasStruct = @struct.Clone(Naming.TranslateLite(TrimName(alias, task), prefix), alias);
                    aliasStruct.Attributes.Add
                    (
                        new()
                    {
                        Name      = "BuildToolsIntrinsic",
                        Arguments = new() { "$VKALIASOF", @struct.NativeName }
                    }
                    );
                    // Create a clone for the alias
                    ret.Add(alias, aliasStruct);
                }

                // Now that we've finished cloning we can add the build intrinsic to the root struct.
                @struct.Attributes.Add
                (
                    new()
                {
                    Name      = "BuildToolsIntrinsic",
                    Arguments = new[] { "$VKALIASES" }.Concat(aList).ToList()
                }
                );
            }

            // Add chain extensions, we have to do this now to account for aliases, we
            if (chainExtensions.Any())
            {
                foreach (var(@struct, chainNames) in chainExtensions)
                {
                    // Get all the aliases of this struct (including this one)
                    var allStructs = GetAllAliasesFromName(@struct.NativeName);
                    // Get all the chains this struct extends (including their aliases)
                    var chains = chainNames.SelectMany(n => GetAllAliasesFromName(n)).ToArray();

                    // Add $VKEXTENDSCHAIN build tools intrinsic attribute to all versions of this struct
                    Attribute attribute = null;
                    foreach (var s in allStructs)
                    {
                        if (attribute is null)
                        {
                            // Create $VKEXTENDSCHAIN build tools intrinsic attribute
                            attribute = new()
                            {
                                Name      = "BuildToolsIntrinsic",
                                Arguments = new[] { "$VKEXTENDSCHAIN" }.Concat(chains.Select(c => c.Name)).ToList()
                            };
                        }
                        else
                        {
                            // Clone existing attribute.
                            attribute = attribute.Clone();
                        }

                        s.Attributes.Add(attribute);
                    }

                    // Add chain starts to all chains and their aliases
                    attribute = null;
                    foreach (var c in chains)
                    {
                        if (attribute is null)
                        {
                            // Create $VKEXTENDSCHAIN build tools intrinsic attribute
                            attribute = new()
                            {
                                Name      = "BuildToolsIntrinsic",
                                Arguments = new[] { "$VKCHAINSTART" }.Concat(allStructs.Select(s => s.Name)).ToList()
                            };
                        }
                        else
                        {
                            // Clone existing attribute.
                            attribute = attribute.Clone();
                        }

                        c.Attributes.Add(attribute);
                    }
                }
            }

            foreach (var h in spec.Handles)
            {
                ret.Add
                (
                    h.Name, new Struct
                {
                    Fields = new List <Field>
                    {
                        new Field {
                            Name = "Handle", Type = new Type {
                                Name = h.CanBeDispatched ? "nint" : "ulong"
                            }
                        }
                    },
                    Name       = Naming.TranslateLite(TrimName(h.Name, task), prefix),
                    NativeName = h.Name
                }
                );
            }

            foreach (var u in spec.Unions)
            {
                ret.Add
                (
                    u.Name, new Struct
                {
                    Attributes = new List <Attribute>
                    {
                        new Attribute {
                            Name = "StructLayout", Arguments = new List <string> {
                                "LayoutKind.Explicit"
                            }
                        }
                    },
                    Fields     = GetFields(u, task).ToList(),
                    Name       = Naming.TranslateLite(TrimName(u.Name, task), prefix),
                    NativeName = u.Name
                }
                );
            }

            return(ret);
        }
예제 #6
0
 /// <inheritdoc />
 public object Load(Stream stream)
 {
     return(VulkanSpecification.LoadFromXmlStream(stream));
 }
예제 #7
0
        private Dictionary <string, Struct> ConvertStructs(VulkanSpecification spec, ProfileConverterOptions opts)
        {
            var prefix = opts.Prefix;
            var ret    = new Dictionary <string, Struct>();

            foreach (var s in spec.Structures)
            {
                ret.Add
                (
                    s.Name, new Struct
                {
                    Fields = s.Members.Select
                             (
                        x => new Field
                    {
                        Count = string.IsNullOrEmpty(x.ElementCountSymbolic)
                                        ? x.ElementCount != 1 ? new Count(x.ElementCount) : null
                                        : new Count(x.ElementCountSymbolic, false),
                        Name              = Naming.Translate(TrimName(x.Name, opts), prefix),
                        Doc               = $"/// <summary>{x.Comment}</summary>",
                        NativeName        = x.Name,
                        NativeType        = x.Type.ToString(),
                        Type              = ConvertType(x.Type),
                        DefaultAssignment =
                            x.Type.Name == "VkStructureType" && !string.IsNullOrWhiteSpace(x.LegalValues)
                                            ? "StructureType." + TryTrim
                            (
                                Naming.Translate
                                (
                                    TrimName(x.LegalValues.Split(',').FirstOrDefault(), opts),
                                    opts.Prefix
                                ),
                                Naming.TranslateLite(TrimName("VkStructureType", opts), opts.Prefix)
                            )
                                            : null
                    }
                             )
                             .ToList(),
                    Name       = Naming.TranslateLite(TrimName(s.Name, opts), prefix),
                    NativeName = s.Name
                }
                );
            }

            foreach (var h in spec.Handles)
            {
                ret.Add
                (
                    h.Name, new Struct
                {
                    Fields = new List <Field>
                    {
                        new Field {
                            Name = "Handle", Type = new Type {
                                Name = h.CanBeDispatched ? "IntPtr" : "ulong"
                            }
                        }
                    },
                    Name       = Naming.TranslateLite(TrimName(h.Name, opts), prefix),
                    NativeName = h.Name
                }
                );
            }

            foreach (var u in spec.Unions)
            {
                ret.Add(u.Name, new Struct
                {
                    Attributes = new List <Attribute> {
                        new Attribute {
                            Name = "StructLayout", Arguments = new List <string> {
                                "LayoutKind.Explicit"
                            }
                        }
                    },
                    Fields     = GetFields(u, opts).ToList(),
                    Name       = Naming.TranslateLite(TrimName(u.Name, opts), prefix),
                    NativeName = u.Name
                });
            }

            return(ret);
        }