コード例 #1
0
ファイル: Helpers.cs プロジェクト: Gaiaxis/Vulkan.NET
        public static string ConvertToCSharpType(string type, int pointerlevel, VulkanSpecification spec)
        {
            string memberType = type;

            if (type.StartsWith("PFN") || IsIntPtr(memberType))
            {
                return("IntPtr");
            }

            string result = ConvertBasicTypes(memberType);

            if (result == string.Empty)
            {
                if (spec.Alias.TryGetValue(memberType, out string alias))
                {
                    memberType = alias;
                }

                spec.BaseTypes.TryGetValue(memberType, out string baseType);
                if (baseType != null)
                {
                    result = ConvertBasicTypes(baseType);
                }
                else
                {
                    var typeDef = spec.TypeDefs.Find(t => t.Name == memberType);
                    if (typeDef != null)
                    {
                        if (typeDef.Requires != null)
                        {
                            result = typeDef.Requires;
                        }
                        else
                        {
                            spec.BaseTypes.TryGetValue(typeDef.Type, out baseType);
                            if (baseType != null)
                            {
                                result = ConvertBasicTypes(baseType);
                            }
                        }
                    }
                    else
                    {
                        result = memberType;
                    }
                }
            }

            if (pointerlevel > 0)
            {
                for (int i = 0; i < pointerlevel; i++)
                {
                    result += "*";
                }
            }

            return(result);
        }
コード例 #2
0
        public string GetParametersSignature(VulkanSpecification spec, bool useTypes = true)
        {
            StringBuilder signature = new StringBuilder();

            foreach (var p in Parameters)
            {
                string convertedType = Helpers.GetPrettyEnumName(Helpers.ConvertToCSharpType(p.Type, p.PointerLevel, spec));
                string convertedName = Helpers.ValidatedName(p.Name);

                if (useTypes)
                {
                    signature.Append($"{convertedType} ");
                }

                signature.Append($"{convertedName}, ");
            }

            signature.Length -= 2;

            return(signature.ToString());
        }
