Example #1
0
        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;
                }
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }