15db71995Sopenharmony_ci#!/usr/bin/python3 -i
25db71995Sopenharmony_ci#
35db71995Sopenharmony_ci# Copyright (c) 2015-2021 The Khronos Group Inc.
45db71995Sopenharmony_ci# Copyright (c) 2015-2021 Valve Corporation
55db71995Sopenharmony_ci# Copyright (c) 2015-2021 LunarG, Inc.
65db71995Sopenharmony_ci# Copyright (c) 2015-2021 Google Inc.
75db71995Sopenharmony_ci#
85db71995Sopenharmony_ci# Licensed under the Apache License, Version 2.0 (the "License");
95db71995Sopenharmony_ci# you may not use this file except in compliance with the License.
105db71995Sopenharmony_ci# You may obtain a copy of the License at
115db71995Sopenharmony_ci#
125db71995Sopenharmony_ci#     http://www.apache.org/licenses/LICENSE-2.0
135db71995Sopenharmony_ci#
145db71995Sopenharmony_ci# Unless required by applicable law or agreed to in writing, software
155db71995Sopenharmony_ci# distributed under the License is distributed on an "AS IS" BASIS,
165db71995Sopenharmony_ci# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
175db71995Sopenharmony_ci# See the License for the specific language governing permissions and
185db71995Sopenharmony_ci# limitations under the License.
195db71995Sopenharmony_ci#
205db71995Sopenharmony_ci# Author: Mark Lobodzinski <mark@lunarg.com>
215db71995Sopenharmony_ci
225db71995Sopenharmony_ciimport os,re,sys
235db71995Sopenharmony_ciimport xml.etree.ElementTree as etree
245db71995Sopenharmony_cifrom generator import *
255db71995Sopenharmony_cifrom collections import namedtuple
265db71995Sopenharmony_cifrom common_codegen import *
275db71995Sopenharmony_ci
285db71995Sopenharmony_cireturn_type_table = {"VkResult": "VK_SUCCESS",
295db71995Sopenharmony_ci                     "uint32_t": "0",
305db71995Sopenharmony_ci                     "uint64_t": "0L",
315db71995Sopenharmony_ci                     "VkDeviceAddress": "0L",
325db71995Sopenharmony_ci                     "VkDeviceSize": "0L"}
335db71995Sopenharmony_ci
345db71995Sopenharmony_ci#
355db71995Sopenharmony_ci# DispatchTableHelperOutputGeneratorOptions - subclass of GeneratorOptions.
365db71995Sopenharmony_ciclass DispatchTableHelperOutputGeneratorOptions(GeneratorOptions):
375db71995Sopenharmony_ci    def __init__(self,
385db71995Sopenharmony_ci                 conventions = None,
395db71995Sopenharmony_ci                 filename = None,
405db71995Sopenharmony_ci                 directory = '.',
415db71995Sopenharmony_ci                 genpath = None,
425db71995Sopenharmony_ci                 apiname = None,
435db71995Sopenharmony_ci                 profile = None,
445db71995Sopenharmony_ci                 versions = '.*',
455db71995Sopenharmony_ci                 emitversions = '.*',
465db71995Sopenharmony_ci                 defaultExtensions = None,
475db71995Sopenharmony_ci                 addExtensions = None,
485db71995Sopenharmony_ci                 removeExtensions = None,
495db71995Sopenharmony_ci                 emitExtensions = None,
505db71995Sopenharmony_ci                 sortProcedure = regSortFeatures,
515db71995Sopenharmony_ci                 prefixText = "",
525db71995Sopenharmony_ci                 genFuncPointers = True,
535db71995Sopenharmony_ci                 apicall = '',
545db71995Sopenharmony_ci                 apientry = '',
555db71995Sopenharmony_ci                 apientryp = '',
565db71995Sopenharmony_ci                 alignFuncParam = 0,
575db71995Sopenharmony_ci                 expandEnumerants = True):
585db71995Sopenharmony_ci        GeneratorOptions.__init__(self,
595db71995Sopenharmony_ci                conventions = conventions,
605db71995Sopenharmony_ci                filename = filename,
615db71995Sopenharmony_ci                directory = directory,
625db71995Sopenharmony_ci                genpath = genpath,
635db71995Sopenharmony_ci                apiname = apiname,
645db71995Sopenharmony_ci                profile = profile,
655db71995Sopenharmony_ci                versions = versions,
665db71995Sopenharmony_ci                emitversions = emitversions,
675db71995Sopenharmony_ci                defaultExtensions = defaultExtensions,
685db71995Sopenharmony_ci                addExtensions = addExtensions,
695db71995Sopenharmony_ci                removeExtensions = removeExtensions,
705db71995Sopenharmony_ci                emitExtensions = emitExtensions,
715db71995Sopenharmony_ci                sortProcedure = sortProcedure)
725db71995Sopenharmony_ci        self.prefixText      = prefixText
735db71995Sopenharmony_ci        self.genFuncPointers = genFuncPointers
745db71995Sopenharmony_ci        self.prefixText      = None
755db71995Sopenharmony_ci        self.apicall         = apicall
765db71995Sopenharmony_ci        self.apientry        = apientry
775db71995Sopenharmony_ci        self.apientryp       = apientryp
785db71995Sopenharmony_ci        self.alignFuncParam  = alignFuncParam
795db71995Sopenharmony_ci#
805db71995Sopenharmony_ci# DispatchTableHelperOutputGenerator - subclass of OutputGenerator.
815db71995Sopenharmony_ci# Generates dispatch table helper header files for LVL
825db71995Sopenharmony_ciclass DispatchTableHelperOutputGenerator(OutputGenerator):
835db71995Sopenharmony_ci    """Generate dispatch table helper header based on XML element attributes"""
845db71995Sopenharmony_ci    def __init__(self,
855db71995Sopenharmony_ci                 errFile = sys.stderr,
865db71995Sopenharmony_ci                 warnFile = sys.stderr,
875db71995Sopenharmony_ci                 diagFile = sys.stdout):
885db71995Sopenharmony_ci        OutputGenerator.__init__(self, errFile, warnFile, diagFile)
895db71995Sopenharmony_ci        # Internal state - accumulators for different inner block text
905db71995Sopenharmony_ci        self.instance_dispatch_list = []      # List of entries for instance dispatch list
915db71995Sopenharmony_ci        self.device_dispatch_list = []        # List of entries for device dispatch list
925db71995Sopenharmony_ci        self.dev_ext_stub_list = []           # List of stub functions for device extension functions
935db71995Sopenharmony_ci        self.device_extension_list = []       # List of device extension functions
945db71995Sopenharmony_ci        self.extension_type = ''
955db71995Sopenharmony_ci    #
965db71995Sopenharmony_ci    # Called once at the beginning of each run
975db71995Sopenharmony_ci    def beginFile(self, genOpts):
985db71995Sopenharmony_ci        OutputGenerator.beginFile(self, genOpts)
995db71995Sopenharmony_ci        write("#pragma once", file=self.outFile)
1005db71995Sopenharmony_ci        # User-supplied prefix text, if any (list of strings)
1015db71995Sopenharmony_ci        if (genOpts.prefixText):
1025db71995Sopenharmony_ci            for s in genOpts.prefixText:
1035db71995Sopenharmony_ci                write(s, file=self.outFile)
1045db71995Sopenharmony_ci        # File Comment
1055db71995Sopenharmony_ci        file_comment = '// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n'
1065db71995Sopenharmony_ci        file_comment += '// See dispatch_table_helper_generator.py for modifications\n'
1075db71995Sopenharmony_ci        write(file_comment, file=self.outFile)
1085db71995Sopenharmony_ci        # Copyright Notice
1095db71995Sopenharmony_ci        copyright =  '/*\n'
1105db71995Sopenharmony_ci        copyright += ' * Copyright (c) 2015-2021 The Khronos Group Inc.\n'
1115db71995Sopenharmony_ci        copyright += ' * Copyright (c) 2015-2021 Valve Corporation\n'
1125db71995Sopenharmony_ci        copyright += ' * Copyright (c) 2015-2021 LunarG, Inc.\n'
1135db71995Sopenharmony_ci        copyright += ' *\n'
1145db71995Sopenharmony_ci        copyright += ' * Licensed under the Apache License, Version 2.0 (the "License");\n'
1155db71995Sopenharmony_ci        copyright += ' * you may not use this file except in compliance with the License.\n'
1165db71995Sopenharmony_ci        copyright += ' * You may obtain a copy of the License at\n'
1175db71995Sopenharmony_ci        copyright += ' *\n'
1185db71995Sopenharmony_ci        copyright += ' *     http://www.apache.org/licenses/LICENSE-2.0\n'
1195db71995Sopenharmony_ci        copyright += ' *\n'
1205db71995Sopenharmony_ci        copyright += ' * Unless required by applicable law or agreed to in writing, software\n'
1215db71995Sopenharmony_ci        copyright += ' * distributed under the License is distributed on an "AS IS" BASIS,\n'
1225db71995Sopenharmony_ci        copyright += ' * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n'
1235db71995Sopenharmony_ci        copyright += ' * See the License for the specific language governing permissions and\n'
1245db71995Sopenharmony_ci        copyright += ' * limitations under the License.\n'
1255db71995Sopenharmony_ci        copyright += ' *\n'
1265db71995Sopenharmony_ci        copyright += ' * Author: Courtney Goeltzenleuchter <courtney@LunarG.com>\n'
1275db71995Sopenharmony_ci        copyright += ' * Author: Jon Ashburn <jon@lunarg.com>\n'
1285db71995Sopenharmony_ci        copyright += ' * Author: Mark Lobodzinski <mark@lunarg.com>\n'
1295db71995Sopenharmony_ci        copyright += ' */\n'
1305db71995Sopenharmony_ci
1315db71995Sopenharmony_ci        preamble = ''
1325db71995Sopenharmony_ci        preamble += '#include <vulkan/vulkan.h>\n'
1335db71995Sopenharmony_ci        preamble += '#include <vulkan/vk_layer.h>\n'
1345db71995Sopenharmony_ci        preamble += '#include <string.h>\n'
1355db71995Sopenharmony_ci        preamble += '#include "loader/generated/vk_layer_dispatch_table.h"\n'
1365db71995Sopenharmony_ci
1375db71995Sopenharmony_ci        write(copyright, file=self.outFile)
1385db71995Sopenharmony_ci        write(preamble, file=self.outFile)
1395db71995Sopenharmony_ci    #
1405db71995Sopenharmony_ci    # Write generate and write dispatch tables to output file
1415db71995Sopenharmony_ci    def endFile(self):
1425db71995Sopenharmony_ci        device_table = ''
1435db71995Sopenharmony_ci        instance_table = ''
1445db71995Sopenharmony_ci
1455db71995Sopenharmony_ci        device_table += self.OutputDispatchTableHelper('device')
1465db71995Sopenharmony_ci        instance_table += self.OutputDispatchTableHelper('instance')
1475db71995Sopenharmony_ci
1485db71995Sopenharmony_ci        for stub in self.dev_ext_stub_list:
1495db71995Sopenharmony_ci            write(stub, file=self.outFile)
1505db71995Sopenharmony_ci        write("\n\n", file=self.outFile)
1515db71995Sopenharmony_ci        write(device_table, file=self.outFile);
1525db71995Sopenharmony_ci        write("\n", file=self.outFile)
1535db71995Sopenharmony_ci        write(instance_table, file=self.outFile);
1545db71995Sopenharmony_ci
1555db71995Sopenharmony_ci        # Finish processing in superclass
1565db71995Sopenharmony_ci        OutputGenerator.endFile(self)
1575db71995Sopenharmony_ci    #
1585db71995Sopenharmony_ci    # Processing at beginning of each feature or extension
1595db71995Sopenharmony_ci    def beginFeature(self, interface, emit):
1605db71995Sopenharmony_ci        OutputGenerator.beginFeature(self, interface, emit)
1615db71995Sopenharmony_ci        self.featureExtraProtect = GetFeatureProtect(interface)
1625db71995Sopenharmony_ci        self.extension_type = interface.get('type')
1635db71995Sopenharmony_ci
1645db71995Sopenharmony_ci    #
1655db71995Sopenharmony_ci    # Process commands, adding to appropriate dispatch tables
1665db71995Sopenharmony_ci    def genCmd(self, cmdinfo, name, alias):
1675db71995Sopenharmony_ci        OutputGenerator.genCmd(self, cmdinfo, name, alias)
1685db71995Sopenharmony_ci
1695db71995Sopenharmony_ci        avoid_entries = ['vkCreateInstance',
1705db71995Sopenharmony_ci                         'vkCreateDevice']
1715db71995Sopenharmony_ci        # Get first param type
1725db71995Sopenharmony_ci        params = cmdinfo.elem.findall('param')
1735db71995Sopenharmony_ci        info = self.getTypeNameTuple(params[0])
1745db71995Sopenharmony_ci
1755db71995Sopenharmony_ci        if name not in avoid_entries:
1765db71995Sopenharmony_ci            self.AddCommandToDispatchList(name, info[0], self.featureExtraProtect, cmdinfo)
1775db71995Sopenharmony_ci
1785db71995Sopenharmony_ci    #
1795db71995Sopenharmony_ci    # Determine if this API should be ignored or added to the instance or device dispatch table
1805db71995Sopenharmony_ci    def AddCommandToDispatchList(self, name, handle_type, protect, cmdinfo):
1815db71995Sopenharmony_ci        handle = self.registry.tree.find("types/type/[name='" + handle_type + "'][@category='handle']")
1825db71995Sopenharmony_ci        if handle is None:
1835db71995Sopenharmony_ci            return
1845db71995Sopenharmony_ci        if handle_type != 'VkInstance' and handle_type != 'VkPhysicalDevice' and name != 'vkGetInstanceProcAddr':
1855db71995Sopenharmony_ci            self.device_dispatch_list.append((name, self.featureExtraProtect))
1865db71995Sopenharmony_ci        else:
1875db71995Sopenharmony_ci            self.instance_dispatch_list.append((name, self.featureExtraProtect))
1885db71995Sopenharmony_ci        return
1895db71995Sopenharmony_ci    #
1905db71995Sopenharmony_ci    # Retrieve the type and name for a parameter
1915db71995Sopenharmony_ci    def getTypeNameTuple(self, param):
1925db71995Sopenharmony_ci        type = ''
1935db71995Sopenharmony_ci        name = ''
1945db71995Sopenharmony_ci        for elem in param:
1955db71995Sopenharmony_ci            if elem.tag == 'type':
1965db71995Sopenharmony_ci                type = noneStr(elem.text)
1975db71995Sopenharmony_ci            elif elem.tag == 'name':
1985db71995Sopenharmony_ci                name = noneStr(elem.text)
1995db71995Sopenharmony_ci        return (type, name)
2005db71995Sopenharmony_ci    #
2015db71995Sopenharmony_ci    # Create a dispatch table from the appropriate list and return it as a string
2025db71995Sopenharmony_ci    def OutputDispatchTableHelper(self, table_type):
2035db71995Sopenharmony_ci        entries = []
2045db71995Sopenharmony_ci        table = ''
2055db71995Sopenharmony_ci        if table_type == 'device':
2065db71995Sopenharmony_ci            entries = self.device_dispatch_list
2075db71995Sopenharmony_ci            table += 'static inline void layer_init_device_dispatch_table(VkDevice device, VkLayerDispatchTable *table, PFN_vkGetDeviceProcAddr gpa) {\n'
2085db71995Sopenharmony_ci            table += '    memset(table, 0, sizeof(*table));\n'
2095db71995Sopenharmony_ci            table += '    table->magic = DEVICE_DISP_TABLE_MAGIC_NUMBER;\n\n'
2105db71995Sopenharmony_ci            table += '    // Device function pointers\n'
2115db71995Sopenharmony_ci        else:
2125db71995Sopenharmony_ci            entries = self.instance_dispatch_list
2135db71995Sopenharmony_ci            table += 'static inline void layer_init_instance_dispatch_table(VkInstance instance, VkLayerInstanceDispatchTable *table, PFN_vkGetInstanceProcAddr gpa) {\n'
2145db71995Sopenharmony_ci            table += '    memset(table, 0, sizeof(*table));\n\n'
2155db71995Sopenharmony_ci            table += '    // Instance function pointers\n'
2165db71995Sopenharmony_ci
2175db71995Sopenharmony_ci        for item in entries:
2185db71995Sopenharmony_ci            # Remove 'vk' from proto name
2195db71995Sopenharmony_ci            base_name = item[0][2:]
2205db71995Sopenharmony_ci
2215db71995Sopenharmony_ci            if item[1] is not None:
2225db71995Sopenharmony_ci                table += '#if defined(%s)\n' % item[1]
2235db71995Sopenharmony_ci
2245db71995Sopenharmony_ci            # If we're looking for the proc we are passing in, just point the table to it.  This fixes the issue where
2255db71995Sopenharmony_ci            # a layer overrides the function name for the loader.
2265db71995Sopenharmony_ci            if (table_type == 'device' and base_name == 'GetDeviceProcAddr'):
2275db71995Sopenharmony_ci                table += '    table->GetDeviceProcAddr = gpa;\n'
2285db71995Sopenharmony_ci            elif (table_type != 'device' and base_name == 'GetInstanceProcAddr'):
2295db71995Sopenharmony_ci                table += '    table->GetInstanceProcAddr = gpa;\n'
2305db71995Sopenharmony_ci            else:
2315db71995Sopenharmony_ci                table += '    table->%s = (PFN_%s) gpa(%s, "%s");\n' % (base_name, item[0], table_type, item[0])
2325db71995Sopenharmony_ci            if item[1] is not None:
2335db71995Sopenharmony_ci                table += '#endif // %s\n' % item[1]
2345db71995Sopenharmony_ci
2355db71995Sopenharmony_ci        table += '}'
2365db71995Sopenharmony_ci        return table
237