1# -*- coding: utf-8 -*- 2 3#------------------------------------------------------------------------- 4# drawElements Quality Program utilities 5# -------------------------------------- 6# 7# Copyright 2018 The Android Open Source Project 8# 9# Licensed under the Apache License, Version 2.0 (the "License"); 10# you may not use this file except in compliance with the License. 11# You may obtain a copy of the License at 12# 13# http://www.apache.org/licenses/LICENSE-2.0 14# 15# Unless required by applicable law or agreed to in writing, software 16# distributed under the License is distributed on an "AS IS" BASIS, 17# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 18# See the License for the specific language governing permissions and 19# limitations under the License. 20# 21#------------------------------------------------------------------------- 22 23import os 24import sys 25 26sys.path.append(os.path.join(os.path.dirname(__file__), "..", "..", "..", "scripts")) 27 28import khr_util.format 29from khr_util import registry 30from collections import defaultdict 31 32VK_INL_FILE = os.path.join(os.path.dirname(__file__), "..", "framework", "vulkan", "vkApiExtensionDependencyInfo.inl") 33VK_INL_HEADER = """\ 34/* WARNING: This is auto-generated file. Do not modify, since changes will 35 * be lost! Modify the generating script instead. 36 */\ 37 38""" 39 40 41def VK_MAKE_VERSION(major, minor, patch): 42 return (((major) << 22) | ((minor) << 12) | (patch)) 43 44VK_EXT_NOT_PROMOTED = 0xFFFFFFFF 45VK_EXT_TYPE_INSTANCE = 0 46VK_EXT_TYPE_DEVICE = 1 47VK_EXT_DEP_INSTANCE = 'instanceExtensionDependencies' 48VK_EXT_DEP_DEVICE = 'deviceExtensionDependencies' 49VK_EXT_API_VERSIONS = 'releasedApiVersions' 50VK_EXT_CORE_VERSIONS = 'extensionRequiredCoreVersion' 51VK_XML_EXT_DEPS = 'requires' 52VK_XML_EXT_NAME = 'name' 53VK_XML_EXT_PROMO = 'promotedto' 54VK_XML_EXT_REQUIRES_CORE = 'requiresCore' 55VK_XML_EXT_SUPPORTED = 'supported' 56VK_XML_EXT_SUPPORTED_VULKAN = 'vulkan' 57VK_XML_EXT_API = 'api' 58VK_XML_EXT_TYPE = 'type' 59VK_XML_EXT_TYPE_DEVICE = 'device' 60VK_XML_EXT_TYPE_INSTANCE = 'instance' 61 62def writeInlFile(filename, lines): 63 khr_util.format.writeInlFile(filename, VK_INL_HEADER, lines) 64 65def genExtDepArray(extDepsName, extDepsDict): 66 yield 'static const std::tuple<deUint32, deUint32, const char*, const char*>\t{}[]\t='.format(extDepsName) 67 yield '{' 68 for ( major, minor, ext, extDeps ) in extDepsDict: 69 for dep in extDeps: 70 yield '\tstd::make_tuple({}, {}, "{}", "{}"),'.format(major, minor, ext, dep) 71 yield '};' 72 73def genApiVersions(name, apiVersions): 74 yield 'static const std::tuple<deUint32, deUint32, deUint32>\t{}[]\t='.format(name) 75 yield '{' 76 for ( version, major, minor ) in apiVersions: 77 yield '\tstd::make_tuple({}, {}, {}),'.format(version, major, minor) 78 yield '};' 79 80def genRequiredCoreVersions(name, coreVersionsDict): 81 yield 'static const std::tuple<deUint32, deUint32, const char*>\t{}[]\t ='.format(name) 82 yield '{' 83 extNames = sorted(coreVersionsDict.keys()) 84 for extName in extNames: 85 (major, minor) = coreVersionsDict[extName] 86 yield '\tstd::make_tuple({}, {}, "{}"),'.format(major, minor, extName) 87 yield '};' 88 89def genExtDepInl(dependenciesAndVersions, filename): 90 allExtDepsDict, apiVersions, allExtCoreVersions = dependenciesAndVersions 91 apiVersions.reverse() 92 lines = [] 93 94 lines.extend(genExtDepArray(VK_EXT_DEP_INSTANCE, allExtDepsDict[VK_EXT_TYPE_INSTANCE])) 95 lines.extend(genExtDepArray(VK_EXT_DEP_DEVICE, allExtDepsDict[VK_EXT_TYPE_DEVICE])) 96 lines.extend(genApiVersions(VK_EXT_API_VERSIONS, apiVersions)) 97 lines.extend(genRequiredCoreVersions(VK_EXT_CORE_VERSIONS, allExtCoreVersions)) 98 99 writeInlFile(filename, lines) 100 101class extInfo: 102 def __init__(self): 103 self.type = VK_EXT_TYPE_INSTANCE 104 self.core = VK_MAKE_VERSION(1, 0, 0) 105 self.coreMajorMinor = (1, 0) 106 self.promo = VK_EXT_NOT_PROMOTED 107 self.deps = [] 108 109def genExtDepsOnApiVersion(ext, extInfoDict, apiVersion): 110 deps = [] 111 112 for dep in extInfoDict[ext].deps: 113 if apiVersion >= extInfoDict[dep].promo: 114 continue 115 116 deps.append(dep) 117 118 return deps 119 120def genExtDeps(extensionsAndVersions): 121 extInfoDict, apiVersionID = extensionsAndVersions 122 123 allExtDepsDict = defaultdict(list) 124 apiVersions = [] 125 126 for (major,minor) in apiVersionID: 127 apiVersions.append((VK_MAKE_VERSION(major, minor, 0),major,minor)) 128 apiVersions.sort(key=lambda x: x[0]) 129 130 for ext, info in extInfoDict.items(): 131 if info.deps == None: 132 continue 133 134 for (version,major,minor) in apiVersions: 135 if info.core <= version: 136 extDeps = genExtDepsOnApiVersion(ext, extInfoDict, version) 137 if extDeps == None: 138 continue 139 allExtDepsDict[info.type].append( ( major, minor, ext, extDeps ) ) 140 141 for key, value in allExtDepsDict.items(): 142 value.sort(key=lambda x: x[2]) 143 144 allExtCoreVersions = {} 145 for (ext, info) in extInfoDict.items(): 146 allExtCoreVersions[ext] = info.coreMajorMinor 147 148 return allExtDepsDict, apiVersions, allExtCoreVersions 149 150def getExtInfoDict(vkRegistry): 151 extInfoDict = {} 152 apiVersionID = [] 153 154 for feature in vkRegistry.features: 155 if feature.attrib[VK_XML_EXT_API] != VK_XML_EXT_SUPPORTED_VULKAN: 156 continue 157 featureName = feature.attrib[VK_XML_EXT_NAME].split('_') 158 if len(featureName)!=4 or featureName[0] != 'VK' or featureName[1] != 'VERSION' : 159 continue 160 apiVersionID.append( (int(featureName[2]), int(featureName[3])) ) 161 162 apiVersionsByName = {} 163 apiVersionsByNumber = {} 164 apiMajorMinorByNumber = {} 165 for (major,minor) in apiVersionID: 166 majorDotMinor = '{}.{}'.format(major,minor) 167 apiVersionsByName['VK_VERSION_{}_{}'.format(major,minor)] = VK_MAKE_VERSION(major, minor, 0); 168 apiVersionsByNumber[majorDotMinor] = VK_MAKE_VERSION(major, minor, 0); 169 apiMajorMinorByNumber[majorDotMinor] = (major, minor) 170 171 for ext in vkRegistry.extensions: 172 if ext.attrib[VK_XML_EXT_SUPPORTED] != VK_XML_EXT_SUPPORTED_VULKAN: 173 continue 174 175 name = ext.attrib[VK_XML_EXT_NAME] 176 extInfoDict[name] = extInfo() 177 if ext.attrib[VK_XML_EXT_TYPE] == VK_XML_EXT_TYPE_DEVICE: 178 extInfoDict[name].type = VK_EXT_TYPE_DEVICE 179 if VK_XML_EXT_REQUIRES_CORE in ext.attrib and ext.attrib[VK_XML_EXT_REQUIRES_CORE] in apiVersionsByNumber: 180 extInfoDict[name].core = apiVersionsByNumber[ext.attrib[VK_XML_EXT_REQUIRES_CORE]] 181 extInfoDict[name].coreMajorMinor = apiMajorMinorByNumber[ext.attrib[VK_XML_EXT_REQUIRES_CORE]] 182 if VK_XML_EXT_PROMO in ext.attrib and ext.attrib[VK_XML_EXT_PROMO] in apiVersionsByName : 183 extInfoDict[name].promo = apiVersionsByName[ext.attrib[VK_XML_EXT_PROMO]] 184 if VK_XML_EXT_DEPS in ext.attrib: 185 extInfoDict[name].deps = ext.attrib[VK_XML_EXT_DEPS].split(',') 186 187 return extInfoDict, apiVersionID 188 189if __name__ == '__main__': 190 191 # script requires output path to which .inl files will be written 192 if len(sys.argv) == 1: 193 sys.exit("Error - output path wasn't specified in argument") 194 outputPath = str(sys.argv[1]) 195 196 VULKAN_XML = os.path.join(os.path.dirname(__file__), "..", "..", "vulkan-docs", "src", "xml", "vk.xml") 197 vkRegistry = registry.parse(VULKAN_XML) 198 199 genExtDepInl(genExtDeps(getExtInfoDict(vkRegistry)), os.path.join(outputPath, "vkApiExtensionDependencyInfo.inl")) 200