コード例 #3
0
        static void Main(string[] args)
        {
            string vkFile     = "..\\..\\..\\..\\..\\..\\KhronosRegistry\\vk.xml";
            string outputPath = "..\\..\\..\\..\\WaveEngine.Bindings.Vulkan\\Generated";

            var vulkanSpec = VulkanSpecification.FromFile(vkFile);

            var vulkanVersion = VulkanVersion.FromSpec(vulkanSpec, "AllVersions", vulkanSpec.Extensions.ToImmutableList());

            // Write Constants
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Constants.cs")))
            {
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");
                file.WriteLine("\tpublic static partial class Vulkan");
                file.WriteLine("\t{");

                foreach (var constant in vulkanVersion.Constants)
                {
                    if (constant.Alias != null)
                    {
                        var refConstant = vulkanVersion.Constants.FirstOrDefault(c => c.Name == constant.Alias);
                        file.WriteLine($"\t\tpublic const {refConstant.Type.ToCSharp()} {constant.Name} = {refConstant.Name};");
                    }
                    else
                    {
                        file.WriteLine($"\t\tpublic const {constant.Type.ToCSharp()} {constant.Name} = {ConstantDefinition.NormalizeValue(constant.Value)};");
                    }
                }

                file.WriteLine("\t}");
                file.WriteLine("}");
            }

            // Delegates
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Delegates.cs")))
            {
                file.WriteLine("using System;\n");
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");

                foreach (var func in vulkanVersion.FuncPointers)
                {
                    file.Write($"\tpublic unsafe delegate {func.Type} {func.Name}(");
                    if (func.Parameters.Count > 0)
                    {
                        file.Write("\n");
                        string type, convertedType;

                        for (int p = 0; p < func.Parameters.Count; p++)
                        {
                            if (p > 0)
                            {
                                file.Write(",\n");
                            }

                            type = func.Parameters[p].Type;
                            var typeDef = vulkanSpec.TypeDefs.Find(t => t.Name == type);
                            if (typeDef != null)
                            {
                                vulkanSpec.BaseTypes.TryGetValue(typeDef.Type, out type);
                            }

                            convertedType = Helpers.ConvertBasicTypes(type);
                            if (convertedType == string.Empty)
                            {
                                convertedType = type;
                            }

                            file.Write($"\t\t{convertedType} {Helpers.ValidatedName(func.Parameters[p].Name)}");
                        }
                    }
                    file.Write(");\n\n");
                }

                file.WriteLine("}");
            }

            // Enums
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Enums.cs")))
            {
                file.WriteLine("using System;\n");
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");

                foreach (var e in vulkanVersion.Enums)
                {
                    if (e.Type == EnumType.Bitmask)
                    {
                        file.WriteLine("\t[Flags]");
                    }

                    file.WriteLine($"\tpublic enum {e.Name}");
                    file.WriteLine("\t{");

                    if (e.Values.Count == 0)
                    {
                        file.WriteLine("\t\tNone = 0,");
                    }
                    else
                    {
                        foreach (var member in e.Values)
                        {
                            file.WriteLine($"\t\t{member.Name} = {member.Value},");
                        }
                    }

                    file.WriteLine("\t}\n");
                }

                file.WriteLine("}");
            }

            // Unions
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Unions.cs")))
            {
                file.WriteLine("using System.Runtime.InteropServices;\n");
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");

                foreach (var union in vulkanVersion.Unions)
                {
                    file.WriteLine("\t[StructLayout(LayoutKind.Explicit)]");
                    file.WriteLine($"\tpublic unsafe partial struct {union.Name}");
                    file.WriteLine("\t{");
                    foreach (var member in union.Members)
                    {
                        string csType = Helpers.ConvertToCSharpType(member.Type, member.PointerLevel, vulkanSpec);

                        file.WriteLine($"\t\t[FieldOffset(0)]");
                        if (member.ElementCount > 1)
                        {
                            file.WriteLine($"\t\tpublic unsafe fixed {csType} {member.Name}[{member.ElementCount}];");
                        }
                        else
                        {
                            file.WriteLine($"\t\tpublic {csType} {member.Name};");
                        }
                    }

                    file.WriteLine("\t}\n");
                }

                file.WriteLine("}\n");
            }

            // structs
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Structs.cs")))
            {
                file.WriteLine("using System;");
                file.WriteLine("using System.Runtime.InteropServices;\n");
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");

                foreach (var structure in vulkanVersion.Structs)
                {
                    file.WriteLine("\t[StructLayout(LayoutKind.Sequential)]");
                    file.WriteLine($"\tpublic unsafe partial struct {structure.Name}");
                    file.WriteLine("\t{");
                    foreach (var member in structure.Members)
                    {
                        string csType = Helpers.ConvertToCSharpType(member.Type, member.PointerLevel, vulkanSpec);

                        if (member.ElementCount > 1)
                        {
                            for (int i = 0; i < member.ElementCount; i++)
                            {
                                file.WriteLine($"\t\tpublic {csType} {member.Name}_{i};");
                            }
                        }
                        else if (member.ConstantValue != null)
                        {
                            var validConstant = vulkanVersion.Constants.FirstOrDefault(c => c.Name == member.ConstantValue);

                            if (Helpers.SupportFixed(csType))
                            {
                                file.WriteLine($"\t\tpublic fixed {csType} {Helpers.ValidatedName(member.Name)}[(int)Vulkan.{validConstant.Name}];");
                            }
                            else
                            {
                                int count = int.Parse(validConstant.Value);
                                for (int i = 0; i < count; i++)
                                {
                                    file.WriteLine($"\t\tpublic {csType} {member.Name}_{i};");
                                }
                            }
                        }
                        else
                        {
                            file.WriteLine($"\t\tpublic {csType} {Helpers.ValidatedName(member.Name)};");
                        }
                    }

                    file.WriteLine("\t}\n");
                }

                file.WriteLine("}\n");
            }

            // Handles
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Handles.cs")))
            {
                file.WriteLine("using System;\n");
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");

                foreach (var handle in vulkanVersion.Handles)
                {
                    file.WriteLine($"\tpublic partial struct {handle.Name} : IEquatable<{handle.Name}>");
                    file.WriteLine("{");
                    string handleType = handle.Dispatchable ? "IntPtr" : "ulong";
                    string nullValue  = handle.Dispatchable ? "IntPtr.Zero" : "0";

                    file.WriteLine($"\t\tpublic readonly {handleType} Handle;");

                    file.WriteLine($"\t\tpublic {handle.Name}({handleType} existingHandle) {{ Handle = existingHandle; }}");
                    file.WriteLine($"\t\tpublic static {handle.Name} Null => new {handle.Name}({nullValue});");
                    file.WriteLine($"\t\tpublic static implicit operator {handle.Name}({handleType} handle) => new {handle.Name}(handle);");
                    file.WriteLine($"\t\tpublic static bool operator ==({handle.Name} left, {handle.Name} right) => left.Handle == right.Handle;");
                    file.WriteLine($"\t\tpublic static bool operator !=({handle.Name} left, {handle.Name} right) => left.Handle != right.Handle;");
                    file.WriteLine($"\t\tpublic static bool operator ==({handle.Name} left, {handleType} right) => left.Handle == right;");
                    file.WriteLine($"\t\tpublic static bool operator !=({handle.Name} left, {handleType} right) => left.Handle != right;");
                    file.WriteLine($"\t\tpublic bool Equals({handle.Name} h) => Handle == h.Handle;");
                    file.WriteLine($"\t\tpublic override bool Equals(object o) => o is {handle.Name} h && Equals(h);");
                    file.WriteLine($"\t\tpublic override int GetHashCode() => Handle.GetHashCode();");
                    file.WriteLine("}\n");
                }

                file.WriteLine("}");
            }

            // Commands
            using (StreamWriter file = File.CreateText(Path.Combine(outputPath, "Commands.cs")))
            {
                file.WriteLine("using System;");
                file.WriteLine("using System.Runtime.InteropServices;\n");
                file.WriteLine("namespace WaveEngine.Bindings.Vulkan");
                file.WriteLine("{");
                file.WriteLine("\tpublic static unsafe partial class VulkanNative");
                file.WriteLine("\t{");

                foreach (var command in vulkanVersion.Commands)
                {
                    string convertedType = Helpers.ConvertToCSharpType(command.Prototype.Type, 0, vulkanSpec);

                    file.WriteLine("\t\t[UnmanagedFunctionPointer(CallConv)]");

                    // Delegate
                    file.WriteLine($"\t\tprivate delegate {convertedType} {command.Prototype.Name}Delegate({command.GetParametersSignature(vulkanSpec)});");

                    // internal function
                    file.WriteLine($"\t\tprivate static {command.Prototype.Name}Delegate {command.Prototype.Name}_ptr;");

                    // public function
                    file.WriteLine($"\t\tpublic static {convertedType} {command.Prototype.Name}({command.GetParametersSignature(vulkanSpec)})");
                    file.WriteLine($"\t\t\t=> {command.Prototype.Name}_ptr({command.GetParametersSignature(vulkanSpec, useTypes: false)});\n");
                }

                file.WriteLine($"\t\tprivate static void LoadFuncionPointers()");
                file.WriteLine("\t\t{");

                foreach (var command in vulkanVersion.Commands)
                {
                    file.WriteLine($"\t\t\tnativeLib.LoadFunction(\"{command.Prototype.Name}\",  out {command.Prototype.Name}_ptr);");
                }

                file.WriteLine("\t\t}");
                file.WriteLine("\t}");
                file.WriteLine("}");
            }
        }
