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