コード例 #1
0
        /// <inheritdoc />
        public IEnumerable <Constant> ReadConstants(object obj, BindTask task)
        {
            var spec = (VulkanSpecification)obj;

            return(spec.Constants.Select
                   (
                       x => new Constant
            {
                Name = Naming.Translate(TrimName(x.Name, task), task.FunctionPrefix),
                NativeName = x.Name,
                Value = x.Value,
                Type = x.Type switch
                {
                    ConstantType.Float32 => new Type {
                        Name = "float"
                    },
                    ConstantType.UInt32 => new Type {
                        Name = "uint"
                    },
                    ConstantType.UInt64 => new Type {
                        Name = "ulong"
                    },
                    _ => new Type {
                        Name = "ulong"
                    }
                },
コード例 #2
0
        /// <summary>
        /// Writes all of the projects, interfaces, and enums to disk.
        /// </summary>
        /// <param name="profile">The profile containing the profiles, interfaces, and enums.</param>
        public static void Flush(this Profile profile, BindTask originalTask)
        {
            var task       = new BindState(originalTask);
            var rootFolder = task.Task.OutputOpts.Folder;

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

            if (!Directory.Exists(Path.Combine(rootFolder, "Extensions")))
            {
                Directory.CreateDirectory(Path.Combine(rootFolder, "Extensions"));
            }

            Console.WriteLine($"Loaded \"{profile.Name}\", writing {profile.Projects.Count} projects...");
            profile.Projects.ForEach
            (
                x =>
                x.Value.Write
                (
                    !task.Task.Controls.Contains("no-extra-dir") ?
                    x.Key == "Core"
                            ? Path.Combine(rootFolder, x.Value.GetProjectName(task.Task))
                            : Path.Combine(rootFolder, "Extensions", x.Value.GetProjectName(task.Task)) :
                    x.Key == "Core"
                            ? Path.Combine(rootFolder)
                            : Path.Combine(rootFolder, "Extensions"),
                    profile,
                    task
                )
            );
            Console.WriteLine($"Successfully wrote \"{profile.Name}\" to disk.");
        }
コード例 #3
0
        /// <inheritdoc />
        public IEnumerable <Enum> ReadEnums(object obj, BindTask task)
        {
            var spec = (VulkanSpecification)obj;

            task.InjectTypeMap(spec.BaseTypes);
            var enums = ConvertEnums(spec, task);
            var tm    = new Dictionary <string, string>();

            foreach (var feature in spec.Features.Select(x => x.Api).RemoveDuplicates())
            {
                foreach (var(_, e) in enums)
                {
                    tm.Add(e.NativeName, e.Name.Replace("FlagBits", "Flags"));
                    yield return(new Enum
                    {
                        Attributes = e.Attributes,
                        ExtensionName = "Core",
                        Name = e.Name.Replace("FlagBits", "Flags"),
                        NativeName = e.NativeName.Replace("FlagBits", "Flags"),
                        ProfileName = feature,
                        ProfileVersion = null,
                        Tokens = e.Tokens
                    });
                }
            }

            task.InjectTypeMap(tm);
        }
コード例 #4
0
        public static void SubstituteWindowsSdkPath(ref BindTask task)
        {
            const string dir = "$windowsSdkDir";
            const string inc = "$windowsSdkIncludes";
            const string ver = "$windowsSdkVersion";
            var          needsSubstitution = task.Sources.Any(x => x.Contains(dir)) ||
                                             task.ClangOpts.Traverse.Any(x => x.Contains(dir)) ||
                                             task.ClangOpts.ClangArgs.Any(x => x.Contains(dir) || x.Contains(inc));

            if (!needsSubstitution)
            {
                return;
            }

            if (!VisualStudioResolver.TryGetVisualStudioInfo(out var info))
            {
                throw new("Unable to locate Visual Studio installation.");
            }

            for (var i = 0; i < task.Sources.Length; i++)
            {
                task.Sources[i] = task.Sources[i]
                                  .Replace(dir, ForwardSlash(info.UcrtSdkDir))
                                  .Replace(ver, info.UcrtVersion.ToString());
            }

            for (var i = 0; i < task.ClangOpts.Traverse.Length; i++)
            {
                task.ClangOpts.Traverse[i] = task.ClangOpts.Traverse[i]
                                             .Replace(dir, ForwardSlash(info.UcrtSdkDir))
                                             .Replace(ver, info.UcrtVersion.ToString());
            }

            var args = new List <string>(task.ClangOpts.ClangArgs);

            for (var i = 0; i < args.Count; i++)
            {
                if (args[i].Contains(inc))
                {
                    var arg = args[i];
                    args.RemoveAt(i);
                    foreach (var includePath in info.UcrtIncludes.Concat(info.MsvcToolsIncludes))
                    {
                        args.Insert(i, arg.Replace(inc, ForwardSlash(includePath)));
                    }
                }

                args[i] = args[i]
                          .Replace(dir, ForwardSlash(info.UcrtSdkDir))
                          .Replace(ver, info.UcrtVersion.ToString());
            }

            task.ClangOpts = task.ClangOpts with {
                ClangArgs = args.ToArray()
            };
        }
    }
コード例 #5
0
ファイル: VulkanReader.cs プロジェクト: KangWeon/Silk.NET
        /// <inheritdoc />
        public IEnumerable <Function> ReadFunctions(object obj, BindTask task)
        {
            var spec      = (VulkanSpecification)obj;
            var functions = ConvertFunctions(spec, task);

            foreach (var feature in spec.Features)
            {
                foreach (var name in feature.CommandNames)
                {
                    if (functions.ContainsKey(name))
                    {
                        var function = functions[name];
                        yield return(new Function
                        {
                            ExtensionName = "Core",
                            Categories = new List <string> {
                                TrimName(feature.Name, task)
                            },
                            Name = function.Name,
                            NativeName = function.NativeName,
                            Parameters = function.Parameters,
                            ReturnType = function.ReturnType,
                            ProfileName = feature.Api,
                            ProfileVersion = feature.Number
                        });
                    }
                }
            }

            foreach (var extension in spec.Extensions)
            {
                foreach (var name in extension.CommandNames)
                {
                    foreach (var api in extension.Supported)
                    {
                        if (functions.ContainsKey(name))
                        {
                            var function = functions[name];
                            yield return(new Function
                            {
                                ExtensionName = TrimName(extension.Name, task),
                                Categories = new List <string> {
                                    TrimName(extension.Name, task)
                                },
                                Name = function.Name,
                                NativeName = function.NativeName,
                                Parameters = function.Parameters,
                                ReturnType = function.ReturnType,
                                ProfileName = api,
                                ProfileVersion = null
                            });
                        }
                    }
                }
            }
        }
コード例 #6
0
        /// <summary>
        /// Trims the API prefix from the function names.
        /// </summary>
        /// <param name="name">The name to trim.</param>
        /// <param name="opts">The converter options.</param>
        /// <returns>The trimmed name.</returns>
        public string TrimName(string name, BindTask task)
        {
            if (name.StartsWith($"{task.FunctionPrefix.ToUpper()}_"))
            {
                return(name.Remove(0, task.FunctionPrefix.Length + 1));
            }

            return(name.StartsWith
                       (task.FunctionPrefix)
                ? name.Remove(0, task.FunctionPrefix.Length)
                : name);
        }
コード例 #7
0
ファイル: VulkanReader.cs プロジェクト: KangWeon/Silk.NET
 private IEnumerable <Field> GetFields(StructureDefinition union, BindTask task)
 {
     foreach (var x in union.Members)
     {
         if (x.ElementCount > 1)
         {
             for (var i = 0; i < x.ElementCount; i++)
             {
                 var fieldSize = GetTypeSize(x.Type.Name, task.TypeMaps);
                 yield return(new Field
                 {
                     Name = $"{Naming.Translate(x.Name, task.FunctionPrefix)}_{i}",
                     Attributes = new List <Attribute>
                     {
                         new Attribute {
                             Name = "FieldOffset", Arguments = new List <string> {
                                 $"{i * fieldSize}"
                             }
                         }
                     },
                     Doc = $"/// <summary>{x.Comment}</summary>",
                     NativeName = x.Name,
                     NativeType = x.Type.ToString(),
                     Type = ConvertType(x.Type),
                     NumBits = x.NumBits
                 });
             }
         }
         else
         {
             yield return(new Field
             {
                 Name = $"{Naming.Translate(x.Name, task.FunctionPrefix)}",
                 Attributes = new List <Attribute>
                 {
                     new Attribute {
                         Name = "FieldOffset", Arguments = new List <string> {
                             "0"
                         }
                     }
                 },
                 Doc = $"/// <summary>{x.Comment}</summary>",
                 NativeName = x.Name,
                 NativeType = x.Type.ToString(),
                 Type = ConvertType(x.Type),
                 NumBits = x.NumBits
             });
         }
     }
 }
コード例 #8
0
ファイル: Naming.cs プロジェクト: storm32600/Silk.NET
        /// <summary>
        /// Trims the API prefix from the function names.
        /// </summary>
        /// <param name="name">The name to trim.</param>
        /// <param name="opts">The converter options.</param>
        /// <returns>The trimmed name.</returns>
        public static string TrimName(string name, BindTask task)
        {
            if (task.FunctionPrefix is null)
            {
                return(name);
            }

            name = name.TrimStart('_');

            if (name.StartsWith($"{task.FunctionPrefix.ToUpper()}_"))
            {
                return(name.Remove(0, task.FunctionPrefix.Length + 1));
            }

            return(name.ToUpper().StartsWith(task.FunctionPrefix.ToUpper())
                ? name.Remove(0, task.FunctionPrefix.Length)
                : name);
        }
コード例 #9
0
        /// <inheritdoc />
        public void WriteStructs(Profile profile, IEnumerable <Struct> structs, BindTask task)
        {
            if (!profile.Projects.ContainsKey("Core"))
            {
                profile.Projects.Add
                (
                    "Core",
                    new Project
                {
                    IsRoot    = true,
                    Namespace = string.Empty,
                    Classes   = new List <Class> {
                        new Class {
                            ClassName = task.ConverterOpts.ClassName
                        }
                    }
                }
                );
            }

            profile.Projects["Core"].Structs.AddRange(structs);
        }
コード例 #10
0
ファイル: VulkanReader.cs プロジェクト: KangWeon/Silk.NET
        /// <inheritdoc />
        public IEnumerable <Struct> ReadStructs(object obj, BindTask task)
        {
            var spec    = (VulkanSpecification)obj;
            var structs = ConvertStructs(spec, task);

            foreach (var feature in spec.Features.Select(x => x.Api).RemoveDuplicates())
            {
                foreach (var(_, s) in structs)
                {
                    yield return(new Struct
                    {
                        Attributes = s.Attributes,
                        ExtensionName = "Core",
                        Fields = s.Fields,
                        Functions = s.Functions,
                        Name = s.Name,
                        NativeName = s.NativeName,
                        ProfileName = feature,
                        ProfileVersion = null
                    });
                }
            }
        }
コード例 #11
0
        /// <inheritdoc />
        public void WriteEnums(Profile profile, IEnumerable <Enum> enums, BindTask task)
        {
            if (!profile.Projects.ContainsKey("Core"))
            {
                profile.Projects.Add
                (
                    "Core",
                    new Project
                {
                    IsRoot    = false,
                    Namespace = string.Empty,
                    Classes   = new List <Class> {
                        new Class {
                            ClassName = task.ConverterOpts.ClassName
                        }
                    }
                }
                );
            }

            profile.Projects["Core"].Enums.AddRange(enums);
            task.TypeMaps.Add(enums.RemoveDuplicates((x, y) => x.NativeName == y.NativeName).ToDictionary(x => x.NativeName, x => x.Name));
        }
コード例 #12
0
        /// <inheritdoc />
        public IEnumerable <Struct> ReadStructs(object obj, BindTask task)
        {
            var xd = (XDocument)obj;

            var rawStructs = xd.Element("registry")?.Element("types")?.Elements("type")
                             .Where(type => type.HasCategoryAttribute("struct"))
                             .Select(StructureDefinition.CreateFromXml)
                             .ToArray();

            var structs = ConvertStructs(rawStructs, task);

            foreach (var feature in xd.Element
                         ("registry")
                     ?.Elements("feature")
                     .Attributes("api")
                     .Select(x => x.Value)
                     .RemoveDuplicates() ?? throw new InvalidDataException())
            {
                foreach (var(_, s) in structs)
                {
                    yield return(new Struct
                    {
                        Attributes = s.Attributes,
                        ExtensionName = "Core",
                        Fields = s.Fields,
                        Functions = s.Functions,
                        Name = s.Name,
                        NativeName = s.NativeName,
                        ProfileName = feature,
                        ProfileVersion = null
                    });
                }
            }

            task.TypeMaps.Add(structs.ToDictionary(x => x.Key, x => x.Value.Name));
        }
コード例 #13
0
ファイル: OpenGLReader.cs プロジェクト: KangWeon/Silk.NET
 /// <inheritdoc />
 public IEnumerable <Struct> ReadStructs(object obj, BindTask task)
 => ReadFunctions(obj, task)
 .SelectMany(x => x.Parameters.Select(y => y.Type).Concat(x.ReturnType))
 .Select(x => x.OriginalClass)
 .Where(x => x is not null)
コード例 #14
0
        /// <inheritdoc />
        public void WriteEnums(Profile profile, IEnumerable <Enum> enums, BindTask task)
        {
            if (!profile.Projects.ContainsKey("Core"))
            {
                profile.Projects.Add
                (
                    "Core",
                    new Project
                {
                    IsRoot    = true,
                    Namespace = string.Empty,
                    Classes   = new List <Class> {
                        new Class {
                            ClassName = task.ConverterOpts.ClassName
                        }
                    }
                }
                );
            }

            var mergedEnums = new Dictionary <string, Enum>();
            var gl          = profile.Projects["Core"].Classes[0].ClassName.ToUpper().CheckMemberName(task.FunctionPrefix);

            mergedEnums.Add
            (
                $"{gl}Enum",
                new Enum
            {
                Name   = $"{gl}Enum", ExtensionName = "Core", Attributes = new List <Attribute>(),
                Tokens = new List <Token>(), NativeName = "GLenum",
            }
            );

            // first, we need to categorise the enums into "Core", or their vendor (i.e. "NV", "SGI", "KHR" etc)
            foreach (var @enum in enums)
            {
                if (@enum.ProfileName != profile.Name || @enum.ProfileVersion?.ToString(2) != profile.Version)
                {
                    continue;
                }

                switch (@enum.ExtensionName)
                {
                case "Core":
                    mergedEnums[$"{gl}Enum"].Tokens.AddRange(@enum.Tokens);
                    break;

                case "Core (Grouped)":
                    @enum.ExtensionName = "Core";
                    profile.Projects["Core"].Enums.Add(@enum);
                    break;

                default:
                {
                    var prefix = FormatCategory(@enum.ExtensionName);
                    if (!mergedEnums.ContainsKey(prefix))
                    {
                        mergedEnums.Add
                        (
                            prefix,
                            new Enum
                            {
                                Name       = prefix.CheckMemberName(task.FunctionPrefix), ExtensionName = prefix,
                                NativeName = "GLenum"
                            }
                        );
                    }
                    mergedEnums[prefix].Tokens.AddRange(@enum.Tokens);
                    break;
                }
                }
            }

            // now that we've categorised them, lets add them into their appropriate projects.
            foreach (var(_, @enum) in mergedEnums)
            {
                if (!profile.Projects.ContainsKey(@enum.ExtensionName))
                {
                    profile.Projects.Add
                    (
                        @enum.ExtensionName,
                        new Project
                    {
                        IsRoot    = @enum.ExtensionName == "Core",
                        Namespace = @enum.ExtensionName == "Core"
                                ? string.Empty
                                : $".{@enum.ExtensionName.CheckMemberName(task.FunctionPrefix)}",
                        Classes = new List <Class> {
                            new Class {
                                ClassName = task.ConverterOpts.ClassName
                            }
                        }
                    }
                    );
                }

                profile.Projects[@enum.ExtensionName].Enums.Add(@enum);
            }
        }
コード例 #15
0
 /// <inheritdoc />
 public void WriteConstants(Profile profile, IEnumerable <Constant> constants, BindTask task)
 {
     // do nothing
 }
コード例 #16
0
 /// <inheritdoc />
 public void WriteConstants(Profile profile, IEnumerable <Constant> constants, BindTask task)
 {
     profile.Projects["Core"].Classes[0].Constants.AddRange(constants);
 }
コード例 #17
0
 /// <inheritdoc />
 public void WriteStructs(Profile profile, IEnumerable <Struct> structs, BindTask task)
 {
     profile.Projects["Core"].Structs.AddRange(structs);
 }
コード例 #18
0
        private Dictionary <string, Struct> ConvertStructs(VulkanSpecification spec, BindTask task)
        {
            var prefix = task.FunctionPrefix;
            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, 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
                    }.WithFixedFieldFixup09072020()
                             )
                             .ToList(),
                    Name       = Naming.TranslateLite(TrimName(s.Name, task), 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 ? "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);
        }
コード例 #19
0
        private static Dictionary <string, Struct> ConvertStructs(IEnumerable <StructureDefinition> spec, BindTask task)
        {
            var prefix = task.FunctionPrefix;
            var ret    = new Dictionary <string, Struct>();

            foreach (var s in spec)
            {
                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, task), prefix),
                        Doc        = $"/// <summary>{x.Comment}</summary>",
                        NativeName = x.Name,
                        NativeType = x.Type.ToString(),
                        Type       = ConvertType(x.Type)
                    }.WithFixedFieldFixup09072020()
                             )
                             .ToList(),
                    Name       = Naming.TranslateLite(TrimName(s.Name, task), prefix),
                    NativeName = s.Name
                }
                );
            }

            return(ret);
        }
