diff options
| author | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-04-12 21:37:16 +0200 |
|---|---|---|
| committer | Lizzy Fleckenstein <lizzy@vlhl.dev> | 2026-04-12 21:37:16 +0200 |
| commit | 165c94e3c1742dabaac73b20662e4d4c823dd310 (patch) | |
| tree | 957d80074c5d0c62db8a92cc97b26646280f4b32 /tools/Vulkan-Tools/scripts | |
| parent | 4fd35dd290c212ed716adeb3be4dea71775e00dd (diff) | |
| download | usermoji-165c94e3c1742dabaac73b20662e4d4c823dd310.tar.xz | |
mkcube: use animtool
Diffstat (limited to 'tools/Vulkan-Tools/scripts')
17 files changed, 0 insertions, 5153 deletions
diff --git a/tools/Vulkan-Tools/scripts/CMakeLists.txt b/tools/Vulkan-Tools/scripts/CMakeLists.txt deleted file mode 100644 index 65c8bade..00000000 --- a/tools/Vulkan-Tools/scripts/CMakeLists.txt +++ /dev/null @@ -1,135 +0,0 @@ -# ~~~ -# Copyright (c) 2023 LunarG, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# ~~~ - -option(UPDATE_DEPS "Run update_deps.py for user") -if (UPDATE_DEPS) - find_package(Python3 REQUIRED QUIET) - - set(update_dep_py "${CMAKE_CURRENT_LIST_DIR}/update_deps.py") - set(known_good_json "${CMAKE_CURRENT_LIST_DIR}/known_good.json") - - set_property(DIRECTORY APPEND PROPERTY CMAKE_CONFIGURE_DEPENDS ${update_dep_py} ${known_good_json}) - - list(APPEND update_dep_command "${update_dep_py}") - list(APPEND update_dep_command "--generator") - list(APPEND update_dep_command "${CMAKE_GENERATOR}") - - if (CMAKE_GENERATOR_PLATFORM) - list(APPEND update_dep_command "--arch") - list(APPEND update_dep_command "${CMAKE_GENERATOR_PLATFORM}") - endif() - - if (NOT CMAKE_BUILD_TYPE) - message(WARNING "CMAKE_BUILD_TYPE not set. Using Debug for dependency build type") - set(_build_type Debug) - else() - set(_build_type ${CMAKE_BUILD_TYPE}) - endif() - list(APPEND update_dep_command "--config") - list(APPEND update_dep_command "${_build_type}") - list(APPEND update_dep_command "--api") - list(APPEND update_dep_command "${API_TYPE}") - - set(UPDATE_DEPS_DIR_SUFFIX "${_build_type}") - if (CMAKE_CROSSCOMPILING) - set(UPDATE_DEPS_DIR_SUFFIX "${CMAKE_SYSTEM_NAME}/${UPDATE_DEPS_DIR_SUFFIX}/${CMAKE_SYSTEM_PROCESSOR}") - else() - math(EXPR bitness "8 * ${CMAKE_SIZEOF_VOID_P}") - set(UPDATE_DEPS_DIR_SUFFIX "${UPDATE_DEPS_DIR_SUFFIX}/${bitness}") - endif() - set(UPDATE_DEPS_DIR "${PROJECT_SOURCE_DIR}/external/${UPDATE_DEPS_DIR_SUFFIX}" CACHE PATH "Location where update_deps.py installs packages") - list(APPEND update_dep_command "--dir" ) - list(APPEND update_dep_command "${UPDATE_DEPS_DIR}") - - if (NOT BUILD_TESTS) - list(APPEND update_dep_command "--optional=tests") - endif() - - if (UPDATE_DEPS_SKIP_EXISTING_INSTALL) - list(APPEND update_dep_command "--skip-existing-install") - endif() - - list(APPEND cmake_vars "CMAKE_TOOLCHAIN_FILE") - - # Avoids manually setting CMAKE_SYSTEM_NAME unless it's needed: - # https://cmake.org/cmake/help/latest/variable/CMAKE_CROSSCOMPILING.html - if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "${CMAKE_HOST_SYSTEM_NAME}") - list(APPEND cmake_vars "CMAKE_SYSTEM_NAME") - endif() - if (APPLE) - list(APPEND cmake_vars "CMAKE_OSX_ARCHITECTURES" "CMAKE_OSX_DEPLOYMENT_TARGET") - endif() - if (NOT MSVC_IDE) - list(APPEND cmake_vars "CMAKE_CXX_COMPILER" "CMAKE_C_COMPILER" "CMAKE_ASM_COMPILER") - endif() - if (ANDROID) - list(APPEND cmake_vars "ANDROID_PLATFORM" "CMAKE_ANDROID_ARCH_ABI" "CMAKE_ANDROID_STL_TYPE" "CMAKE_ANDROID_RTTI" "CMAKE_ANDROID_EXCEPTIONS" "ANDROID_USE_LEGACY_TOOLCHAIN_FILE") - endif() - - set(cmake_var) - foreach(var IN LISTS cmake_vars) - if (DEFINED ${var}) - list(APPEND update_dep_command "--cmake_var") - list(APPEND update_dep_command "${var}=${${var}}") - endif() - endforeach() - - if (cmake_var) - list(APPEND update_dep_command "${cmake_var}") - endif() - - file(TIMESTAMP ${update_dep_py} timestamp_1) - file(TIMESTAMP ${known_good_json} timestamp_2) - - string("MD5" md5_hash "${timestamp_1}-${timestamp_2}-${update_dep_command}") - - set(UPDATE_DEPS_HASH "0" CACHE STRING "Default value until we run update_deps.py") - mark_as_advanced(UPDATE_DEPS_HASH) - - if ("${UPDATE_DEPS_HASH}" STREQUAL "0") - list(APPEND update_dep_command "--clean-build") - list(APPEND update_dep_command "--clean-install") - endif() - - if ("${md5_hash}" STREQUAL $CACHE{UPDATE_DEPS_HASH}) - message(DEBUG "update_deps.py: no work to do.") - else() - execute_process( - COMMAND ${Python3_EXECUTABLE} ${update_dep_command} - RESULT_VARIABLE _update_deps_result - ) - if (NOT (${_update_deps_result} EQUAL 0)) - message(FATAL_ERROR "Could not run update_deps.py which is necessary to download dependencies.") - endif() - set(UPDATE_DEPS_HASH ${md5_hash} CACHE STRING "Ensure we only run update_deps.py when we need to." FORCE) - include("${UPDATE_DEPS_DIR}/helper.cmake") - endif() -endif() -if (VULKAN_HEADERS_INSTALL_DIR) - list(APPEND CMAKE_PREFIX_PATH ${VULKAN_HEADERS_INSTALL_DIR}) -endif() -if (GOOGLETEST_INSTALL_DIR) - list(APPEND CMAKE_PREFIX_PATH ${GOOGLETEST_INSTALL_DIR}) -endif() -if (VULKAN_LOADER_INSTALL_DIR) - list(APPEND CMAKE_PREFIX_PATH ${VULKAN_LOADER_INSTALL_DIR}) -endif() - -if (CMAKE_CROSSCOMPILING) - set(CMAKE_FIND_ROOT_PATH ${CMAKE_FIND_ROOT_PATH} ${CMAKE_PREFIX_PATH} PARENT_SCOPE) -else() - set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} PARENT_SCOPE) -endif() diff --git a/tools/Vulkan-Tools/scripts/android.py b/tools/Vulkan-Tools/scripts/android.py deleted file mode 100755 index 20cc69d4..00000000 --- a/tools/Vulkan-Tools/scripts/android.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2023 Valve Corporation -# Copyright (c) 2023 LunarG, Inc. - -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# NOTE: Android this documentation is crucial for understanding the layout of the NDK. -# https://android.googlesource.com/platform/ndk/+/master/docs/BuildSystemMaintainers.md - -# NOTE: Environment variables we can rely on users/environments setting. -# https://github.com/actions/runner-images/blob/main/images/linux/Ubuntu2204-Readme.md#environment-variables-2 - -import argparse -import os -import sys -import shutil -import subprocess - -# helper to define paths relative to the repo root -def RepoRelative(path): - return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', path)) - -# Points to the directory containing the top level CMakeLists.txt -PROJECT_SRC_DIR = os.path.abspath(os.path.join(os.path.split(os.path.abspath(__file__))[0], '..')) -if not os.path.isfile(f'{PROJECT_SRC_DIR}/CMakeLists.txt'): - print(f'PROJECT_SRC_DIR invalid! {PROJECT_SRC_DIR}') - sys.exit(1) - -# Runs a command in a directory and returns its return code. -# Directory is project root by default, or a relative path from project root -def RunShellCmd(command, start_dir = PROJECT_SRC_DIR, env=None, verbose=False): - # Flush stdout here. Helps when debugging on CI. - sys.stdout.flush() - - if start_dir != PROJECT_SRC_DIR: - start_dir = RepoRelative(start_dir) - cmd_list = command.split(" ") - - if verbose: - print(f'CICMD({cmd_list}, env={env})') - subprocess.check_call(cmd_list, cwd=start_dir, env=env) - -# Manifest file describing out test application -def get_android_manifest() -> str: - manifest = RepoRelative('cube/android/AndroidManifest.xml') - if not os.path.isfile(manifest): - print(f"Unable to find manifest for APK! {manifest}") - sys.exit(-1) - return manifest - -# Generate the APK from the CMake binaries -def generate_apk(SDK_ROOT : str, CMAKE_INSTALL_DIR : str) -> str: - apk_dir = RepoRelative('build-android/bin') - - # Delete APK directory since it could contain files from old runs - if os.path.isdir(apk_dir): - shutil.rmtree(apk_dir) - - shutil.copytree(CMAKE_INSTALL_DIR, apk_dir) - - android_manifest = get_android_manifest() - - android_jar = f"{SDK_ROOT}/platforms/android-26/android.jar" - if not os.path.isfile(android_jar): - print(f"Unable to find {android_jar}!") - sys.exit(-1) - - apk_name = 'VkCube' - - unaligned_apk = f'{apk_dir}/{apk_name}-unaligned.apk' - test_apk = f'{apk_dir}/{apk_name}.apk' - - # Create APK - RunShellCmd(f'aapt package -f -M {android_manifest} -I {android_jar} -F {unaligned_apk} {CMAKE_INSTALL_DIR}') - - # Align APK - RunShellCmd(f'zipalign -f 4 {unaligned_apk} {test_apk}') - - # Create Key (If it doesn't already exist) - debug_key = RepoRelative(f'{apk_dir}/debug.keystore') - ks_pass = 'android' - if not os.path.isfile(debug_key): - dname = 'CN=Android-Debug,O=Android,C=US' - RunShellCmd(f'keytool -genkey -v -keystore {debug_key} -alias androiddebugkey -storepass {ks_pass} -keypass {ks_pass} -keyalg RSA -keysize 2048 -validity 10000 -dname {dname}') - - # Sign APK - RunShellCmd(f'apksigner sign --verbose --ks {debug_key} --ks-pass pass:{ks_pass} {test_apk}') - -# Android APKs can contain binaries for multiple ABIs (armeabi-v7a, arm64-v8a, x86, x86_64). -# https://en.wikipedia.org/wiki/Apk_(file_format)#Package_contents -# -# As a result CMake will need to be run multiple times to create a complete test APK that can be run on any Android device. -def main(): - configs = ['Release', 'Debug'] - - parser = argparse.ArgumentParser() - parser.add_argument('--config', type=str, choices=configs, default=configs[0]) - parser.add_argument('--app-abi', dest='android_abi', type=str, default="arm64-v8a") - parser.add_argument('--app-stl', dest='android_stl', type=str, choices=["c++_static", "c++_shared"], default="c++_static") - parser.add_argument('--apk', action='store_true', help='Generate an APK as a post build step.') - parser.add_argument('--clean', action='store_true', help='Cleans CMake build artifacts') - args = parser.parse_args() - - cmake_config = args.config - android_abis = args.android_abi.split(" ") - android_stl = args.android_stl - create_apk = args.apk - clean = args.clean - - if "ANDROID_NDK_HOME" not in os.environ: - print("Cannot find ANDROID_NDK_HOME!") - sys.exit(1) - - android_ndk_home = os.environ.get('ANDROID_NDK_HOME') - android_toolchain = f'{android_ndk_home}/build/cmake/android.toolchain.cmake' - - # The only tool we require for building is CMake/Ninja - required_cli_tools = ['cmake', 'ninja'] - - # If we are building an APK we need a few more tools. - if create_apk: - if "ANDROID_SDK_ROOT" not in os.environ: - print("Cannot find ANDROID_SDK_ROOT!") - sys.exit(1) - - android_sdk_root = os.environ.get('ANDROID_SDK_ROOT') - print(f"ANDROID_SDK_ROOT = {android_sdk_root}") - required_cli_tools += ['aapt', 'zipalign', 'keytool', 'apksigner'] - - print(f"ANDROID_NDK_HOME = {android_ndk_home}") - print(f"Build configured for {cmake_config} | {android_stl} | {android_abis} | APK {create_apk}") - - if not os.path.isfile(android_toolchain): - print(f'Unable to find android.toolchain.cmake at {android_toolchain}') - exit(-1) - - for tool in required_cli_tools: - path = shutil.which(tool) - if path is None: - print(f"Unable to find {tool}!") - exit(-1) - - print(f"Using {tool} : {path}") - - cmake_install_dir = RepoRelative('build-android/libs') - - # Delete install directory since it could contain files from old runs - if os.path.isdir(cmake_install_dir): - print("Cleaning CMake install") - shutil.rmtree(cmake_install_dir) - - for abi in android_abis: - build_dir = RepoRelative(f'build-android/cmake/{abi}') - lib_dir = f'lib/{abi}' - - if clean: - print("Deleting CMakeCache.txt") - - # Delete CMakeCache.txt to ensure clean builds - # NOTE: CMake 3.24 has --fresh which would be better to use in the future. - cmake_cache = f'{build_dir}/CMakeCache.txt' - if os.path.isfile(cmake_cache): - os.remove(cmake_cache) - - cmake_cmd = f'cmake -S . -B {build_dir} -G Ninja' - - cmake_cmd += f' -D CMAKE_BUILD_TYPE={cmake_config}' - cmake_cmd += f' -D UPDATE_DEPS=ON -D UPDATE_DEPS_DIR={build_dir}' - cmake_cmd += f' -D CMAKE_TOOLCHAIN_FILE={android_toolchain}' - cmake_cmd += f' -D CMAKE_ANDROID_ARCH_ABI={abi}' - cmake_cmd += f' -D CMAKE_INSTALL_LIBDIR={lib_dir}' - cmake_cmd += f' -D CMAKE_ANDROID_STL_TYPE={android_stl}' - - cmake_cmd += ' -D ANDROID_PLATFORM=26' - cmake_cmd += ' -D ANDROID_USE_LEGACY_TOOLCHAIN_FILE=NO' - - RunShellCmd(cmake_cmd) - - build_cmd = f'cmake --build {build_dir}' - RunShellCmd(build_cmd) - - install_cmd = f'cmake --install {build_dir} --prefix {cmake_install_dir}' - RunShellCmd(install_cmd) - - if create_apk: - generate_apk(SDK_ROOT = android_sdk_root, CMAKE_INSTALL_DIR = cmake_install_dir) - -if __name__ == '__main__': - main() diff --git a/tools/Vulkan-Tools/scripts/common_codegen.py b/tools/Vulkan-Tools/scripts/common_codegen.py deleted file mode 100644 index d44cd643..00000000 --- a/tools/Vulkan-Tools/scripts/common_codegen.py +++ /dev/null @@ -1,114 +0,0 @@ -#!/usr/bin/python3 -i -# -# Copyright (c) 2015-2017, 2019-2021 The Khronos Group Inc. -# Copyright (c) 2015-2017, 2019-2021 Valve Corporation -# Copyright (c) 2015-2017, 2019-2021 LunarG, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Author: Mark Lobodzinski <mark@lunarg.com> - -import os -import sys -import subprocess - -# Copyright text prefixing all headers (list of strings). -prefixStrings = [ - '/*', - '** Copyright (c) 2015-2017, 2019-2021 The Khronos Group Inc.', - '** Copyright (c) 2015-2017, 2019-2021 Valve Corporation', - '** Copyright (c) 2015-2017, 2019-2021 LunarG, Inc.', - '** Copyright (c) 2015-2017, 2019-2021 Google Inc.', - '**', - '** Licensed under the Apache License, Version 2.0 (the "License");', - '** you may not use this file except in compliance with the License.', - '** You may obtain a copy of the License at', - '**', - '** http://www.apache.org/licenses/LICENSE-2.0', - '**', - '** Unless required by applicable law or agreed to in writing, software', - '** distributed under the License is distributed on an "AS IS" BASIS,', - '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', - '** See the License for the specific language governing permissions and', - '** limitations under the License.', - '*/', - '' -] - - -platform_dict = { - 'android' : 'VK_USE_PLATFORM_ANDROID_KHR', - 'fuchsia' : 'VK_USE_PLATFORM_FUCHSIA', - 'ggp': 'VK_USE_PLATFORM_GGP', - 'ios' : 'VK_USE_PLATFORM_IOS_MVK', - 'macos' : 'VK_USE_PLATFORM_MACOS_MVK', - 'metal' : 'VK_USE_PLATFORM_METAL_EXT', - 'vi' : 'VK_USE_PLATFORM_VI_NN', - 'wayland' : 'VK_USE_PLATFORM_WAYLAND_KHR', - 'win32' : 'VK_USE_PLATFORM_WIN32_KHR', - 'xcb' : 'VK_USE_PLATFORM_XCB_KHR', - 'xlib' : 'VK_USE_PLATFORM_XLIB_KHR', - 'xlib_xrandr' : 'VK_USE_PLATFORM_XLIB_XRANDR_EXT', - 'provisional' : 'VK_ENABLE_BETA_EXTENSIONS', - 'directfb' : 'VK_USE_PLATFORM_DIRECTFB_EXT', - 'screen' : 'VK_USE_PLATFORM_SCREEN_QNX', - 'sci' : 'VK_USE_PLATFORM_SCI', - 'ohos' : 'VK_USE_PLATFORM_OHOS', -} - -# -# Return appropriate feature protect string from 'platform' tag on feature -def GetFeatureProtect(interface): - """Get platform protection string""" - platform = interface.get('platform') - if platform is not None: - return platform_dict[platform] - - provisional = interface.get('provisional') - if provisional == 'true': - return platform_dict['provisional'] - -# Returns true if we are running in GitHub actions -# https://docs.github.com/en/actions/learn-github-actions/variables#default-environment-variables -def IsGHA(): - if 'GITHUB_ACTION' in os.environ: - return True - return False - -# Points to the directory containing the top level CMakeLists.txt -PROJECT_SRC_DIR = os.path.abspath(os.path.join(os.path.split(os.path.abspath(__file__))[0], '..')) -if not os.path.isfile(f'{PROJECT_SRC_DIR}/CMakeLists.txt'): - print(f'PROJECT_SRC_DIR invalid! {PROJECT_SRC_DIR}') - sys.exit(1) - -# helper to define paths relative to the repo root -def RepoRelative(path): - return os.path.abspath(os.path.join(os.path.dirname(__file__), '..', path)) - -# Runs a command in a directory and returns its return code. -# Directory is project root by default, or a relative path from project root -def RunShellCmd(command, start_dir = PROJECT_SRC_DIR, env=None, verbose=False): - # Flush stdout here. Helps when debugging on CI. - sys.stdout.flush() - - if start_dir != PROJECT_SRC_DIR: - start_dir = RepoRelative(start_dir) - cmd_list = command.split(" ") - - # Helps a lot when debugging CI issues - if IsGHA(): - verbose = True - - if verbose: - print(f'CICMD({cmd_list}, env={env})') - subprocess.check_call(cmd_list, cwd=start_dir, env=env)
\ No newline at end of file diff --git a/tools/Vulkan-Tools/scripts/generate_source.py b/tools/Vulkan-Tools/scripts/generate_source.py deleted file mode 100755 index 59314533..00000000 --- a/tools/Vulkan-Tools/scripts/generate_source.py +++ /dev/null @@ -1,279 +0,0 @@ -#!/usr/bin/env python3 -# Copyright (c) 2019 The Khronos Group Inc. -# Copyright (c) 2019 Valve Corporation -# Copyright (c) 2019 LunarG, Inc. -# Copyright (c) 2019 Google Inc. -# Copyright (c) 2021-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. -# Copyright (c) 2023-2023 RasterGrid Kft. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Author: Mike Schuchardt <mikes@lunarg.com> - -import argparse -import filecmp -import os -import shutil -import sys -import re -import tempfile -import json -import common_codegen - -from xml.etree import ElementTree - -# Because we have special logic to import the Registry from input arguments and the BaseGenerator comes from the registry, we have to delay defining it until *after* -# the Registry has been imported. Yes this is awkward, but it was the least awkward way to make --verify work. -generators = {} - -def RunGenerators(api: str, registry: str, video_registry: str, directory: str, styleFile: str, targetFilter: str, flatOutput: bool): - - try: - common_codegen.RunShellCmd(f'clang-format --version') - has_clang_format = True - except: - has_clang_format = False - if not has_clang_format: - print("WARNING: Unable to find clang-format!") - - # These live in the Vulkan-Docs repo, but are pulled in via the - # Vulkan-Headers/registry folder - # At runtime we inject python path to find these helper scripts - scripts = os.path.dirname(registry) - scripts_directory_path = os.path.dirname(os.path.abspath(__file__)) - registry_headers_path = os.path.join(scripts_directory_path, scripts) - sys.path.insert(0, registry_headers_path) - try: - from reg import Registry - except: - print("ModuleNotFoundError: No module named 'reg'") # normal python error message - print(f'{registry_headers_path} is not pointing to the Vulkan-Headers registry directory.') - print("Inside Vulkan-Headers there is a registry/reg.py file that is used.") - sys.exit(1) # Return without call stack so easy to spot error - - from base_generator import BaseGeneratorOptions - from generators.mock_icd_generator import MockICDOutputGenerator - from generators.vulkan_tools_helper_file_generator import HelperFileOutputGenerator - from generators.vulkaninfo_generator import VulkanInfoGenerator - - # These set fields that are needed by both OutputGenerator and BaseGenerator, - # but are uniform and don't need to be set at a per-generated file level - from base_generator import (SetTargetApiName, SetMergedApiNames) - SetTargetApiName(api) - - # Generated directory and dispatch table helper file name may be API specific (e.g. Vulkan SC) - mock_icd_generated_directory = 'icd/generated' - vulkaninfo_generated_directory = 'vulkaninfo/generated' - - generators.update({ - 'vk_typemap_helper.h': { - 'generator' : HelperFileOutputGenerator, - 'genCombined': False, - 'directory' : mock_icd_generated_directory, - }, - 'function_declarations.h': { - 'generator' : MockICDOutputGenerator, - 'genCombined': False, - 'directory' : mock_icd_generated_directory, - }, - 'function_definitions.h': { - 'generator' : MockICDOutputGenerator, - 'genCombined': False, - 'directory' : mock_icd_generated_directory, - }, - 'vulkaninfo.hpp': { - 'generator' : VulkanInfoGenerator, - 'genCombined': False, - 'directory' : vulkaninfo_generated_directory, - }, - }) - - unknownTargets = [x for x in (targetFilter if targetFilter else []) if x not in generators.keys()] - if unknownTargets: - print(f'ERROR: No generator options for unknown target(s): {", ".join(unknownTargets)}', file=sys.stderr) - return 1 - - # Filter if --target is passed in - targets = [x for x in generators.keys() if not targetFilter or x in targetFilter] - - for index, target in enumerate(targets, start=1): - print(f'[{index}|{len(targets)}] Generating {target}') - - # First grab a class constructor object and create an instance - generator = generators[target]['generator'] - gen = generator() - - # This code and the 'genCombined' generator metadata is used by downstream - # users to generate code with all Vulkan APIs merged into the target API variant - # (e.g. Vulkan SC) when needed. The constructed apiList is also used to filter - # out non-applicable extensions later below. - apiList = [api] - if api != 'vulkan' and generators[target]['genCombined']: - SetMergedApiNames('vulkan') - apiList.append('vulkan') - else: - SetMergedApiNames(None) - - # For people who want to generate all the files in a single director - if flatOutput: - outDirectory = os.path.abspath(os.path.join(directory)) - else: - outDirectory = os.path.abspath(os.path.join(directory, generators[target]['directory'])) - - options = BaseGeneratorOptions( - customFileName = target, - customDirectory = outDirectory) - - if not os.path.exists(outDirectory): - os.makedirs(outDirectory) - - # 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 - tree = ElementTree.parse(registry) - - # Load the XML tree into the registry object - reg.loadElementTree(tree) - - # Set the path to the video registry so that videoStd is available - reg.genOpts.videoXmlPath = video_registry - - # Finally, use the output generator to create the requested target - reg.apiGen() - - # Run clang-format on the file - if has_clang_format and styleFile: - common_codegen.RunShellCmd(f'clang-format -i --style=file:{styleFile} {os.path.join(outDirectory, target)}') - - -def main(argv): - - # files to exclude from --verify check - verify_exclude = ['.clang-format'] # None currently - - parser = argparse.ArgumentParser(description='Generate source code for this repository') - parser.add_argument('registry', metavar='REGISTRY_PATH', help='path to the Vulkan-Headers registry directory') - parser.add_argument('--api', - default='vulkan', - choices=['vulkan', 'vulkansc'], - help='Specify API name to generate') - parser.add_argument('--generated-version', help='sets the header version used to generate the repo') - group = parser.add_mutually_exclusive_group() - group.add_argument('--target', nargs='+', help='only generate file names passed in') - group.add_argument('-i', '--incremental', action='store_true', help='only update repo files that change') - group.add_argument('-v', '--verify', action='store_true', help='verify repo files match generator output') - group.add_argument('-o', action='store', dest='directory', help='Create target and related files in specified directory') - args = parser.parse_args(argv) - - repo_dir = common_codegen.RepoRelative('.') - - registry = os.path.abspath(os.path.join(args.registry, 'vk.xml')) - video_registry = os.path.abspath(os.path.join(args.registry, 'video.xml')) - if not os.path.isfile(registry) and not os.path.isfile(registry): - registry = os.path.abspath(os.path.join(args.registry, 'Vulkan-Headers/registry/vk.xml')) - if not os.path.isfile(registry): - print(f'cannot find vk.xml in {args.registry}') - return -1 - video_registry = os.path.abspath(os.path.join(args.registry, 'Vulkan-Headers/registry/video.xml')) - if not os.path.isfile(video_registry): - print(f'{video_registry} does not exist') - return -1 - - # Need pass style file incase running with --verify and it can't find the file automatically in the temp directory - style_file = os.path.join(repo_dir, '.clang-format') - - # get directory where generators will run - if args.verify or args.incremental: - # generate in temp directory so we can compare or copy later - temp_obj = tempfile.TemporaryDirectory(prefix='vulkan_tools_codegen_') - temp_dir = temp_obj.name - gen_dir = temp_dir - elif args.directory: - gen_dir = args.directory - else: - # generate directly in the repo - gen_dir = repo_dir - - RunGenerators(api=args.api,registry=registry, video_registry=video_registry, directory=gen_dir, styleFile=style_file, targetFilter=args.target, flatOutput=False) - - # optional post-generation steps - if args.verify: - # compare contents of temp dir and repo - temp_files = {} - repo_files = {} - for details in generators.values(): - if details['directory'] not in temp_files: - temp_files[details['directory']] = set() - temp_files[details['directory']].update(set(os.listdir(os.path.join(temp_dir, details['directory'])))) - if details['directory'] not in repo_files: - repo_files[details['directory']] = set() - repo_files[details['directory']].update(set(os.listdir(os.path.join(repo_dir, details['directory']))) - set(verify_exclude)) - - # compare contents of temp dir and repo - files_match = True - for filename, details in generators.items(): - if filename not in repo_files[details['directory']]: - print('ERROR: Missing repo file', filename) - files_match = False - elif filename not in temp_files[details['directory']]: - print('ERROR: Missing generator for', filename) - files_match = False - elif not filecmp.cmp(os.path.join(temp_dir, details['directory'], filename), - os.path.join(repo_dir, details['directory'], filename), - shallow=False): - print('ERROR: Repo files do not match generator output for', filename) - files_match = False - - # return code for test scripts - if files_match: - print('SUCCESS: Repo files match generator output') - return 0 - return 1 - - elif args.incremental: - # copy missing or differing files from temp directory to repo - for filename, details in generators.items(): - temp_filename = os.path.join(temp_dir, details['directory'], filename) - repo_filename = os.path.join(repo_dir, details['directory'], filename) - if not os.path.exists(repo_filename) or \ - not filecmp.cmp(temp_filename, repo_filename, shallow=False): - print('update', repo_filename) - shutil.copyfile(temp_filename, repo_filename) - - # write out the header version used to generate the code to a checked in CMake file - if args.generated_version: - json_files = [] - json_files.append(common_codegen.RepoRelative('icd/VkICD_mock_icd.json.in')) - for json_file in json_files: - with open(json_file) as f: - data = json.load(f) - - data["ICD"]["api_version"] = args.generated_version - - with open(json_file, mode='w', encoding='utf-8', newline='\n') as f: - f.write(json.dumps(data, indent=4)) - - # Update the CMake project version - with open(common_codegen.RepoRelative('CMakeLists.txt'), "r+") as f: - data = f.read() - f.seek(0) - f.write(re.sub("project.*VERSION.*", f"project(Vulkan-Tools VERSION {args.generated_version})", data)) - f.truncate() - - return 0 - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) - diff --git a/tools/Vulkan-Tools/scripts/generators/mock_icd_generator.py b/tools/Vulkan-Tools/scripts/generators/mock_icd_generator.py deleted file mode 100644 index b1d81c42..00000000 --- a/tools/Vulkan-Tools/scripts/generators/mock_icd_generator.py +++ /dev/null @@ -1,1452 +0,0 @@ -#!/usr/bin/python3 -i -# -# Copyright (c) 2015-2025 The Khronos Group Inc. -# Copyright (c) 2015-2025 Valve Corporation -# Copyright (c) 2015-2025 LunarG, Inc. -# Copyright (c) 2015-2025 Google Inc. -# Copyright (c) 2023-2025 RasterGrid Kft. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Author: Tobin Ehlis <tobine@google.com> -# -# This script generates a Mock ICD that intercepts almost all Vulkan -# functions. That layer is not intended to be useful or even compilable -# in its initial state. Rather it's intended to be a starting point that -# can be copied and customized to assist in creation of a new layer. - -from base_generator import BaseGenerator - -CUSTOM_C_INTERCEPTS = { -'vkCreateInstance': ''' - // TODO: If loader ver <=4 ICD must fail with VK_ERROR_INCOMPATIBLE_DRIVER for all vkCreateInstance calls with - // apiVersion set to > Vulkan 1.0 because the loader is still at interface version <= 4. Otherwise, the - // ICD should behave as normal. - if (loader_interface_version <= 4) { - return VK_ERROR_INCOMPATIBLE_DRIVER; - } - *pInstance = (VkInstance)CreateDispObjHandle(); - for (auto& physical_device : physical_device_map[*pInstance]) - physical_device = (VkPhysicalDevice)CreateDispObjHandle(); - // TODO: If emulating specific device caps, will need to add intelligence here - return VK_SUCCESS; -''', -'vkDestroyInstance': ''' - if (instance) { - for (const auto physical_device : physical_device_map.at(instance)) { - display_map.erase(physical_device); - DestroyDispObjHandle((void*)physical_device); - } - physical_device_map.erase(instance); - DestroyDispObjHandle((void*)instance); - } -''', -'vkAllocateCommandBuffers': ''' - unique_lock_t lock(global_lock); - for (uint32_t i = 0; i < pAllocateInfo->commandBufferCount; ++i) { - pCommandBuffers[i] = (VkCommandBuffer)CreateDispObjHandle(); - command_pool_buffer_map[pAllocateInfo->commandPool].push_back(pCommandBuffers[i]); - } - return VK_SUCCESS; -''', -'vkFreeCommandBuffers': ''' - unique_lock_t lock(global_lock); - for (auto i = 0u; i < commandBufferCount; ++i) { - if (!pCommandBuffers[i]) { - continue; - } - - for (auto& pair : command_pool_buffer_map) { - auto& cbs = pair.second; - auto it = std::find(cbs.begin(), cbs.end(), pCommandBuffers[i]); - if (it != cbs.end()) { - cbs.erase(it); - } - } - - DestroyDispObjHandle((void*) pCommandBuffers[i]); - } -''', -'vkCreateCommandPool': ''' - unique_lock_t lock(global_lock); - *pCommandPool = (VkCommandPool)global_unique_handle++; - command_pool_map[device].insert(*pCommandPool); - return VK_SUCCESS; -''', -'vkDestroyCommandPool': ''' - // destroy command buffers for this pool - unique_lock_t lock(global_lock); - auto it = command_pool_buffer_map.find(commandPool); - if (it != command_pool_buffer_map.end()) { - for (auto& cb : it->second) { - DestroyDispObjHandle((void*) cb); - } - command_pool_buffer_map.erase(it); - } - command_pool_map[device].erase(commandPool); -''', -'vkEnumeratePhysicalDevices': ''' - VkResult result_code = VK_SUCCESS; - if (pPhysicalDevices) { - const auto return_count = (std::min)(*pPhysicalDeviceCount, icd_physical_device_count); - for (uint32_t i = 0; i < return_count; ++i) pPhysicalDevices[i] = physical_device_map.at(instance)[i]; - if (return_count < icd_physical_device_count) result_code = VK_INCOMPLETE; - *pPhysicalDeviceCount = return_count; - } else { - *pPhysicalDeviceCount = icd_physical_device_count; - } - return result_code; -''', -'vkCreateDevice': ''' - *pDevice = (VkDevice)CreateDispObjHandle(); - // TODO: If emulating specific device caps, will need to add intelligence here - return VK_SUCCESS; -''', -'vkDestroyDevice': ''' - unique_lock_t lock(global_lock); - // First destroy sub-device objects - // Destroy Queues - for (auto queue_family_map_pair : queue_map[device]) { - for (auto index_queue_pair : queue_map[device][queue_family_map_pair.first]) { - DestroyDispObjHandle((void*)index_queue_pair.second); - } - } - - for (auto& cp : command_pool_map[device]) { - for (auto& cb : command_pool_buffer_map[cp]) { - DestroyDispObjHandle((void*) cb); - } - command_pool_buffer_map.erase(cp); - } - command_pool_map[device].clear(); - - queue_map.erase(device); - buffer_map.erase(device); - image_memory_size_map.erase(device); - // Now destroy device - DestroyDispObjHandle((void*)device); - // TODO: If emulating specific device caps, will need to add intelligence here -''', -'vkGetDeviceQueue': ''' - unique_lock_t lock(global_lock); - auto queue = queue_map[device][queueFamilyIndex][queueIndex]; - if (queue) { - *pQueue = queue; - } else { - *pQueue = queue_map[device][queueFamilyIndex][queueIndex] = (VkQueue)CreateDispObjHandle(); - } - // TODO: If emulating specific device caps, will need to add intelligence here - return; -''', -'vkGetDeviceQueue2': ''' - GetDeviceQueue(device, pQueueInfo->queueFamilyIndex, pQueueInfo->queueIndex, pQueue); - // TODO: Add further support for GetDeviceQueue2 features -''', -'vkEnumerateInstanceLayerProperties': ''' - return VK_SUCCESS; -''', -'vkEnumerateInstanceVersion': ''' - *pApiVersion = VK_HEADER_VERSION_COMPLETE; - return VK_SUCCESS; -''', -'vkEnumerateDeviceLayerProperties': ''' - return VK_SUCCESS; -''', -'vkEnumerateInstanceExtensionProperties': ''' - // If requesting number of extensions, return that - if (!pLayerName) { - if (!pProperties) { - *pPropertyCount = (uint32_t)instance_extension_map.size(); - } else { - uint32_t i = 0; - for (const auto &name_ver_pair : instance_extension_map) { - if (i == *pPropertyCount) { - break; - } - std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName)); - pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0; - pProperties[i].specVersion = name_ver_pair.second; - ++i; - } - if (i != instance_extension_map.size()) { - return VK_INCOMPLETE; - } - } - } - // If requesting extension properties, fill in data struct for number of extensions - return VK_SUCCESS; -''', -'vkEnumerateDeviceExtensionProperties': ''' - // If requesting number of extensions, return that - if (!pLayerName) { - if (!pProperties) { - *pPropertyCount = (uint32_t)device_extension_map.size(); - } else { - uint32_t i = 0; - for (const auto &name_ver_pair : device_extension_map) { - if (i == *pPropertyCount) { - break; - } - std::strncpy(pProperties[i].extensionName, name_ver_pair.first.c_str(), sizeof(pProperties[i].extensionName)); - pProperties[i].extensionName[sizeof(pProperties[i].extensionName) - 1] = 0; - pProperties[i].specVersion = name_ver_pair.second; - ++i; - } - *pPropertyCount = i; - if (i != device_extension_map.size()) { - return VK_INCOMPLETE; - } - } - } - // If requesting extension properties, fill in data struct for number of extensions - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSurfacePresentModesKHR': ''' - // Currently always say that all present modes are supported - if (!pPresentModes) { - *pPresentModeCount = 6; - } else { - if (*pPresentModeCount >= 6) pPresentModes[5] = VK_PRESENT_MODE_SHARED_CONTINUOUS_REFRESH_KHR; - if (*pPresentModeCount >= 5) pPresentModes[4] = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR; - if (*pPresentModeCount >= 4) pPresentModes[3] = VK_PRESENT_MODE_FIFO_RELAXED_KHR; - if (*pPresentModeCount >= 3) pPresentModes[2] = VK_PRESENT_MODE_FIFO_KHR; - if (*pPresentModeCount >= 2) pPresentModes[1] = VK_PRESENT_MODE_MAILBOX_KHR; - if (*pPresentModeCount >= 1) pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR; - *pPresentModeCount = *pPresentModeCount < 6 ? *pPresentModeCount : 6; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSurfaceFormatsKHR': ''' - // Currently always say that RGBA8 & BGRA8 are supported - if (!pSurfaceFormats) { - *pSurfaceFormatCount = 2; - } else { - if (*pSurfaceFormatCount >= 2) { - pSurfaceFormats[1].format = VK_FORMAT_R8G8B8A8_UNORM; - pSurfaceFormats[1].colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - } - if (*pSurfaceFormatCount >= 1) { - pSurfaceFormats[0].format = VK_FORMAT_B8G8R8A8_UNORM; - pSurfaceFormats[0].colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - } - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSurfaceFormats2KHR': ''' - // Currently always say that RGBA8 & BGRA8 are supported - if (!pSurfaceFormats) { - *pSurfaceFormatCount = 2; - } else { - if (*pSurfaceFormatCount >= 2) { - pSurfaceFormats[1].pNext = nullptr; - pSurfaceFormats[1].surfaceFormat.format = VK_FORMAT_R8G8B8A8_UNORM; - pSurfaceFormats[1].surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - } - if (*pSurfaceFormatCount >= 1) { - pSurfaceFormats[1].pNext = nullptr; - pSurfaceFormats[0].surfaceFormat.format = VK_FORMAT_B8G8R8A8_UNORM; - pSurfaceFormats[0].surfaceFormat.colorSpace = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR; - } - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSurfaceSupportKHR': ''' - // Currently say that all surface/queue combos are supported - *pSupported = VK_TRUE; - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSurfaceCapabilitiesKHR': ''' - // In general just say max supported is available for requested surface - pSurfaceCapabilities->minImageCount = 1; - pSurfaceCapabilities->maxImageCount = 0; - pSurfaceCapabilities->currentExtent.width = 0xFFFFFFFF; - pSurfaceCapabilities->currentExtent.height = 0xFFFFFFFF; - pSurfaceCapabilities->minImageExtent.width = 1; - pSurfaceCapabilities->minImageExtent.height = 1; - pSurfaceCapabilities->maxImageExtent.width = 0xFFFF; - pSurfaceCapabilities->maxImageExtent.height = 0xFFFF; - pSurfaceCapabilities->maxImageArrayLayers = 128; - pSurfaceCapabilities->supportedTransforms = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR | - VK_SURFACE_TRANSFORM_ROTATE_90_BIT_KHR | - VK_SURFACE_TRANSFORM_ROTATE_180_BIT_KHR | - VK_SURFACE_TRANSFORM_ROTATE_270_BIT_KHR | - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_BIT_KHR | - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_90_BIT_KHR | - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_180_BIT_KHR | - VK_SURFACE_TRANSFORM_HORIZONTAL_MIRROR_ROTATE_270_BIT_KHR | - VK_SURFACE_TRANSFORM_INHERIT_BIT_KHR; - pSurfaceCapabilities->currentTransform = VK_SURFACE_TRANSFORM_IDENTITY_BIT_KHR; - pSurfaceCapabilities->supportedCompositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR | - VK_COMPOSITE_ALPHA_PRE_MULTIPLIED_BIT_KHR | - VK_COMPOSITE_ALPHA_POST_MULTIPLIED_BIT_KHR | - VK_COMPOSITE_ALPHA_INHERIT_BIT_KHR; - pSurfaceCapabilities->supportedUsageFlags = VK_IMAGE_USAGE_TRANSFER_SRC_BIT | - VK_IMAGE_USAGE_TRANSFER_DST_BIT | - VK_IMAGE_USAGE_SAMPLED_BIT | - VK_IMAGE_USAGE_STORAGE_BIT | - VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | - VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | - VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | - VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT; - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSurfaceCapabilities2KHR': ''' - GetPhysicalDeviceSurfaceCapabilitiesKHR(physicalDevice, pSurfaceInfo->surface, &pSurfaceCapabilities->surfaceCapabilities); - - auto *present_mode_compatibility = lvl_find_mod_in_chain<VkSurfacePresentModeCompatibilityEXT>(pSurfaceCapabilities->pNext); - if (present_mode_compatibility) { - if (!present_mode_compatibility->pPresentModes) { - present_mode_compatibility->presentModeCount = 3; - } else { - // arbitrary - present_mode_compatibility->pPresentModes[0] = VK_PRESENT_MODE_IMMEDIATE_KHR; - present_mode_compatibility->pPresentModes[1] = VK_PRESENT_MODE_FIFO_KHR; - present_mode_compatibility->pPresentModes[2] = VK_PRESENT_MODE_SHARED_DEMAND_REFRESH_KHR; - } - } - return VK_SUCCESS; -''', -'vkGetInstanceProcAddr': ''' - if (!negotiate_loader_icd_interface_called) { - loader_interface_version = 0; - } - const auto &item = name_to_funcptr_map.find(pName); - if (item != name_to_funcptr_map.end()) { - return reinterpret_cast<PFN_vkVoidFunction>(item->second); - } - // Mock should intercept all functions so if we get here just return null - return nullptr; -''', -'vkGetDeviceProcAddr': ''' - return GetInstanceProcAddr(nullptr, pName); -''', -'vkGetPhysicalDeviceMemoryProperties': ''' - pMemoryProperties->memoryTypeCount = 6; - // Host visible Coherent - pMemoryProperties->memoryTypes[0].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - pMemoryProperties->memoryTypes[0].heapIndex = 0; - // Host visible Cached - pMemoryProperties->memoryTypes[1].propertyFlags = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT; - pMemoryProperties->memoryTypes[1].heapIndex = 0; - // Device local and Host visible - pMemoryProperties->memoryTypes[2].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; - pMemoryProperties->memoryTypes[2].heapIndex = 1; - // Device local lazily - pMemoryProperties->memoryTypes[3].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT; - pMemoryProperties->memoryTypes[3].heapIndex = 1; - // Device local protected - pMemoryProperties->memoryTypes[4].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT | VK_MEMORY_PROPERTY_PROTECTED_BIT; - pMemoryProperties->memoryTypes[4].heapIndex = 1; - // Device local only - pMemoryProperties->memoryTypes[5].propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; - pMemoryProperties->memoryTypes[5].heapIndex = 1; - pMemoryProperties->memoryHeapCount = 2; - pMemoryProperties->memoryHeaps[0].flags = VK_MEMORY_HEAP_MULTI_INSTANCE_BIT; - pMemoryProperties->memoryHeaps[0].size = 8000000000; - pMemoryProperties->memoryHeaps[1].flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT; - pMemoryProperties->memoryHeaps[1].size = 8000000000; -''', -'vkGetPhysicalDeviceMemoryProperties2KHR': ''' - GetPhysicalDeviceMemoryProperties(physicalDevice, &pMemoryProperties->memoryProperties); -''', -'vkGetPhysicalDeviceQueueFamilyProperties': ''' - if (pQueueFamilyProperties) { - std::vector<VkQueueFamilyProperties2KHR> props2(*pQueueFamilyPropertyCount, { - VK_STRUCTURE_TYPE_QUEUE_FAMILY_PROPERTIES_2_KHR}); - GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, props2.data()); - for (uint32_t i = 0; i < *pQueueFamilyPropertyCount; ++i) { - pQueueFamilyProperties[i] = props2[i].queueFamilyProperties; - } - } else { - GetPhysicalDeviceQueueFamilyProperties2KHR(physicalDevice, pQueueFamilyPropertyCount, nullptr); - } -''', -'vkGetPhysicalDeviceQueueFamilyProperties2KHR': ''' - if (pQueueFamilyProperties) { - if (*pQueueFamilyPropertyCount >= 1) { - auto props = &pQueueFamilyProperties[0].queueFamilyProperties; - props->queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT - | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_PROTECTED_BIT; - props->queueCount = 1; - props->timestampValidBits = 16; - props->minImageTransferGranularity = {1,1,1}; - } - if (*pQueueFamilyPropertyCount >= 2) { - auto props = &pQueueFamilyProperties[1].queueFamilyProperties; - props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_DECODE_BIT_KHR; - props->queueCount = 1; - props->timestampValidBits = 16; - props->minImageTransferGranularity = {1,1,1}; - - auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[1].pNext); - if (status_query_props) { - status_query_props->queryResultStatusSupport = VK_TRUE; - } - auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[1].pNext); - if (video_props) { - video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_DECODE_H264_BIT_KHR - | VK_VIDEO_CODEC_OPERATION_DECODE_H265_BIT_KHR - | VK_VIDEO_CODEC_OPERATION_DECODE_AV1_BIT_KHR; - } - } - if (*pQueueFamilyPropertyCount >= 3) { - auto props = &pQueueFamilyProperties[2].queueFamilyProperties; - props->queueFlags = VK_QUEUE_TRANSFER_BIT | VK_QUEUE_PROTECTED_BIT | VK_QUEUE_VIDEO_ENCODE_BIT_KHR; - props->queueCount = 1; - props->timestampValidBits = 16; - props->minImageTransferGranularity = {1,1,1}; - - auto status_query_props = lvl_find_mod_in_chain<VkQueueFamilyQueryResultStatusPropertiesKHR>(pQueueFamilyProperties[2].pNext); - if (status_query_props) { - status_query_props->queryResultStatusSupport = VK_TRUE; - } - auto video_props = lvl_find_mod_in_chain<VkQueueFamilyVideoPropertiesKHR>(pQueueFamilyProperties[2].pNext); - if (video_props) { - video_props->videoCodecOperations = VK_VIDEO_CODEC_OPERATION_ENCODE_H264_BIT_KHR - | VK_VIDEO_CODEC_OPERATION_ENCODE_H265_BIT_KHR - | VK_VIDEO_CODEC_OPERATION_ENCODE_AV1_BIT_KHR; - } - } - if (*pQueueFamilyPropertyCount > 3) { - *pQueueFamilyPropertyCount = 3; - } - } else { - *pQueueFamilyPropertyCount = 3; - } -''', -'vkGetPhysicalDeviceFeatures': ''' - uint32_t num_bools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32); - VkBool32 *bool_array = &pFeatures->robustBufferAccess; - SetBoolArrayTrue(bool_array, num_bools); -''', -'vkGetPhysicalDeviceFeatures2KHR': ''' - GetPhysicalDeviceFeatures(physicalDevice, &pFeatures->features); - uint32_t num_bools = 0; // Count number of VkBool32s in extension structs - VkBool32* feat_bools = nullptr; - auto vk_1_1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan11Features>(pFeatures->pNext); - if (vk_1_1_features) { - vk_1_1_features->protectedMemory = VK_TRUE; - } - auto vk_1_3_features = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan13Features>(pFeatures->pNext); - if (vk_1_3_features) { - vk_1_3_features->synchronization2 = VK_TRUE; - } - auto prot_features = lvl_find_mod_in_chain<VkPhysicalDeviceProtectedMemoryFeatures>(pFeatures->pNext); - if (prot_features) { - prot_features->protectedMemory = VK_TRUE; - } - auto sync2_features = lvl_find_mod_in_chain<VkPhysicalDeviceSynchronization2FeaturesKHR>(pFeatures->pNext); - if (sync2_features) { - sync2_features->synchronization2 = VK_TRUE; - } - auto video_maintenance1_features = lvl_find_mod_in_chain<VkPhysicalDeviceVideoMaintenance1FeaturesKHR>(pFeatures->pNext); - if (video_maintenance1_features) { - video_maintenance1_features->videoMaintenance1 = VK_TRUE; - } - const auto *desc_idx_features = lvl_find_in_chain<VkPhysicalDeviceDescriptorIndexingFeaturesEXT>(pFeatures->pNext); - if (desc_idx_features) { - const auto bool_size = sizeof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT) - offsetof(VkPhysicalDeviceDescriptorIndexingFeaturesEXT, shaderInputAttachmentArrayDynamicIndexing); - num_bools = bool_size/sizeof(VkBool32); - feat_bools = (VkBool32*)&desc_idx_features->shaderInputAttachmentArrayDynamicIndexing; - SetBoolArrayTrue(feat_bools, num_bools); - } - const auto *blendop_features = lvl_find_in_chain<VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT>(pFeatures->pNext); - if (blendop_features) { - const auto bool_size = sizeof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT) - offsetof(VkPhysicalDeviceBlendOperationAdvancedFeaturesEXT, advancedBlendCoherentOperations); - num_bools = bool_size/sizeof(VkBool32); - feat_bools = (VkBool32*)&blendop_features->advancedBlendCoherentOperations; - SetBoolArrayTrue(feat_bools, num_bools); - } - const auto *host_image_copy_features = lvl_find_in_chain<VkPhysicalDeviceHostImageCopyFeaturesEXT>(pFeatures->pNext); - if (host_image_copy_features) { - feat_bools = (VkBool32*)&host_image_copy_features->hostImageCopy; - SetBoolArrayTrue(feat_bools, 1); - } -''', -'vkGetPhysicalDeviceFormatProperties': ''' - if (VK_FORMAT_UNDEFINED == format) { - *pFormatProperties = { 0x0, 0x0, 0x0 }; - } else { - // Default to a color format, skip DS bit - *pFormatProperties = { 0x00FFFDFF, 0x00FFFDFF, 0x00FFFDFF }; - switch (format) { - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_X8_D24_UNORM_PACK32: - case VK_FORMAT_D32_SFLOAT: - case VK_FORMAT_S8_UINT: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - // Don't set color bits for DS formats - *pFormatProperties = { 0x00FFFE7F, 0x00FFFE7F, 0x00FFFE7F }; - break; - case VK_FORMAT_G8_B8R8_2PLANE_420_UNORM: - case VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM: - case VK_FORMAT_G8_B8R8_2PLANE_422_UNORM: - case VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16: - case VK_FORMAT_G8_B8R8_2PLANE_444_UNORM: - // Set decode/encode bits for these formats - *pFormatProperties = { 0x1EFFFDFF, 0x1EFFFDFF, 0x00FFFDFF }; - break; - default: - break; - } - } -''', -'vkGetPhysicalDeviceFormatProperties2KHR': ''' - GetPhysicalDeviceFormatProperties(physicalDevice, format, &pFormatProperties->formatProperties); - VkFormatProperties3KHR *props_3 = lvl_find_mod_in_chain<VkFormatProperties3KHR>(pFormatProperties->pNext); - if (props_3) { - props_3->linearTilingFeatures = pFormatProperties->formatProperties.linearTilingFeatures; - props_3->optimalTilingFeatures = pFormatProperties->formatProperties.optimalTilingFeatures; - props_3->bufferFeatures = pFormatProperties->formatProperties.bufferFeatures; - props_3->optimalTilingFeatures |= VK_FORMAT_FEATURE_2_HOST_IMAGE_TRANSFER_BIT_EXT; - } -''', -'vkGetPhysicalDeviceImageFormatProperties': ''' - // A hardcoded unsupported format - if (format == VK_FORMAT_E5B9G9R9_UFLOAT_PACK32) { - return VK_ERROR_FORMAT_NOT_SUPPORTED; - } - - // TODO: Just hard-coding some values for now - // TODO: If tiling is linear, limit the mips, levels, & sample count - if (VK_IMAGE_TILING_LINEAR == tiling) { - *pImageFormatProperties = { { 4096, 4096, 256 }, 1, 1, VK_SAMPLE_COUNT_1_BIT, 4294967296 }; - } else { - // We hard-code support for all sample counts except 64 bits. - *pImageFormatProperties = { { 4096, 4096, 256 }, 12, 256, 0x7F & ~VK_SAMPLE_COUNT_64_BIT, 4294967296 }; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceImageFormatProperties2KHR': ''' - auto *external_image_prop = lvl_find_mod_in_chain<VkExternalImageFormatProperties>(pImageFormatProperties->pNext); - auto *external_image_format = lvl_find_in_chain<VkPhysicalDeviceExternalImageFormatInfo>(pImageFormatInfo->pNext); - if (external_image_prop && external_image_format) { - external_image_prop->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; - external_image_prop->externalMemoryProperties.compatibleHandleTypes = external_image_format->handleType; - } - - GetPhysicalDeviceImageFormatProperties(physicalDevice, pImageFormatInfo->format, pImageFormatInfo->type, pImageFormatInfo->tiling, pImageFormatInfo->usage, pImageFormatInfo->flags, &pImageFormatProperties->imageFormatProperties); - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceSparseImageFormatProperties': ''' - if (!pProperties) { - *pPropertyCount = 1; - } else { - // arbitrary - pProperties->imageGranularity = {4, 4, 4}; - pProperties->flags = VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT; - switch (format) { - case VK_FORMAT_D16_UNORM: - case VK_FORMAT_D32_SFLOAT: - pProperties->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT; - break; - case VK_FORMAT_S8_UINT: - pProperties->aspectMask = VK_IMAGE_ASPECT_STENCIL_BIT; - break; - case VK_FORMAT_X8_D24_UNORM_PACK32: - case VK_FORMAT_D16_UNORM_S8_UINT: - case VK_FORMAT_D24_UNORM_S8_UINT: - case VK_FORMAT_D32_SFLOAT_S8_UINT: - pProperties->aspectMask = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT; - break; - default: - pProperties->aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - break; - } - } -''', -'vkGetPhysicalDeviceSparseImageFormatProperties2KHR': ''' - if (pPropertyCount && pProperties) { - GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling, pPropertyCount, &pProperties->properties); - } else { - GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, pFormatInfo->format, pFormatInfo->type, pFormatInfo->samples, pFormatInfo->usage, pFormatInfo->tiling, pPropertyCount, nullptr); - } -''', -'vkGetPhysicalDeviceProperties': ''' - pProperties->apiVersion = VK_HEADER_VERSION_COMPLETE; - pProperties->driverVersion = 1; - pProperties->vendorID = 0xba5eba11; - pProperties->deviceID = 0xf005ba11; - pProperties->deviceType = VK_PHYSICAL_DEVICE_TYPE_VIRTUAL_GPU; - //std::string devName = "Vulkan Mock Device"; - strcpy(pProperties->deviceName, "Vulkan Mock Device"); - pProperties->pipelineCacheUUID[0] = 18; - pProperties->limits = SetLimits(&pProperties->limits); - pProperties->sparseProperties = { VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE, VK_TRUE }; -''', -'vkGetPhysicalDeviceProperties2KHR': ''' - // The only value that need to be set are those the Profile layer can't set - // see https://github.com/KhronosGroup/Vulkan-Profiles/issues/352 - // All values set are arbitrary - GetPhysicalDeviceProperties(physicalDevice, &pProperties->properties); - - auto *props_11 = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan11Properties>(pProperties->pNext); - if (props_11) { - props_11->protectedNoFault = VK_FALSE; - } - - auto *props_12 = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan12Properties>(pProperties->pNext); - if (props_12) { - props_12->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL; - props_12->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL; - } - - auto *props_13 = lvl_find_mod_in_chain<VkPhysicalDeviceVulkan13Properties>(pProperties->pNext); - if (props_13) { - props_13->storageTexelBufferOffsetSingleTexelAlignment = VK_TRUE; - props_13->uniformTexelBufferOffsetSingleTexelAlignment = VK_TRUE; - props_13->storageTexelBufferOffsetAlignmentBytes = 16; - props_13->uniformTexelBufferOffsetAlignmentBytes = 16; - } - - auto *protected_memory_props = lvl_find_mod_in_chain<VkPhysicalDeviceProtectedMemoryProperties>(pProperties->pNext); - if (protected_memory_props) { - protected_memory_props->protectedNoFault = VK_FALSE; - } - - auto *float_controls_props = lvl_find_mod_in_chain<VkPhysicalDeviceFloatControlsProperties>(pProperties->pNext); - if (float_controls_props) { - float_controls_props->denormBehaviorIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL; - float_controls_props->roundingModeIndependence = VK_SHADER_FLOAT_CONTROLS_INDEPENDENCE_ALL; - } - - auto *conservative_raster_props = lvl_find_mod_in_chain<VkPhysicalDeviceConservativeRasterizationPropertiesEXT>(pProperties->pNext); - if (conservative_raster_props) { - conservative_raster_props->primitiveOverestimationSize = 0.00195313f; - conservative_raster_props->conservativePointAndLineRasterization = VK_TRUE; - conservative_raster_props->degenerateTrianglesRasterized = VK_TRUE; - conservative_raster_props->degenerateLinesRasterized = VK_TRUE; - } - - auto *rt_pipeline_props = lvl_find_mod_in_chain<VkPhysicalDeviceRayTracingPipelinePropertiesKHR>(pProperties->pNext); - if (rt_pipeline_props) { - rt_pipeline_props->shaderGroupHandleSize = 32; - rt_pipeline_props->shaderGroupBaseAlignment = 64; - rt_pipeline_props->shaderGroupHandleCaptureReplaySize = 32; - } - - auto *rt_pipeline_nv_props = lvl_find_mod_in_chain<VkPhysicalDeviceRayTracingPropertiesNV>(pProperties->pNext); - if (rt_pipeline_nv_props) { - rt_pipeline_nv_props->shaderGroupHandleSize = 32; - rt_pipeline_nv_props->shaderGroupBaseAlignment = 64; - } - - auto *texel_buffer_props = lvl_find_mod_in_chain<VkPhysicalDeviceTexelBufferAlignmentProperties>(pProperties->pNext); - if (texel_buffer_props) { - texel_buffer_props->storageTexelBufferOffsetSingleTexelAlignment = VK_TRUE; - texel_buffer_props->uniformTexelBufferOffsetSingleTexelAlignment = VK_TRUE; - texel_buffer_props->storageTexelBufferOffsetAlignmentBytes = 16; - texel_buffer_props->uniformTexelBufferOffsetAlignmentBytes = 16; - } - - auto *descriptor_buffer_props = lvl_find_mod_in_chain<VkPhysicalDeviceDescriptorBufferPropertiesEXT>(pProperties->pNext); - if (descriptor_buffer_props) { - descriptor_buffer_props->combinedImageSamplerDescriptorSingleArray = VK_TRUE; - descriptor_buffer_props->bufferlessPushDescriptors = VK_TRUE; - descriptor_buffer_props->allowSamplerImageViewPostSubmitCreation = VK_TRUE; - descriptor_buffer_props->descriptorBufferOffsetAlignment = 4; - } - - auto *mesh_shader_props = lvl_find_mod_in_chain<VkPhysicalDeviceMeshShaderPropertiesEXT>(pProperties->pNext); - if (mesh_shader_props) { - mesh_shader_props->meshOutputPerVertexGranularity = 32; - mesh_shader_props->meshOutputPerPrimitiveGranularity = 32; - mesh_shader_props->prefersLocalInvocationVertexOutput = VK_TRUE; - mesh_shader_props->prefersLocalInvocationPrimitiveOutput = VK_TRUE; - mesh_shader_props->prefersCompactVertexOutput = VK_TRUE; - mesh_shader_props->prefersCompactPrimitiveOutput = VK_TRUE; - } - - auto *fragment_density_map2_props = lvl_find_mod_in_chain<VkPhysicalDeviceFragmentDensityMap2PropertiesEXT>(pProperties->pNext); - if (fragment_density_map2_props) { - fragment_density_map2_props->subsampledLoads = VK_FALSE; - fragment_density_map2_props->subsampledCoarseReconstructionEarlyAccess = VK_FALSE; - fragment_density_map2_props->maxSubsampledArrayLayers = 2; - fragment_density_map2_props->maxDescriptorSetSubsampledSamplers = 1; - } - - auto *maintenance3_props = lvl_find_mod_in_chain<VkPhysicalDeviceMaintenance3Properties>(pProperties->pNext); - if (maintenance3_props) { - maintenance3_props->maxMemoryAllocationSize = 1073741824; - maintenance3_props->maxPerSetDescriptors = 1024; - } - - const uint32_t num_copy_layouts = 5; - const VkImageLayout HostCopyLayouts[]{ - VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_GENERAL, - VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL, - VK_IMAGE_LAYOUT_STENCIL_ATTACHMENT_OPTIMAL, - VK_IMAGE_LAYOUT_DEPTH_ATTACHMENT_OPTIMAL, - }; - - auto *host_image_copy_props = lvl_find_mod_in_chain<VkPhysicalDeviceHostImageCopyPropertiesEXT>(pProperties->pNext); - if (host_image_copy_props){ - if (host_image_copy_props->pCopyDstLayouts == nullptr) host_image_copy_props->copyDstLayoutCount = num_copy_layouts; - else { - uint32_t num_layouts = (std::min)(host_image_copy_props->copyDstLayoutCount, num_copy_layouts); - for (uint32_t i = 0; i < num_layouts; i++) { - host_image_copy_props->pCopyDstLayouts[i] = HostCopyLayouts[i]; - } - } - if (host_image_copy_props->pCopySrcLayouts == nullptr) host_image_copy_props->copySrcLayoutCount = num_copy_layouts; - else { - uint32_t num_layouts = (std::min)(host_image_copy_props->copySrcLayoutCount, num_copy_layouts); - for (uint32_t i = 0; i < num_layouts; i++) { - host_image_copy_props->pCopySrcLayouts[i] = HostCopyLayouts[i]; - } - } - } - - auto *driver_properties = lvl_find_mod_in_chain<VkPhysicalDeviceDriverProperties>(pProperties->pNext); - if (driver_properties) { - std::strncpy(driver_properties->driverName, "Vulkan Mock Device", VK_MAX_DRIVER_NAME_SIZE); -#if defined(GIT_BRANCH_NAME) && defined(GIT_TAG_INFO) - std::strncpy(driver_properties->driverInfo, "Branch: " GIT_BRANCH_NAME " Tag Info: " GIT_TAG_INFO, VK_MAX_DRIVER_INFO_SIZE); -#else - std::strncpy(driver_properties->driverInfo, "Branch: --unknown-- Tag Info: --unknown--", VK_MAX_DRIVER_INFO_SIZE); -#endif - } - - auto *layered_properties = lvl_find_mod_in_chain<VkPhysicalDeviceLayeredApiPropertiesListKHR>(pProperties->pNext); - if (layered_properties) { - layered_properties->layeredApiCount = 1; - if (layered_properties->pLayeredApis) { - layered_properties->pLayeredApis[0] = VkPhysicalDeviceLayeredApiPropertiesKHR{ - VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_API_PROPERTIES_KHR, - nullptr, - 0xba5eba11, - 0xf005ba11, - VK_PHYSICAL_DEVICE_LAYERED_API_VULKAN_KHR - }; - std::strncpy(layered_properties->pLayeredApis[0].deviceName, "Fake Driver", VK_MAX_PHYSICAL_DEVICE_NAME_SIZE); - } - } -''', -'vkGetPhysicalDeviceExternalSemaphoreProperties':''' - // Hard code support for all handle types and features - pExternalSemaphoreProperties->exportFromImportedHandleTypes = 0x1F; - pExternalSemaphoreProperties->compatibleHandleTypes = 0x1F; - pExternalSemaphoreProperties->externalSemaphoreFeatures = 0x3; -''', -'vkGetPhysicalDeviceExternalSemaphorePropertiesKHR':''' - GetPhysicalDeviceExternalSemaphoreProperties(physicalDevice, pExternalSemaphoreInfo, pExternalSemaphoreProperties); -''', -'vkGetPhysicalDeviceExternalFenceProperties':''' - // Hard-code support for all handle types and features - pExternalFenceProperties->exportFromImportedHandleTypes = 0xF; - pExternalFenceProperties->compatibleHandleTypes = 0xF; - pExternalFenceProperties->externalFenceFeatures = 0x3; -''', -'vkGetPhysicalDeviceExternalFencePropertiesKHR':''' - GetPhysicalDeviceExternalFenceProperties(physicalDevice, pExternalFenceInfo, pExternalFenceProperties); -''', -'vkGetPhysicalDeviceExternalBufferProperties':''' - constexpr VkExternalMemoryHandleTypeFlags supported_flags = 0x1FF; - if (pExternalBufferInfo->handleType & VK_EXTERNAL_MEMORY_HANDLE_TYPE_ANDROID_HARDWARE_BUFFER_BIT_ANDROID) { - // Can't have dedicated memory with AHB - pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = VK_EXTERNAL_MEMORY_FEATURE_IMPORTABLE_BIT | VK_EXTERNAL_MEMORY_FEATURE_EXPORTABLE_BIT; - pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = pExternalBufferInfo->handleType; - pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = pExternalBufferInfo->handleType; - } else if (pExternalBufferInfo->handleType & supported_flags) { - pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = 0x7; - pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = supported_flags; - pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = supported_flags; - } else { - pExternalBufferProperties->externalMemoryProperties.externalMemoryFeatures = 0; - pExternalBufferProperties->externalMemoryProperties.exportFromImportedHandleTypes = 0; - // According to spec, handle type is always compatible with itself. Even if export/import - // not supported, it's important to properly implement self-compatibility property since - // application's control flow can rely on this. - pExternalBufferProperties->externalMemoryProperties.compatibleHandleTypes = pExternalBufferInfo->handleType; - } -''', -'vkGetPhysicalDeviceExternalBufferPropertiesKHR':''' - GetPhysicalDeviceExternalBufferProperties(physicalDevice, pExternalBufferInfo, pExternalBufferProperties); -''', -'vkGetBufferMemoryRequirements': ''' - // TODO: Just hard-coding reqs for now - pMemoryRequirements->size = 4096; - pMemoryRequirements->alignment = 1; - pMemoryRequirements->memoryTypeBits = 0xFFFF; - // Return a better size based on the buffer size from the create info. - unique_lock_t lock(global_lock); - auto d_iter = buffer_map.find(device); - if (d_iter != buffer_map.end()) { - auto iter = d_iter->second.find(buffer); - if (iter != d_iter->second.end()) { - pMemoryRequirements->size = ((iter->second.size + 4095) / 4096) * 4096; - } - } -''', -'vkGetBufferMemoryRequirements2KHR': ''' - GetBufferMemoryRequirements(device, pInfo->buffer, &pMemoryRequirements->memoryRequirements); -''', -'vkGetDeviceBufferMemoryRequirements': ''' - // TODO: Just hard-coding reqs for now - pMemoryRequirements->memoryRequirements.alignment = 1; - pMemoryRequirements->memoryRequirements.memoryTypeBits = 0xFFFF; - - // Return a size based on the buffer size from the create info. - pMemoryRequirements->memoryRequirements.size = ((pInfo->pCreateInfo->size + 4095) / 4096) * 4096; -''', -'vkGetDeviceBufferMemoryRequirementsKHR': ''' - GetDeviceBufferMemoryRequirements(device, pInfo, pMemoryRequirements); -''', -'vkGetImageMemoryRequirements': ''' - pMemoryRequirements->size = 0; - pMemoryRequirements->alignment = 1; - - unique_lock_t lock(global_lock); - auto d_iter = image_memory_size_map.find(device); - if(d_iter != image_memory_size_map.end()){ - auto iter = d_iter->second.find(image); - if (iter != d_iter->second.end()) { - pMemoryRequirements->size = iter->second; - } - } - // Here we hard-code that the memory type at index 3 doesn't support this image. - pMemoryRequirements->memoryTypeBits = 0xFFFF & ~(0x1 << 3); -''', -'vkGetImageMemoryRequirements2KHR': ''' - GetImageMemoryRequirements(device, pInfo->image, &pMemoryRequirements->memoryRequirements); -''', -'vkGetDeviceImageMemoryRequirements': ''' - pMemoryRequirements->memoryRequirements.size = GetImageSizeFromCreateInfo(pInfo->pCreateInfo); - pMemoryRequirements->memoryRequirements.alignment = 1; - // Here we hard-code that the memory type at index 3 doesn't support this image. - pMemoryRequirements->memoryRequirements.memoryTypeBits = 0xFFFF & ~(0x1 << 3); -''', -'vkGetDeviceImageMemoryRequirementsKHR': ''' - GetDeviceImageMemoryRequirements(device, pInfo, pMemoryRequirements); -''', -'vkMapMemory': ''' - unique_lock_t lock(global_lock); - if (VK_WHOLE_SIZE == size) { - if (allocated_memory_size_map.count(memory) != 0) - size = allocated_memory_size_map[memory] - offset; - else - size = 0x10000; - } - void* map_addr = malloc((size_t)size); - mapped_memory_map[memory].push_back(map_addr); - *ppData = map_addr; - return VK_SUCCESS; -''', -'vkMapMemory2KHR': ''' - return MapMemory(device, pMemoryMapInfo->memory, pMemoryMapInfo->offset, pMemoryMapInfo->size, pMemoryMapInfo->flags, ppData); -''', -'vkUnmapMemory': ''' - unique_lock_t lock(global_lock); - for (auto map_addr : mapped_memory_map[memory]) { - free(map_addr); - } - mapped_memory_map.erase(memory); -''', -'vkUnmapMemory2KHR': ''' - UnmapMemory(device, pMemoryUnmapInfo->memory); - return VK_SUCCESS; -''', -'vkGetImageSubresourceLayout': ''' - // Need safe values. Callers are computing memory offsets from pLayout, with no return code to flag failure. - *pLayout = VkSubresourceLayout(); // Default constructor zero values. -''', -'vkCreateSwapchainKHR': ''' - unique_lock_t lock(global_lock); - *pSwapchain = (VkSwapchainKHR)global_unique_handle++; - for(uint32_t i = 0; i < icd_swapchain_image_count; ++i){ - swapchain_image_map[*pSwapchain][i] = (VkImage)global_unique_handle++; - } - return VK_SUCCESS; -''', -'vkDestroySwapchainKHR': ''' - unique_lock_t lock(global_lock); - swapchain_image_map.clear(); -''', -'vkGetSwapchainImagesKHR': ''' - if (!pSwapchainImages) { - *pSwapchainImageCount = icd_swapchain_image_count; - } else { - unique_lock_t lock(global_lock); - for (uint32_t img_i = 0; img_i < (std::min)(*pSwapchainImageCount, icd_swapchain_image_count); ++img_i){ - pSwapchainImages[img_i] = swapchain_image_map.at(swapchain)[img_i]; - } - - if (*pSwapchainImageCount < icd_swapchain_image_count) return VK_INCOMPLETE; - else if (*pSwapchainImageCount > icd_swapchain_image_count) *pSwapchainImageCount = icd_swapchain_image_count; - } - return VK_SUCCESS; -''', -'vkAcquireNextImageKHR': ''' - *pImageIndex = 0; - return VK_SUCCESS; -''', -'vkAcquireNextImage2KHR': ''' - *pImageIndex = 0; - return VK_SUCCESS; -''', -'vkCreateBuffer': ''' - unique_lock_t lock(global_lock); - *pBuffer = (VkBuffer)global_unique_handle++; - buffer_map[device][*pBuffer] = { - pCreateInfo->size, - current_available_address - }; - current_available_address += pCreateInfo->size; - // Always align to next 64-bit pointer - const uint64_t alignment = current_available_address % 64; - if (alignment != 0) { - current_available_address += (64 - alignment); - } - return VK_SUCCESS; -''', -'vkDestroyBuffer': ''' - unique_lock_t lock(global_lock); - buffer_map[device].erase(buffer); -''', -'vkCreateImage': ''' - unique_lock_t lock(global_lock); - *pImage = (VkImage)global_unique_handle++; - image_memory_size_map[device][*pImage] = GetImageSizeFromCreateInfo(pCreateInfo); - return VK_SUCCESS; -''', -'vkDestroyImage': ''' - unique_lock_t lock(global_lock); - image_memory_size_map[device].erase(image); -''', -'vkEnumeratePhysicalDeviceGroupsKHR': ''' - if (!pPhysicalDeviceGroupProperties) { - *pPhysicalDeviceGroupCount = 1; - } else { - // arbitrary - pPhysicalDeviceGroupProperties->physicalDeviceCount = 1; - pPhysicalDeviceGroupProperties->physicalDevices[0] = physical_device_map.at(instance)[0]; - pPhysicalDeviceGroupProperties->subsetAllocation = VK_FALSE; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceMultisamplePropertiesEXT': ''' - if (pMultisampleProperties) { - // arbitrary - pMultisampleProperties->maxSampleLocationGridSize = {32, 32}; - } -''', -'vkGetPhysicalDeviceFragmentShadingRatesKHR': ''' - if (!pFragmentShadingRates) { - *pFragmentShadingRateCount = 1; - } else { - // arbitrary - pFragmentShadingRates->sampleCounts = VK_SAMPLE_COUNT_1_BIT | VK_SAMPLE_COUNT_4_BIT; - pFragmentShadingRates->fragmentSize = {8, 8}; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceCalibrateableTimeDomainsEXT': ''' - if (!pTimeDomains) { - *pTimeDomainCount = 1; - } else { - // arbitrary - *pTimeDomains = VK_TIME_DOMAIN_DEVICE_EXT; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceCalibrateableTimeDomainsKHR': ''' - if (!pTimeDomains) { - *pTimeDomainCount = 1; - } else { - // arbitrary - *pTimeDomains = VK_TIME_DOMAIN_DEVICE_KHR; - } - return VK_SUCCESS; -''', -'vkGetFenceWin32HandleKHR': ''' - *pHandle = (HANDLE)0x12345678; - return VK_SUCCESS; -''', -'vkGetFenceFdKHR': ''' - *pFd = 0x42; - return VK_SUCCESS; -''', -'vkEnumeratePhysicalDeviceQueueFamilyPerformanceQueryCountersKHR': ''' - if (!pCounters) { - *pCounterCount = 3; - } else { - if (*pCounterCount == 0){ - return VK_INCOMPLETE; - } - // arbitrary - pCounters[0].unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR; - pCounters[0].scope = VK_QUERY_SCOPE_COMMAND_BUFFER_KHR; - pCounters[0].storage = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR; - pCounters[0].uuid[0] = 0x01; - if (*pCounterCount == 1){ - return VK_INCOMPLETE; - } - pCounters[1].unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR; - pCounters[1].scope = VK_QUERY_SCOPE_RENDER_PASS_KHR; - pCounters[1].storage = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR; - pCounters[1].uuid[0] = 0x02; - if (*pCounterCount == 2){ - return VK_INCOMPLETE; - } - pCounters[2].unit = VK_PERFORMANCE_COUNTER_UNIT_GENERIC_KHR; - pCounters[2].scope = VK_QUERY_SCOPE_COMMAND_KHR; - pCounters[2].storage = VK_PERFORMANCE_COUNTER_STORAGE_INT32_KHR; - pCounters[2].uuid[0] = 0x03; - *pCounterCount = 3; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceQueueFamilyPerformanceQueryPassesKHR': ''' - if (pNumPasses) { - // arbitrary - *pNumPasses = 1; - } -''', -'vkGetShaderModuleIdentifierEXT': ''' - if (pIdentifier) { - // arbitrary - pIdentifier->identifierSize = 1; - pIdentifier->identifier[0] = 0x01; - } -''', -'vkGetImageSparseMemoryRequirements': ''' - if (!pSparseMemoryRequirements) { - *pSparseMemoryRequirementCount = 1; - } else { - // arbitrary - pSparseMemoryRequirements->imageMipTailFirstLod = 0; - pSparseMemoryRequirements->imageMipTailSize = 8; - pSparseMemoryRequirements->imageMipTailOffset = 0; - pSparseMemoryRequirements->imageMipTailStride = 4; - pSparseMemoryRequirements->formatProperties.imageGranularity = {4, 4, 4}; - pSparseMemoryRequirements->formatProperties.flags = VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT; - // Would need to track the VkImage to know format for better value here - pSparseMemoryRequirements->formatProperties.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT; - } - -''', -'vkGetImageSparseMemoryRequirements2KHR': ''' - if (pSparseMemoryRequirementCount && pSparseMemoryRequirements) { - GetImageSparseMemoryRequirements(device, pInfo->image, pSparseMemoryRequirementCount, &pSparseMemoryRequirements->memoryRequirements); - } else { - GetImageSparseMemoryRequirements(device, pInfo->image, pSparseMemoryRequirementCount, nullptr); - } -''', -'vkGetBufferDeviceAddress': ''' - VkDeviceAddress address = 0; - auto d_iter = buffer_map.find(device); - if (d_iter != buffer_map.end()) { - auto iter = d_iter->second.find(pInfo->buffer); - if (iter != d_iter->second.end()) { - address = iter->second.address; - } - } - return address; -''', -'vkGetBufferDeviceAddressKHR': ''' - return GetBufferDeviceAddress(device, pInfo); -''', -'vkGetBufferDeviceAddressEXT': ''' - return GetBufferDeviceAddress(device, pInfo); -''', -'vkGetDescriptorSetLayoutSizeEXT': ''' - // Need to give something non-zero - *pLayoutSizeInBytes = 4; -''', -'vkGetAccelerationStructureBuildSizesKHR': ''' - // arbitrary - pSizeInfo->accelerationStructureSize = 4; - pSizeInfo->updateScratchSize = 4; - pSizeInfo->buildScratchSize = 4; -''', -'vkGetAccelerationStructureMemoryRequirementsNV': ''' - // arbitrary - pMemoryRequirements->memoryRequirements.size = 4096; - pMemoryRequirements->memoryRequirements.alignment = 1; - pMemoryRequirements->memoryRequirements.memoryTypeBits = 0xFFFF; -''', -'vkGetAccelerationStructureDeviceAddressKHR': ''' - // arbitrary - need to be aligned to 256 bytes - return 0x262144; -''', -'vkGetVideoSessionMemoryRequirementsKHR': ''' - if (!pMemoryRequirements) { - *pMemoryRequirementsCount = 1; - } else { - // arbitrary - pMemoryRequirements[0].memoryBindIndex = 0; - pMemoryRequirements[0].memoryRequirements.size = 4096; - pMemoryRequirements[0].memoryRequirements.alignment = 1; - pMemoryRequirements[0].memoryRequirements.memoryTypeBits = 0xFFFF; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR': ''' - if (!pProperties) { - *pPropertyCount = 2; - } else { - // arbitrary - pProperties[0].MSize = 16; - pProperties[0].NSize = 16; - pProperties[0].KSize = 16; - pProperties[0].AType = VK_COMPONENT_TYPE_UINT32_KHR; - pProperties[0].BType = VK_COMPONENT_TYPE_UINT32_KHR; - pProperties[0].CType = VK_COMPONENT_TYPE_UINT32_KHR; - pProperties[0].ResultType = VK_COMPONENT_TYPE_UINT32_KHR; - pProperties[0].saturatingAccumulation = VK_FALSE; - pProperties[0].scope = VK_SCOPE_SUBGROUP_KHR; - - pProperties[1] = pProperties[0]; - pProperties[1].scope = VK_SCOPE_DEVICE_KHR; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceVideoCapabilitiesKHR': ''' - return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; -''', -'vkGetPhysicalDeviceVideoFormatPropertiesKHR': ''' - return VK_ERROR_VIDEO_PROFILE_CODEC_NOT_SUPPORTED_KHR; -''', -'vkGetDescriptorSetLayoutSupport':''' - if (pSupport) { - pSupport->supported = VK_TRUE; - } -''', -'vkGetDescriptorSetLayoutSupportKHR':''' - GetDescriptorSetLayoutSupport(device, pCreateInfo, pSupport); -''', -'vkGetRenderAreaGranularity': ''' - pGranularity->width = 1; - pGranularity->height = 1; -''', -'vkGetMemoryFdKHR': ''' - *pFd = 1; - return VK_SUCCESS; -''', -'vkGetMemoryHostPointerPropertiesEXT': ''' - pMemoryHostPointerProperties->memoryTypeBits = 1 << 5; // DEVICE_LOCAL only type - return VK_SUCCESS; -''', -'vkGetAndroidHardwareBufferPropertiesANDROID': ''' - pProperties->allocationSize = 65536; - pProperties->memoryTypeBits = 1 << 5; // DEVICE_LOCAL only type - - auto *format_prop = lvl_find_mod_in_chain<VkAndroidHardwareBufferFormatPropertiesANDROID>(pProperties->pNext); - if (format_prop) { - // Likley using this format - format_prop->format = VK_FORMAT_R8G8B8A8_UNORM; - format_prop->externalFormat = 37; - } - - auto *format_resolve_prop = lvl_find_mod_in_chain<VkAndroidHardwareBufferFormatResolvePropertiesANDROID>(pProperties->pNext); - if (format_resolve_prop) { - format_resolve_prop->colorAttachmentFormat = VK_FORMAT_R8G8B8A8_UNORM; - } - return VK_SUCCESS; -''', -'vkGetPhysicalDeviceDisplayPropertiesKHR': ''' - if (!pProperties) { - *pPropertyCount = 1; - } else { - unique_lock_t lock(global_lock); - pProperties[0].display = (VkDisplayKHR)global_unique_handle++; - display_map[physicalDevice].insert(pProperties[0].display); - } - return VK_SUCCESS; -''', -'vkRegisterDisplayEventEXT': ''' - unique_lock_t lock(global_lock); - *pFence = (VkFence)global_unique_handle++; - return VK_SUCCESS; -''', -'vkQueueSubmit': ''' - // Special way to cause DEVICE_LOST - // Picked VkExportFenceCreateInfo because needed some struct that wouldn't get cleared by validation Safe Struct - // ... TODO - It would be MUCH nicer to have a layer or other setting control when this occured - // For now this is used to allow Validation Layers test reacting to device losts - if (submitCount > 0 && pSubmits) { - auto pNext = reinterpret_cast<const VkBaseInStructure *>(pSubmits[0].pNext); - if (pNext && pNext->sType == VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO && pNext->pNext == nullptr) { - return VK_ERROR_DEVICE_LOST; - } - } - return VK_SUCCESS; -''', -'vkGetMemoryWin32HandlePropertiesKHR': ''' - pMemoryWin32HandleProperties->memoryTypeBits = 0xFFFF; - return VK_SUCCESS; -''', -'vkCreatePipelineBinariesKHR': ''' - unique_lock_t lock(global_lock); - if (pBinaries->pPipelineBinaries != nullptr) - { - for (uint32_t i = 0; i < pBinaries->pipelineBinaryCount; ++i) { - pBinaries->pPipelineBinaries[i] = (VkPipelineBinaryKHR)global_unique_handle++; - } - } - else - { - // In this case, we need to return a return count, let's set it to 3 - pBinaries->pipelineBinaryCount = 3; - } - return VK_SUCCESS; -''', -'vkGetPipelineKeyKHR': ''' - if (pPipelineKey != nullptr) - { - pPipelineKey->keySize = 16; - std::memset(pPipelineKey->key, 0x12, pPipelineKey->keySize); - } - return VK_SUCCESS; -''', -'vkGetPipelineBinaryDataKHR': ''' - static uint32_t fake_size = 64; - if (pPipelineBinaryDataSize != nullptr) - { - if (pPipelineBinaryData == nullptr) - { - *pPipelineBinaryDataSize = fake_size; - } - else - { - std::memset(pPipelineBinaryData, 0xABCD, fake_size); - } - } - return VK_SUCCESS; -''' -} - -# MockICDOutputGenerator -# Generates a mock vulkan ICD. -# This is intended to be a minimal replacement for a vulkan device in order -# to enable testing of Vulkan applications and layers -# -class MockICDOutputGenerator(BaseGenerator): - def __init__(self): - BaseGenerator.__init__(self) - - # Ignore extensions that ICDs should not implement or are not safe to report - self.ignore_exts = ['VK_EXT_validation_cache', 'VK_KHR_portability_subset'] - - # Dispatchable handles - self.dispatchable_handles = ['VkInstance','VkPhysicalDevice', 'VkDevice', 'VkCommandBuffer', 'VkQueue'] - - def generate_function_declarations(self, out): - - out.append('#include <stdint.h>\n') - out.append('#include <cstring>\n') - out.append('#include <string>\n') - out.append('#include <unordered_map>\n') - out.append('#include <vulkan/vulkan.h>\n') - out.append('\n') - out.append('namespace vkmock {\n') - out.append('// Map of instance extension name to version\n') - out.append('static const std::unordered_map<std::string, uint32_t> instance_extension_map = {\n') - for ext in [x for x in self.vk.extensions.values() if x.instance and x.name not in self.ignore_exts]: - if ext.protect: - out.append(f'#ifdef {ext.protect}\n') - out.append(f' {{"{ext.name}", {ext.specVersion}}},\n') - if ext.protect: - out.append('#endif\n') - out.append('};\n') - out.append('// Map of device extension name to version\n') - out.append('static const std::unordered_map<std::string, uint32_t> device_extension_map = {\n') - for ext in [x for x in self.vk.extensions.values() if x.device and x.name not in self.ignore_exts]: - if ext.protect: - out.append(f'#ifdef {ext.protect}\n') - out.append(f' {{"{ext.name}", {ext.specVersion}}},\n') - if ext.protect: - out.append('#endif\n') - out.append('};\n') - - current_protect = None - for name, cmd in self.vk.commands.items(): - prepend_newline = '\n' - if cmd.protect != current_protect: - if current_protect is not None: - out.append(f'#endif /* {current_protect} */\n') - prepend_newline = '' - if current_protect is not None and cmd.protect is not None: - out.append('\n') - if cmd.protect is not None: - out.append(f'#ifdef {cmd.protect}\n') - current_protect = cmd.protect - out.append(f'{prepend_newline}static {cmd.cPrototype.replace(name, name[2:])}\n') - if current_protect is not None: - out.append('#endif\n') - - # record intercepted procedures - out.append('// Map of all APIs to be intercepted by this layer\n') - out.append('static const std::unordered_map<std::string, void*> name_to_funcptr_map = {\n') - for name, cmd in self.vk.commands.items(): - if cmd.protect: - out.append(f'#ifdef {cmd.protect}\n') - out.append(f' {{"{name}", (void*){name[2:]}}},\n') - if cmd.protect: - out.append('#endif\n') - out.append('};\n') - - def generate_function_definitions(self, out): - out.append('#include "mock_icd.h"\n') - out.append('#include "function_declarations.h"\n') - out.append('namespace vkmock {\n') - - manual_functions = [ - # Include functions here to be intercepted w/ manually implemented function bodies - 'vkGetDeviceProcAddr', - 'vkGetInstanceProcAddr', - 'vkCreateDevice', - 'vkDestroyDevice', - 'vkCreateInstance', - 'vkDestroyInstance', - 'vkFreeCommandBuffers', - 'vkAllocateCommandBuffers', - 'vkDestroyCommandPool', - #'vkCreateDebugReportCallbackEXT', - #'vkDestroyDebugReportCallbackEXT', - 'vkEnumerateInstanceLayerProperties', - 'vkEnumerateInstanceVersion', - 'vkEnumerateInstanceExtensionProperties', - 'vkEnumerateDeviceLayerProperties', - 'vkEnumerateDeviceExtensionProperties', - 'vkGetPipelineKeyKHR', - 'vkGetPipelineBinaryDataKHR', - ] - - current_protect = None - for name, cmd in self.vk.commands.items(): - if cmd.protect != current_protect: - if current_protect is not None: - out.append(f'#endif /* {current_protect} */\n') - if current_protect is not None and cmd.protect is not None: - out.append('\n') - if cmd.protect is not None: - out.append(f'#ifdef {cmd.protect}\n') - current_protect = cmd.protect - - if name in manual_functions: - if name not in CUSTOM_C_INTERCEPTS: - out.append(f'static {cmd.cPrototype.replace(name, name[2:])}\n') - out.append('// TODO: Implement custom intercept body\n') - else: - out.append(f'static {cmd.cPrototype[:-1].replace(name, name[2:])}\n') - out.append(f'{{{CUSTOM_C_INTERCEPTS[name]}}}\n') - continue - - out.append(f'static {cmd.cPrototype[:-1].replace(name, name[2:])}\n') - if name in CUSTOM_C_INTERCEPTS: - out.append(f'{{{CUSTOM_C_INTERCEPTS[name]}}}\n') - continue - - # if the name w/ KHR postfix is in the CUSTOM_C_INTERCEPTS - # Call the KHR custom version instead of generating separate code - khr_name = name + "KHR" - if khr_name in CUSTOM_C_INTERCEPTS: - return_string = '' - if cmd.returnType != 'void': - return_string = 'return ' - - param_names = [] - for param in cmd.params: - param_names.append(param.name) - out.append(f'{{\n {return_string}{khr_name[2:]}({", ".join(param_names)});\n}}\n') - continue - out.append('{\n') - - # GET THE TYPE OF FUNCTION - if any(name.startswith(ftxt) for ftxt in ('vkCreate', 'vkAllocate')): - # Get last param - last_param = cmd.params[-1] - lp_txt = last_param.name - lp_len = None - if last_param.length is not None: - lp_len = last_param.length - lp_len = lp_len.replace('::', '->') - lp_type = last_param.type - handle_type = 'dispatchable' - allocator_txt = 'CreateDispObjHandle()' - if lp_type not in self.dispatchable_handles: - handle_type = 'non-' + handle_type - allocator_txt = 'global_unique_handle++' - # Need to lock in both cases - out.append(' unique_lock_t lock(global_lock);\n') - if lp_len is not None: - #print("%s last params (%s) has len %s" % (handle_type, lp_txt, lp_len)) - out.append(f' for (uint32_t i = 0; i < {lp_len}; ++i) {{\n') - out.append(f' {lp_txt}[i] = ({lp_type}){allocator_txt};\n') - out.append(' }\n') - else: - #print("Single %s last param is '%s' w/ type '%s'" % (handle_type, lp_txt, lp_type)) - if 'AllocateMemory' in name: - # Store allocation size in case it's mapped - out.append(' allocated_memory_size_map[(VkDeviceMemory)global_unique_handle] = pAllocateInfo->allocationSize;\n') - out.append(f' *{lp_txt} = ({lp_type}){allocator_txt};\n') - elif True in [ftxt in name for ftxt in ['Destroy', 'Free']]: - out.append('//Destroy object\n') - if 'FreeMemory' in name: - # If the memory is mapped, unmap it - out.append(' UnmapMemory(device, memory);\n') - # Remove from allocation map - out.append(' unique_lock_t lock(global_lock);\n') - out.append(' allocated_memory_size_map.erase(memory);\n') - else: - out.append('//Not a CREATE or DESTROY function\n') - - # Return result variable, if any. - if cmd.returnType != 'void': - if name == 'vkGetEventStatus': - out.append(' return VK_EVENT_SET;\n') - else: - out.append(' return VK_SUCCESS;\n') - out.append('}\n') - if current_protect is not None: - out.append('#endif\n') - - def generate(self): - out = [] - out.append('''/* -** Copyright (c) 2015-2025 The Khronos Group Inc. -** -** Licensed under the Apache License, Version 2.0 (the "License"); -** you may not use this file except in compliance with the License. -** You may obtain a copy of the License at -** -** http://www.apache.org/licenses/LICENSE-2.0 -** -** Unless required by applicable law or agreed to in writing, software -** distributed under the License is distributed on an "AS IS" BASIS, -** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -** See the License for the specific language governing permissions and -** limitations under the License. -*/ - -/* -** This header is generated from the Khronos Vulkan XML API Registry. -** -*/ - -#pragma once -''') - - if self.filename == "function_declarations.h": - self.generate_function_declarations(out) - else: - self.generate_function_definitions(out) - - out.append('\n') - out.append('} // namespace vkmock\n') - out.append('\n') - self.write(''.join(out)) diff --git a/tools/Vulkan-Tools/scripts/generators/vulkan_tools_helper_file_generator.py b/tools/Vulkan-Tools/scripts/generators/vulkan_tools_helper_file_generator.py deleted file mode 100644 index baf3e816..00000000 --- a/tools/Vulkan-Tools/scripts/generators/vulkan_tools_helper_file_generator.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/python3 -i -# -# Copyright (c) 2015-2021 The Khronos Group Inc. -# Copyright (c) 2015-2021 Valve Corporation -# Copyright (c) 2015-2021 LunarG, Inc. -# Copyright (c) 2015-2021 Google Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Author: Mark Lobodzinski <mark@lunarg.com> -# Author: Tobin Ehlis <tobine@google.com> -# Author: John Zulauf <jzulauf@lunarg.com> - -from base_generator import BaseGenerator - -# HelperFileOutputGenerator - subclass of OutputGenerator. Outputs Vulkan helper files -class HelperFileOutputGenerator(BaseGenerator): - def __init__(self): - BaseGenerator.__init__(self) - - - def generate(self): - out = [] - - # File Comment - out.append('// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n') - out.append('// See vulkan_tools_helper_file_generator.py for modifications\n') - - # Copyright Notice - out.append(''' - -/*************************************************************************** - * - * Copyright (c) 2015-2017 The Khronos Group Inc. - * Copyright (c) 2015-2017 Valve Corporation - * Copyright (c) 2015-2017 LunarG, Inc. - * Copyright (c) 2015-2017 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Mark Lobodzinski <mark@lunarg.com> - * Author: Courtney Goeltzenleuchter <courtneygo@google.com> - * Author: Tobin Ehlis <tobine@google.com> - * Author: Chris Forbes <chrisforbes@google.com> - * Author: John Zulauf<jzulauf@lunarg.com> - * - ****************************************************************************/ -''') - - # Generate header - out.append(''' -#pragma once -#include <vulkan/vulkan.h> - -// These empty generic templates are specialized for each type with sType -// members and for each sType -- providing a two way map between structure -// types and sTypes - -template <VkStructureType id> struct LvlSTypeMap {}; -template <typename T> struct LvlTypeMap {}; - -''') - - # Generate the specializations for each type and stype - for struct in self.vk.structs.values(): - if struct.sType is None: - continue - - if struct.protect is not None: - out.append(f'#ifdef {struct.protect}\n') - - out.append(f'// Map type {struct.name} to id {struct.sType}\n') - out.append(f'template <> struct LvlTypeMap<{struct.name}> {{\n') - out.append(f' static const VkStructureType kSType = {struct.sType};\n') - out.append('};\n\n') - - - out.append(f'template <> struct LvlSTypeMap<{struct.sType}> {{\n') - out.append(f' typedef {struct.name} Type;\n') - out.append('};\n\n') - - if struct.protect is not None: - out.append(f'#endif // {struct.protect}\n') - - # Define the utilities (here so any renaming stays consistent), if this grows large, refactor to a fixed .h file - - out.append('''// Header "base class" for pNext chain traversal -struct LvlGenericHeader { - VkStructureType sType; - const LvlGenericHeader *pNext; -}; -struct LvlGenericModHeader { - VkStructureType sType; - LvlGenericModHeader *pNext; -}; - -// Find an entry of the given type in the pNext chain -template <typename T> const T *lvl_find_in_chain(const void *next) { - const LvlGenericHeader *current = reinterpret_cast<const LvlGenericHeader *>(next); - const T *found = nullptr; - while (current) { - if (LvlTypeMap<T>::kSType == current->sType) { - found = reinterpret_cast<const T*>(current); - current = nullptr; - } else { - current = current->pNext; - } - } - return found; -} -// Find an entry of the given type in the pNext chain -template <typename T> T *lvl_find_mod_in_chain(void *next) { - LvlGenericModHeader *current = reinterpret_cast<LvlGenericModHeader *>(next); - T *found = nullptr; - while (current) { - if (LvlTypeMap<T>::kSType == current->sType) { - found = reinterpret_cast<T*>(current); - current = nullptr; - } else { - current = current->pNext; - } - } - return found; -} - -// Init the header of an sType struct with pNext -template <typename T> T lvl_init_struct(void *p_next) { - T out = {}; - out.sType = LvlTypeMap<T>::kSType; - out.pNext = p_next; - return out; -} - -// Init the header of an sType struct -template <typename T> T lvl_init_struct() { - T out = {}; - out.sType = LvlTypeMap<T>::kSType; - return out; -} -''') - - self.write(''.join(out)) - diff --git a/tools/Vulkan-Tools/scripts/generators/vulkaninfo_generator.py b/tools/Vulkan-Tools/scripts/generators/vulkaninfo_generator.py deleted file mode 100644 index 472459ac..00000000 --- a/tools/Vulkan-Tools/scripts/generators/vulkaninfo_generator.py +++ /dev/null @@ -1,1165 +0,0 @@ -#!/usr/bin/python3 -# -# Copyright (c) 2019-2026 Valve Corporation -# Copyright (c) 2019-2026 LunarG, Inc. -# Copyright (c) 2019-2022 Google Inc. -# Copyright (c) 2023-2024 RasterGrid Kft. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Author: Charles Giessen <charles@lunarg.com> - -from base_generator import BaseGenerator - -from collections import OrderedDict - -LICENSE_HEADER = ''' -/* - * Copyright (c) 2019-2026 The Khronos Group Inc. - * Copyright (c) 2019-2026 Valve Corporation - * Copyright (c) 2019-2026 LunarG, Inc. - * Copyright (c) 2023-2024 RasterGrid Kft. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - * Author: Charles Giessen <charles@lunarg.com> - * - */ - -/* - * This file is generated from the Khronos Vulkan XML API Registry. - */ -''' - -CUSTOM_FORMATTERS = r''' -template <typename T> -std::string to_hex_str(const T i) { - std::stringstream stream; - stream << "0x" << std::setfill('0') << std::setw(sizeof(T)) << std::hex << i; - return stream.str(); -} - -template <typename T> -std::string to_hex_str(Printer &p, const T i) { - if (p.Type() == OutputType::json) - return std::to_string(i); - else if (p.Type() == OutputType::vkconfig_output) - return std::string("\"") + to_hex_str(i) + std::string("\""); - else - return to_hex_str(i); -} - -''' - - -# used in the .cpp code -STRUCTURES_TO_GEN = ['VkExtent3D', 'VkExtent2D', 'VkPhysicalDeviceLimits', 'VkPhysicalDeviceFeatures', 'VkPhysicalDeviceSparseProperties', - 'VkSurfaceCapabilitiesKHR', 'VkSurfaceFormatKHR', 'VkLayerProperties', 'VkPhysicalDeviceToolProperties', 'VkFormatProperties', - 'VkSurfacePresentScalingCapabilitiesKHR', 'VkSurfacePresentModeCompatibilityKHR', 'VkPhysicalDeviceHostImageCopyProperties', - 'VkVideoProfileInfoKHR', 'VkVideoCapabilitiesKHR', 'VkVideoFormatPropertiesKHR', 'VkCooperativeMatrixPropertiesKHR', - 'VkPhysicalDeviceFragmentShadingRateKHR', 'VkMultisamplePropertiesEXT', - 'VkDisplayPropertiesKHR', 'VkDisplayPlanePropertiesKHR', 'VkDisplayPlaneCapabilitiesKHR', 'VkDisplayModePropertiesKHR', - 'VkDisplayModeParametersKHR'] - -ENUMS_TO_GEN = ['VkResult', 'VkFormat', 'VkPresentModeKHR', - 'VkPhysicalDeviceType', 'VkImageTiling', 'VkTimeDomainKHR'] -FLAGS_TO_GEN = ['VkSurfaceTransformFlagsKHR', 'VkCompositeAlphaFlagsKHR', 'VkSurfaceCounterFlagsEXT', 'VkQueueFlags', - 'VkDeviceGroupPresentModeFlagsKHR', 'VkFormatFeatureFlags', 'VkFormatFeatureFlags2', 'VkMemoryPropertyFlags', 'VkMemoryHeapFlags'] -FLAG_STRINGS_TO_GEN = ['VkQueueFlags'] - -STRUCT_SHORT_VERSIONS_TO_GEN = ['VkExtent3D', 'VkExtent2D'] - -STRUCT_COMPARISONS_TO_GEN = ['VkSurfaceFormatKHR', 'VkSurfaceFormat2KHR', 'VkSurfaceCapabilitiesKHR', - 'VkSurfaceCapabilities2KHR', 'VkSurfaceCapabilities2EXT'] -# don't generate these structures -STRUCT_BLACKLIST = ['VkVideoProfileListInfoKHR', 'VkDrmFormatModifierPropertiesListEXT', 'VkDrmFormatModifierPropertiesEXT', 'VkDrmFormatModifierPropertiesList2EXT'] -# These structures are only used in version 1.1, otherwise they are included in the promoted structs -STRUCT_1_1_LIST = ['VkPhysicalDeviceProtectedMemoryFeatures', 'VkPhysicalDeviceShaderDrawParametersFeatures', 'VkPhysicalDeviceSubgroupProperties', 'VkPhysicalDeviceProtectedMemoryProperties'] - -# generate these structures such that they only print when not in json mode (as json wants them separate) -PORTABILITY_STRUCTS = ['VkPhysicalDevicePortabilitySubsetFeaturesKHR', 'VkPhysicalDevicePortabilitySubsetPropertiesKHR'] - -# iostream or custom outputter handles these types -PREDEFINED_TYPES = ['char', 'VkBool32', 'uint32_t', 'uint8_t', 'int32_t', - 'float', 'uint64_t', 'size_t', 'VkDeviceSize', 'int64_t'] - -NAMES_TO_IGNORE = ['sType', 'pNext', 'displayMode', 'display', 'currentDisplay'] - -EXTENSION_TYPE_INSTANCE = 'instance' -EXTENSION_TYPE_DEVICE = 'device' -EXTENSION_TYPE_BOTH = 'both' - -# Types that need pNext Chains built. 'extends' is the xml tag used in the structextends member. 'type' can be device, instance, or both -EXTENSION_CATEGORIES = OrderedDict(( - ('phys_device_props2', - {'extends': 'VkPhysicalDeviceProperties2', - 'type': EXTENSION_TYPE_BOTH, - 'print_iterator': True, - 'can_show_promoted_structs': True, - 'ignore_vendor_exclusion': False}), - ('phys_device_mem_props2', - {'extends': 'VkPhysicalDeviceMemoryProperties2', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': False, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': False}), - ('phys_device_features2', - {'extends': 'VkPhysicalDeviceFeatures2', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': True, - 'can_show_promoted_structs': True, - 'ignore_vendor_exclusion': False}), - ('surface_capabilities2', - {'extends': 'VkSurfaceCapabilities2KHR', - 'type': EXTENSION_TYPE_BOTH, - 'print_iterator': True, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': False, - 'exclude': ['VkSurfacePresentScalingCapabilitiesKHR', 'VkSurfacePresentModeCompatibilityKHR']}), - ('format_properties2', - {'extends': 'VkFormatProperties2', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': True, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': False}), - ('queue_properties2', - {'extends': 'VkQueueFamilyProperties2', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': True, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': False}), - ('video_profile_info', - {'extends': 'VkVideoProfileInfoKHR', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': True, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': True}), - ('video_capabilities', - {'extends': 'VkVideoCapabilitiesKHR', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': True, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': True,}), - ('video_format_properties', - {'extends': 'VkVideoFormatPropertiesKHR', - 'type': EXTENSION_TYPE_DEVICE, - 'print_iterator': True, - 'can_show_promoted_structs': False, - 'ignore_vendor_exclusion': True}) - )) -class VulkanInfoGenerator(BaseGenerator): - def __init__(self): - BaseGenerator.__init__(self) - self.format_ranges = [] - - def generate(self): - self.findFormatRanges() - - # gather the types that are needed to generate - types_to_gen = set() - types_to_gen.update(ENUMS_TO_GEN) - types_to_gen.update(FLAGS_TO_GEN) - types_to_gen.update(STRUCTURES_TO_GEN) - - extension_types = {} - for key, ext_info in EXTENSION_CATEGORIES.items(): - extension_types[key] = [] - - for extended_struct in self.vk.structs[ext_info.get('extends')].extendedBy: - if ext_info.get('exclude') is not None and extended_struct in ext_info.get('exclude'): - continue - elif ext_info.get('ignore_vendor_exclusion'): - extension_types[key].append(extended_struct) - continue - vendor_tags = [] - for extension in self.vk.structs[extended_struct].extensions: - vendor_tags.append(extension.split('_')[1]) - if len(vendor_tags) == 0 or 'KHR' in vendor_tags or 'EXT' in vendor_tags: - extension_types[key].append(extended_struct) - extension_types[key] = sorted(extension_types[key]) - types_to_gen.update(extension_types[key]) - - # find all the types that need - types_to_gen.update(self.findAllTypesToGen(types_to_gen)) - - types_to_gen = sorted(types_to_gen) - - comparison_types_to_gen = set() - comparison_types_to_gen.update(STRUCT_COMPARISONS_TO_GEN) - comparison_types_to_gen.update(self.findAllTypesToGen(comparison_types_to_gen)) - comparison_types_to_gen = sorted(comparison_types_to_gen) - - - # print the types gathered - out = [] - out.append(LICENSE_HEADER + '\n') - out.append('#include "vulkaninfo.h"\n') - out.append('#include "outputprinter.h"\n') - out.append(CUSTOM_FORMATTERS) - - out.extend(self.genVideoEnums()) - - for enum in (e for e in types_to_gen if e in self.vk.enums): - out.extend(self.PrintEnumToString(self.vk.enums[enum])) - out.extend(self.PrintEnum(self.vk.enums[enum])) - - # Need to go through all flags to find if they or their associated bitmask needs printing - # This is because both bitmask and flag types are generated in PrintBitMask - for name in (x for x in sorted(self.vk.flags.keys()) if x in types_to_gen or self.vk.flags[x].bitmaskName in types_to_gen): - bitmask = self.vk.bitmasks[self.vk.flags[name].bitmaskName] - - out.extend(self.PrintBitMask(bitmask, bitmask.flagName)) - - if bitmask.flagName in FLAG_STRINGS_TO_GEN: - out.extend(self.PrintBitMaskToString(bitmask, bitmask.flagName)) - # make sure dump functions for nested structures are declared before use - for s in (x for x in types_to_gen if x in self.vk.structs and x not in STRUCT_BLACKLIST): - out.extend(self.PrintStructure(self.vk.structs[s], True)) - for s in (x for x in types_to_gen if x in self.vk.structs and x not in STRUCT_BLACKLIST): - out.extend(self.PrintStructure(self.vk.structs[s], False)) - - for key, value in EXTENSION_CATEGORIES.items(): - out.extend(self.PrintChainStruct(key, extension_types[key], value)) - - for s in (x for x in comparison_types_to_gen if x in self.vk.structs): - out.extend(self.PrintStructComparisonForwardDecl(self.vk.structs[s])) - for s in (x for x in comparison_types_to_gen if x in self.vk.structs): - out.extend(self.PrintStructComparison(self.vk.structs[s])) - for s in (x for x in types_to_gen if x in self.vk.structs and x in STRUCT_SHORT_VERSIONS_TO_GEN): - out.extend(self.PrintStructShort(self.vk.structs[s])) - - out.append('auto format_ranges = std::array{\n') - for f in self.format_ranges: - out.append(f' FormatRange{{{f.minimum_instance_version}, {self.vk.extensions[f.extensions[0]].nameString if len(f.extensions) > 0 else "nullptr"}, ') - out.append(f'static_cast<VkFormat>({f.first_format}), static_cast<VkFormat>({f.last_format})}},\n') - out.append('};\n') - - out.extend(self.genVideoProfileUtils()) - - self.write(''.join(out)) - - - def genVideoEnums(self): - out = [] - for enum in self.vk.videoStd.enums.values(): - out.append(f'std::string {enum.name}String({enum.name} value) {{\n') - out.append(' switch (value) {\n') - for field in enum.fields: - # Ignore aliases - if field.value is not None: - out.append(f' case {field.name}: return "{field.name}";\n') - out.append(f' default: return std::string("UNKNOWN_{enum.name}_value") + std::to_string(value);\n') - out.append(' }\n}\n') - out.append(f'void Dump{enum.name}(Printer &p, std::string name, {enum.name} value) {{\n') - out.append(f' p.PrintKeyString(name, {enum.name}String(value));\n}}\n') - return out - - - # Utility to get the extension / version precondition of a list of type names - def GetTypesPrecondition(self, typelist, indent): - indent = ' ' * indent - out = [] - extEnables = [] - for typename in typelist: - extEnables.extend(self.vk.structs[typename].extensions) - - version = None - for typename in typelist: - for v in self.vk.versions.values(): - if typename in v.name: - if version is not None and (v.major > version.major or (v.major == version.major and v.minor > version.minor)): - version = v - - - has_version = version is not None - has_extNameStr = len(extEnables) > 0 - if has_version or has_extNameStr: - out.append(f'{indent}if (') - has_printed_condition = False - if has_extNameStr: - for ext in extEnables: - if has_printed_condition: - out.append(f'\n{indent} || ') - else: - has_printed_condition = True - if has_version: - out.append('(') - if self.vk.extensions[ext].device: - out.append(f'gpu.CheckPhysicalDeviceExtensionIncluded({self.vk.extensions[ext].nameString})') - else: - assert False, 'Should never get here' - if has_version: - if has_printed_condition: - out.append(f'\n{indent} || (gpu.api_version >= {version.nameApi})') - else: - out.append(f'gpu.api_version >= {version.nameApi}') - out.append(') {\n') - else: - out = f'{indent}{{\n' - return out - - # Utility to construct a capability prerequisite condition evaluation expression - def GetRequiredCapsCondition(self, structName, memberName, memberRef, value): - condition = '' - requiredCapStructDef = self.vk.structs[structName] - for member in requiredCapStructDef.members: - if member.name == memberName: - if member.type in self.vk.flags: - # Check that the flags contain all the required values - def genExpressionFromValue(value): - return value if value == "" else f"({memberRef} & {value}) != 0" - - for char in condition: - if char in ['(', ')', '+', ',']: - condition += genExpressionFromValue(value) - value = "" - if char == '+': - # '+' means AND - condition += ' && ' - elif char == ',': - # ',' means OR - condition += ' || ' - else: - condition += char - else: - value += char - condition += genExpressionFromValue(value) - else: - condition = f'{memberRef} == {value}' - if condition == '': - return 'true' - else: - return f'({condition})' - - def genVideoProfileUtils(self): - out = [] - - # Generate video format properties comparator - out.append(''' -bool is_video_format_same(const VkVideoFormatPropertiesKHR &format_a, const VkVideoFormatPropertiesKHR &format_b) { - auto a = reinterpret_cast<const VkBaseInStructure*>(&format_a); - auto b = reinterpret_cast<const VkBaseInStructure*>(&format_b); - bool same = true; - while (same && a != nullptr && b != nullptr) { - if (a->sType != b->sType) { - // Structure type mismatch (extension structures are expected to be chained in the same order) - same = false; - } else { - switch (a->sType) {''') - - if 'VkVideoFormatPropertiesKHR' in self.registry.validextensionstructs: - for extstruct in ['VkVideoFormatPropertiesKHR'] + self.registry.validextensionstructs['VkVideoFormatPropertiesKHR']: - extstructDef = self.vk.structs[extstruct] - out.append(f''' - case {extstructDef.sType}: - same = same && memcmp(reinterpret_cast<const char*>(a) + sizeof(VkBaseInStructure), - reinterpret_cast<const char*>(b) + sizeof(VkBaseInStructure), - sizeof({extstruct}) - sizeof(VkBaseInStructure)) == 0; - break;''') - - out.append(''' - default: - // Unexpected structure type - same = false; - break; - } - } - a = a->pNext; - b = b->pNext; - } - return same; -} -''') - - # Generate video profile info capture utilities - out.append(''' -std::vector<std::unique_ptr<AppVideoProfile>> enumerate_supported_video_profiles(AppGpu &gpu) { - std::vector<std::unique_ptr<AppVideoProfile>> result{}; - - struct ChromaSubsamplingInfo { - VkVideoChromaSubsamplingFlagsKHR value; - const char* name; - }; - const std::vector<ChromaSubsamplingInfo> chroma_subsampling_list = { - {VK_VIDEO_CHROMA_SUBSAMPLING_420_BIT_KHR, "4:2:0"}, - {VK_VIDEO_CHROMA_SUBSAMPLING_422_BIT_KHR, "4:2:2"}, - {VK_VIDEO_CHROMA_SUBSAMPLING_444_BIT_KHR, "4:4:4"}, - {VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR, "monochrome"} - }; - - struct BitDepthInfo { - VkVideoComponentBitDepthFlagsKHR value; - const char* name; - }; - const std::vector<BitDepthInfo> bit_depth_list = { - {VK_VIDEO_COMPONENT_BIT_DEPTH_8_BIT_KHR, "8"}, - {VK_VIDEO_COMPONENT_BIT_DEPTH_10_BIT_KHR, "10"}, - {VK_VIDEO_COMPONENT_BIT_DEPTH_12_BIT_KHR, "12"} - }; - - auto find_caps_struct = [](const VkVideoCapabilitiesKHR &capabilities, VkStructureType stype) -> const VkBaseInStructure* { - auto p = reinterpret_cast<const VkBaseInStructure*>(&capabilities); - while (p != nullptr) { - if (p->sType == stype) { - return p; - } - p = p->pNext; - } - return nullptr; - }; - - auto base_format = [] - (const ChromaSubsamplingInfo &chroma_subsampling, const BitDepthInfo &luma_bit_depth, const BitDepthInfo &chroma_bit_depth) { - std::string result{}; - result += " ("; - result += chroma_subsampling.name; - result += " "; - result += luma_bit_depth.name; - if (luma_bit_depth.value != chroma_bit_depth.value) { - result += ":"; - result += chroma_bit_depth.name; - } - result += "-bit)"; - return result; - }; - - auto add_profile = [&]( - const std::string &name, - const VkVideoProfileInfoKHR &profile_info, - AppVideoProfile::CreateProfileInfoChainCb create_profile_info_chain, - AppVideoProfile::CreateCapabilitiesChainCb create_capabilities_chain, - const AppVideoProfile::CreateFormatPropertiesChainCbList &create_format_properties_chain_list, - AppVideoProfile::InitProfileCb init_profile) { - auto profile = std::make_unique<AppVideoProfile>(gpu, gpu.phys_device, - name, profile_info, - create_profile_info_chain, - create_capabilities_chain, - create_format_properties_chain_list, - init_profile); - if (profile->supported) { - result.push_back(std::move(profile)); - } - }; -''') - - # Generate individual video profiles from the video codec metadata - for videoCodec in self.vk.videoCodecs.values(): - # Ignore video codec categories - if videoCodec.value is None: - continue - - out.append('\n') - out.extend(self.GetTypesPrecondition(videoCodec.profiles.keys(), 4)) - out.append(f'{" " * 8}const std::string codec_name = "{videoCodec.name}";\n') - - out.append(''' - for (auto chroma_subsampling : chroma_subsampling_list) { - for (auto luma_bit_depth : bit_depth_list) { - for (auto chroma_bit_depth : bit_depth_list) { - if (chroma_subsampling.value == VK_VIDEO_CHROMA_SUBSAMPLING_MONOCHROME_BIT_KHR && luma_bit_depth.value != chroma_bit_depth.value) { - // Ignore the chroma bit depth dimension for monochrome - continue; - } - - std::string profile_base_name = codec_name + base_format(chroma_subsampling, luma_bit_depth, chroma_bit_depth); -''') - - # Setup video profile info - out.append(f'{" " * 20}VkVideoProfileInfoKHR profile_info{{\n') - out.append(f'{" " * 20} VK_STRUCTURE_TYPE_VIDEO_PROFILE_INFO_KHR,\n') - out.append(f'{" " * 20} nullptr,\n') - out.append(f'{" " * 20} {videoCodec.value},\n') - out.append(f'{" " * 20} chroma_subsampling.value,\n') - out.append(f'{" " * 20} luma_bit_depth.value,\n') - out.append(f'{" " * 20} chroma_bit_depth.value\n') - out.append(f'{" " * 20}}};\n\n') - - # Setup video profile info chain creation callback - out.append(f'{" " * 20}auto create_profile_info_chain = [&](const void **ppnext) -> std::unique_ptr<video_profile_info_chain> {{\n') - out.append(f'{" " * 20} auto profile_info_chain = std::make_unique<video_profile_info_chain>();\n') - for profileStruct in videoCodec.profiles: - structDef = self.vk.structs[profileStruct] - out.append(self.AddGuardHeader(structDef)) - out.append(f'{" " * 24}if (profile_info_chain != nullptr) {{\n') - out.append(f'{" " * 28}profile_info_chain->{profileStruct[2:]}.sType = {structDef.sType};\n') - out.append(f'{" " * 28}profile_info_chain->{profileStruct[2:]}.pNext = nullptr;\n') - out.append(f'{" " * 28}*ppnext = &profile_info_chain->{profileStruct[2:]};\n') - out.append(f'{" " * 28}ppnext = &profile_info_chain->{profileStruct[2:]}.pNext;\n') - out.append(f'{" " * 24}}}\n') - if structDef.protect: - out.append(f'#else\n{" " * 20}profile_info_chain = nullptr;\n') - out.append(self.AddGuardFooter(structDef)) - out.append(f'{" " * 20} return profile_info_chain;\n') - out.append(f'{" " * 20}}};\n\n') - - # Setup video capabilities chain creation callback - out.append(f'{" " * 20}auto create_capabilities_chain = [&](void **ppnext) -> std::unique_ptr<video_capabilities_chain> {{\n') - out.append(f'{" " * 20} auto capabilities_chain = std::make_unique<video_capabilities_chain>();\n') - for capabilities in videoCodec.capabilities: - structDef = self.vk.structs[capabilities] - out.append(self.AddGuardHeader(structDef)) - out.append(f'{" " * 24}if (capabilities_chain != nullptr) {{\n') - out.extend(self.GetTypesPrecondition([capabilities], 28)) - out.append(f'{" " * 32}capabilities_chain->{capabilities[2:]}.sType = {structDef.sType};\n') - out.append(f'{" " * 32}capabilities_chain->{capabilities[2:]}.pNext = nullptr;\n') - out.append(f'{" " * 32}*ppnext = &capabilities_chain->{capabilities[2:]};\n') - out.append(f'{" " * 32}ppnext = &capabilities_chain->{capabilities[2:]}.pNext;\n') - out.append(f'{" " * 28}}}\n') - out.append(f'{" " * 24}}}\n') - out.append(self.AddGuardFooter(structDef)) - out.append(f'{" " * 20} return capabilities_chain;\n') - out.append(f'{" " * 20}}};\n\n') - - # Setup video format properties chain creation callbacks - out.append(f'{" " * 20}const AppVideoProfile::CreateFormatPropertiesChainCbList create_format_properties_chain_list = {{\n') - for format in videoCodec.formats.values(): - out.append(f'{" " * 24}AppVideoProfile::CreateFormatPropertiesChainCb {{\n') - out.append(f'{" " * 28}"{format.name}",\n') - out.append(f'{" " * 28}{format.usage.replace("+", " | ")},\n') - - # Callback to check required capabilities - out.append(f'{" " * 28}[&](const VkVideoCapabilitiesKHR &capabilities) -> bool {{\n') - out.append(f'{" " * 28} bool supported = true;\n') - for requiredCap in format.requiredCaps: - structDef = self.vk.structs[requiredCap.struct] - out.append(self.AddGuardHeader(structDef)) - out.extend(self.GetTypesPrecondition([requiredCap.struct], 32)) - out.append(f'{" " * 32} auto caps = reinterpret_cast<const {requiredCap.struct}*>(find_caps_struct(capabilities, {structDef.sType}));\n') - out.append(f'{" " * 32} if (caps != nullptr) {{\n') - out.append(f'{" " * 32} supported = supported && {self.GetRequiredCapsCondition(requiredCap.struct, requiredCap.member, f"caps->{requiredCap.member}", requiredCap.value)};\n') - out.append(f'{" " * 32} }} else {{\n') - out.append(f'{" " * 32} supported = false;\n') - out.append(f'{" " * 32} }}\n') - out.append(f'{" " * 32}}} else {{\n') - out.append(f'{" " * 32} supported = false;\n') - out.append(f'{" " * 32}}}\n') - if structDef.protect: - out.append(f'#else\n{" " * 32}supported = false;\n') - out.append(self.AddGuardFooter(structDef)) - out.append(f'{" " * 28} return supported;\n') - out.append(f'{" " * 28}}},\n') - - # Callback to create video format properties chain - out.append(f'{" " * 28}[&](void **ppnext) -> std::unique_ptr<video_format_properties_chain> {{\n') - out.append(f'{" " * 28} auto format_properties_chain = std::make_unique<video_format_properties_chain>();\n') - for formatProps in format.properties: - structDef = self.vk.structs[formatProps] - out.append(self.AddGuardHeader(structDef)) - out.append(f'{" " * 32}if (format_properties_chain != nullptr) {{\n') - out.extend(self.GetTypesPrecondition([formatProps], 36)) - out.append(f'{" " * 40}format_properties_chain->{formatProps[2:]}.sType = {structDef.sType};\n') - out.append(f'{" " * 40}format_properties_chain->{formatProps[2:]}.pNext = nullptr;\n') - out.append(f'{" " * 40}*ppnext = &format_properties_chain->{formatProps[2:]};\n') - out.append(f'{" " * 40}ppnext = &format_properties_chain->{formatProps[2:]}.pNext;\n') - out.append(f'{" " * 36}}}\n') - out.append(f'{" " * 32}}}\n') - out.append(self.AddGuardFooter(structDef)) - out.append(f'{" " * 28} return format_properties_chain;\n') - out.append(f'{" " * 28}}},\n') - - out.append(f'{" " * 24}}},\n') - out.append(f'{" " * 20}}};\n\n') - - # Permute profiles for each profile struct member value - profiles = {'': []} - for profileStruct in videoCodec.profiles.values(): - for profileStructMember in profileStruct.members.values(): - newProfiles = {} - for profileStructMemberValue, profileStructMemberName in profileStructMember.values.items(): - for profileName, profile in profiles.items(): - # Only add video profile name suffix to the full descriptive name if not empty to avoid excess whitespace - newProfileName = profileName if profileStructMemberName == '' else f'{profileName} {profileStructMemberName}' - newProfiles[newProfileName] = profile + [{ - "struct": profileStruct.name, - "member": profileStructMember.name, - "value": profileStructMemberValue - }] - profiles = newProfiles - - for profileName, profile in profiles.items(): - out.append(f'{" " * 20}add_profile(profile_base_name + "{profileName}", profile_info,\n') - out.append(f'{" " * 20} create_profile_info_chain, create_capabilities_chain,\n') - out.append(f'{" " * 20} create_format_properties_chain_list,\n') - out.append(f'{" " * 20} [](AppVideoProfile& profile) {{\n') - for profileStruct in videoCodec.profiles: - structDef = self.vk.structs[profileStruct] - out.append(self.AddGuardHeader(structDef)) - for elem in profile: - if elem['struct'] == profileStruct: - out.append(f'{" " * 24}profile.profile_info_chain->{elem["struct"][2:]}.{elem["member"]} = {elem["value"]};\n') - out.append(self.AddGuardFooter(structDef)) - out.append(f'{" " * 20}}});\n') - - out.append(f'{" " * 16}}}\n') - out.append(f'{" " * 12}}}\n') - out.append(f'{" " * 8}}}\n') - out.append(f'{" " * 4}}}\n') - - out.append(' return result;\n') - out.append('}\n\n') - - return out - - - # finds all the ranges of formats from core (1.0), core versions (1.1+), and extensions - def findFormatRanges(self): - min_val = 2**32 - prev_field = None - max_val = 0 - for f in self.vk.enums['VkFormat'].fields: - if f.value is None: - continue - if prev_field is not None and f.value != prev_field.value + 1: - for ext in prev_field.extensions: - if self.vk.extensions[ext].promotedTo is not None: - self.format_ranges.append(VulkanFormatRange(self.vk.extensions[ext].promotedTo.replace("VK_", "VK_API_"), [], min_val, max_val)) - break - # only bother with the first extension - self.format_ranges.append(VulkanFormatRange(0, prev_field.extensions, min_val, max_val)) - min_val = 2**32 - max_val = 0 - min_val = min(min_val, f.value) - max_val = max(max_val, f.value) - - prev_field = f - - for ext in prev_field.extensions: - if self.vk.extensions[ext].promotedTo is not None: - self.format_ranges.append(VulkanFormatRange(self.vk.extensions[ext].promotedTo.replace("VK_", "VK_API_"), [], min_val, max_val)) - break - - self.format_ranges.append(VulkanFormatRange(0, prev_field.extensions, min_val, max_val)) - - def findAllTypesToGen(self, initial_type_set): - out_set = set() - current_set = initial_type_set - while len(current_set) > 0: - out_set.update(current_set) - next_set = set() - - for current_item in current_set: - if current_item in self.vk.structs: - for member in self.vk.structs[current_item].members: - if member.type not in out_set and member.name not in NAMES_TO_IGNORE: - next_set.add(member.type) - - current_set = next_set - return out_set - - def AddGuardHeader(self,obj): - if obj is not None and obj.protect is not None: - return f'#ifdef {obj.protect}\n' - else: - return '' - - - def AddGuardFooter(self,obj): - if obj is not None and obj.protect is not None: - return f'#endif // {obj.protect}\n' - else: - return '' - - def PrintEnumToString(self,enum): - out = [] - out.append(self.AddGuardHeader(enum)) - out.append(f'std::string {enum.name}String({enum.name} value) {{\n') - out.append(' switch (value) {\n') - for v in enum.fields: - out.append(f' case ({v.name}): return "{v.name[3:]}";\n') - out.append(f' default: return std::string("UNKNOWN_{enum.name}_value") + std::to_string(value);\n') - out.append(' }\n}\n') - out.append(self.AddGuardFooter(enum)) - return out - - - def PrintEnum(self,enum): - out = [] - out.append(self.AddGuardHeader(enum)) - out.append(f'''void Dump{enum.name}(Printer &p, std::string name, {enum.name} value) {{ - if (p.Type() == OutputType::json) - p.PrintKeyString(name, std::string("VK_") + {enum.name}String(value)); - else - p.PrintKeyString(name, {enum.name}String(value)); -}} -''') - out.append(self.AddGuardFooter(enum)) - return out - - - def PrintGetFlagStrings(self,name, bitmask): - out = [] - out.append(f'std::vector<const char *> {name}GetStrings({name} value) {{\n') - out.append(' std::vector<const char *> strings;\n') - # If a bitmask contains a field whose value is zero, we want to support printing the correct bitflag - # Otherwise, use "None" for when there are not bits set in the bitmask - if bitmask.flags[0].value != 0: - out.append(' if (value == 0) { strings.push_back("None"); return strings; }\n') - else: - out.append(f' if (value == 0) {{ strings.push_back("{bitmask.flags[0].name[3:]}"); return strings; }}\n') - for v in bitmask.flags: - # only check single-bit flags - if v.value != 0 and (v.value & (v.value - 1)) == 0: - out.append(f' if ({v.name} & value) strings.push_back("{v.name[3:]}");\n') - out.append(' return strings;\n}\n') - return out - - - def PrintFlags(self, bitmask, name): - out = [] - out.append(f'void Dump{name}(Printer &p, std::string name, {name} value) {{\n') - out.append(f''' if (static_cast<{bitmask.name}>(value) == 0) {{ - ArrayWrapper arr(p, name, 0); - if (p.Type() != OutputType::json && p.Type() != OutputType::vkconfig_output) - p.SetAsType().PrintString("None"); - return; - }} - auto strings = {bitmask.name}GetStrings(static_cast<{bitmask.name}>(value)); - ArrayWrapper arr(p, name, strings.size()); - for(auto& str : strings){{ - if (p.Type() == OutputType::json) - p.SetAsType().PrintString(std::string("VK_") + str); - else - p.SetAsType().PrintString(str); - }} -}} -''') - return out - - - def PrintFlagBits(self, bitmask): - return [f'''void Dump{bitmask.name}(Printer &p, std::string name, {bitmask.name} value) {{ - auto strings = {bitmask.name}GetStrings(value); - if (strings.size() > 0) {{ - if (p.Type() == OutputType::json) - p.PrintKeyString(name, std::string("VK_") + strings.at(0)); - else - p.PrintKeyString(name, strings.at(0)); - }} -}} -'''] - - - def PrintBitMask(self,bitmask, name): - out = [] - out.extend(self.PrintGetFlagStrings(bitmask.name, bitmask)) - out.append(self.AddGuardHeader(bitmask)) - out.extend(self.PrintFlags(bitmask, name)) - out.extend(self.PrintFlagBits(bitmask)) - out.append(self.AddGuardFooter(bitmask)) - out.append('\n') - return out - - - def PrintBitMaskToString(self, bitmask, name): - out = [] - out.append(self.AddGuardHeader(bitmask)) - out.append(f'std::string {name}String({name} value) {{\n') - out.append(' std::string out;\n') - out.append(' bool is_first = true;\n') - for v in bitmask.flags: - out.append(f' if ({v.name} & value) {{\n') - out.append(' if (is_first) { is_first = false; } else { out += " | "; }\n') - out.append(f' out += "{str(v.name)[3:]}";\n') - out.append(' }\n') - out.append(' return out;\n') - out.append('}\n') - out.append(self.AddGuardFooter(bitmask)) - return out - - - def PrintStructure(self,struct, declare_only): - if len(struct.members) == 0: - return [] - out = [] - out.append(self.AddGuardHeader(struct)) - max_key_len = 0 - for v in struct.members: - if (v.type in PREDEFINED_TYPES or v.type in STRUCT_BLACKLIST) and (v.length is None or v.type in ['char'] or v.fixedSizeArray[0] in ['VK_UUID_SIZE', 'VK_LUID_SIZE']): - max_key_len = max(max_key_len, len(v.name)) - out.append(f'void Dump{struct.name}(Printer &p, std::string name, const {struct.name} &obj)') - if declare_only: - out.append(';\n') - out.append(self.AddGuardFooter(struct)) - return out - out.append(' {\n') - if struct.name == 'VkPhysicalDeviceLimits': - out.append(' if (p.Type() == OutputType::json)\n') - out.append(' p.ObjectStart("limits");\n') - out.append(' else\n') - out.append(' p.SetSubHeader().ObjectStart(name);\n') - elif struct.name == 'VkPhysicalDeviceSparseProperties': - out.append(' if (p.Type() == OutputType::json)\n') - out.append(' p.ObjectStart("sparseProperties");\n') - out.append(' else\n') - out.append(' p.SetSubHeader().ObjectStart(name);\n') - else: - out.append(' ObjectWrapper object{p, name};\n') - if max_key_len > 0: - out.append(f' p.SetMinKeyWidth({max_key_len});\n') - for v in struct.members: - # strings - if v.type == 'char': - if v.pointer == True: - out.append(f' if (obj.{v.name} == nullptr) {{') - out.append(f' p.PrintKeyString("{v.name}", "NULL");\n') - out.append(' } else {') - out.append(f' p.PrintKeyString("{v.name}", obj.{v.name});\n') - if v.pointer == True: - out.append(' }') - # arrays - elif v.length is not None: - # uuid's - if v.type == 'uint8_t' and (v.fixedSizeArray[0] == 'VK_LUID_SIZE' or v.fixedSizeArray[0] == 'VK_UUID_SIZE'): # VK_UUID_SIZE - if v.fixedSizeArray[0] == 'VK_LUID_SIZE': - out.append(' if (obj.deviceLUIDValid) { // special case\n') - out.append(f' p.PrintKeyValue("{v.name}", obj.{v.name});\n') - if v.fixedSizeArray[0] == 'VK_LUID_SIZE': - out.append(' }\n') - elif struct.name == 'VkQueueFamilyGlobalPriorityProperties' and v.name == 'priorities': - out.append(f' ArrayWrapper arr(p,"{v.name}", obj.priorityCount);\n') - out.append(' for (uint32_t i = 0; i < obj.priorityCount; i++) {\n') - out.append(' if (p.Type() == OutputType::json)\n') - out.append(' p.PrintString(std::string("VK_") + VkQueueGlobalPriorityString(obj.priorities[i]));\n') - out.append(' else\n') - out.append(' p.PrintString(VkQueueGlobalPriorityString(obj.priorities[i]));\n') - out.append(' }\n') - elif len(v.fixedSizeArray) == 2: - out.append(f' {{\n ArrayWrapper arr(p,"{v.name}", ' + v.fixedSizeArray[0] + ');\n') - out.append(f' for (uint32_t i = 0; i < {v.fixedSizeArray[0]}; i++) {{\n') - out.append(f' for (uint32_t j = 0; j < {v.fixedSizeArray[1]}; j++) {{\n') - out.append(f' p.PrintElement(obj.{v.name}[i][j]); }} }}\n') - out.append(' }\n') - elif len(v.fixedSizeArray) == 1: - out.append(f' {{\n ArrayWrapper arr(p,"{v.name}", ' + v.fixedSizeArray[0] + ');\n') - out.append(f' for (uint32_t i = 0; i < {v.fixedSizeArray[0]}; i++) {{ p.PrintElement(obj.{v.name}[i]); }}\n') - out.append(' }\n') - else: # dynamic array length based on other member - out.append(f' if (obj.{v.length} == 0 || obj.{v.name} == nullptr) {{\n') - out.append(f' p.PrintKeyString("{v.name}", "NULL");\n') - out.append(' } else {\n') - out.append(f' ArrayWrapper arr(p,"{v.name}", obj.{v.length});\n') - out.append(f' for (uint32_t i = 0; i < obj.{v.length}; i++) {{\n') - out.append(f' Dump{v.type}(p, std::to_string(i), obj.{v.name}[i]);\n') - out.append(' }\n') - out.append(' }\n') - elif v.type == 'VkBool32': - out.append(f' p.PrintKeyBool("{v.name}", static_cast<bool>(obj.{v.name}));\n') - elif v.type == 'uint8_t': - out.append(f' p.PrintKeyValue("{v.name}", static_cast<uint32_t>(obj.{v.name}));\n') - elif v.type == 'VkDeviceSize' or (v.type == 'uint32_t' and v.name in ['vendorID', 'deviceID']): - out.append(f' p.PrintKeyValue("{v.name}", to_hex_str(p, obj.{v.name}));\n') - elif v.type in PREDEFINED_TYPES: - out.append(f' p.PrintKeyValue("{v.name}", obj.{v.name});\n') - elif v.name not in NAMES_TO_IGNORE: - # if it is an enum/flag/bitmask - if v.type in ['VkFormatFeatureFlags', 'VkFormatFeatureFlags2']: - out.append(' p.SetOpenDetails();\n') # special case so that feature flags are open in html output - out.append(f' Dump{v.type}(p, "{v.name}", obj.{v.name});\n') - - if struct.name in ['VkPhysicalDeviceLimits', 'VkPhysicalDeviceSparseProperties']: - out.append(' p.ObjectEnd();\n') - out.append('}\n') - - out.append(self.AddGuardFooter(struct)) - return out - - - def PrintStructShort(self,struct): - out = [] - out.append(self.AddGuardHeader(struct)) - out.append(f'std::ostream &operator<<(std::ostream &o, {struct.name} &obj) {{\n') - out.append(' return o << "(" << ') - - first = True - for v in struct.members: - if first: - first = False - out.append(f'obj.{v.name} << ') - else: - out.append(f'\',\' << obj.{v.name} << ') - out.append('")";\n') - out.append('}\n') - out.append(self.AddGuardFooter(struct)) - return out - - def PrintChainStruct(self, listName, structs_to_print, chain_details): - version_desc = '' - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - version_desc = 'gpu.api_version' - else: - version_desc = 'inst.instance_version' - - out = [] - - # use default constructor and delete copy & move operators - out.append(f'''struct {listName}_chain {{ - {listName}_chain() = default; - {listName}_chain(const {listName}_chain &) = delete; - {listName}_chain& operator=(const {listName}_chain &) = delete; - {listName}_chain({listName}_chain &&) = delete; - {listName}_chain& operator=({listName}_chain &&) = delete; -''') - - out.append(' void* start_of_chain = nullptr;\n') - for s in structs_to_print: - if s in STRUCT_BLACKLIST: - continue - struct = self.vk.structs[s] - out.append(self.AddGuardHeader(struct)) - if struct.sType is not None: - out.append(f' {struct.name} {struct.name[2:]}{{}};\n') - # Specific versions of drivers have an incorrect definition of the size of these structs. - # We need to artificially pad the structure it just so the driver doesn't write out of bounds and - # into other structures that are adjacent. This bug comes from the in-development version of - # the extension having a larger size than the final version, so older drivers try to write to - # members which don't exist. - if struct.name in ['VkPhysicalDeviceShaderIntegerDotProductFeatures', 'VkPhysicalDeviceHostImageCopyFeaturesEXT']: - out.append(f' char {struct.name}_padding[64];\n') - for member in struct.members: - if member.length is not None and len(member.fixedSizeArray) == 0: - out.append(f' std::vector<{member.type}> {struct.name}_{member.name};\n') - out.append(self.AddGuardFooter(struct)) - out.append(' void initialize_chain(') - args = [] - if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: - args.append('AppInstance &inst') - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - args.append('AppGpu &gpu') - if chain_details.get('can_show_promoted_structs'): - args.append('bool show_promoted_structs') - out.append(f'{", ".join(args)}) noexcept {{\n') - for s in structs_to_print: - if s in STRUCT_BLACKLIST: - continue - struct = self.vk.structs[s] - - out.append(self.AddGuardHeader(struct)) - out.append(f' {struct.name[2:]}.sType = {struct.sType};\n') - out.append(self.AddGuardFooter(struct)) - - out.append(' std::vector<VkBaseOutStructure*> chain_members{};\n') - for s in structs_to_print: - if s in STRUCT_BLACKLIST: - continue - struct = self.vk.structs[s] - out.append(self.AddGuardHeader(struct)) - - has_version = struct.version is not None - has_extNameStr = len(struct.extensions) > 0 or len(struct.aliases) > 0 - if has_version or has_extNameStr: - out.append(' if (') - has_printed_condition = False - if has_extNameStr: - for ext in struct.extensions: - if has_printed_condition: - out.append('\n || ') - else: - has_printed_condition = True - if has_version: - out.append('(') - if self.vk.extensions[ext].device: - out.append(f'gpu.CheckPhysicalDeviceExtensionIncluded({self.vk.extensions[ext].nameString})') - elif self.vk.extensions[ext].instance: - out.append(f'inst.CheckExtensionEnabled({self.vk.extensions[ext].nameString})') - else: - assert False, 'Should never get here' - if has_version: - str_show_promoted_structs = '|| show_promoted_structs' if chain_details.get('can_show_promoted_structs') else '' - if struct.name in STRUCT_1_1_LIST: - out.append(f'{version_desc} == {struct.version.nameApi} {str_show_promoted_structs}') - elif has_printed_condition: - out.append(f')\n && ({version_desc} < {struct.version.nameApi} {str_show_promoted_structs})') - else: - out.append(f'({version_desc} >= {struct.version.nameApi})') - out.append(')\n ') - else: - out.append(' ') - out.append(f'chain_members.push_back(reinterpret_cast<VkBaseOutStructure*>(&{struct.name[2:]}));\n') - out.append(self.AddGuardFooter(struct)) - chain_param_list = [] - chain_arg_list = [] - if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: - chain_param_list.append('AppInstance &inst') - chain_arg_list.append('inst') - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - chain_param_list.append('AppGpu &gpu') - chain_arg_list.append('gpu') - if chain_details.get('can_show_promoted_structs'): - chain_param_list.append('bool show_promoted_structs') - chain_arg_list.append('show_promoted_structs') - - out.append(f''' - if (!chain_members.empty()) {{ - for(size_t i = 0; i < chain_members.size() - 1; i++){{ - chain_members[i]->pNext = chain_members[i + 1]; - }} - start_of_chain = chain_members[0]; - }} - }} -}}; -void setup_{listName}_chain({chain_details['extends']}& start, std::unique_ptr<{listName}_chain>& chain, {','.join(chain_param_list)}){{ - chain = std::unique_ptr<{listName}_chain>(new {listName}_chain()); - chain->initialize_chain({','.join(chain_arg_list)}); - start.pNext = chain->start_of_chain; -}}; -''') - if chain_details.get('print_iterator'): - out.append('\n') - out.append(f'void chain_iterator_{listName}(') - args = ['Printer &p'] - if chain_details.get('type') in [EXTENSION_TYPE_INSTANCE, EXTENSION_TYPE_BOTH]: - args.append('AppInstance &inst') - if chain_details.get('type') in [EXTENSION_TYPE_DEVICE, EXTENSION_TYPE_BOTH]: - args.append('AppGpu &gpu') - if chain_details.get('can_show_promoted_structs'): - args.append('bool show_promoted_structs') - args.append('const void * place') - out.append(f'{", ".join(args)}) {{\n') - out.append(' while (place) {\n') - out.append(' const VkBaseOutStructure *structure = (const VkBaseOutStructure *)place;\n') - out.append(' p.SetSubHeader();\n') - - for s in structs_to_print: - if s in STRUCT_BLACKLIST: - continue - struct = self.vk.structs[s] - - out.append(self.AddGuardHeader(struct)) - out.append(f' if (structure->sType == {struct.sType}') - if struct.name in PORTABILITY_STRUCTS: - out.append(' && p.Type() != OutputType::json') - out.append(') {\n') - out.append(f' const {struct.name}* props = (const {struct.name}*)structure;\n') - out.extend(self.PrintStructNameDecisionLogic(struct, version_desc, chain_details.get('can_show_promoted_structs'))) - out.append(' p.AddNewline();\n') - out.append(' }\n') - out.append(self.AddGuardFooter(struct)) - out.append(' place = structure->pNext;\n') - out.append(' }\n') - out.append('}\n') - - out.append('\n') - out.append(f'bool prepare_{listName}_twocall_chain_vectors(std::unique_ptr<{listName}_chain>& chain) {{\n') - out.append(' (void)chain;\n') - is_twocall = False - for s in structs_to_print: - if s in STRUCT_BLACKLIST: - continue - struct = self.vk.structs[s] - has_length = False - for member in struct.members: - if member.length is not None and len(member.fixedSizeArray) == 0: - has_length = True - if not has_length: - continue - out.append(self.AddGuardHeader(struct)) - for member in struct.members: - if member.length is not None and len(member.fixedSizeArray) == 0: - out.append(f' chain->{struct.name}_{member.name}.resize(chain->{struct.name[2:]}.{member.length});\n') - out.append(f' chain->{struct.name[2:]}.{member.name} = chain->{struct.name}_{member.name}.data();\n') - out.append(self.AddGuardFooter(struct)) - is_twocall = True - out.append(f' return {"true" if is_twocall else "false"};\n') - out.append('}\n') - - return out - - def GetStructCheckStringForMatchingExtension(self, struct, structName): - for ext_name in struct.extensions: - ext = self.vk.extensions[ext_name] - vendor = ext.name.split('_')[1] - if structName.endswith(vendor): - if ext.device: - return f'gpu.CheckPhysicalDeviceExtensionIncluded({ext.nameString})' - elif ext.instance: - return f'inst.CheckExtensionEnabled({ext.nameString})' - return None - - # Function is complex because it has to do the following: - # Always print the struct with the most appropriate name given the gpu api version & enabled instance/device extensions - # Print struct aliases when --show-promoted-structs is set - # Not let alias printing duplicate the most appropriate name - def PrintStructNameDecisionLogic(self, struct, version_desc, can_show_promoted_structs): - out = [] - out.append(f'{" " * 12}const char* name = ') - # Get a list of all the conditions to check and the type name to use - check_list = [] - if struct.version is not None: - check_list.append([f'{version_desc} >= {struct.version.nameApi}', struct.name]) - else: - check_list.append([f'{self.GetStructCheckStringForMatchingExtension(struct, struct.name)}', struct.name]) - - for alias in struct.aliases: - ext_str = self.GetStructCheckStringForMatchingExtension(struct, alias) - if ext_str is not None: - check_list.append([f'{self.GetStructCheckStringForMatchingExtension(struct, alias)}', alias]) - end_parens = '' - # Turn the conditions into a nested ternary condition - - for check in check_list: - if check == check_list[-1]: - out.append( f'"{check[1]}"') - else: - out.append( f'{check[0]} ? "{check[1]}" : (') - end_parens += ')' - out.append(f'{end_parens};\n') - out.append(f'{" " * 12}Dump{struct.name}(p, name, *props);\n') - if not can_show_promoted_structs: - return out - for alias in struct.aliases: - ext_str = self.GetStructCheckStringForMatchingExtension(struct, alias) - if ext_str is not None: - out.append(f'{" " * 12}if (show_promoted_structs && strcmp(name, "{alias}") != 0 && {ext_str}) {{\n') - out.append(f'{" " * 16}p.AddNewline();\n') - out.append(f'{" " * 16}p.SetSubHeader();\n') - out.append(f'{" " * 16}Dump{struct.name}(p, "{alias}", *props);\n') - out.append(f'{" " * 12}}}\n') - return out - - def PrintStructComparisonForwardDecl(self,structure): - out = [] - out.append(f'bool operator==(const {structure.name} & a, const {structure.name} b);\n') - return out - - - def PrintStructComparison(self,structure): - out = [] - out.append(f'bool operator==(const {structure.name} & a, const {structure.name} b) {{\n') - out.append(' return ') - is_first = True - for m in structure.members: - if m.name not in NAMES_TO_IGNORE: - if not is_first: - out.append('\n && ') - else: - is_first = False - out.append(f'a.{m.name} == b.{m.name}') - out.append(';\n') - out.append('}\n') - return out - -class VulkanFormatRange: - def __init__(self, min_inst_version, extensions, first, last): - self.minimum_instance_version = min_inst_version - self.extensions = extensions - self.first_format = first - self.last_format = last diff --git a/tools/Vulkan-Tools/scripts/gn/DEPS b/tools/Vulkan-Tools/scripts/gn/DEPS deleted file mode 100644 index 8cf931a8..00000000 --- a/tools/Vulkan-Tools/scripts/gn/DEPS +++ /dev/null @@ -1,68 +0,0 @@ -gclient_gn_args_file = 'build/config/gclient_args.gni' - -vars = { - 'chromium_git': 'https://chromium.googlesource.com', - 'ninja_version': 'version:2@1.11.1.chromium.6', -} - -deps = { - - 'build': { - 'url': '{chromium_git}/chromium/src/build.git@1015724d82945f9ef7e51c6f804034ccf5f79951', - }, - - 'buildtools': { - 'url': '{chromium_git}/chromium/src/buildtools.git@3c7e3f1b8b1e4c0b6ec693430379cea682de78d6', - }, - - 'buildtools/linux64': { - 'packages': [ - { - 'package': 'gn/gn/linux-${{arch}}', - 'version': 'git_revision:5e19d2fb166fbd4f6f32147fbb2f497091a54ad8', - } - ], - 'dep_type': 'cipd', - 'condition': 'host_os == "linux"', - }, - - 'testing': { - 'url': '{chromium_git}/chromium/src/testing@949b2864b6bd27656753b917c9aa7731dc7a06f6', - }, - - 'tools/clang': { - 'url': '{chromium_git}/chromium/src/tools/clang.git@566877f1ff1a5fa6beaca3ab4b47bd0b92eb614f', - }, - - 'third_party/ninja': { - 'packages': [ - { - 'package': 'infra/3pp/tools/ninja/${{platform}}', - 'version': Var('ninja_version'), - } - ], - 'dep_type': 'cipd', - }, - -} - -hooks = [ - { - 'name': 'sysroot_x64', - 'pattern': '.', - 'condition': 'checkout_linux and checkout_x64', - 'action': ['python3', 'build/linux/sysroot_scripts/install-sysroot.py', - '--arch=x64'], - }, - { - # Note: On Win, this should run after win_toolchain, as it may use it. - 'name': 'clang', - 'pattern': '.', - 'action': ['python3', 'tools/clang/scripts/update.py'], - }, -] - -recursedeps = [ - # buildtools provides clang_format. - 'buildtools', -] diff --git a/tools/Vulkan-Tools/scripts/gn/generate_vulkan_icd_json.py b/tools/Vulkan-Tools/scripts/gn/generate_vulkan_icd_json.py deleted file mode 100755 index 467ba616..00000000 --- a/tools/Vulkan-Tools/scripts/gn/generate_vulkan_icd_json.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python - -# Copyright (c) 2022-2023 LunarG, Inc. -# Copyright (C) 2016 The ANGLE Project Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -"""Generate copies of the Vulkan layers JSON files, with no paths, forcing -Vulkan to use the default search path to look for layers.""" - -from __future__ import print_function - -import argparse -import glob -import json -import os -import platform -import sys - -def glob_slash(dirname): - r"""Like regular glob but replaces \ with / in returned paths.""" - return [s.replace('\\', '/') for s in glob.glob(dirname)] - -def main(): - parser = argparse.ArgumentParser(description=__doc__) - parser.add_argument('--icd', action='store_true') - parser.add_argument('--no-path-prefix', action='store_true') - parser.add_argument('--platform', type=str, default=platform.system(), - help='Target platform to build validation layers for: ' - 'Linux|Darwin|Windows|Fuchsia|...') - parser.add_argument('source_dir') - parser.add_argument('target_dir') - parser.add_argument('json_files', nargs='*') - args = parser.parse_args() - - source_dir = args.source_dir - target_dir = args.target_dir - - json_files = [j for j in args.json_files if j.endswith('.json')] - json_in_files = [j for j in args.json_files if j.endswith('.json.in')] - - data_key = 'ICD' if args.icd else 'layer' - - if not os.path.isdir(source_dir): - print(source_dir + ' is not a directory.', file=sys.stderr) - return 1 - - if not os.path.exists(target_dir): - os.makedirs(target_dir) - - # Copy the *.json files from source dir to target dir - if (set(glob_slash(os.path.join(source_dir, '*.json'))) != set(json_files)): - print(glob.glob(os.path.join(source_dir, '*.json'))) - print('.json list in gn file is out-of-date', file=sys.stderr) - return 1 - - for json_fname in json_files: - if not json_fname.endswith('.json'): - continue - with open(json_fname) as infile: - data = json.load(infile) - - # Update the path. - if not data_key in data: - raise Exception( - "Could not find '%s' key in %s" % (data_key, json_fname)) - - # The standard validation layer has no library path. - if 'library_path' in data[data_key]: - prev_name = os.path.basename(data[data_key]['library_path']) - data[data_key]['library_path'] = prev_name - - target_fname = os.path.join(target_dir, os.path.basename(json_fname)) - with open(target_fname, 'w') as outfile: - json.dump(data, outfile) - - # Set json file prefix and suffix for generating files, default to Linux. - if args.no_path_prefix: - relative_path_prefix = '' - elif args.platform == 'Windows': - relative_path_prefix = r'..\\' # json-escaped, hence two backslashes. - else: - relative_path_prefix = '../lib' - file_type_suffix = '.so' - if args.platform == 'Windows': - file_type_suffix = '.dll' - elif args.platform == 'Darwin': - file_type_suffix = '.dylib' - - # For each *.json.in template files in source dir generate actual json file - # in target dir - if (set(glob_slash(os.path.join(source_dir, '*.json.in'))) != - set(json_in_files)): - print('.json.in list in gn file is out-of-date', file=sys.stderr) - return 1 - for json_in_name in json_in_files: - if not json_in_name.endswith('.json.in'): - continue - json_in_fname = os.path.basename(json_in_name) - layer_name = json_in_fname[:-len('.json.in')] - layer_lib_name = layer_name + file_type_suffix - json_out_fname = os.path.join(target_dir, json_in_fname[:-len('.in')]) - with open(json_out_fname,'w') as json_out_file, \ - open(json_in_name) as infile: - for line in infile: - line = line.replace('@JSON_LIBRARY_PATH@', relative_path_prefix + layer_lib_name) - json_out_file.write(line) - -if __name__ == '__main__': - sys.exit(main()) diff --git a/tools/Vulkan-Tools/scripts/gn/gn.py b/tools/Vulkan-Tools/scripts/gn/gn.py deleted file mode 100755 index 52b20c58..00000000 --- a/tools/Vulkan-Tools/scripts/gn/gn.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/env python3 -# Copyright 2023 The Khronos Group Inc. -# Copyright 2023 Valve Corporation -# Copyright 2023 LunarG, Inc. -# -# SPDX-License-Identifier: Apache-2.0 - -import os -import subprocess -import sys - -# helper to define paths relative to the repo root -def RepoRelative(path): - return os.path.abspath(os.path.join(os.path.dirname(__file__), '../../', path)) - -def BuildGn(): - if not os.path.exists(RepoRelative("depot_tools")): - print("Cloning Chromium depot_tools\n", flush=True) - clone_cmd = 'git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git depot_tools'.split(" ") - subprocess.call(clone_cmd) - - os.environ['PATH'] = os.environ.get('PATH') + ":" + RepoRelative("depot_tools") - - print("Updating Repo Dependencies and GN Toolchain\n", flush=True) - update_cmd = './scripts/gn/update_deps.sh' - subprocess.call(update_cmd) - - print("Checking Header Dependencies\n", flush=True) - gn_check_cmd = 'gn gen --check out/Debug'.split(" ") - subprocess.call(gn_check_cmd) - - print("Generating Ninja Files\n", flush=True) - gn_gen_cmd = 'gn gen out/Debug'.split(" ") - subprocess.call(gn_gen_cmd) - - print("Running Ninja Build\n", flush=True) - ninja_build_cmd = 'ninja -C out/Debug'.split(" ") - subprocess.call(ninja_build_cmd) - -# -# Module Entrypoint -def main(): - try: - BuildGn() - - except subprocess.CalledProcessError as proc_error: - print('Command "%s" failed with return code %s' % (' '.join(proc_error.cmd), proc_error.returncode)) - sys.exit(proc_error.returncode) - except Exception as unknown_error: - print('An unkown error occured: %s', unknown_error) - sys.exit(1) - - sys.exit(0) - -if __name__ == '__main__': - main() diff --git a/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/build.gni b/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/build.gni deleted file mode 100644 index dbf47039..00000000 --- a/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/build.gni +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) 2019-2023 LunarG, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -build_with_chromium = false -ignore_elf32_limitations = true -linux_use_bundled_binutils_override = false -use_system_xcode = true diff --git a/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/vulkan_headers.gni b/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/vulkan_headers.gni deleted file mode 100644 index 5f24b39e..00000000 --- a/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/vulkan_headers.gni +++ /dev/null @@ -1,15 +0,0 @@ -# Copyright (c) 2020-2023 LunarG, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -vulkan_use_x11 = true diff --git a/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/vulkan_tools.gni b/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/vulkan_tools.gni deleted file mode 100644 index c62fb64d..00000000 --- a/tools/Vulkan-Tools/scripts/gn/secondary/build_overrides/vulkan_tools.gni +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2019-2023 LunarG, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Paths to vulkan tools dependencies -vulkan_headers_dir = "//external/Vulkan-Headers" - -# Subdirectories for generated files -vulkan_data_subdir = "" -vulkan_gen_subdir = "" - diff --git a/tools/Vulkan-Tools/scripts/gn/update_deps.sh b/tools/Vulkan-Tools/scripts/gn/update_deps.sh deleted file mode 100755 index 763c3058..00000000 --- a/tools/Vulkan-Tools/scripts/gn/update_deps.sh +++ /dev/null @@ -1,49 +0,0 @@ -#!/bin/sh - -# Copyright (c) 2019-2023 LunarG, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Execute at repo root -cd "$(dirname $0)/../../" - -# Use update_deps.py to update source dependencies from /scripts/known_good.json -scripts/update_deps.py --dir="external" --no-build - -cat << EOF > .gn -buildconfig = "//build/config/BUILDCONFIG.gn" -secondary_source = "//scripts/gn/secondary/" - -script_executable = "python3" - -default_args = { - clang_use_chrome_plugins = false - use_custom_libcxx = false -} -EOF - -# Use gclient to update toolchain dependencies from /scripts/gn/DEPS (from chromium) -cat << EOF >> .gclient -solutions = [ - { "name" : ".", - "url" : "https://github.com/KhronosGroup/Vulkan-Tools", - "deps_file" : "scripts/gn/DEPS", - "managed" : False, - "custom_deps" : { - }, - "custom_vars": {}, - }, -] -EOF -gclient sync - diff --git a/tools/Vulkan-Tools/scripts/known_good.json b/tools/Vulkan-Tools/scripts/known_good.json deleted file mode 100644 index 14e6f5b8..00000000 --- a/tools/Vulkan-Tools/scripts/known_good.json +++ /dev/null @@ -1,79 +0,0 @@ -{ - "repos": [ - { - "name": "Vulkan-Headers", - "api": "vulkan", - "url": "https://github.com/KhronosGroup/Vulkan-Headers.git", - "sub_dir": "Vulkan-Headers", - "build_dir": "Vulkan-Headers/build", - "install_dir": "Vulkan-Headers/build/install", - "commit": "v1.4.347" - }, - { - "name": "MoltenVK", - "url": "https://github.com/KhronosGroup/MoltenVK.git", - "sub_dir": "MoltenVK", - "build_dir": "MoltenVK", - "install_dir": "MoltenVK", - "commit": "v1.4.1", - "custom_build": [ - "./fetchDependencies --macos", - "xcodebuild -project MoltenVKPackaging.xcodeproj GCC_PREPROCESSOR_DEFINITIONS='$GCC_PREPROCESSOR_DEFINITIONS MVK_CONFIG_LOG_LEVEL=1' -scheme \"MoltenVK Package (macOS only)\" build" - ], - "build_step": "custom", - "build_platforms": [ - "darwin" - ] - }, - { - "name": "googletest", - "url": "https://github.com/google/googletest.git", - "sub_dir": "googletest", - "build_dir": "googletest/build", - "install_dir": "googletest/build/install", - "cmake_options": [ - "-DBUILD_GMOCK=OFF", - "-Dgtest_force_shared_crt=ON", - "-DBUILD_SHARED_LIBS=OFF" - ], - "build_platforms": [ - "windows", - "linux", - "darwin" - ], - "commit": "v1.14.0", - "optional": [ - "tests" - ] - }, - { - "name": "Vulkan-Loader", - "api": "vulkan", - "url": "https://github.com/KhronosGroup/Vulkan-Loader.git", - "sub_dir": "Vulkan-Loader", - "build_dir": "Vulkan-Loader/build", - "install_dir": "Vulkan-Loader/build/install", - "cmake_options": [ - "-DLOADER_USE_UNSAFE_FILE_SEARCH=ON" - ], - "commit": "v1.4.347", - "build_platforms": [ - "windows", - "linux", - "darwin" - ], - "deps": [ - { - "var_name": "VULKAN_HEADERS_INSTALL_DIR", - "repo_name": "Vulkan-Headers" - } - ] - } - ], - "install_names": { - "Vulkan-Headers": "VULKAN_HEADERS_INSTALL_DIR", - "MoltenVK": "MOLTENVK_REPO_ROOT", - "googletest": "GOOGLETEST_INSTALL_DIR", - "Vulkan-Loader": "VULKAN_LOADER_INSTALL_DIR" - } -} diff --git a/tools/Vulkan-Tools/scripts/kvt_genvk.py b/tools/Vulkan-Tools/scripts/kvt_genvk.py deleted file mode 100644 index 868cc3fb..00000000 --- a/tools/Vulkan-Tools/scripts/kvt_genvk.py +++ /dev/null @@ -1,416 +0,0 @@ -#!/usr/bin/python3 -# -# Copyright (c) 2013-2025 The Khronos Group Inc. -# Copyright (c) 2023-2025 RasterGrid Kft. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -import argparse -import pdb -import sys -import time -import os - -# Simple timer functions -startTime = None - - -def startTimer(timeit): - global startTime - if timeit: - startTime = time.process_time() - - -def endTimer(timeit, msg): - global startTime - if timeit: - endTime = time.process_time() - write(msg, endTime - startTime, file=sys.stderr) - startTime = None - -# Turn a list of strings into a regexp string matching exactly those strings - - -def makeREstring(list, default=None): - if len(list) > 0 or default is None: - return '^(' + '|'.join(list) + ')$' - else: - return default - -# 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. - - -def makeGenOpts(args): - global genOpts - genOpts = {} - - # API to generate sources for - apiname = args.api - - # Default class of extensions to include, or None - if args.defaultExtensions is not None: - defaultExtensions = args.defaultExtensions - else: - defaultExtensions = apiname - - # 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 - - # 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 api.py - genpath = args.genpath - - # Descriptive names for various regexp patterns used to select - # versions and extensions - allFeatures = allExtensions = '.*' - noFeatures = noExtensions = None - - # Turn lists of names/patterns into matching regular expressions - addExtensionsPat = makeREstring(extensions, None) - removeExtensionsPat = makeREstring(removeExtensions, None) - emitExtensionsPat = makeREstring(emitExtensions, allExtensions) - featuresPat = makeREstring(features, allFeatures) - - # Copyright text prefixing all headers (list of strings). - prefixStrings = [ - '/*', - '** Copyright (c) 2015-2025 The Khronos Group Inc.', - '**', - '** Licensed under the Apache License, Version 2.0 (the "License");', - '** you may not use this file except in compliance with the License.', - '** You may obtain a copy of the License at', - '**', - '** http://www.apache.org/licenses/LICENSE-2.0', - '**', - '** Unless required by applicable law or agreed to in writing, software', - '** distributed under the License is distributed on an "AS IS" BASIS,', - '** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.', - '** See the License for the specific language governing permissions and', - '** limitations under the License.', - '*/', - '' - ] - - # Text specific to Vulkan headers - vkPrefixStrings = [ - '/*', - '** This header is generated from the Khronos Vulkan XML API Registry.', - '**', - '*/', - '' - ] - - # Defaults for generating re-inclusion protection wrappers (or not) - protectFeature = protect - - # An API style conventions object - conventions = VulkanConventions() - - # Helper file generator options for typemap_helper.h - genOpts['vk_typemap_helper.h'] = [ - HelperFileOutputGenerator, - HelperFileOutputGeneratorOptions( - conventions=conventions, - filename='vk_typemap_helper.h', - directory=directory, - genpath=None, - apiname=apiname, - profile=None, - versions=featuresPat, - emitversions=featuresPat, - defaultExtensions=defaultExtensions, - addExtensions=addExtensionsPat, - removeExtensions=removeExtensionsPat, - emitExtensions=emitExtensionsPat, - prefixText=prefixStrings + vkPrefixStrings, - protectFeature=False, - apicall='VKAPI_ATTR ', - apientry='VKAPI_CALL ', - apientryp='VKAPI_PTR *', - alignFuncParam=48, - expandEnumerants=False, - helper_file_type='typemap_helper_header') - ] - - # Options for mock ICD header - genOpts['function_declarations.h'] = [ - MockICDOutputGenerator, - MockICDGeneratorOptions( - conventions=conventions, - filename='function_declarations.h', - directory=directory, - genpath=None, - apiname=apiname, - profile=None, - versions=featuresPat, - emitversions=featuresPat, - defaultExtensions=defaultExtensions, - addExtensions=addExtensionsPat, - removeExtensions=removeExtensionsPat, - emitExtensions=emitExtensionsPat, - prefixText=prefixStrings + vkPrefixStrings, - protectFeature=False, - apicall='VKAPI_ATTR ', - apientry='VKAPI_CALL ', - apientryp='VKAPI_PTR *', - alignFuncParam=48, - expandEnumerants=False, - helper_file_type='mock_icd_function_declaration_implementation') - ] - - # Options for mock ICD cpp - genOpts['function_definitions.h'] = [ - MockICDOutputGenerator, - MockICDGeneratorOptions( - conventions=conventions, - filename='function_definitions.h', - directory=directory, - genpath=None, - apiname=apiname, - profile=None, - versions=featuresPat, - emitversions=featuresPat, - defaultExtensions=defaultExtensions, - addExtensions=addExtensionsPat, - removeExtensions=removeExtensionsPat, - emitExtensions=emitExtensionsPat, - prefixText=prefixStrings + vkPrefixStrings, - protectFeature=False, - apicall='VKAPI_ATTR ', - apientry='VKAPI_CALL ', - apientryp='VKAPI_PTR *', - alignFuncParam=48, - expandEnumerants=False, - helper_file_type='mock_icd_function_definition_implementation') - ] - - # Options for vulkaninfo.hpp - genOpts['vulkaninfo.hpp'] = [ - VulkanInfoGenerator, - VulkanInfoGeneratorOptions( - conventions=conventions, - filename='vulkaninfo.hpp', - directory=directory, - genpath=None, - apiname=apiname, - profile=None, - versions=featuresPat, - emitversions=featuresPat, - defaultExtensions=defaultExtensions, - addExtensions=addExtensionsPat, - removeExtensions=removeExtensionsPat, - emitExtensions=emitExtensionsPat, - prefixText=prefixStrings + vkPrefixStrings, - protectFeature=False, - apicall='VKAPI_ATTR ', - apientry='VKAPI_CALL ', - apientryp='VKAPI_PTR *', - alignFuncParam=48, - expandEnumerants=False, - registryFile=args.registry) - ] - - -# Generate a target based on the options in the matching genOpts{} object. -# 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 -def genTarget(args): - global genOpts - - # Create generator options with specified parameters - makeGenOpts(args) - - if (args.target in genOpts.keys()): - createGenerator = genOpts[args.target][0] - options = genOpts[args.target][1] - - if not args.quiet: - write('* Building', options.filename, file=sys.stderr) - write('* options.apiname =', options.apiname, file=sys.stderr) - write('* options.versions =', options.versions, file=sys.stderr) - write('* options.emitversions =', options.emitversions, file=sys.stderr) - write('* options.defaultExtensions =', options.defaultExtensions, file=sys.stderr) - write('* options.addExtensions =', options.addExtensions, file=sys.stderr) - write('* options.removeExtensions =', options.removeExtensions, file=sys.stderr) - write('* options.emitExtensions =', options.emitExtensions, file=sys.stderr) - - gen = createGenerator(errFile=errWarn, - warnFile=errWarn, - diagFile=diag) - if not args.quiet: - write('* Generated', options.filename, file=sys.stderr) - return (gen, options) - else: - write('No generator options for unknown target:', - args.target, file=sys.stderr) - 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('-api', action='store', - default='vulkan', - choices=['vulkan', 'vulkansc'], - help='Specify API name to generate') - parser.add_argument('-defaultExtensions', action='store', - default=None, - help='Specify a single class of extensions to add to targets') - parser.add_argument('-directory', action='store', default='.', - help='Specify where the built file is place') - 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('-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') - parser.add_argument('-time', action='store_true', - help='Enable timing') - parser.add_argument('-validate', action='store_true', - help='Enable XML group validation') - 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.') - - # This argument tells us where to load the script from the Vulkan-Headers registry - parser.add_argument('-scripts', action='store', - help='Find additional scripts in this directory') - - args = parser.parse_args() - - # default scripts path to be same as registry - if not args.scripts: - args.scripts = os.path.dirname(args.registry) - - scripts_directory_path = os.path.dirname(os.path.abspath(__file__)) - registry_headers_path = os.path.join(scripts_directory_path, args.scripts) - sys.path.insert(0, registry_headers_path) - - from reg import * - from generator import write - from cgenerator import CGeneratorOptions, COutputGenerator - - # Generator Modifications - from generators.mock_icd_generator import MockICDGeneratorOptions, MockICDOutputGenerator - from generators.vulkan_tools_helper_file_generator import HelperFileOutputGenerator, HelperFileOutputGeneratorOptions - from generators.vulkaninfo_generator import VulkanInfoGenerator, VulkanInfoGeneratorOptions - # Temporary workaround for vkconventions python2 compatibility - import abc - abc.ABC = abc.ABCMeta('ABC', (object,), {}) - from vkconventions import VulkanConventions - - # 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 =') - - # Load the XML tree into the registry object - startTimer(args.time) - reg.loadElementTree(tree) - endTimer(args.time, '* Time to parse ElementTree =') - - if (args.validate): - reg.validateGroups() - - if (args.dump): - write('* Dumping registry to regdump.txt', file=sys.stderr) - 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() - endTimer(args.time, '* Time to generate ' + options.filename + ' =') - genTarget(args) diff --git a/tools/Vulkan-Tools/scripts/update_deps.py b/tools/Vulkan-Tools/scripts/update_deps.py deleted file mode 100755 index 7d300865..00000000 --- a/tools/Vulkan-Tools/scripts/update_deps.py +++ /dev/null @@ -1,804 +0,0 @@ -#!/usr/bin/env python3 - -# Copyright 2017 The Glslang Authors. All rights reserved. -# Copyright (c) 2018-2023 Valve Corporation -# Copyright (c) 2018-2023 LunarG, Inc. -# Copyright (c) 2023-2023 RasterGrid Kft. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# This script was heavily leveraged from KhronosGroup/glslang -# update_glslang_sources.py. -"""update_deps.py - -Get and build dependent repositories using known-good commits. - -Purpose -------- - -This program is intended to assist a developer of this repository -(the "home" repository) by gathering and building the repositories that -this home repository depend on. It also checks out each dependent -repository at a "known-good" commit in order to provide stability in -the dependent repositories. - -Known-Good JSON Database ------------------------- - -This program expects to find a file named "known-good.json" in the -same directory as the program file. This JSON file is tailored for -the needs of the home repository by including its dependent repositories. - -Program Options ---------------- - -See the help text (update_deps.py --help) for a complete list of options. - -Program Operation ------------------ - -The program uses the user's current directory at the time of program -invocation as the location for fetching and building the dependent -repositories. The user can override this by using the "--dir" option. - -For example, a directory named "build" in the repository's root directory -is a good place to put the dependent repositories because that directory -is not tracked by Git. (See the .gitignore file.) The "external" directory -may also be a suitable location. -A user can issue: - -$ cd My-Repo -$ mkdir build -$ cd build -$ ../scripts/update_deps.py - -or, to do the same thing, but using the --dir option: - -$ cd My-Repo -$ mkdir build -$ scripts/update_deps.py --dir=build - -With these commands, the "build" directory is considered the "top" -directory where the program clones the dependent repositories. The -JSON file configures the build and install working directories to be -within this "top" directory. - -Note that the "dir" option can also specify an absolute path: - -$ cd My-Repo -$ scripts/update_deps.py --dir=/tmp/deps - -The "top" dir is then /tmp/deps (Linux filesystem example) and is -where this program will clone and build the dependent repositories. - -Helper CMake Config File ------------------------- - -When the program finishes building the dependencies, it writes a file -named "helper.cmake" to the "top" directory that contains CMake commands -for setting CMake variables for locating the dependent repositories. -This helper file can be used to set up the CMake build files for this -"home" repository. - -A complete sequence might look like: - -$ git clone git@github.com:My-Group/My-Repo.git -$ cd My-Repo -$ mkdir build -$ cd build -$ ../scripts/update_deps.py -$ cmake -C helper.cmake .. -$ cmake --build . - -JSON File Schema ----------------- - -There's no formal schema for the "known-good" JSON file, but here is -a description of its elements. All elements are required except those -marked as optional. Please see the "known_good.json" file for -examples of all of these elements. - -- name - -The name of the dependent repository. This field can be referenced -by the "deps.repo_name" structure to record a dependency. - -- api - -The name of the API the dependency is specific to (e.g. "vulkan"). - -- url - -Specifies the URL of the repository. -Example: https://github.com/KhronosGroup/Vulkan-Loader.git - -- sub_dir - -The directory where the program clones the repository, relative to -the "top" directory. - -- build_dir - -The directory used to build the repository, relative to the "top" -directory. - -- install_dir - -The directory used to store the installed build artifacts, relative -to the "top" directory. - -- commit - -The commit used to checkout the repository. This can be a SHA-1 -object name or a refname used with the remote name "origin". - -- deps (optional) - -An array of pairs consisting of a CMake variable name and a -repository name to specify a dependent repo and a "link" to -that repo's install artifacts. For example: - -"deps" : [ - { - "var_name" : "VULKAN_HEADERS_INSTALL_DIR", - "repo_name" : "Vulkan-Headers" - } -] - -which represents that this repository depends on the Vulkan-Headers -repository and uses the VULKAN_HEADERS_INSTALL_DIR CMake variable to -specify the location where it expects to find the Vulkan-Headers install -directory. -Note that the "repo_name" element must match the "name" element of some -other repository in the JSON file. - -- prebuild (optional) -- prebuild_linux (optional) (For Linux and MacOS) -- prebuild_windows (optional) - -A list of commands to execute before building a dependent repository. -This is useful for repositories that require the execution of some -sort of "update" script or need to clone an auxillary repository like -googletest. - -The commands listed in "prebuild" are executed first, and then the -commands for the specific platform are executed. - -- custom_build (optional) - -A list of commands to execute as a custom build instead of using -the built in CMake way of building. Requires "build_step" to be -set to "custom" - -You can insert the following keywords into the commands listed in -"custom_build" if they require runtime information (like whether the -build config is "Debug" or "Release"). - -Keywords: -{0} reference to a dictionary of repos and their attributes -{1} reference to the command line arguments set before start -{2} reference to the CONFIG_MAP value of config. - -Example: -{2} returns the CONFIG_MAP value of config e.g. debug -> Debug -{1}.config returns the config variable set when you ran update_dep.py -{0}[Vulkan-Headers][repo_root] returns the repo_root variable from - the Vulkan-Headers GoodRepo object. - -- cmake_options (optional) - -A list of options to pass to CMake during the generation phase. - -- ci_only (optional) - -A list of environment variables where one must be set to "true" -(case-insensitive) in order for this repo to be fetched and built. -This list can be used to specify repos that should be built only in CI. - -- build_step (optional) - -Specifies if the dependent repository should be built or not. This can -have a value of 'build', 'custom', or 'skip'. The dependent repositories are -built by default. - -- build_platforms (optional) - -A list of platforms the repository will be built on. -Legal options include: -"windows" -"linux" -"darwin" -"android" - -Builds on all platforms by default. - -Note ----- - -The "sub_dir", "build_dir", and "install_dir" elements are all relative -to the effective "top" directory. Specifying absolute paths is not -supported. However, the "top" directory specified with the "--dir" -option can be a relative or absolute path. - -""" - -import argparse -import json -import os -import os.path -import subprocess -import sys -import platform -import multiprocessing -import shlex -import shutil -import stat -import time - -KNOWN_GOOD_FILE_NAME = 'known_good.json' - -CONFIG_MAP = { - 'debug': 'Debug', - 'release': 'Release', - 'relwithdebinfo': 'RelWithDebInfo', - 'minsizerel': 'MinSizeRel' -} - -# NOTE: CMake also uses the VERBOSE environment variable. This is intentional. -VERBOSE = os.getenv("VERBOSE") - -DEVNULL = open(os.devnull, 'wb') - - -def on_rm_error( func, path, exc_info): - """Error handler for recursively removing a directory. The - shutil.rmtree function can fail on Windows due to read-only files. - This handler will change the permissions for the file and continue. - """ - os.chmod( path, stat.S_IWRITE ) - os.unlink( path ) - -def make_or_exist_dirs(path): - "Wrapper for os.makedirs that tolerates the directory already existing" - # Could use os.makedirs(path, exist_ok=True) if we drop python2 - if not os.path.isdir(path): - os.makedirs(path) - -def command_output(cmd, directory): - # Runs a command in a directory and returns its standard output stream. - # Captures the standard error stream and prints it an error occurs. - # Raises a RuntimeError if the command fails to launch or otherwise fails. - if VERBOSE: - print('In {d}: {cmd}'.format(d=directory, cmd=cmd)) - - result = subprocess.run(cmd, cwd=directory, capture_output=True, text=True) - - if result.returncode != 0: - print(f'{result.stderr}', file=sys.stderr) - raise RuntimeError(f'Failed to run {cmd} in {directory}') - - if VERBOSE: - print(result.stdout) - return result.stdout - -def run_cmake_command(cmake_cmd): - # NOTE: Because CMake is an exectuable that runs executables - # stdout/stderr are mixed together. So this combines the outputs - # and prints them properly in case there is a non-zero exit code. - result = subprocess.run(cmake_cmd, - stdout = subprocess.PIPE, - stderr = subprocess.STDOUT, - text = True - ) - - if VERBOSE: - print(result.stdout) - print(f"CMake command: {cmake_cmd} ", flush=True) - - if result.returncode != 0: - print(result.stdout, file=sys.stderr) - sys.exit(result.returncode) - -def escape(path): - return path.replace('\\', '/') - -class GoodRepo(object): - """Represents a repository at a known-good commit.""" - - def __init__(self, json, args): - """Initializes this good repo object. - - Args: - 'json': A fully populated JSON object describing the repo. - 'args': Results from ArgumentParser - """ - self._json = json - self._args = args - # Required JSON elements - self.name = json['name'] - self.url = json['url'] - self.sub_dir = json['sub_dir'] - self.commit = json['commit'] - # Optional JSON elements - self.build_dir = None - self.install_dir = None - if json.get('build_dir'): - self.build_dir = os.path.normpath(json['build_dir']) - if json.get('install_dir'): - self.install_dir = os.path.normpath(json['install_dir']) - self.deps = json['deps'] if ('deps' in json) else [] - self.prebuild = json['prebuild'] if ('prebuild' in json) else [] - self.prebuild_linux = json['prebuild_linux'] if ( - 'prebuild_linux' in json) else [] - self.prebuild_windows = json['prebuild_windows'] if ( - 'prebuild_windows' in json) else [] - self.custom_build = json['custom_build'] if ('custom_build' in json) else [] - self.cmake_options = json['cmake_options'] if ( - 'cmake_options' in json) else [] - self.ci_only = json['ci_only'] if ('ci_only' in json) else [] - self.build_step = json['build_step'] if ('build_step' in json) else 'build' - self.build_platforms = json['build_platforms'] if ('build_platforms' in json) else [] - self.optional = set(json.get('optional', [])) - self.api = json['api'] if ('api' in json) else None - # Absolute paths for a repo's directories - dir_top = os.path.abspath(args.dir) - self.repo_dir = os.path.join(dir_top, self.sub_dir) - if self.build_dir: - self.build_dir = os.path.join(dir_top, self.build_dir) - if self.install_dir: - self.install_dir = os.path.join(dir_top, self.install_dir) - - # By default the target platform is the host platform. - target_platform = platform.system().lower() - # However, we need to account for cross-compiling. - for cmake_var in self._args.cmake_var: - if "android.toolchain.cmake" in cmake_var: - target_platform = 'android' - - self.on_build_platform = False - if self.build_platforms == [] or target_platform in self.build_platforms: - self.on_build_platform = True - - def Clone(self, retries=10, retry_seconds=60): - if VERBOSE: - print('Cloning {n} into {d}'.format(n=self.name, d=self.repo_dir)) - for retry in range(retries): - make_or_exist_dirs(self.repo_dir) - try: - command_output(['git', 'clone', self.url, '.'], self.repo_dir) - # If we get here, we didn't raise an error - return - except RuntimeError as e: - print("Error cloning on iteration {}/{}: {}".format(retry + 1, retries, e)) - if retry + 1 < retries: - if retry_seconds > 0: - print("Waiting {} seconds before trying again".format(retry_seconds)) - time.sleep(retry_seconds) - if os.path.isdir(self.repo_dir): - print("Removing old tree {}".format(self.repo_dir)) - shutil.rmtree(self.repo_dir, onerror=on_rm_error) - continue - - # If we get here, we've exhausted our retries. - print("Failed to clone {} on all retries.".format(self.url)) - raise e - - def Fetch(self, retries=10, retry_seconds=60): - for retry in range(retries): - try: - command_output(['git', 'fetch', 'origin'], self.repo_dir) - # if we get here, we didn't raise an error, and we're done - return - except RuntimeError as e: - print("Error fetching on iteration {}/{}: {}".format(retry + 1, retries, e)) - if retry + 1 < retries: - if retry_seconds > 0: - print("Waiting {} seconds before trying again".format(retry_seconds)) - time.sleep(retry_seconds) - continue - - # If we get here, we've exhausted our retries. - print("Failed to fetch {} on all retries.".format(self.url)) - raise e - - def Checkout(self): - if VERBOSE: - print('Checking out {n} in {d}'.format(n=self.name, d=self.repo_dir)) - - if os.path.exists(os.path.join(self.repo_dir, '.git')): - url_changed = command_output(['git', 'config', '--get', 'remote.origin.url'], self.repo_dir).strip() != self.url - else: - url_changed = False - - if self._args.do_clean_repo or url_changed: - if os.path.isdir(self.repo_dir): - if VERBOSE: - print('Clearing directory {d}'.format(d=self.repo_dir)) - shutil.rmtree(self.repo_dir, onerror = on_rm_error) - if not os.path.exists(os.path.join(self.repo_dir, '.git')): - self.Clone() - self.Fetch() - if len(self._args.ref): - command_output(['git', 'checkout', self._args.ref], self.repo_dir) - else: - command_output(['git', 'checkout', self.commit], self.repo_dir) - - if VERBOSE: - print(command_output(['git', 'status'], self.repo_dir)) - - def CustomPreProcess(self, cmd_str, repo_dict): - return cmd_str.format(repo_dict, self._args, CONFIG_MAP[self._args.config]) - - def PreBuild(self): - """Execute any prebuild steps from the repo root""" - for p in self.prebuild: - command_output(shlex.split(p), self.repo_dir) - if platform.system() == 'Linux' or platform.system() == 'Darwin': - for p in self.prebuild_linux: - command_output(shlex.split(p), self.repo_dir) - if platform.system() == 'Windows': - for p in self.prebuild_windows: - command_output(shlex.split(p), self.repo_dir) - - def CustomBuild(self, repo_dict): - """Execute any custom_build steps from the repo root""" - for p in self.custom_build: - cmd = self.CustomPreProcess(p, repo_dict) - command_output(shlex.split(cmd), self.repo_dir) - - def CMakeConfig(self, repos): - """Build CMake command for the configuration phase and execute it""" - if self._args.do_clean_build: - if os.path.isdir(self.build_dir): - shutil.rmtree(self.build_dir, onerror=on_rm_error) - if self._args.do_clean_install: - if os.path.isdir(self.install_dir): - shutil.rmtree(self.install_dir, onerror=on_rm_error) - - # Create and change to build directory - make_or_exist_dirs(self.build_dir) - os.chdir(self.build_dir) - - cmake_cmd = [ - 'cmake', self.repo_dir, - '-DCMAKE_INSTALL_PREFIX=' + self.install_dir - ] - - # Allow users to pass in arbitrary cache variables - for cmake_var in self._args.cmake_var: - pieces = cmake_var.split('=', 1) - cmake_cmd.append('-D{}={}'.format(pieces[0], pieces[1])) - - # For each repo this repo depends on, generate a CMake variable - # definitions for "...INSTALL_DIR" that points to that dependent - # repo's install dir. - for d in self.deps: - dep_commit = [r for r in repos if r.name == d['repo_name']] - if len(dep_commit) and dep_commit[0].on_build_platform: - cmake_cmd.append('-D{var_name}={install_dir}'.format( - var_name=d['var_name'], - install_dir=dep_commit[0].install_dir)) - - # Add any CMake options - for option in self.cmake_options: - cmake_cmd.append(escape(option.format(**self.__dict__))) - - # Set build config for single-configuration generators (this is a no-op on multi-config generators) - cmake_cmd.append(f'-D CMAKE_BUILD_TYPE={CONFIG_MAP[self._args.config]}') - - # Use the CMake -A option to select the platform architecture - # without needing a Visual Studio generator. - if platform.system() == 'Windows' and not self._args.generator in ["Ninja", "MinGW Makefiles"]: - cmake_cmd.append('-A') - if self._args.arch.lower() == '64' or self._args.arch == 'x64' or self._args.arch == 'win64': - cmake_cmd.append('x64') - elif self._args.arch == 'arm64': - cmake_cmd.append('arm64') - else: - cmake_cmd.append('Win32') - - # Apply a generator, if one is specified. This can be used to supply - # a specific generator for the dependent repositories to match - # that of the main repository. - if self._args.generator is not None: - cmake_cmd.extend(['-G', self._args.generator]) - - # Removes warnings related to unused CLI - # EX: Setting CMAKE_CXX_COMPILER for a C project - if not VERBOSE: - cmake_cmd.append("--no-warn-unused-cli") - - run_cmake_command(cmake_cmd) - - def CMakeBuild(self): - """Build CMake command for the build phase and execute it""" - cmake_cmd = ['cmake', '--build', self.build_dir, '--target', 'install', '--config', CONFIG_MAP[self._args.config]] - if self._args.do_clean: - cmake_cmd.append('--clean-first') - - # Xcode / Ninja are parallel by default. - if self._args.generator != "Ninja" or self._args.generator != "Xcode": - cmake_cmd.append('--parallel') - cmake_cmd.append(format(multiprocessing.cpu_count())) - - run_cmake_command(cmake_cmd) - - def Build(self, repos, repo_dict): - """Build the dependent repo and time how long it took""" - if VERBOSE: - print('Building {n} in {d}'.format(n=self.name, d=self.repo_dir)) - print('Build dir = {b}'.format(b=self.build_dir)) - print('Install dir = {i}\n'.format(i=self.install_dir)) - - start = time.time() - - # Run any prebuild commands - self.PreBuild() - - if self.build_step == 'custom': - self.CustomBuild(repo_dict) - return - - # Build and execute CMake command for creating build files - self.CMakeConfig(repos) - - # Build and execute CMake command for the build - self.CMakeBuild() - - total_time = time.time() - start - - print(f"Installed {self.name} ({self.commit}) in {total_time} seconds", flush=True) - - def IsOptional(self, opts): - return len(self.optional.intersection(opts)) > 0 - -def GetGoodRepos(args): - """Returns the latest list of GoodRepo objects. - - The known-good file is expected to be in the same - directory as this script unless overridden by the 'known_good_dir' - parameter. - """ - if args.known_good_dir: - known_good_file = os.path.join( os.path.abspath(args.known_good_dir), - KNOWN_GOOD_FILE_NAME) - else: - known_good_file = os.path.join( - os.path.dirname(os.path.abspath(__file__)), KNOWN_GOOD_FILE_NAME) - with open(known_good_file) as known_good: - return [ - GoodRepo(repo, args) - for repo in json.loads(known_good.read())['repos'] - ] - - -def GetInstallNames(args): - """Returns the install names list. - - The known-good file is expected to be in the same - directory as this script unless overridden by the 'known_good_dir' - parameter. - """ - if args.known_good_dir: - known_good_file = os.path.join(os.path.abspath(args.known_good_dir), - KNOWN_GOOD_FILE_NAME) - else: - known_good_file = os.path.join( - os.path.dirname(os.path.abspath(__file__)), KNOWN_GOOD_FILE_NAME) - with open(known_good_file) as known_good: - install_info = json.loads(known_good.read()) - if install_info.get('install_names'): - return install_info['install_names'] - else: - return None - - -def CreateHelper(args, repos, filename): - """Create a CMake config helper file. - - The helper file is intended to be used with 'cmake -C <file>' - to build this home repo using the dependencies built by this script. - - The install_names dictionary represents the CMake variables used by the - home repo to locate the install dirs of the dependent repos. - This information is baked into the CMake files of the home repo and so - this dictionary is kept with the repo via the json file. - """ - install_names = GetInstallNames(args) - with open(filename, 'w') as helper_file: - for repo in repos: - # If the repo has an API tag and that does not match - # the target API then skip it - if repo.api is not None and repo.api != args.api: - continue - if install_names and repo.name in install_names and repo.on_build_platform: - helper_file.write('set({var} "{dir}" CACHE STRING "")\n' - .format( - var=install_names[repo.name], - dir=escape(repo.install_dir))) - - -def main(): - parser = argparse.ArgumentParser( - description='Get and build dependent repos at known-good commits') - parser.add_argument( - '--known_good_dir', - dest='known_good_dir', - help="Specify directory for known_good.json file.") - parser.add_argument( - '--dir', - dest='dir', - default='.', - help="Set target directory for repository roots. Default is \'.\'.") - parser.add_argument( - '--ref', - dest='ref', - default='', - help="Override 'commit' with git reference. E.g., 'origin/main'") - parser.add_argument( - '--no-build', - dest='do_build', - action='store_false', - help= - "Clone/update repositories and generate build files without performing compilation", - default=True) - parser.add_argument( - '--clean', - dest='do_clean', - action='store_true', - help="Clean files generated by compiler and linker before building", - default=False) - parser.add_argument( - '--clean-repo', - dest='do_clean_repo', - action='store_true', - help="Delete repository directory before building", - default=False) - parser.add_argument( - '--clean-build', - dest='do_clean_build', - action='store_true', - help="Delete build directory before building", - default=False) - parser.add_argument( - '--clean-install', - dest='do_clean_install', - action='store_true', - help="Delete install directory before building", - default=False) - parser.add_argument( - '--skip-existing-install', - dest='skip_existing_install', - action='store_true', - help="Skip build if install directory exists", - default=False) - parser.add_argument( - '--arch', - dest='arch', - choices=['32', '64', 'x86', 'x64', 'win32', 'win64', 'arm64'], - type=str.lower, - help="Set build files architecture (Visual Studio Generator Only)", - default='64') - parser.add_argument( - '--config', - dest='config', - choices=['debug', 'release', 'relwithdebinfo', 'minsizerel'], - type=str.lower, - help="Set build files configuration", - default='debug') - parser.add_argument( - '--api', - dest='api', - default='vulkan', - choices=['vulkan'], - help="Target API") - parser.add_argument( - '--generator', - dest='generator', - help="Set the CMake generator", - default=None) - parser.add_argument( - '--optional', - dest='optional', - type=lambda a: set(a.lower().split(',')), - help="Comma-separated list of 'optional' resources that may be skipped. Only 'tests' is currently supported as 'optional'", - default=set()) - parser.add_argument( - '--cmake_var', - dest='cmake_var', - action='append', - metavar='VAR[=VALUE]', - help="Add CMake command line option -D'VAR'='VALUE' to the CMake generation command line; may be used multiple times", - default=[]) - - args = parser.parse_args() - save_cwd = os.getcwd() - - # Create working "top" directory if needed - make_or_exist_dirs(args.dir) - abs_top_dir = os.path.abspath(args.dir) - - repos = GetGoodRepos(args) - repo_dict = {} - - print('Starting builds in {d}'.format(d=abs_top_dir)) - for repo in repos: - # If the repo has an API tag and that does not match - # the target API then skip it - if repo.api is not None and repo.api != args.api: - continue - - # If the repo has a platform whitelist, skip the repo - # unless we are building on a whitelisted platform. - if not repo.on_build_platform: - continue - - # Skip building the repo if its install directory already exists - # and requested via an option. This is useful for cases where the - # install directory is restored from a cache that is known to be up - # to date. - if args.skip_existing_install and os.path.isdir(repo.install_dir): - print('Skipping build for repo {n} due to existing install directory'.format(n=repo.name)) - continue - - # Skip test-only repos if the --tests option was not passed in - if repo.IsOptional(args.optional): - continue - - field_list = ('url', - 'sub_dir', - 'commit', - 'build_dir', - 'install_dir', - 'deps', - 'prebuild', - 'prebuild_linux', - 'prebuild_windows', - 'custom_build', - 'cmake_options', - 'ci_only', - 'build_step', - 'build_platforms', - 'repo_dir', - 'on_build_platform') - repo_dict[repo.name] = {field: getattr(repo, field) for field in field_list} - - # If the repo has a CI whitelist, skip the repo unless - # one of the CI's environment variable is set to true. - if len(repo.ci_only): - do_build = False - for env in repo.ci_only: - if env not in os.environ: - continue - if os.environ[env].lower() == 'true': - do_build = True - break - if not do_build: - continue - - # Clone/update the repository - repo.Checkout() - - # Build the repository - if args.do_build and repo.build_step != 'skip': - repo.Build(repos, repo_dict) - - # Need to restore original cwd in order for CreateHelper to find json file - os.chdir(save_cwd) - CreateHelper(args, repos, os.path.join(abs_top_dir, 'helper.cmake')) - - sys.exit(0) - - -if __name__ == '__main__': - main() |