コード例 #4
0
        public static VulkanSpecification FromFile(string xmlFile)
        {
            XDocument           file = XDocument.Load(xmlFile);
            VulkanSpecification spec = new VulkanSpecification();

            var registry = file.Element("registry");

            // Platforms
            var platforms = registry.Element("platforms").Elements("platform");

            foreach (var platform in platforms)
            {
                spec.Platforms.Add(PlatformDefinition.FromXML(platform));
            }

            // Tags
            var tags = registry.Element("tags").Elements("tag");

            foreach (var tag in tags)
            {
                spec.Tags.Add(TagDefinition.FromXML(tag));
            }

            // Constants
            var constants = (registry.Elements("enums").Where(e => e.Attribute("name").Value == "API Constants")).Elements("enum");

            foreach (var c in constants)
            {
                spec.Constants.Add(ConstantDefinition.FromXML(c));
            }

            // Enums
            var enums = registry.Elements("enums").Where(e => e.Attribute("type")?.Value == "enum" || e.Attribute("type")?.Value == "bitmask");

            foreach (var e in enums)
            {
                spec.Enums.Add(EnumDefinition.FromXML(e));
            }

            var types = registry.Elements("types");

            // FuncPointers
            var funcPointers = types.Elements("type").Where(f => f.Attribute("category")?.Value == "funcpointer");

            foreach (var func in funcPointers)
            {
                spec.FuncPointers.Add(FuncpointerDefinition.FromXML(func));
            }

            // Alias
            spec.Alias = types.Elements("type").Where(a => a.Attribute("alias") != null)
                         .ToDictionary(
                a => a.Attribute("name").Value,
                a => a.Attribute("alias").Value);

            // Command Alias
            var commandAlias = registry.Element("commands").Elements("command").Where(c => c.Attribute("alias") != null);

            foreach (var c in commandAlias)
            {
                spec.Alias.Add(c.Attribute("name").Value, c.Attribute("alias").Value);
            }

            // Structs
            var structs = types.Elements("type").Where(s => s.Attribute("category")?.Value == "struct" && s.Attribute("alias") == null);

            foreach (var s in structs)
            {
                spec.Structs.Add(StructureDefinition.FromXML(s));
            }

            // Unions
            var unions = types.Elements("type").Where(u => u.Attribute("category")?.Value == "union");

            foreach (var u in unions)
            {
                spec.Unions.Add(StructureDefinition.FromXML(u));
            }

            // TypeDef
            var typeDefs = types.Elements("type").Where(t => t.Value.Contains("typedef") && t.Attribute("category")?.Value == "bitmask");

            foreach (var type in typeDefs)
            {
                spec.TypeDefs.Add(TypedefDefinition.FromXML(type));
            }

            // BaseTypes
            spec.BaseTypes = types.Elements("type").Where(bt => bt.Attribute("category")?.Value == "basetype")
                             .ToDictionary(
                bt => bt.Element("name").Value,
                bt => bt.Element("type")?.Value);

            // Handles
            var handles = types.Elements("type").Where(h => h.Attribute("category")?.Value == "handle");

            foreach (var h in handles)
            {
                spec.Handles.Add(HandleDefinition.FromXML(h));
            }

            // Commands
            var commands = registry.Element("commands").Elements("command").Where(c => c.Attribute("alias") == null);

            foreach (var command in commands)
            {
                spec.Commands.Add(CommandDefinition.FromXML(command));
            }

            // Features
            var features = registry.Elements("feature");

            foreach (var feature in features)
            {
                spec.Features.Add(FeatureDefinition.FromXML(feature));
            }

            // Extensions
            var extensions = registry.Element("extensions").Elements("extension");

            foreach (var extension in extensions)
            {
                spec.Extensions.Add(ExtensionDefinition.FromXML(extension));
            }

            return(spec);
        }