コード例 #20
0
 /// <summary>
 /// Gets the full project name of this project, given the profile's root namespace.
 /// </summary>
 /// <returns>The full project name.</returns>
 public string GetProjectName(BindTask task)
 {
     return(GetNamespace(task));
 }
コード例 #21
0
        /// <inheritdoc />
        public void WriteConstants(Profile profile, IEnumerable <Constant> constants, BindTask task)
        {
            foreach (var constant in constants)
            {
                var category = constant.ExtensionName == "Core" ? "Core" : FormatCategory(constant.ExtensionName);
                if (category == "RESERVED")
                {
                    continue;
                }

                // check that the root project exists
                if (!profile.Projects.ContainsKey("Core"))
                {
                    profile.Projects.Add
                    (
                        "Core",
                        new Project
                    {
                        IsRoot    = true,
                        Namespace = string.Empty,
                        Classes   = new List <Class> {
                            new Class {
                                ClassName = task.ConverterOpts.ClassName
                            }
                        }
                    }
                    );
                }

                // check that the extension project exists, if applicable
                if (constant.ExtensionName != "Core" && !profile.Projects.ContainsKey(category))
                {
                    profile.Projects.Add
                    (
                        category,
                        new Project
                    {
                        IsRoot    = false,
                        Namespace = $".{category.CheckMemberName(task.FunctionPrefix)}",
                        Classes   = new List <Class> {
                            new Class {
                                ClassName = task.ConverterOpts.ClassName
                            }
                        }
                    }
                    );
                }

                var constantCollection = profile.Projects[category].Classes[0].Constants;
                if (constantCollection.All(x => x.Name != constant.Name))
                {
                    constantCollection.Add(constant);
                }
            }
        }
