/// <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" } },
/// <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."); }
/// <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); }
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() }; } }
/// <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 }); } } } } }
/// <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); }
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 }); } } }
/// <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); }
/// <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); }
/// <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 }); } } }
/// <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)); }
/// <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)); }
/// <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)
/// <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); } }
/// <inheritdoc /> public void WriteConstants(Profile profile, IEnumerable <Constant> constants, BindTask task) { // do nothing }
/// <inheritdoc /> public void WriteConstants(Profile profile, IEnumerable <Constant> constants, BindTask task) { profile.Projects["Core"].Classes[0].Constants.AddRange(constants); }
/// <inheritdoc /> public void WriteStructs(Profile profile, IEnumerable <Struct> structs, BindTask task) { profile.Projects["Core"].Structs.AddRange(structs); }
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); }
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); }
/// <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)); }
/// <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); } } }
/// <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); }
/// <inheritdoc /> public IEnumerable <Struct> ReadStructs(object obj, BindTask task) { return(Enumerable.Empty <Struct>()); }
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); }
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) }
public BindState(BindTask task) => Task = task;
/// <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); }
/// <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); } } }
//////////////////////////////////////////////////////////////////////////////////////// // 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); } } } } }
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); } }