コード例 #5
0
ファイル: VulkanVersion.cs プロジェクト: Gaiaxis/Vulkan.NET
        public static VulkanVersion FromSpec(VulkanSpecification spec, string versionName, IEnumerable <ExtensionDefinition> extensions)
        {
            VulkanVersion version = new VulkanVersion();

            version.Constants    = spec.Constants;
            version.FuncPointers = spec.FuncPointers;
            version.Handles      = spec.Handles;
            version.Unions       = spec.Unions;
            version.Structs      = spec.Structs;
            version.Enums        = spec.Enums;

            for (int i = 0; i < spec.Features.Count; i++)
            {
                FeatureDefinition feature = spec.Features[i];

                // Extend Enums
                foreach (var enumType in feature.Enums)
                {
                    if (enumType.Extends != null & enumType.Alias == null)
                    {
                        string name           = enumType.Extends;
                        var    enumDefinition = spec.Enums.Find(c => c.Name == name);

                        EnumValue newValue = new EnumValue();
                        newValue.Name  = enumType.Name;
                        newValue.Value = int.Parse(enumType.Value);
                        enumDefinition.Values.Add(newValue);
                    }
                }

                // Add commands
                foreach (var command in feature.Commands)
                {
                    string name = command;
                    if (spec.Alias.TryGetValue(name, out string alias))
                    {
                        name = alias;
                    }

                    var commandDefinition = spec.Commands.Find(c => c.Prototype.Name == name);
                    version.Commands.Add(commandDefinition);
                }

                if (feature.Name == versionName)
                {
                    break;
                }
            }

            foreach (var extension in extensions)
            {
                // Extend Enums
                foreach (var enumType in extension.Enums)
                {
                    if (enumType.Extends != null & enumType.Alias == null)
                    {
                        string name           = enumType.Extends;
                        var    enumDefinition = spec.Enums.Find(c => c.Name == name);


                        if (!enumDefinition.Values.Exists(e => e.Name == enumType.Name))
                        {
                            EnumValue newValue = new EnumValue();
                            newValue.Name  = enumType.Name;
                            newValue.Value = int.Parse(enumType.Value);
                            enumDefinition.Values.Add(newValue);
                        }
                    }
                }

                // Add commands
                foreach (var command in extension.Commands)
                {
                    string name = command;
                    if (spec.Alias.TryGetValue(name, out string alias))
                    {
                        name = alias;
                    }

                    var commandDefinition = spec.Commands.Find(c => c.Prototype.Name == name);

                    if (!version.Commands.Exists(c => c.Prototype.Name == name))
                    {
                        version.Commands.Add(commandDefinition);
                    }
                }
            }

            return(version);
        }