コード例 #22
0
        /// <inheritdoc />
        public void WriteStructs(Profile profile, IEnumerable <Struct> structs, BindTask task)
        {
            var map = new Dictionary <string, string>();

            foreach (var @struct in structs)
            {
                if (@struct.ProfileName != profile.Name || @struct.ProfileVersion?.ToString(2) != profile.Version)
                {
                    continue;
                }

                var category = FormatCategory(@struct.ExtensionName);
                if (category == "RESERVED")
                {
                    continue;
                }

                // check that the root project exists
                if (!profile.Projects.ContainsKey("Core"))
                {
                    profile.Projects.Add
                    (
                        "Core",
                        new Project
                    {
                        IsRoot    = true,
                        Namespace = string.Empty,
                        Classes   = new List <Class> {
                            new Class {
                                ClassName = task.ConverterOpts.ClassName
                            }
                        }
                    }
                    );
                }

                // check that the extension project exists, if applicable
                if (@struct.ExtensionName != "Core" && !profile.Projects.ContainsKey(category))
                {
                    profile.Projects.Add
                    (
                        category,
                        new Project
                    {
                        IsRoot    = false,
                        Namespace = $".{category.CheckMemberName(task.FunctionPrefix)}",
                        Classes   = new List <Class> {
                            new Class {
                                ClassName = task.ConverterOpts.ClassName
                            }
                        }
                    }
                    );
                }

                // add the struct
                profile.Projects[@struct.ExtensionName == "Core" ? "Core" : category].Structs.Add(@struct);

                // add the struct to the type map
                map[@struct.NativeName] = @struct.Name;
            }

            // register the type map
            task.TypeMaps.Add(map);
        }
