2023-11-06 10:19:32 -08:00
|
|
|
#!/usr/bin/python3
|
|
|
|
|
#
|
|
|
|
|
# Copyright 2013-2023 The Khronos Group Inc.
|
|
|
|
|
#
|
|
|
|
|
# SPDX-License-Identifier: Apache-2.0
|
|
|
|
|
|
|
|
|
|
import argparse
|
|
|
|
|
import os
|
|
|
|
|
import pdb
|
|
|
|
|
import re
|
|
|
|
|
import sys
|
|
|
|
|
import copy
|
|
|
|
|
import time
|
|
|
|
|
import xml.etree.ElementTree as etree
|
|
|
|
|
|
|
|
|
|
sys.path.append(os.path.abspath(os.path.dirname(__file__)))
|
|
|
|
|
|
|
|
|
|
from cgenerator import CGeneratorOptions, COutputGenerator
|
2024-09-13 09:36:56 -07:00
|
|
|
|
2023-11-06 10:19:32 -08:00
|
|
|
from generator import write
|
|
|
|
|
from reg import Registry
|
|
|
|
|
from apiconventions import APIConventions
|
|
|
|
|
|
2023-11-07 09:38:12 -07:00
|
|
|
# gfxstream + cereal modules
|
|
|
|
|
from cerealgenerator import CerealGenerator
|
|
|
|
|
|
2023-11-06 10:19:32 -08:00
|
|
|
# Simple timer functions
|
|
|
|
|
startTime = None
|
2023-11-07 11:55:13 -07:00
|
|
|
from typing import Optional
|
2023-11-06 10:19:32 -08:00
|
|
|
|
|
|
|
|
def startTimer(timeit):
|
|
|
|
|
global startTime
|
|
|
|
|
if timeit:
|
|
|
|
|
startTime = time.process_time()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def endTimer(timeit, msg):
|
|
|
|
|
global startTime
|
|
|
|
|
if timeit and startTime is not None:
|
|
|
|
|
endTime = time.process_time()
|
|
|
|
|
startTime = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def makeREstring(strings, default=None, strings_are_regex=False):
|
|
|
|
|
"""Turn a list of strings into a regexp string matching exactly those strings."""
|
|
|
|
|
if strings or default is None:
|
|
|
|
|
if not strings_are_regex:
|
|
|
|
|
strings = (re.escape(s) for s in strings)
|
|
|
|
|
return '^(' + '|'.join(strings) + ')$'
|
|
|
|
|
return default
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def makeGenOpts(args):
|
|
|
|
|
"""Returns a directory of [ generator function, generator options ] indexed
|
|
|
|
|
by specified short names. The generator options incorporate the following
|
|
|
|
|
parameters:
|
|
|
|
|
|
|
|
|
|
args is an parsed argument object; see below for the fields that are used."""
|
|
|
|
|
global genOpts
|
|
|
|
|
genOpts = {}
|
|
|
|
|
|
|
|
|
|
# Default class of extensions to include, or None
|
|
|
|
|
defaultExtensions = args.defaultExtensions
|
|
|
|
|
|
|
|
|
|
# Additional extensions to include (list of extensions)
|
|
|
|
|
extensions = args.extension
|
|
|
|
|
|
|
|
|
|
# Extensions to remove (list of extensions)
|
|
|
|
|
removeExtensions = args.removeExtensions
|
|
|
|
|
|
|
|
|
|
# Extensions to emit (list of extensions)
|
|
|
|
|
emitExtensions = args.emitExtensions
|
|
|
|
|
|
|
|
|
|
# SPIR-V capabilities / features to emit (list of extensions & capabilities)
|
|
|
|
|
emitSpirv = args.emitSpirv
|
|
|
|
|
|
|
|
|
|
# Vulkan Formats to emit
|
|
|
|
|
emitFormats = args.emitFormats
|
|
|
|
|
|
|
|
|
|
# Features to include (list of features)
|
|
|
|
|
features = args.feature
|
|
|
|
|
|
|
|
|
|
# Whether to disable inclusion protect in headers
|
|
|
|
|
protect = args.protect
|
|
|
|
|
|
|
|
|
|
# Output target directory
|
|
|
|
|
directory = args.directory
|
|
|
|
|
|
|
|
|
|
# Path to generated files, particularly apimap.py
|
|
|
|
|
genpath = args.genpath
|
|
|
|
|
|
|
|
|
|
# Generate MISRA C-friendly headers
|
|
|
|
|
misracstyle = args.misracstyle;
|
|
|
|
|
|
|
|
|
|
# Generate MISRA C++-friendly headers
|
|
|
|
|
misracppstyle = args.misracppstyle;
|
|
|
|
|
|
|
|
|
|
# Descriptive names for various regexp patterns used to select
|
|
|
|
|
# versions and extensions
|
|
|
|
|
allFormats = allSpirv = allFeatures = allExtensions = r'.*'
|
|
|
|
|
|
|
|
|
|
# Turn lists of names/patterns into matching regular expressions
|
|
|
|
|
addExtensionsPat = makeREstring(extensions, None)
|
|
|
|
|
removeExtensionsPat = makeREstring(removeExtensions, None)
|
|
|
|
|
emitExtensionsPat = makeREstring(emitExtensions, allExtensions)
|
|
|
|
|
emitSpirvPat = makeREstring(emitSpirv, allSpirv)
|
|
|
|
|
emitFormatsPat = makeREstring(emitFormats, allFormats)
|
|
|
|
|
featuresPat = makeREstring(features, allFeatures)
|
|
|
|
|
|
|
|
|
|
# Copyright text prefixing all headers (list of strings).
|
|
|
|
|
# The SPDX formatting below works around constraints of the 'reuse' tool
|
|
|
|
|
prefixStrings = [
|
|
|
|
|
'/*',
|
|
|
|
|
'** Copyright 2015-2023 The Khronos Group Inc.',
|
|
|
|
|
'**',
|
|
|
|
|
'** SPDX-License-Identifier' + ': Apache-2.0',
|
|
|
|
|
'*/',
|
|
|
|
|
''
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# Text specific to Vulkan headers
|
|
|
|
|
vkPrefixStrings = [
|
|
|
|
|
'/*',
|
|
|
|
|
'** This header is generated from the Khronos Vulkan XML API Registry.',
|
|
|
|
|
'**',
|
|
|
|
|
'*/',
|
|
|
|
|
''
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
vulkanLayer = args.vulkanLayer
|
|
|
|
|
|
|
|
|
|
# Defaults for generating re-inclusion protection wrappers (or not)
|
|
|
|
|
protectFile = protect
|
|
|
|
|
|
|
|
|
|
# An API style conventions object
|
|
|
|
|
conventions = APIConventions()
|
|
|
|
|
|
|
|
|
|
if args.apiname is not None:
|
|
|
|
|
defaultAPIName = args.apiname
|
|
|
|
|
else:
|
|
|
|
|
defaultAPIName = conventions.xml_api_name
|
|
|
|
|
|
|
|
|
|
# APIs to merge
|
|
|
|
|
mergeApiNames = args.mergeApiNames
|
|
|
|
|
|
|
|
|
|
isCTS = args.isCTS
|
|
|
|
|
|
|
|
|
|
# Platform extensions, in their own header files
|
|
|
|
|
# Each element of the platforms[] array defines information for
|
|
|
|
|
# generating a single platform:
|
|
|
|
|
# [0] is the generated header file name
|
|
|
|
|
# [1] is the set of platform extensions to generate
|
|
|
|
|
# [2] is additional extensions whose interfaces should be considered,
|
|
|
|
|
# but suppressed in the output, to avoid duplicate definitions of
|
|
|
|
|
# dependent types like VkDisplayKHR and VkSurfaceKHR which come from
|
|
|
|
|
# non-platform extensions.
|
|
|
|
|
|
|
|
|
|
# Track all platform extensions, for exclusion from vulkan_core.h
|
|
|
|
|
allPlatformExtensions = []
|
|
|
|
|
|
|
|
|
|
# Extensions suppressed for all WSI platforms (WSI extensions required
|
|
|
|
|
# by all platforms)
|
|
|
|
|
commonSuppressExtensions = [ 'VK_KHR_display', 'VK_KHR_swapchain' ]
|
|
|
|
|
|
|
|
|
|
# Extensions required and suppressed for beta "platform". This can
|
|
|
|
|
# probably eventually be derived from the requires= attributes of
|
|
|
|
|
# the extension blocks.
|
|
|
|
|
betaRequireExtensions = [
|
|
|
|
|
'VK_KHR_portability_subset',
|
|
|
|
|
'VK_KHR_video_encode_queue',
|
|
|
|
|
'VK_EXT_video_encode_h264',
|
|
|
|
|
'VK_EXT_video_encode_h265',
|
|
|
|
|
'VK_NV_displacement_micromap',
|
|
|
|
|
'VK_AMDX_shader_enqueue',
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
betaSuppressExtensions = [
|
|
|
|
|
'VK_KHR_video_queue',
|
|
|
|
|
'VK_EXT_opacity_micromap',
|
|
|
|
|
'VK_KHR_pipeline_library',
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
platforms = [
|
|
|
|
|
[ 'vulkan_android.h', [ 'VK_KHR_android_surface',
|
|
|
|
|
'VK_ANDROID_external_memory_android_hardware_buffer',
|
|
|
|
|
'VK_ANDROID_external_format_resolve'
|
|
|
|
|
], commonSuppressExtensions +
|
|
|
|
|
[ 'VK_KHR_format_feature_flags2',
|
|
|
|
|
] ],
|
|
|
|
|
[ 'vulkan_fuchsia.h', [ 'VK_FUCHSIA_imagepipe_surface',
|
|
|
|
|
'VK_FUCHSIA_external_memory',
|
|
|
|
|
'VK_FUCHSIA_external_semaphore',
|
|
|
|
|
'VK_FUCHSIA_buffer_collection' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_ggp.h', [ 'VK_GGP_stream_descriptor_surface',
|
|
|
|
|
'VK_GGP_frame_token' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_ios.h', [ 'VK_MVK_ios_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_macos.h', [ 'VK_MVK_macos_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_vi.h', [ 'VK_NN_vi_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_wayland.h', [ 'VK_KHR_wayland_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_win32.h', [ 'VK_.*_win32(|_.*)', 'VK_.*_winrt(|_.*)', 'VK_EXT_full_screen_exclusive' ],
|
|
|
|
|
commonSuppressExtensions +
|
|
|
|
|
[ 'VK_KHR_external_semaphore',
|
|
|
|
|
'VK_KHR_external_memory_capabilities',
|
|
|
|
|
'VK_KHR_external_fence',
|
|
|
|
|
'VK_KHR_external_fence_capabilities',
|
|
|
|
|
'VK_KHR_get_surface_capabilities2',
|
|
|
|
|
'VK_NV_external_memory_capabilities',
|
|
|
|
|
] ],
|
|
|
|
|
[ 'vulkan_xcb.h', [ 'VK_KHR_xcb_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_xlib.h', [ 'VK_KHR_xlib_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_directfb.h', [ 'VK_EXT_directfb_surface' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_xlib_xrandr.h', [ 'VK_EXT_acquire_xlib_display' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_metal.h', [ 'VK_EXT_metal_surface',
|
|
|
|
|
'VK_EXT_metal_objects' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_screen.h', [ 'VK_QNX_screen_surface',
|
|
|
|
|
'VK_QNX_external_memory_screen_buffer' ], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_sci.h', [ 'VK_NV_external_sci_sync',
|
|
|
|
|
'VK_NV_external_sci_sync2',
|
|
|
|
|
'VK_NV_external_memory_sci_buf'], commonSuppressExtensions ],
|
|
|
|
|
[ 'vulkan_beta.h', betaRequireExtensions, betaSuppressExtensions ],
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
for platform in platforms:
|
|
|
|
|
headername = platform[0]
|
|
|
|
|
|
|
|
|
|
allPlatformExtensions += platform[1]
|
|
|
|
|
|
|
|
|
|
addPlatformExtensionsRE = makeREstring(
|
|
|
|
|
platform[1] + platform[2], strings_are_regex=True)
|
|
|
|
|
emitPlatformExtensionsRE = makeREstring(
|
|
|
|
|
platform[1], strings_are_regex=True)
|
|
|
|
|
|
|
|
|
|
opts = CGeneratorOptions(
|
|
|
|
|
conventions = conventions,
|
|
|
|
|
filename = headername,
|
|
|
|
|
directory = directory,
|
|
|
|
|
genpath = None,
|
|
|
|
|
apiname = defaultAPIName,
|
|
|
|
|
mergeApiNames = mergeApiNames,
|
|
|
|
|
profile = None,
|
|
|
|
|
versions = featuresPat,
|
|
|
|
|
emitversions = None,
|
|
|
|
|
defaultExtensions = None,
|
|
|
|
|
addExtensions = addPlatformExtensionsRE,
|
|
|
|
|
removeExtensions = None,
|
|
|
|
|
emitExtensions = emitPlatformExtensionsRE,
|
|
|
|
|
prefixText = prefixStrings + vkPrefixStrings,
|
|
|
|
|
genFuncPointers = True,
|
|
|
|
|
protectFile = protectFile,
|
|
|
|
|
protectFeature = False,
|
|
|
|
|
protectProto = '#ifndef',
|
|
|
|
|
protectProtoStr = 'VK_NO_PROTOTYPES',
|
|
|
|
|
apicall = 'VKAPI_ATTR ',
|
|
|
|
|
apientry = 'VKAPI_CALL ',
|
|
|
|
|
apientryp = 'VKAPI_PTR *',
|
|
|
|
|
alignFuncParam = 48,
|
|
|
|
|
misracstyle = misracstyle,
|
|
|
|
|
misracppstyle = misracppstyle)
|
|
|
|
|
|
|
|
|
|
genOpts[headername] = [ COutputGenerator, opts ]
|
|
|
|
|
|
|
|
|
|
# Header for core API + extensions.
|
|
|
|
|
# To generate just the core API,
|
|
|
|
|
# change to 'defaultExtensions = None' below.
|
|
|
|
|
#
|
|
|
|
|
# By default this adds all enabled, non-platform extensions.
|
|
|
|
|
# It removes all platform extensions (from the platform headers options
|
|
|
|
|
# constructed above) as well as any explicitly specified removals.
|
|
|
|
|
|
|
|
|
|
removeExtensionsPat = makeREstring(
|
|
|
|
|
allPlatformExtensions + removeExtensions, None, strings_are_regex=True)
|
|
|
|
|
|
|
|
|
|
genOpts['vulkan_core.h'] = [
|
|
|
|
|
COutputGenerator,
|
|
|
|
|
CGeneratorOptions(
|
|
|
|
|
conventions = conventions,
|
|
|
|
|
filename = 'vulkan_core.h',
|
|
|
|
|
directory = directory,
|
|
|
|
|
genpath = None,
|
|
|
|
|
apiname = defaultAPIName,
|
|
|
|
|
mergeApiNames = mergeApiNames,
|
|
|
|
|
profile = None,
|
|
|
|
|
versions = featuresPat,
|
|
|
|
|
emitversions = featuresPat,
|
|
|
|
|
defaultExtensions = defaultExtensions,
|
|
|
|
|
addExtensions = addExtensionsPat,
|
|
|
|
|
removeExtensions = removeExtensionsPat,
|
|
|
|
|
emitExtensions = emitExtensionsPat,
|
|
|
|
|
prefixText = prefixStrings + vkPrefixStrings,
|
|
|
|
|
genFuncPointers = True,
|
|
|
|
|
protectFile = protectFile,
|
|
|
|
|
protectFeature = False,
|
|
|
|
|
protectProto = '#ifndef',
|
|
|
|
|
protectProtoStr = 'VK_NO_PROTOTYPES',
|
|
|
|
|
apicall = 'VKAPI_ATTR ',
|
|
|
|
|
apientry = 'VKAPI_CALL ',
|
|
|
|
|
apientryp = 'VKAPI_PTR *',
|
|
|
|
|
alignFuncParam = 48,
|
|
|
|
|
misracstyle = misracstyle,
|
|
|
|
|
misracppstyle = misracppstyle)
|
|
|
|
|
]
|
|
|
|
|
|
2023-11-07 09:38:12 -07:00
|
|
|
# Serializer for spec
|
|
|
|
|
genOpts['cereal'] = [
|
|
|
|
|
CerealGenerator,
|
|
|
|
|
CGeneratorOptions(
|
|
|
|
|
conventions = conventions,
|
|
|
|
|
directory = directory,
|
|
|
|
|
apiname = 'vulkan',
|
|
|
|
|
profile = None,
|
|
|
|
|
versions = featuresPat,
|
|
|
|
|
emitversions = featuresPat,
|
|
|
|
|
defaultExtensions = defaultExtensions,
|
|
|
|
|
addExtensions = None,
|
|
|
|
|
removeExtensions = None,
|
|
|
|
|
emitExtensions = emitExtensionsPat,
|
|
|
|
|
prefixText = prefixStrings + vkPrefixStrings,
|
|
|
|
|
genFuncPointers = True,
|
|
|
|
|
protectFile = protectFile,
|
|
|
|
|
protectFeature = False,
|
|
|
|
|
protectProto = '#ifndef',
|
|
|
|
|
protectProtoStr = 'VK_NO_PROTOTYPES',
|
|
|
|
|
apicall = 'VKAPI_ATTR ',
|
|
|
|
|
apientry = 'VKAPI_CALL ',
|
|
|
|
|
apientryp = 'VKAPI_PTR *',
|
|
|
|
|
alignFuncParam = 48)
|
|
|
|
|
]
|
|
|
|
|
|
2023-11-07 11:55:13 -07:00
|
|
|
gfxstreamPrefixStrings = [
|
|
|
|
|
'#pragma once',
|
|
|
|
|
'#ifdef VK_GFXSTREAM_STRUCTURE_TYPE_EXT',
|
|
|
|
|
'#include "vulkan_gfxstream_structure_type.h"',
|
|
|
|
|
'#endif',
|
|
|
|
|
]
|
|
|
|
|
|
|
|
|
|
# gfxstream specific header
|
|
|
|
|
genOpts['vulkan_gfxstream.h'] = [
|
|
|
|
|
COutputGenerator,
|
|
|
|
|
CGeneratorOptions(
|
|
|
|
|
conventions = conventions,
|
|
|
|
|
filename = 'vulkan_gfxstream.h',
|
|
|
|
|
directory = directory,
|
|
|
|
|
genpath = None,
|
|
|
|
|
apiname = 'vulkan',
|
|
|
|
|
profile = None,
|
|
|
|
|
versions = featuresPat,
|
|
|
|
|
emitversions = None,
|
|
|
|
|
defaultExtensions = None,
|
|
|
|
|
addExtensions = makeREstring(['VK_GOOGLE_gfxstream'], None),
|
|
|
|
|
removeExtensions = None,
|
|
|
|
|
emitExtensions = makeREstring(['VK_GOOGLE_gfxstream'], None),
|
|
|
|
|
prefixText = prefixStrings + vkPrefixStrings + gfxstreamPrefixStrings,
|
|
|
|
|
genFuncPointers = True,
|
|
|
|
|
# Use #pragma once in the prefixText instead, so that we can put the copyright comments
|
|
|
|
|
# at the beginning of the file.
|
|
|
|
|
protectFile = False,
|
|
|
|
|
protectFeature = False,
|
|
|
|
|
protectProto = '#ifndef',
|
|
|
|
|
protectProtoStr = 'VK_NO_PROTOTYPES',
|
|
|
|
|
apicall = 'VKAPI_ATTR ',
|
|
|
|
|
apientry = 'VKAPI_CALL ',
|
|
|
|
|
apientryp = 'VKAPI_PTR *',
|
|
|
|
|
alignFuncParam = 48,
|
|
|
|
|
misracstyle = misracstyle,
|
|
|
|
|
misracppstyle = misracppstyle)
|
|
|
|
|
]
|
2023-11-06 10:19:32 -08:00
|
|
|
|
|
|
|
|
def genTarget(args):
|
|
|
|
|
"""Create an API generator and corresponding generator options based on
|
|
|
|
|
the requested target and command line options.
|
|
|
|
|
|
|
|
|
|
This is encapsulated in a function so it can be profiled and/or timed.
|
|
|
|
|
The args parameter is an parsed argument object containing the following
|
|
|
|
|
fields that are used:
|
|
|
|
|
|
|
|
|
|
- target - target to generate
|
|
|
|
|
- directory - directory to generate it in
|
|
|
|
|
- protect - True if re-inclusion wrappers should be created
|
|
|
|
|
- extensions - list of additional extensions to include in generated interfaces"""
|
|
|
|
|
|
|
|
|
|
# Create generator options with parameters specified on command line
|
|
|
|
|
makeGenOpts(args)
|
|
|
|
|
|
|
|
|
|
# Select a generator matching the requested target
|
|
|
|
|
if args.target in genOpts:
|
|
|
|
|
createGenerator = genOpts[args.target][0]
|
|
|
|
|
options = genOpts[args.target][1]
|
|
|
|
|
|
|
|
|
|
gen = createGenerator(errFile=errWarn,
|
|
|
|
|
warnFile=errWarn,
|
|
|
|
|
diagFile=diag)
|
|
|
|
|
return (gen, options)
|
|
|
|
|
else:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# -feature name
|
|
|
|
|
# -extension name
|
|
|
|
|
# For both, "name" may be a single name, or a space-separated list
|
|
|
|
|
# of names, or a regular expression.
|
|
|
|
|
if __name__ == '__main__':
|
|
|
|
|
parser = argparse.ArgumentParser()
|
|
|
|
|
|
|
|
|
|
parser.add_argument('-apiname', action='store',
|
|
|
|
|
default=None,
|
|
|
|
|
help='Specify API to generate (defaults to repository-specific conventions object value)')
|
|
|
|
|
parser.add_argument('-mergeApiNames', action='store',
|
|
|
|
|
default=None,
|
|
|
|
|
help='Specify a comma separated list of APIs to merge into the target API')
|
|
|
|
|
parser.add_argument('-defaultExtensions', action='store',
|
|
|
|
|
default=APIConventions().xml_api_name,
|
|
|
|
|
help='Specify a single class of extensions to add to targets')
|
|
|
|
|
parser.add_argument('-extension', action='append',
|
|
|
|
|
default=[],
|
|
|
|
|
help='Specify an extension or extensions to add to targets')
|
|
|
|
|
parser.add_argument('-removeExtensions', action='append',
|
|
|
|
|
default=[],
|
|
|
|
|
help='Specify an extension or extensions to remove from targets')
|
|
|
|
|
parser.add_argument('-emitExtensions', action='append',
|
|
|
|
|
default=[],
|
|
|
|
|
help='Specify an extension or extensions to emit in targets')
|
|
|
|
|
parser.add_argument('-emitSpirv', action='append',
|
|
|
|
|
default=[],
|
|
|
|
|
help='Specify a SPIR-V extension or capability to emit in targets')
|
|
|
|
|
parser.add_argument('-emitFormats', action='append',
|
|
|
|
|
default=[],
|
|
|
|
|
help='Specify Vulkan Formats to emit in targets')
|
|
|
|
|
parser.add_argument('-feature', action='append',
|
|
|
|
|
default=[],
|
|
|
|
|
help='Specify a core API feature name or names to add to targets')
|
|
|
|
|
parser.add_argument('-debug', action='store_true',
|
|
|
|
|
help='Enable debugging')
|
|
|
|
|
parser.add_argument('-dump', action='store_true',
|
|
|
|
|
help='Enable dump to stderr')
|
|
|
|
|
parser.add_argument('-diagfile', action='store',
|
|
|
|
|
default=None,
|
|
|
|
|
help='Write diagnostics to specified file')
|
|
|
|
|
parser.add_argument('-errfile', action='store',
|
|
|
|
|
default=None,
|
|
|
|
|
help='Write errors and warnings to specified file instead of stderr')
|
|
|
|
|
parser.add_argument('-noprotect', dest='protect', action='store_false',
|
|
|
|
|
help='Disable inclusion protection in output headers')
|
|
|
|
|
parser.add_argument('-profile', action='store_true',
|
|
|
|
|
help='Enable profiling')
|
|
|
|
|
parser.add_argument('-registry', action='store',
|
|
|
|
|
default='vk.xml',
|
|
|
|
|
help='Use specified registry file instead of vk.xml')
|
2023-11-07 11:55:13 -07:00
|
|
|
parser.add_argument('-registryGfxstream', action='store',
|
|
|
|
|
default=None,
|
|
|
|
|
help='Use specified gfxstream registry file')
|
2023-11-06 10:19:32 -08:00
|
|
|
parser.add_argument('-time', action='store_true',
|
|
|
|
|
help='Enable timing')
|
|
|
|
|
parser.add_argument('-genpath', action='store', default='gen',
|
|
|
|
|
help='Path to generated files')
|
|
|
|
|
parser.add_argument('-o', action='store', dest='directory',
|
|
|
|
|
default='.',
|
|
|
|
|
help='Create target and related files in specified directory')
|
|
|
|
|
parser.add_argument('target', metavar='target', nargs='?',
|
|
|
|
|
help='Specify target')
|
|
|
|
|
parser.add_argument('-quiet', action='store_true', default=True,
|
|
|
|
|
help='Suppress script output during normal execution.')
|
|
|
|
|
parser.add_argument('-verbose', action='store_false', dest='quiet', default=True,
|
|
|
|
|
help='Enable script output during normal execution.')
|
|
|
|
|
parser.add_argument('--vulkanLayer', action='store_true', dest='vulkanLayer',
|
|
|
|
|
help='Enable scripts to generate VK specific vulkan_json_data.hpp for json_gen_layer.')
|
|
|
|
|
parser.add_argument('-misracstyle', dest='misracstyle', action='store_true',
|
|
|
|
|
help='generate MISRA C-friendly headers')
|
|
|
|
|
parser.add_argument('-misracppstyle', dest='misracppstyle', action='store_true',
|
|
|
|
|
help='generate MISRA C++-friendly headers')
|
|
|
|
|
parser.add_argument('--iscts', action='store_true', dest='isCTS',
|
|
|
|
|
help='Specify if this should generate CTS compatible code')
|
|
|
|
|
|
|
|
|
|
args = parser.parse_args()
|
|
|
|
|
|
|
|
|
|
# This splits arguments which are space-separated lists
|
|
|
|
|
args.feature = [name for arg in args.feature for name in arg.split()]
|
|
|
|
|
args.extension = [name for arg in args.extension for name in arg.split()]
|
|
|
|
|
|
|
|
|
|
# create error/warning & diagnostic files
|
|
|
|
|
if args.errfile:
|
|
|
|
|
errWarn = open(args.errfile, 'w', encoding='utf-8')
|
|
|
|
|
else:
|
|
|
|
|
errWarn = sys.stderr
|
|
|
|
|
|
|
|
|
|
if args.diagfile:
|
|
|
|
|
diag = open(args.diagfile, 'w', encoding='utf-8')
|
|
|
|
|
else:
|
|
|
|
|
diag = None
|
|
|
|
|
|
|
|
|
|
# Create the API generator & generator options
|
|
|
|
|
(gen, options) = genTarget(args)
|
|
|
|
|
|
|
|
|
|
# Create the registry object with the specified generator and generator
|
|
|
|
|
# options. The options are set before XML loading as they may affect it.
|
|
|
|
|
reg = Registry(gen, options)
|
|
|
|
|
|
|
|
|
|
# Parse the specified registry XML into an ElementTree object
|
|
|
|
|
startTimer(args.time)
|
|
|
|
|
tree = etree.parse(args.registry)
|
|
|
|
|
endTimer(args.time, '* Time to make ElementTree =')
|
|
|
|
|
|
2023-11-07 11:55:13 -07:00
|
|
|
# Merge the gfxstream registry with the official Vulkan registry if the
|
|
|
|
|
# target is the cereal generator
|
|
|
|
|
if args.registryGfxstream is not None and args.target == 'cereal':
|
|
|
|
|
treeGfxstream = etree.parse(args.registryGfxstream)
|
|
|
|
|
treeRoot = tree.getroot()
|
|
|
|
|
treeGfxstreamRoot = treeGfxstream.getroot()
|
|
|
|
|
|
|
|
|
|
def getEntryName(entry) -> Optional[str]:
|
|
|
|
|
name = entry.get("name")
|
|
|
|
|
if name is not None:
|
|
|
|
|
return name
|
|
|
|
|
try:
|
2023-12-04 13:08:33 -08:00
|
|
|
return entry.find("proto").find("name").text
|
2023-11-07 11:55:13 -07:00
|
|
|
except AttributeError:
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
for entriesName in ['types', 'commands', 'extensions']:
|
|
|
|
|
treeEntries = treeRoot.find(entriesName)
|
|
|
|
|
|
|
|
|
|
originalEntryDict = {}
|
|
|
|
|
for entry in treeEntries:
|
|
|
|
|
name = getEntryName(entry)
|
|
|
|
|
if name is not None:
|
|
|
|
|
originalEntryDict[name] = entry
|
|
|
|
|
|
|
|
|
|
for entry in treeGfxstreamRoot.find(entriesName):
|
|
|
|
|
name = getEntryName(entry)
|
|
|
|
|
# New entry, just append to entry list
|
|
|
|
|
if name not in originalEntryDict.keys():
|
|
|
|
|
treeEntries.append(entry)
|
|
|
|
|
continue
|
2023-12-04 13:08:33 -08:00
|
|
|
print(f'Entry {entriesName}:{name}')
|
2023-11-07 11:55:13 -07:00
|
|
|
|
|
|
|
|
originalEntry = originalEntryDict[name]
|
|
|
|
|
|
|
|
|
|
# Extending an existing entry. This happens for MVK.
|
|
|
|
|
if entriesName == "extensions":
|
|
|
|
|
for key, value in entry.attrib.items():
|
|
|
|
|
originalEntry.set(key, value)
|
|
|
|
|
require = entry.find("require")
|
|
|
|
|
if require is not None:
|
|
|
|
|
for child in require:
|
|
|
|
|
originalEntry.find("require").append(child)
|
|
|
|
|
continue
|
|
|
|
|
|
|
|
|
|
# Overwriting an existing entry. This happen for
|
|
|
|
|
# VkNativeBufferANDROID
|
2023-12-04 13:08:33 -08:00
|
|
|
if entriesName == "types" or entriesName == "commands":
|
2023-11-07 11:55:13 -07:00
|
|
|
originalEntry.clear()
|
|
|
|
|
originalEntry.attrib = entry.attrib
|
|
|
|
|
for child in entry:
|
|
|
|
|
originalEntry.append(child)
|
|
|
|
|
|
2023-11-06 10:19:32 -08:00
|
|
|
# Load the XML tree into the registry object
|
|
|
|
|
startTimer(args.time)
|
|
|
|
|
reg.loadElementTree(tree)
|
|
|
|
|
endTimer(args.time, '* Time to parse ElementTree =')
|
|
|
|
|
|
|
|
|
|
if args.dump:
|
|
|
|
|
reg.dumpReg(filehandle=open('regdump.txt', 'w', encoding='utf-8'))
|
|
|
|
|
|
|
|
|
|
# Finally, use the output generator to create the requested target
|
|
|
|
|
if args.debug:
|
|
|
|
|
pdb.run('reg.apiGen()')
|
|
|
|
|
else:
|
|
|
|
|
startTimer(args.time)
|
|
|
|
|
reg.apiGen()
|
2024-01-04 17:17:09 -08:00
|
|
|
endTimer(args.time, '* Time to generate ' + args.target + ' =')
|