void Replace(VkSpec spec, VkType existingType, VkType newType) { var vkStructs = spec.Structs.ToList(); for (int x = 0; x < vkStructs.Count; x++) { var vkStruct = vkStructs[x]; for (int y = 0; y < vkStruct.Members.Length; y++) { var vkParam = vkStruct.Members[y]; if (vkParam.Type == existingType) { vkParam.Type = newType; } } } var vkCommands = spec.Commands; for (int x = 0; x < vkCommands.Length; x++) { var vkCommand = vkCommands[x]; for (int y = 0; y < vkCommand.Parameters.Length; y++) { var vkParam = vkCommand.Parameters[y]; if (vkParam.Type == existingType) { vkParam.Type = newType; } } if (vkCommand.ReturnType == existingType) { vkCommand.ReturnType = newType; } } }
public VkSpec Rewrite(VkSpec spec) { // // `CSharpSpecRewriter` takes a spec generated by `VKSpecReader` and prepares // it for C# code generation. Remember that all the type data is linked by `VkType` // objects, so changing the name of a struct will change the name in any other structs // and all commands where it is referenced. // MergeExtensionEnums(spec.Enums.ToArray(), spec.Extensions); var apiConstants = spec.Enums.First(x => x.Name == "API Constants"); MergeExtensionConstants(apiConstants, spec.Extensions); foreach (var vkEnum in spec.Enums) { RewriteEnumDefinition(vkEnum); } foreach (var vkHandle in spec.Handles) { RewriteHandleDefinition(vkHandle); } foreach (var vkStruct in spec.Structs) { RewriteStructDefinition(vkStruct); } foreach (var vkStruct in spec.Structs) { RewriteStructMemberLen(vkStruct, spec.Structs.ToArray()); } foreach (var vkCmd in spec.Commands) { RewriteCommandDefinition(vkCmd); } foreach (var vkCmd in spec.Commands) { RewriteCommandParamLen(vkCmd, spec.Structs.ToArray()); } // Replace all imported type refrences with IntPtr var intPtr = spec.AllTypes.FirstOrDefault(x => x.Name == "IntPtr"); var platfromTypes = spec.AllTypes.Where(x => x.IsImportedType); foreach (var vkType in platfromTypes) { Replace(spec, vkType, intPtr); } spec.AllTypes = spec.AllTypes.Except(platfromTypes).ToList(); var functionPointers = spec.AllTypes.Where(x => x.Name.StartsWith("PFN_")); foreach (var vkType in functionPointers) { Replace(spec, vkType, intPtr); } spec.AllTypes = spec.AllTypes.Except(functionPointers).ToList(); if (!UseDeviceSize) { var deviceSize = spec.AllTypes.FirstOrDefault(x => x.Name == "DeviceSize"); var uint64 = spec.AllTypes.FirstOrDefault(x => x.Name == "UInt64"); Replace(spec, deviceSize, uint64); } return(spec); }
public VkSpec Read(string raw) { // Read the Vulkan spec into memory // // Besides simply reading the spec into classes, VKSpecReader links type information // across commands and structures via the `VkType` base class. So for example an enum // like `VkSomeNameFlags` will have a `VkEnum : VkType` class generated for it, and all // commands and structures that use `VkSomeNameFlags` will reference this class. This // approach should make bulk-renaming and other transformations on the spec easier to accomplish. // // This class is concerned with reading the spec into memory _only_. Beyond // linking type data, it should preform no additional transformations on the // data (unless necessary, as in bitmasks). // var spec = new VkSpec(); var xdoc = XDocument.Parse(raw); var registry = xdoc.Root; var xtypes = registry.Element("types").Elements("type"); // 'Plaform' types // { // These are mainly primitives like void, uint32_t, size_t, etc. They are treated // specially by the pipeline. var plaformTypes = xtypes .Where(TypePlatformFilter) .Select(x => x.Attribute("name").Value) .ToList(); var platformStructs = plaformTypes.Select(CreatePlatformStruct).ToList(); foreach (var vkStruct in platformStructs) { allTypes.Add(vkStruct.Name, vkStruct); } } // Enums / Bitmask // { // Bitmask types are weirdly defined, if the 'requires' // attribute is present, the enum is defined somewhere in // the file. If the 'requires' is missing, the enum is empty var bitmaskTypes = xtypes .Where(TypeBitmaskFilter) .ToList(); var emptyBitmaskNames = bitmaskTypes .Where(x => x.Attribute("requires") == null) .Select(x => x.Element("name").Value) .ToList(); var emptyBitmasks = emptyBitmaskNames.Select(GenerateEmptyBitmask); var xenums = registry.Elements("enums"); var enums = xenums.Select(ReadEnum); enums = enums.Concat(emptyBitmasks); // Add the empty bitmasks generated above foreach (var vkEnum in enums) { allTypes.Add(vkEnum.Name, vkEnum); } } // Handles // { var handles = xtypes .Where(TypeHandleFilter) .Select(ReadHandle); foreach (var handle in handles) { allTypes.Add(handle.Name, handle); } } // Structs // { var xstructs = xtypes.Where(TypeStructFilter); // Create a map of `struct name` -> `struct xml definition` var structDefMap = CreateStructureDictionary(xstructs); // Create a VkStruct object for each class before reading the xml definitions, // this is so the struct members can refrence other struct types var structs = structDefMap.Keys.Select(x => new VkStruct { Name = x }).ToArray(); foreach (var vkStruct in structs) { allTypes.Add(vkStruct.Name, vkStruct); } // Read the struct definitions foreach (var vkStruct in structs) { ReadStruct(structDefMap[vkStruct.Name], vkStruct); } } // Commands // var commandsRoot = registry.Element("commands"); var commands = commandsRoot.Elements("command"); spec.Commands = commands.Select(ReadCommand).ToArray(); // Features // var features = registry.Elements("feature"); spec.Features = features.Select(ReadFeature).ToArray(); spec.AllTypes = allTypes.Values.ToList(); // Extensions // var extensionsRoot = registry.Element("extensions"); spec.Extensions = extensionsRoot .Elements() .Select(ReadExtension) .ToArray(); return(spec); }