コード例 #23
0
ファイル: OpenGLReader.cs プロジェクト: limocute/Silk.NET
 /// <inheritdoc />
 public IEnumerable <Struct> ReadStructs(object obj, BindTask task)
 {
     return(Enumerable.Empty <Struct>());
 }
コード例 #24
0
ファイル: VulkanReader.cs プロジェクト: KangWeon/Silk.NET
        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);
        }
コード例 #25
0
ファイル: VulkanReader.cs プロジェクト: KangWeon/Silk.NET
        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)
                    }
コード例 #26
0
ファイル: BindState.cs プロジェクト: storm32600/Silk.NET
 public BindState(BindTask task) => Task = task;
コード例 #27
0
 /// <summary>
 /// Gets the full namespace of this project, given the profile's root namespace.
 /// </summary>
 /// <returns>The full namespace.</returns>
 public string GetNamespace(BindTask taskConfig)
 {
     return((!IsRoot ? taskConfig.ExtensionsNamespace : taskConfig.Namespace) + Namespace);
 }
コード例 #28
0
        /// <inheritdoc />
        public void WriteFunctions(Profile profile, IEnumerable <Function> functions, BindTask task)
        {
            foreach (var function in functions)
            {
                if (function.ProfileName != profile.Name || function.ProfileVersion?.ToString(2) != profile.Version)
                {
                    continue;
                }

                foreach (var rawCategory in function.Categories)
                {
                    var category = FormatCategory(rawCategory);
                    // check that the root project exists
                    if (!profile.Projects.ContainsKey("Core"))
                    {
                        profile.Projects.Add
                        (
                            "Core",
                            new Project
                        {
                            IsRoot    = true,
                            Namespace = string.Empty,
                            Classes   = new List <Class> {
                                new Class {
                                    ClassName = task.ConverterOpts.ClassName
                                }
                            }
                        }
                        );
                    }

                    // check that the extension project exists, if applicable
                    if (function.ExtensionName != "Core" && !profile.Projects.ContainsKey(category))
                    {
                        profile.Projects.Add
                        (
                            category,
                            new Project
                        {
                            IsRoot    = false,
                            Namespace = $".{category.CheckMemberName(task.FunctionPrefix)}",
                            Classes   = new List <Class> {
                                new Class {
                                    ClassName = task.ConverterOpts.ClassName
                                }
                            }
                        }
                        );
                    }

                    // check that the interface exists
                    if
                    (
                        !profile.Projects[function.ExtensionName == "Core" ? "Core" : category]
                        .Classes[0].NativeApis.ContainsKey(rawCategory)
                    )
                    {
                        profile.Projects[function.ExtensionName == "Core" ? "Core" : category]
                        .Classes[0].NativeApis.Add
                        (
                            rawCategory,
                            new NativeApiSet
                        {
                            Name =
                                $"I{Naming.Translate(TrimName(rawCategory, task), task.FunctionPrefix).CheckMemberName(task.FunctionPrefix)}"
                        }
                        );
                    }

                    // add the function to the interface
                    profile.Projects[function.ExtensionName == "Core" ? "Core" : category]
                    .Classes[0].NativeApis[rawCategory]
                    .Functions.Add(function);
                }
            }
        }
