Exemplo n.º 1
0
        public static int GetSizeInBytes(StructureDefinition s, VulkanVersion vulkanVersion)
        {
            int size = 0;

            foreach (var member in s.Members)
            {
                int multiply = 1;
                if (member.ElementCount > 0)
                {
                    multiply = member.ElementCount;
                }

                size += Member.GetSizeInBytes(member, vulkanVersion) * multiply;
            }

            return(size);
        }
Exemplo n.º 2
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("}");
            }
        }
Exemplo n.º 3
0
        public static int GetSizeInBytes(Member m, VulkanVersion vulkanVersion)
        {
            if (m.ExplicityLayoutValue.HasValue)
            {
                return(m.ExplicityLayoutValue.Value / 8);
            }
            else
            {
                switch (m.Type)
                {
                case "int8_t":
                case "int8_t*":
                case "uint8_t":
                case "char":
                case "uint8_t*":
                case "char*":
                    return(1);

                case "uint16_t":
                case "uint16_t*":
                case "int16_t":
                case "int16_t*":
                    return(2);

                case "uint32_t":
                case "DWORD":
                case "uint32_t*":
                case "int32_t":
                case "int32_t*":
                case "size_t":
                case "float":
                case "float*":
                    return(4);

                case "uint64_t":
                case "uint64_t*":
                case "int64_t":
                case "int64_t*":
                case "double":
                case "double*":
                case "void":
                    return(8);

                case "VkBool32":
                    return(4);

                case "VkExtent2D":
                case "VkOffset2D":
                    return(8);

                case "VkRect2D":
                    return(16);

                default:
                    var @struct = vulkanVersion.Structs.Find(s => s.Name == m.Type);

                    if (@struct != null)     // structs
                    {
                        return(StructureDefinition.GetSizeInBytes(@struct, vulkanVersion));
                    }
                    else
                    {
                        return(4);    // enums
                    }
                }
            }
        }
Exemplo n.º 4
0
        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);
        }