// Generate the constants private static void GenerateConstants(ProcessedSpec spec) { // Open constants file and class using var file = new SourceFile("Constants.cs"); using var block = file.PushBlock("public static class VkConstants"); // Write the constants block.WriteLine("/* API Constants */"); foreach (var @const in spec.Constants.Values) { var typestr = @const.Type switch { ConstantValue.ValueType.Float => "float", ConstantValue.ValueType.Int => "uint", _ => "ulong" }; var valstr = (@const.Type == ConstantValue.ValueType.Float) ? $"{@const.ValueFloat}f" : $"{@const.ValueInt}"; block.WriteLine($"public const {typestr} {@const.Name} = {valstr};"); } block.WriteLine(); // Write the extension values block.WriteLine("/* Extensions */"); foreach (var ext in spec.Extensions.Values) { var upper = ext.Name.Substring("VK_".Length).ToUpperInvariant(); var namename = upper + "_EXTENSION_NAME"; var versname = upper + "_SPEC_VERSION"; block.WriteLine($"public const string {namename} = \"{ext.Name}\";"); block.WriteLine($"public const uint {versname} = {ext.Version};"); } } }
// Generate the function tables private static void GenerateCommands(ProcessedSpec spec) { // Generate instance table using (var file = new SourceFile("InstanceFunctionTable.cs")) using (var table = file.PushBlock("public unsafe sealed partial class InstanceFunctionTable")) { // Global functions table.WriteLine("/* Global Functions */"); foreach (var cmd in spec.Commands.Values.Where(cmd => cmd.Scope == CommandType.CommandScope.Global)) { table.WriteLine($"public static readonly {cmd.TypeString} {cmd.Name} = null;"); } table.WriteLine(); // Instance functions table.WriteLine("/* Instance Functions */"); foreach (var cmd in spec.Commands.Values.Where(cmd => cmd.Scope == CommandType.CommandScope.Instance)) { table.WriteLine($"public readonly {cmd.TypeString} {cmd.Name} = null;"); } table.WriteLine(); // Null ctor table.WriteLine("/// <summary>Creates a new function table with all null pointers.</summary>"); table.WriteLine("public InstanceFunctionTable() { }"); table.WriteLine(); // Real ctor table.WriteLine("/// <summary>Creates a new function table and loads the functions.</summary>"); table.WriteLine("/// <param name=\"inst\">The instance to load the functions for.</param>"); table.WriteLine("/// <param name=\"version\">The core API version that the instance was created with.</param>"); using (var ctor = table.PushBlock("public InstanceFunctionTable(VulkanHandle<VkInstance> inst, VkVersion version)")) { ctor.WriteLine("void* addr = null;"); ctor.WriteLine("CoreVersion = version;"); ctor.WriteLine(); foreach (var cmd in spec.Commands.Values.Where(cmd => cmd.Scope == CommandType.CommandScope.Instance)) { if (cmd.Spec.Alias is not null) { ctor.WriteLine($"{cmd.Name} = {cmd.Spec.Alias.Name};"); ctor.WriteLine($"if (({cmd.Name} == null) && TryLoadFunc(inst, \"{cmd.Name}\", out addr)) {{"); ctor.WriteLine($"\t{cmd.Name} = ({cmd.TypeString})addr;"); ctor.WriteLine("}"); } else if (cmd.IsCore) { if (cmd.Spec.FeatureLevel ! > 10) { ctor.WriteLine($"if (version >= VkVersion.VK_VERSION_1_{cmd.Spec.FeatureLevel % 10}) {{"); ctor.WriteLine($"\t{cmd.Name} = ({cmd.TypeString})LoadFunc(inst, \"{cmd.Name}\");"); ctor.WriteLine("}"); } else { ctor.WriteLine($"{cmd.Name} = ({cmd.TypeString})LoadFunc(inst, \"{cmd.Name}\");"); } }
// Perform generation public static bool Generate(ProcessedSpec spec) { // Ensure output directories are created try { if (!Directory.Exists(ArgParse.OutputPath)) { Directory.CreateDirectory(ArgParse.OutputPath); } foreach (var vendor in spec.Vendors) { if (!vendor.Value.IsCore) { var vdir = Path.Combine(ArgParse.OutputPath, vendor.Key); if (!Directory.Exists(vdir)) { Directory.CreateDirectory(vdir); } } } } catch (Exception e) { Program.PrintError($"Failed to generate output directories - {e.Message}"); return(false); } // Create the constants try { GenerateConstants(spec); } catch (Exception e) { Program.PrintError($"Failed to generate constants - {e.Message}"); return(false); } Program.Print("Generated constants"); // Create the function tables try { GenerateCommands(spec); } catch (Exception e) { Program.PrintError($"Failed to generate function tables - {e.Message}"); return(false); } Program.Print("Generated function tables"); // Generate the vendor types foreach (var vendor in spec.Vendors.Values) { try { GenerateBitmasks(vendor); } catch (Exception e) { Program.PrintError($"Failed to generate bitmasks for '{vendor.Tag}' - {e.Message}"); return(false); } try { GenerateHandles(vendor); } catch (Exception e) { Program.PrintError($"Failed to generate handles for '{vendor.Tag}' - {e.Message}"); return(false); } try { GenerateEnums(vendor); } catch (Exception e) { Program.PrintError($"Failed to generate enums for '{vendor.Tag}' - {e.Message}"); return(false); } try { GenerateStructs(vendor); } catch (Exception e) { Program.PrintError($"Failed to generate structs for '{vendor.Tag}' - {e.Message}"); return(false); } Program.Print($"Generated types for vendor '{vendor.Tag}'"); } return(true); }