コード例 #29
0
        ////////////////////////////////////////////////////////////////////////////////////////
        // Function Parsing
        ////////////////////////////////////////////////////////////////////////////////////////

        /// <inheritdoc />
        public IEnumerable <Function> ReadFunctions(object obj, BindTask task)
        {
            var doc = obj as XDocument;

            Debug.Assert(doc != null, nameof(doc) + " != null");

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

            Debug.Assert(registry != null, $"{nameof(registry)} != null");

            var allFunctions = registry
                               .Elements("commands")
                               .Elements("command")
                               .Select(x => TranslateCommand(x, task))
                               .ToDictionary(x => x.Attribute("name")?.Value, x => x);

            Debug.Assert(allFunctions != null, nameof(allFunctions) + " != null");

            var apis = registry.Elements("feature")
                       .Concat(registry
                               .Elements("extensions")
                               .Elements("extension") ?? throw new InvalidDataException());

            Debug.Assert(apis != null, nameof(apis) + " != null");

            var removals = registry.Elements("feature")
                           .Elements("remove")
                           .Elements("command")
                           .Attributes("name")
                           .Select(x => x.Value)
                           .ToList();

            Debug.Assert(removals != null, nameof(removals) + " != null");

            foreach (var api in apis)
            {
                foreach (var requirement in api.Elements("require"))
                {
                    var apiName = requirement.Attribute("api")?.Value ??
                                  api.Attribute("api")?.Value ??
                                  api.Attribute("supported")?.Value ??
                                  "opencl";
                    var apiVersion = api.Attribute("number") != null
                        ? Version.Parse(api.Attribute("number")?.Value ?? throw new InvalidDataException())
                        : null;

                    foreach (var name in apiName.Split('|'))
                    {
                        foreach (var function in requirement.Elements("command")
                                 .Attributes("name")
                                 .Select(x => x.Value))
                        {
                            var xf = allFunctions[TrimName(function, task)];

                            var ret = new Function
                            {
                                Attributes = removals.Contains(function)
                                    ? new List <Attribute>
                                {
                                    new Attribute
                                    {
                                        Name      = "System.Obsolete",
                                        Arguments = new List <string>
                                        {
                                            $"\"Deprecated in version {apiVersion?.ToString(2)}\""
                                        }
                                    }
                                }
                                    : new List <Attribute>(),
                                Categories = new List <string> {
                                    ExtensionName(api.Attribute("name")?.Value, task)
                                },
                                Doc                   = string.Empty,
                                ExtensionName         = api.Name == "feature" ? "Core" : ExtensionName(api.Attribute("name")?.Value, task),
                                GenericTypeParameters = new List <GenericTypeParameter>(),
                                Name                  = Naming.Translate(NameTrimmer.Trim(TrimName(xf.Attribute("name")?.Value, task), task.FunctionPrefix), task.FunctionPrefix),
                                NativeName            = function,
                                Parameters            = ParseParameters(xf),
                                ProfileName           = name,
                                ProfileVersion        = apiVersion,
                                ReturnType            = ParseTypeSignature(xf.Element("returns") ?? throw new InvalidDataException())
                            };

                            yield return(ret);

                            allFunctions.Remove(function);
                        }
                    }
                }
            }
        }
