1#!/usr/bin/python3 -i
2#
3# Copyright 2020-2023 The Khronos Group Inc.
4#
5# SPDX-License-Identifier: Apache-2.0
6
7# Description:
8# -----------
9# This script generates a .hpp file that can be included in an application
10# to generate json data that can then be used to generate the pipeline cache.
11
12import os
13import re
14import xml.dom.minidom
15from generator import (GeneratorOptions, OutputGenerator, noneStr,
16                       regSortFeatures, write)
17
18copyright = """
19/*
20** Copyright (c) 2020 The Khronos Group Inc.
21**
22** SPDX-License-Identifier: Apache-2.0
23*/
24"""
25
26
27predefinedCode = """
28/********************************************************************************************/
29/** This code is generated. To make changes, please modify the scripts or the relevant xml **/
30/********************************************************************************************/
31
32#pragma once
33
34#include <stdio.h>
35#include <vulkan/vulkan.h>
36
37const char* getJSONOutput(void);
38void resetJSONOutput(void);
39"""
40
41class JSONHeaderGeneratorOptions(GeneratorOptions):
42    """JSONHeaderGeneratorOptions - subclass of GeneratorOptions.
43
44    Adds options used by JSONHeaderOutputGenerator objects during C language header
45    generation."""
46
47    def __init__(self,
48                 prefixText="",
49                 genFuncPointers=True,
50                 protectFile=True,
51                 protectFeature=True,
52                 protectProto=None,
53                 protectProtoStr=None,
54                 apicall='',
55                 apientry='',
56                 apientryp='',
57                 indentFuncProto=True,
58                 indentFuncPointer=False,
59                 alignFuncParam=0,
60                 genEnumBeginEndRange=False,
61                 genAliasMacro=False,
62                 aliasMacro='',
63                 **kwargs
64                 ):
65
66        GeneratorOptions.__init__(self, **kwargs)
67
68
69class JSONHeaderOutputGenerator(OutputGenerator):
70    # This is an ordered list of sections in the header file.
71    TYPE_SECTIONS = ['basetype', 'handle', 'enum',
72                     'group', 'bitmask', 'struct']
73    ALL_SECTIONS = TYPE_SECTIONS
74
75    def __init__(self, *args, **kwargs):
76        super().__init__(*args, **kwargs)
77        # Internal state - accumulators for different inner block text
78        self.sections = {section: [] for section in self.ALL_SECTIONS}
79        self.feature_not_empty = False
80        self.may_alias         = None
81        self.featureDict       = {}
82        self.vkscFeatureList   = []
83        self.baseTypeList      = ["int32_t",
84                                  "uint32_t",
85                                  "uint8_t",
86                                  "uint64_t",
87                                  "float",
88                                  "int",
89                                  "double",
90                                  "int64_t",
91                                  "uint16_t",
92                                  "char"]
93
94
95    def createvkscFeatureList(self):
96        for feature in self.registry.reg.findall('feature'):
97            if feature.get('api').find('vulkansc') != -1:
98                # Remove entries that are removed in features in VKSC profile.
99                requiredList = feature.findall("require")
100
101                for requiredItem in requiredList:
102                    typeList = requiredItem.findall("type")
103                    for typeName in typeList:
104                        if typeName.get("name") != "":
105                            self.featureDict[typeName.get("name")] = feature.get("name")
106                            self.vkscFeatureList.append(typeName.get("name"))
107
108                removeItemList = feature.findall("remove")
109                for removeItem in removeItemList:
110                    removeTypes = removeItem.findall("type")
111                    for item in removeTypes:
112                        if self.vkscFeatureList.count(item.get("name")) > 0:
113                            self.vkscFeatureList.remove(item.get("name"))
114
115        allExtensions = self.registry.reg.findall('extensions')
116        for extensions in allExtensions:
117            extensionList = extensions.findall("extension")
118            for extension in extensionList:
119                if extension.get("supported").find("vulkansc") != -1:
120                    requiredList = extension.findall("require")
121                    for requiredItem in requiredList:
122                        typeList = requiredItem.findall("type")
123                        for typeName in typeList:
124                            self.featureDict[typeName.get("name")] = extension.get("name")
125                            self.vkscFeatureList.append(typeName.get("name"))
126
127    def printPrototypes(self):
128       code = ""
129
130       code += "/*************************************** Begin prototypes ***********************************/\n"
131       typesList = self.registry.reg.findall('types')
132       currentExtension = "VK_VERSION_1_0"
133       for types in typesList:
134            typeList = types.findall("type")
135
136            for type in typeList:
137                if type.get("name") != "":
138                    cat  = type.get("category")
139                    name = type.get("name")
140
141                    if cat in {"handle", "bitmask", "basetype", "enum", "struct"} and name in self.vkscFeatureList:
142                        if name in self.featureDict and currentExtension != self.featureDict[name]:
143                            if currentExtension != "VK_VERSION_1_0":
144                                code += "#endif\n"
145                            currentExtension = self.featureDict[name]
146                            if self.featureDict[name] != "VK_VERSION_1_0":
147                                code += "#ifdef %s\n" %(currentExtension)
148                        code += "void print_%s(const %s* obj, const char* str, int commaNeeded);\n" %(name, name)
149
150       if currentExtension != "VK_VERSION_1_0":
151            code += "#endif\n"
152       code += "/*************************************** End prototypes ***********************************/\n\n"
153
154       return code
155
156    def beginFile(self, genOpts):
157        OutputGenerator.beginFile(self, genOpts)
158
159        self.createvkscFeatureList()
160
161        write(copyright, file=self.outFile)
162        write(predefinedCode, file=self.outFile)
163
164        write(self.printPrototypes(), file=self.outFile)
165        write("void dumpPNextChain(const void* pNext);\n", file=self.outFile)
166
167    def endFile(self):
168        OutputGenerator.endFile(self)
169
170    def beginFeature(self, interface, emit):
171        OutputGenerator.beginFeature(self, interface, emit)
172        self.sections = {section: [] for section in self.ALL_SECTIONS}
173        self.feature_not_empty = False
174
175    def endFeature(self):
176        if self.emit:
177            if self.feature_not_empty:
178                if self.genOpts.conventions.writeFeature(self.featureExtraProtect, self.genOpts.filename):
179
180                    for section in self.TYPE_SECTIONS:
181                        contents = self.sections[section]
182                        if contents:
183                            write('\n'.join(contents), file=self.outFile)
184
185        # Finish processing in superclass
186        OutputGenerator.endFeature(self)
187
188    def genType(self, typeinfo, name, alias):
189        OutputGenerator.genType(self, typeinfo, name, alias)
190
191    def genStruct(self, typeinfo, typeName, alias):
192        OutputGenerator.genStruct(self, typeinfo, typeName, alias)
193
194    def genGroup(self, groupinfo, groupName, alias=None):
195        OutputGenerator.genGroup(self, groupinfo, groupName, alias)
196
197