コード例 #30
0
        public static IEnumerable <Profile> ReadProfiles
            (IReader reader, IConstructor ctor, Stream input, BindTask task)
        {
            var obj = reader.Load(input);

            Console.WriteLine("Reading enums...");
            var enums = reader.ReadEnums(obj, task)
                        .OrderBy(x => x.Name)
                        .Where(x => task.ExcludedNativeNames is null || !task.ExcludedNativeNames.Contains(x.NativeName))
                        .ToArray();

            Console.WriteLine("Reading functions...");
            var functions = reader.ReadFunctions(obj, task)
                            .OrderBy(x => x.Name)
                            .Where(x => task.ExcludedNativeNames is null || !task.ExcludedNativeNames.Contains(x.NativeName))
                            .ToArray();

            Console.WriteLine("Reading structs...");
            var structs = reader.ReadStructs(obj, task)
                          .OrderBy(x => x.Name)
                          .Where(x => task.ExcludedNativeNames is null || !task.ExcludedNativeNames.Contains(x.NativeName))
                          .ToArray();

            Console.WriteLine("Reading constants...");
            var constants = reader.ReadConstants(obj, task)
                            .OrderBy(x => x.Name)
                            .Where(x => task.ExcludedNativeNames is null || !task.ExcludedNativeNames.Contains(x.NativeName))
                            .ToArray();

            Console.WriteLine("Creating profiles...");
            var profiles = enums.Select(x => (x.ProfileName, x.ProfileVersion))
                           .Concat(functions.Select(x => (x.ProfileName, x.ProfileVersion)))
                           .Concat(structs.Select(x => (x.ProfileName, x.ProfileVersion)))
                           .Distinct()
                           .Select(x => CreateBlankProfile(x.ProfileName, x.ProfileVersion));

            foreach (var profile in profiles)
            {
                ctor.WriteEnums(profile, enums, task);
                ctor.WriteFunctions(profile, functions, task);
                ctor.WriteStructs(profile, structs, task);
                ctor.WriteConstants(profile, constants, task);
                foreach (var typeMap in task.TypeMaps)
                {
                    TypeMapper.Map
                    (
                        typeMap,
                        profile.Projects.Values.SelectMany(x => x.Classes.SelectMany(y => y.NativeApis.Values))
                        .SelectMany(x => x.Functions)
                    );
                }

                foreach (var typeMap in task.TypeMaps)
                {
                    TypeMapper.Map(typeMap, structs);
                }

                foreach (var kvp in profile.Projects)
                {
                    foreach (var @class in kvp.Value.Classes)
                    {
                        foreach (var constant in @class.Constants)
                        {
                            constant.Type = TypeMapper.MapOne(task.TypeMaps, constant.Type);
                        }
                    }
                }

                Console.WriteLine($"Created profile \"{profile.Name}\" version {profile.Version}");

                yield return(profile);
            }
        }