update to v1.3.275

Signed-off-by: andrew0229 <zhangzhao62@huawei.com>
Change-Id: Ifc4224db2c6ea7c159d3cabe8f075475d47a41a8
This commit is contained in:
andrew0229 2024-05-13 07:01:37 +00:00
parent 8b5f1310fb
commit 0281b281d0
168 changed files with 31520 additions and 16019 deletions

View File

@ -1,34 +0,0 @@
# Configuration for cmake-format (v0.4.1, circa Jul 2018)
# https://github.com/cheshirekow/cmake_format
# How wide to allow formatted cmake files
line_width = 132
# How many spaces to tab for indent
tab_size = 4
# If arglists are longer than this, break them always
max_subargs_per_line = 3
# If true, separate flow control names from their parentheses with a space
separate_ctrl_name_with_space = False
# If true, separate function names from parentheses with a space
separate_fn_name_with_space = False
# If a statement is wrapped to more than one line, than dangle the closing
# parenthesis on it's own line
dangle_parens = False
# What character to use for bulleted lists
bullet_char = u'*'
# What character to use as punctuation after numerals in an enumerated list
enum_char = u'.'
# What style line endings to use in the output.
line_ending = u'unix'
# Format command names consistently as 'lower' or 'upper' case
command_case = u'lower'

7
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"
open-pull-requests-limit: 3

View File

@ -1,5 +1,5 @@
# Copyright (c) 2021 Valve Corporation
# Copyright (c) 2021 LunarG, Inc.
# Copyright (c) 2021-2023 Valve Corporation
# Copyright (c) 2021-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.
@ -14,137 +14,380 @@
# limitations under the License.
#
# Author: Lenny Komow <lenny@lunarg.com>
# Author: Charles Giessen <charles@lunarg.com>
name: CI Build
# https://docs.github.com/en/actions/using-jobs/using-concurrency
concurrency:
# github.head_ref is only defined on pull_request
# Fallback to the run ID, which is guaranteed to be both unique and defined for the run.
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
cancel-in-progress: true
on:
push:
pull_request:
branches:
- master
- main
permissions: read-all
jobs:
linux:
runs-on: ${{matrix.os}}
strategy:
matrix:
cc: [ gcc, clang ]
cxx: [ g++, clang++ ]
compiler: [ {cc: gcc, cxx: g++}, {cc: clang, cxx: clang++} ]
config: [ Debug, Release ]
os: [ ubuntu-18.04, ubuntu-20.04 ]
exclude:
- cc: gcc
cxx: clang++
- cc: clang
cxx: g++
os: [ ubuntu-20.04, ubuntu-22.04 ]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- name: Test CMake min
# NOTE: The main users who benefit from an older CMake version
# are linux users stuck on older LTS releases. It's idiomatic best
# practice to try and support them so they don't have to install
# the CMake tarball. Ideally the minimum we use matches what the default
# package provided by Ubuntu via APT.
if: ${{ matrix.os == 'ubuntu-20.04' }}
uses: lukka/get-cmake@latest
with:
cmakeVersion: 3.17.2
- run: sudo apt update
- run: sudo apt install libwayland-dev libxrandr-dev
- run: sudo apt install --yes --no-install-recommends libwayland-dev libxrandr-dev
- run: |
cmake -S. -B build \
-D CMAKE_BUILD_TYPE=${{ matrix.config }} \
-D BUILD_TESTS=ON \
-D UPDATE_DEPS=ON \
-D LOADER_ENABLE_ADDRESS_SANITIZER=ON \
-D BUILD_WERROR=ON \
-D CMAKE_CXX_COMPILER=${{ matrix.compiler.cxx }} \
-D CMAKE_C_COMPILER=${{ matrix.compiler.cc }}
- run: cmake --build build
- run: ctest --output-on-failure --test-dir build/
- run: cmake --install build --prefix /tmp
- name: Generate build files
run: cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{matrix.config}} -DBUILD_TESTS=On -DUPDATE_DEPS=ON -DTEST_USE_ADDRESS_SANITIZER=ON
codegen:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: scripts/update_deps.py --dir ext --no-build
- run: scripts/generate_source.py --verify ext/Vulkan-Headers/registry/
linux-no-asm:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- run: sudo apt update
- run: sudo apt install --yes --no-install-recommends libwayland-dev libxrandr-dev
- run: |
cmake -S. -B build \
-D CMAKE_BUILD_TYPE=Release \
-D BUILD_TESTS=ON \
-D UPDATE_DEPS=ON \
-D BUILD_WERROR=ON \
-D USE_GAS=OFF \
-D CMAKE_C_COMPILER=clang \
-D CMAKE_CXX_COMPILER=clang++
- run: cmake --build build
- run: cmake --install build --prefix /tmp
- run: ctest --output-on-failure -E UnknownFunction --test-dir build/
linux-32:
runs-on: ubuntu-22.04
strategy:
matrix:
config: [ Debug, Release ]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- uses: lukka/get-cmake@latest
with:
cmakeVersion: 3.17.2
- name: Enable 32 bit
run: sudo dpkg --add-architecture i386
- run: sudo apt-get update
- run: |
sudo apt install --yes --no-install-recommends \
gcc-multilib g++-multilib libc6:i386 libc6-dev-i386 libgcc-s1:i386 \
libwayland-dev:i386 libxrandr-dev:i386
- run: |
cmake -S. -B build \
-D CMAKE_BUILD_TYPE=${{matrix.config}} \
-D BUILD_TESTS=ON \
-D UPDATE_DEPS=ON \
-D BUILD_WERROR=ON \
-D SYSCONFDIR=/etc/not_vulkan \
-G Ninja
env:
CC: ${{matrix.cc}}
CXX: ${{matrix.cxx}}
CFLAGS: -m32
CXXFLAGS: -m32
LDFLAGS: -m32
ASFLAGS: --32
- run: cmake --build build
- run: cmake --install build --prefix /tmp
- run: ctest --output-on-failure
working-directory: build/
- name: Build the loader
run: make -C build
- name: Run regression tests
working-directory: ./build
run: ctest --output-on-failure
- name: Verify generated source files
run: python scripts/generate_source.py --verify external/Vulkan-Headers/registry
- name: Verify code formatting with clang-format
run: ./scripts/check_code_format.sh
- name: Verify commit message formatting
run: ./scripts/check_commit_message_format.sh
windows:
runs-on: ${{matrix.os}}
linux-32-no-asm:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- uses: lukka/get-cmake@latest
with:
cmakeVersion: 3.17.2
- name: Enable 32 bit
run: sudo dpkg --add-architecture i386
- run: sudo apt-get update
- run: |
sudo apt install --yes --no-install-recommends \
gcc-multilib g++-multilib libc6:i386 libc6-dev-i386 libgcc-s1:i386 \
libwayland-dev:i386 libxrandr-dev:i386
- run: |
cmake -S. -B build \
-D CMAKE_BUILD_TYPE=Release \
-D BUILD_TESTS=ON \
-D UPDATE_DEPS=ON \
-D BUILD_WERROR=ON \
-D USE_GAS=OFF \
-G Ninja
env:
CFLAGS: -m32
CXXFLAGS: -m32
LDFLAGS: -m32
ASFLAGS: --32
- run: cmake --build build
- run: ctest --output-on-failure -E UnknownFunction
working-directory: build/
windows_vs:
runs-on: windows-latest
strategy:
matrix:
arch: [ Win32, x64 ]
config: [ Debug, Release ]
os: [ windows-latest ]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
with:
python-version: '3.7'
- uses: actions/checkout@v4
- run: |
cmake -S. -B build `
-D BUILD_TESTS=ON `
-D UPDATE_DEPS=ON `
-D CMAKE_BUILD_TYPE=${{matrix.config}} `
-A ${{ matrix.arch }} `
-D BUILD_WERROR=ON
- run: cmake --build build/ --config ${{matrix.config}}
- run: cmake --install build --prefix build/install --config ${{matrix.config}}
- run: ctest --output-on-failure -C ${{matrix.config}} --test-dir build/
- name: Generate build files
run: cmake -S. -Bbuild -A${{matrix.arch}} -DBUILD_TESTS=On -DUPDATE_DEPS=ON
windows_vs-no-asm:
runs-on: windows-latest
strategy:
matrix:
arch: [ Win32, x64 ]
steps:
- uses: actions/checkout@v4
- run: |
cmake -S. -B build `
-D BUILD_TESTS=ON `
-D UPDATE_DEPS=ON `
-D USE_MASM=OFF `
-D CMAKE_BUILD_TYPE=Release `
-A ${{ matrix.arch }} `
-D BUILD_WERROR=ON
- run: cmake --build build/ --config Release
- run: ctest --output-on-failure -C Release -E UnknownFunction --test-dir build/
- name: Build the loader
run: cmake --build ./build --config ${{matrix.config}}
- name: Run regression tests
working-directory: ./build
run: ctest --output-on-failure
- name: Verify generated source files
run: python scripts/generate_source.py --verify external/Vulkan-Headers/registry
# Test both clang and clang-cl (Chromium project uses clang-cl)
windows_clang:
runs-on: windows-2022
strategy:
matrix:
compiler: [ clang, clang-cl ]
config: [ Debug, Release ]
steps:
- uses: actions/checkout@v4
- uses: ilammy/msvc-dev-cmd@v1
- run: |
cmake -S. -B build `
-D CMAKE_C_COMPILER=${{matrix.compiler}} `
-D CMAKE_CXX_COMPILER=${{matrix.compiler}} `
-D UPDATE_DEPS=ON `
-D CMAKE_BUILD_TYPE=${{matrix.config}} `
-D BUILD_WERROR=ON `
-D BUILD_TESTS=ON `
-G Ninja
- run: cmake --build build/
- run: ctest --output-on-failure --test-dir build/
- run: cmake --install build --prefix build/install
mac:
runs-on: macos-latest
runs-on: macos-11
strategy:
matrix:
config: [ Debug, Release ]
static_build: [ APPLE_STATIC_LOADER=ON, APPLE_STATIC_LOADER=OFF ]
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- uses: lukka/get-cmake@latest
- run: |
cmake -S. -B build \
-D CMAKE_BUILD_TYPE=${{matrix.config}} \
-D ${{matrix.static_build}} \
-D BUILD_TESTS=ON \
-D UPDATE_DEPS=ON \
-D BUILD_WERROR=ON \
-D LOADER_ENABLE_ADDRESS_SANITIZER=ON \
-G Ninja
env:
# Prevents regression of KhronosGroup/Vulkan-Loader/issues/1332
LDFLAGS: -Wl,-fatal_warnings
- run: cmake --build build
- run: cmake --install build --prefix /tmp
- run: ctest --output-on-failure --test-dir build/
- name: Generate build files
run: cmake -S. -Bbuild -DCMAKE_BUILD_TYPE=${{matrix.config}} -DBUILD_TESTS=On -DUPDATE_DEPS=ON -DTEST_USE_ADDRESS_SANITIZER=ON
- name: Build the loader
run: make -C build
- name: Run regression tests
working-directory: ./build
run: ctest --output-on-failure
gn:
runs-on: ubuntu-18.04
apple-cross-compile:
name: ${{ matrix.CMAKE_SYSTEM_NAME }}
runs-on: macos-12
strategy:
matrix:
config: [ Debug, Release ]
CMAKE_SYSTEM_NAME: [ iOS, tvOS ]
steps:
- uses: actions/checkout@v2
- name: Get depot tools
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- uses: lukka/get-cmake@latest
- run: |
cmake -S . -B build \
-D CMAKE_SYSTEM_NAME=${{ matrix.CMAKE_SYSTEM_NAME }} \
"-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
-D CMAKE_BUILD_TYPE=Debug \
-D UPDATE_DEPS=ON \
-D BUILD_WERROR=ON \
-G Ninja
env:
LDFLAGS: -Wl,-fatal_warnings
- run: cmake --build build
- run: cmake --install build --prefix /tmp
- name: Verify Universal Binary
run: |
git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git depot_tools
echo "$GITHUB_WORKSPACE/depot_tools" >> $GITHUB_PATH
vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture x86_64'
vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture arm64'
- name: Fetch and install headers
run: ./build-gn/update_deps.sh
# Building a universal binary disables assembly automatically
# Furthermore the Vulkan SDK ships universal binaries
mac-univeral:
name: "Universal Binary Testing (STATIC ${{ matrix.static }}) w/ ${{ matrix.generator }}"
runs-on: macos-latest
strategy:
matrix:
static: [ 'ON', 'OFF' ]
generator: [ Ninja, Xcode ]
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.7'
- uses: lukka/get-cmake@latest
- run: |
cmake -S. -B build \
-D CMAKE_BUILD_TYPE=Release \
-D APPLE_STATIC_LOADER=${{matrix.static}} \
"-D CMAKE_OSX_ARCHITECTURES=arm64;x86_64" \
-D BUILD_TESTS=ON \
-D UPDATE_DEPS=ON \
-D BUILD_WERROR=ON \
-G ${{ matrix.generator }}
env:
LDFLAGS: -Wl,-fatal_warnings
- run: cmake --build build --config Release
- run: ctest --output-on-failure --build-config Release -E UnknownFunction --test-dir build/
- run: cmake --install build --config Release --prefix /tmp
- name: Verify Universal Binary
if: ${{ matrix.static == 'OFF' }}
run: |
vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture x86_64'
vtool -show-build /tmp/lib/libvulkan.dylib | grep 'architecture arm64'
- name: Generate build files
run: gn gen out/${{matrix.config}} --args="is_debug=true"
if: matrix.config != 'Release'
chromium:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: scripts/gn/gn.py
- name: Generate build files
run: gn gen out/${{matrix.config}} --args="is_debug=false"
if: matrix.config == 'Release'
mingw:
runs-on: windows-2022
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.8'
- uses: lukka/get-cmake@latest
- name: Setup uasm
run: |
C:/msys64/usr/bin/pacman -Sy --noconfirm --needed mingw-w64-x86_64-uasm
printf '%s\n' 'C:/msys64/mingw64/bin' >> $GITHUB_PATH
- name: UASM Check
run: uasm -?
- run: |
cmake -S. -B build \
-D UPDATE_DEPS=ON \
-D CMAKE_BUILD_TYPE=Release \
-D BUILD_WERROR=ON \
-G Ninja
- run: cmake --build build
- run: cmake --install build --prefix /tmp
- name: Build the loader
run: ninja -C out/${{matrix.config}}
mingw-no-asm:
runs-on: windows-2022
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: '3.8'
- uses: lukka/get-cmake@latest
# Make sure this doesn't fail even without explicitly setting '-D USE_MASM=OFF' and without uasm
- run: |
cmake -S. -B build \
-D UPDATE_DEPS=ON \
-D CMAKE_BUILD_TYPE=Release \
-D BUILD_WERROR=ON \
-G Ninja
- run: cmake --build build
- run: cmake --install build --prefix /tmp
mingw-no-asm-explicit:
runs-on: windows-2022
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
- uses: lukka/get-cmake@latest
- run: |
cmake -S. -B build \
-D UPDATE_DEPS=ON \
-D CMAKE_BUILD_TYPE=Release \
-D BUILD_WERROR=ON \
-D USE_MASM=OFF \
-G Ninja
- run: cmake --build build
- run: cmake --install build --prefix /tmp

101
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,101 @@
# Copyright 2023 Google LLC
#
# 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: Joyce Brum <joycebrum@google.com>
name: "CodeQL"
on:
push:
branches: [ "main" ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ "main" ]
schedule:
- cron: '26 7 * * 1'
permissions: {}
jobs:
analyze:
name: Analyze
# Runner size impacts CodeQL analysis time. To learn more, please see:
# - https://gh.io/recommended-hardware-resources-for-running-codeql
# - https://gh.io/supported-runners-and-hardware-resources
# - https://gh.io/using-larger-runners
# Consider using larger runners for possible analysis time improvements.
runs-on: 'ubuntu-latest'
timeout-minutes: 360
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'cpp', 'python' ]
steps:
- name: Checkout repository
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, Java, or Swift).
# If this step fails, then you should remove it and run the build manually
- name: Autobuild
if: matrix.language == 'python'
uses: github/codeql-action/autobuild@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
- uses: actions/setup-python@v5
if: matrix.language == 'cpp'
with:
python-version: '3.7'
- uses: lukka/get-cmake@latest
if: matrix.language == 'cpp'
with:
cmakeVersion: 3.17.2
- name: Install Dependencies
if: matrix.language == 'cpp'
run: |
sudo apt update
sudo apt install --yes --no-install-recommends libwayland-dev libxrandr-dev
- name: Generate build files
if: matrix.language == 'cpp'
run: cmake -S. -B build -D CMAKE_BUILD_TYPE=Release -D UPDATE_DEPS=ON
env:
CC: gcc
CXX: g++
- name: Build the loader
if: matrix.language == 'cpp'
run: cmake --build build
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@012739e5082ff0c22ca6d6ab32e07c36df03c4a4 # v3.22.12
with:
category: "/language:${{matrix.language}}"

43
.github/workflows/format.yml vendored Normal file
View File

@ -0,0 +1,43 @@
# 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.
name: format
on:
push:
pull_request:
branches:
- main
permissions:
contents: read
jobs:
clang-format:
name: clang-format
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
path:
- 'loader'
- 'tests'
steps:
- uses: actions/checkout@v4
- name: Run clang-format
uses: jidicula/clang-format-action@v4.11.0
with:
clang-format-version: '16'
check-path: ${{ matrix.path }}

26
.gitignore vendored
View File

@ -1,3 +1,9 @@
# By default we install dependencies to the external directory
/external/*
# Ignore any build directories
*build*/
CMakeCache.txt
CMakeLists.txt.user
CMakeFiles/
@ -5,12 +11,7 @@ cmake_install.cmake
Makefile
scripts/__pycache__
VKConfig.h
build
build32
dbuild
external/*
!external/CMakeLists.txt
!external/README.md
*.so
*.so.*
*.pyc
@ -30,3 +31,16 @@ external/*
_out64
out32/*
out64/*
# Chromium build artifacts
.cipd/
.gn
.gclient
.gclient_entries
.gclient_previous_sync_commits
out/
third_party/
buildtools/
depot_tools/
testing/
tools/

22
.gn
View File

@ -1,22 +0,0 @@
# Copyright (C) 2019 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.
buildconfig = "//build/config/BUILDCONFIG.gn"
secondary_source = "//build-gn/secondary/"
default_args = {
clang_use_chrome_plugins = false
use_custom_libcxx = false
}

View File

@ -1,4 +1,6 @@
# Copyright (c) 2023 Huawei Device Co., Ltd.
# Copyright (C) 2018-2019 The ANGLE Project Authors.
# Copyright (C) 2019-2023 LunarG, Inc.
# Copyright (c) 2023-2024 Huawei Device Co., Ltd.
# 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
@ -18,14 +20,10 @@ import("//build/ohos.gni")
## Build libvulkan.so {{{
config("vulkan_internal_config") {
defines = [
"VULKAN_NON_CMAKE_BUILD",
"VK_ENABLE_BETA_EXTENSIONS",
]
defines = [ "VK_ENABLE_BETA_EXTENSIONS" ]
cflags = [
"-Wno-conversion",
"-Wno-extra-semi",
"-Wno-implicit-fallthrough",
"-Wno-sign-compare",
"-Wno-unreachable-code",
"-Wno-unused-function",
@ -46,10 +44,7 @@ config("vulkan_loader_config") {
"loader",
"openharmony",
]
defines = [
"API_NAME=\"Vulkan\"",
"USE_UNSAFE_FILE_SEARCH=1",
]
defines = [ "LOADER_USE_UNSAFE_FILE_SEARCH=1" ]
}
ohos_shared_library("vulkan_loader") {
@ -67,16 +62,18 @@ ohos_shared_library("vulkan_loader") {
"loader/generated/vk_layer_dispatch_table.h",
"loader/generated/vk_loader_extensions.h",
"loader/generated/vk_object_types.h",
"loader/get_environment.c",
"loader/get_environment.h",
"loader/gpa_helper.c",
"loader/gpa_helper.h",
"loader/loader.c",
"loader/loader.h",
"loader/loader_common.h",
"loader/loader_environment.c",
"loader/loader_environment.h",
"loader/log.c",
"loader/log.h",
"loader/phys_dev_ext.c",
"loader/settings.c",
"loader/settings.h",
"loader/stack_allocation.h",
"loader/terminator.c",
"loader/trampoline.c",

491
BUILD.md
View File

@ -4,33 +4,58 @@ Instructions for building this repository on Linux, Windows, and MacOS.
## Table Of Contents
- [Contributing to the Repository](#contributing-to-the-repository)
- [Repository Content](#repository-content)
- [Build Instructions](#build-instructions)
- [Table Of Contents](#table-of-contents)
- [Contributing to the Repository](#contributing-to-the-repository)
- [Repository Content](#repository-content)
- [Installed Files](#installed-files)
- [Repository Set-Up](#repository-set-up)
- [Build Requirements](#build-requirements)
- [Test Requirements](#test-requirements)
- [Repository Set-Up](#repository-set-up)
- [Display Drivers](#display-drivers)
- [Download the Repository](#download-the-repository)
- [Repository Dependencies](#repository-dependencies)
- [Build and Install Directories](#build-and-install-directories)
- [Vulkan-Headers](#vulkan-headers)
- [Test Dependencies](#test-dependencies)
- [Build and Install Directory Locations](#build-and-install-directory-locations)
- [Building Dependent Repositories with Known-Good Revisions](#building-dependent-repositories-with-known-good-revisions)
- [Automatically](#automatically)
- [Manually](#manually)
- [Notes About the Manual Option](#notes-about-the-manual-option)
- [Generated source code](#generated-source-code)
- [Build Options](#build-options)
- [Building On Windows](#building-on-windows)
- [Building On Windows](#building-on-windows)
- [Windows Development Environment Requirements](#windows-development-environment-requirements)
- [Windows Build - Microsoft Visual Studio](#windows-build---microsoft-visual-studio)
- [Windows Notes](#windows-notes)
- [CMake Visual Studio Generators](#cmake-visual-studio-generators)
- [Using The Vulkan Loader Library in this Repository on Windows](#using-the-vulkan-loader-library-in-this-repository-on-windows)
- [Building On Linux](#building-on-linux)
- [Windows Quick Start](#windows-quick-start)
- [Use `CMake` to Create the Visual Studio Project Files](#use-cmake-to-create-the-visual-studio-project-files)
- [Build the Solution From the Command Line](#build-the-solution-from-the-command-line)
- [Build the Solution With Visual Studio](#build-the-solution-with-visual-studio)
- [Windows Install Target](#windows-install-target)
- [Building On Linux](#building-on-linux)
- [Linux Development Environment Requirements](#linux-development-environment-requirements)
- [Required Package List](#required-package-list)
- [Linux Build](#linux-build)
- [Building on MacOS](#building-on-macos)
- [Linux Quick Start](#linux-quick-start)
- [Use CMake to Create the Make Files](#use-cmake-to-create-the-make-files)
- [Build the Project](#build-the-project)
- [Linux Notes](#linux-notes)
- [WSI Support Build Options](#wsi-support-build-options)
- [Linux Install to System Directories](#linux-install-to-system-directories)
- [Linux 32-bit support](#linux-32-bit-support)
- [Building on MacOS](#building-on-macos)
- [MacOS Development Environment Requirements](#macos-development-environment-requirements)
- [Clone the Repository](#clone-the-repository)
- [MacOS build](#macos-build)
- [Building on Fuchsia](#building-on-fuchsia)
- [Building on QNX](#building-on-qnx)
- [Building with the Unix Makefiles Generator](#building-with-the-unix-makefiles-generator)
- [Building with the Xcode Generator](#building-with-the-xcode-generator)
- [Building on Fuchsia](#building-on-fuchsia)
- [SDK Symbols](#sdk-symbols)
- [Building on QNX](#building-on-qnx)
- [Cross Compilation](#cross-compilation)
- [Unknown function handling which requires explicit assembly implementations](#unknown-function-handling-which-requires-explicit-assembly-implementations)
- [Platforms which fully support unknown function handling](#platforms-which-fully-support-unknown-function-handling)
- [Link Time Optimization](#link-time-optimization)
- [Tests](#tests)
## Contributing to the Repository
@ -53,8 +78,15 @@ indicated by *install_dir*:
- *install_dir*`/lib` : The Vulkan loader library
- *install_dir*`/bin` : The Vulkan loader library DLL (Windows)
The `uninstall` target can be used to remove the above files from the install
directory.
## Build Requirements
1. `C99` capable compiler
2. `CMake` version 3.17.2 or greater
3. `Git`
### Test Requirements
1. `C++17` capable compiler
## Repository Set-Up
@ -64,20 +96,14 @@ This repository does not contain a Vulkan-capable driver. You will need to
obtain and install a Vulkan driver from your graphics hardware vendor or from
some other suitable source if you intend to run Vulkan applications.
### Download the Repository
To create your local git repository:
git clone https://github.com/KhronosGroup/Vulkan-Loader.git
### Repository Dependencies
This repository attempts to resolve some of its dependencies by using
components found from the following places, in this order:
1. CMake or Environment variable overrides (e.g., -DVULKAN_HEADERS_INSTALL_DIR)
1. LunarG Vulkan SDK, located by the `VULKAN_SDK` environment variable
1. System-installed packages, mostly applicable on Linux
1. CMake or Environment variable overrides (e.g., -D VULKAN_HEADERS_INSTALL_DIR)
2. System-installed packages, mostly applicable on Linux
Dependencies that cannot be resolved by the SDK or installed packages must be
resolved with the "install directory" override and are listed below. The
@ -87,24 +113,31 @@ version of that dependency.
#### Vulkan-Headers
This repository has a required dependency on the [Vulkan Headers repository](https://github.com/KhronosGroup/Vulkan-Headers).
You must clone the headers repository and build its `install` target before
building this repository. The Vulkan-Headers repository is required because it
contains the Vulkan API definition files (registry) that are required to build
the loader. You must also take note of the headers install directory and pass
it on the CMake command line for building this repository, as described below.
The Vulkan-Headers repository contains the Vulkan API definition files that are
required to build the loader.
#### Test Dependencies
The loader tests depend on the [Google Test](https://github.com/google/googletest) library and
on Windows platforms depends on the [Microsoft Detours](https://github.com/microsoft/Detours) library.
To build the tests, pass the `-DUPDATE_DEPS=ON` and `-DBUILD_TESTS=ON` options when generating the project:
To build the tests, pass both `-D UPDATE_DEPS=ON` and `-D BUILD_TESTS=ON` options when generating the project:
```bash
cmake ... -DUPDATE_DEPS=ON -DBUILD_TESTS=ON ...
cmake ... -D UPDATE_DEPS=ON -D BUILD_TESTS=ON ...
```
This will ensure googletest and detours is downloaded and the appropriate version is used.
### Build and Install Directories
### Warnings as errors off by default!
By default `BUILD_WERROR` is `OFF`. The idiom for open source projects is to NOT enable warnings as errors.
System/language package managers have to build on multiple different platforms and compilers.
By defaulting to `ON` we cause issues for package managers since there is no standard way to disable warnings.
Add `-D BUILD_WERROR=ON` to your workflow
### Build and Install Directory Locations
A common convention is to place the `build` directory in the top directory of
the repository and place the `install` directory as a child of the `build`
@ -115,11 +148,11 @@ although you can place these directories in any location.
There is a Python utility script, `scripts/update_deps.py`, that you can use
to gather and build the dependent repositories mentioned above.
This program also uses information stored in the `scripts/known-good.json` file
This program uses information stored in the `scripts/known-good.json` file
to checkout dependent repository revisions that are known to be compatible with
the revision of this repository that you currently have checked out.
You can choose to do this manually or automatically.
You can choose to do this automatically or manually.
The first step to either is cloning the Vulkan-Loader repo and stepping into
that newly cloned folder:
@ -128,6 +161,16 @@ that newly cloned folder:
cd Vulkan-Loader
```
#### Automatically
On the other hand, if you choose to let the CMake scripts do all the
heavy-lifting, you may just trigger the following CMake commands:
```
cmake -S . -B build -D UPDATE_DEPS=On
cmake --build build
```
#### Manually
To manually update the dependencies you now must create the build folder, and
@ -136,7 +179,7 @@ run the update deps script followed by the necessary CMake build commands:
```
mkdir build
cd build
../scripts/update_deps.py
python ../scripts/update_deps.py
cmake -C helper.cmake ..
cmake --build .
```
@ -146,22 +189,16 @@ run the update deps script followed by the necessary CMake build commands:
- You may need to adjust some of the CMake options based on your platform. See
the platform-specific sections later in this document.
- The `update_deps.py` script fetches and builds the dependent repositories in
the current directory when it is invoked. In this case, they are built in
the `build` directory.
- The `build` directory is also being used to build this
(Vulkan-ValidationLayers) repository. But there shouldn't be any conflicts
inside the `build` directory between the dependent repositories and the
build files for this repository.
the current directory when it is invoked.
- The `--dir` option for `update_deps.py` can be used to relocate the
dependent repositories to another arbitrary directory using an absolute or
relative path.
- The `update_deps.py` script generates a file named `helper.cmake` and places
it in the same directory as the dependent repositories (`build` in this
case). This file contains CMake commands to set the CMake `*_INSTALL_DIR`
variables that are used to point to the install artifacts of the dependent
repositories. You can use this file with the `cmake -C` option to set these
variables when you generate your build files with CMake. This lets you avoid
entering several `*_INSTALL_DIR` variable settings on the CMake command line.
it in the same directory as the dependent repositories.
This file contains CMake commands to set the CMake `*_INSTALL_DIR` variables
that are used to point to the install artifacts of the dependent repositories.
The `-C helper.cmake` option is used to set these variables when you generate
the build files.
- If using "MINGW" (Git For Windows), you may wish to run
`winpty update_deps.py` in order to avoid buffering all of the script's
"print" output until the end and to retain the ability to interrupt script
@ -169,50 +206,33 @@ run the update deps script followed by the necessary CMake build commands:
- Please use `update_deps.py --help` to list additional options and read the
internal documentation in `update_deps.py` for further information.
#### Automatically
On the other hand, if you choose to let the CMake scripts do all the
heavy-lifting, you may just trigger the following CMake commands:
```
cmake -S. -Bbuild -DUPDATE_DEPS=On
cmake --build build
```
##### Notes About the Automatic Option
- You may need to adjust some of the CMake options based on your platform. See
the platform-specific sections later in this document.
- The `build` directory is also being used to build this
(Vulkan-ValidationLayers) repository. But there shouldn't be any conflicts
inside the `build` directory between the dependent repositories and the
build files for this repository.
### Generated source code
This repository contains generated source code in the `loader/generated`
directory which is not intended to be modified directly. Instead, changes should be
made to the corresponding generator in the `scripts` directory. The source files can
then be regenerated using `scripts/generate_source.py`:
directory which is not intended to be modified directly.
Instead, changes should be made to the corresponding generator in the `scripts` directory.
The source files can then be regenerated using `scripts/generate_source.py`.
python3 scripts/generate_source.py PATH_TO_VULKAN_HEADERS_REGISTRY_DIR
Run `python scripts/generate_source.py --help` to see how to invoke it.
A helper CMake target `VulkanLoader_generated_source` is also provided to simplify
the invocation of `scripts/generate_source.py` from the build directory:
A helper CMake target `loader_codegen` is also provided to simplify the invocation of `scripts/generate_source.py`.
cmake --build . --target VulkanLoader_generated_source
Note: By default this helper target is disabled. To enable it, add `-D LOADER_CODEGEN=ON`
to CMake, as shown below.
```
cmake -S . -B build -D LOADER_CODEGEN=ON
cmake --build . --target loader_codegen
```
### Build Options
When generating native platform build files through CMake, several options can
be specified to customize the build. Some of the options are binary on/off
options, while others take a string as input. The following is a table of all
on/off options currently supported by this repository:
When generating build files through CMake, several options can be specified to
customize the build.
The following is a table of all on/off options currently supported by this repository:
| Option | Platform | Default | Description |
| ---------------------------- | -------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| ------------------------------- | ------------- | ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| BUILD_TESTS | All | `OFF` | Controls whether or not the loader tests are built. |
| BUILD_WSI_XCB_SUPPORT | Linux | `ON` | Build the loader with the XCB entry points enabled. Without this, the XCB headers should not be needed, but the extension `VK_KHR_xcb_surface` won't be available. |
| BUILD_WSI_XLIB_SUPPORT | Linux | `ON` | Build the loader with the Xlib entry points enabled. Without this, the X11 headers should not be needed, but the extension `VK_KHR_xlib_surface` won't be available. |
@ -220,15 +240,19 @@ on/off options currently supported by this repository:
| BUILD_WSI_DIRECTFB_SUPPORT | Linux | `OFF` | Build the loader with the DirectFB entry points enabled. Without this, the DirectFB headers should not be needed, but the extension `VK_EXT_directfb_surface` won't be available. |
| BUILD_WSI_SCREEN_QNX_SUPPORT | QNX | `OFF` | Build the loader with the QNX Screen entry points enabled. Without this the extension `VK_QNX_screen_surface` won't be available. |
| ENABLE_WIN10_ONECORE | Windows | `OFF` | Link the loader to the [OneCore](https://msdn.microsoft.com/en-us/library/windows/desktop/mt654039.aspx) umbrella library, instead of the standard Win32 ones. |
| USE_CCACHE | Linux | `OFF` | Enable caching with the CCache program. |
| USE_GAS | Linux | `ON` | Controls whether to build assembly files with the GNU assembler, else fallback to C code. |
| USE_MASM | Windows | `ON` | Controls whether to build assembly files with MS assembler, else fallback to C code |
| BUILD_STATIC_LOADER | macOS | `OFF` | This allows the loader to be built as a static library on macOS. Not tested, use at your own risk. |
| LOADER_ENABLE_ADDRESS_SANITIZER | Linux & macOS | `OFF` | Enables Address Sanitizer in the loader and tests. |
| LOADER_ENABLE_THREAD_SANITIZER | Linux & macOS | `OFF` | Enables Thread Sanitizer in the loader and tests. |
| LOADER_USE_UNSAFE_FILE_SEARCH | All | `OFF` | Disables security policies that prevent unsecure locations from being used when running with elevated permissions. |
| LOADER_CODEGEN | All | `OFF` | Creates a helper CMake target to generate code. |
NOTE: `LOADER_USE_UNSAFE_FILE_SEARCH` should NOT be enabled except in very specific contexts (like isolated test environments)!
The following is a table of all string options currently supported by this repository:
| Option | Platform | Default | Description |
| --------------------------- | ----------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| CMAKE_OSX_DEPLOYMENT_TARGET | MacOS | `10.12` | The minimum version of MacOS for loader deployment. |
| --------------------- | ----------- | ----------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
| FALLBACK_CONFIG_DIRS | Linux/MacOS | `/etc/xdg` | Configuration path(s) to use instead of `XDG_CONFIG_DIRS` if that environment variable is unavailable. The default setting is freedesktop compliant. |
| FALLBACK_DATA_DIRS | Linux/MacOS | `/usr/local/share:/usr/share` | Configuration path(s) to use instead of `XDG_DATA_DIRS` if that environment variable is unavailable. The default setting is freedesktop compliant. |
| BUILD_DLL_VERSIONINFO | Windows | `""` (empty string) | Allows setting the Windows specific version information for the Loader DLL. Format is "major.minor.patch.build". |
@ -243,12 +267,11 @@ These variables should be set using the `-D` option when invoking CMake to gener
- Any Personal Computer version supported by Microsoft
- Microsoft [Visual Studio](https://www.visualstudio.com/)
- Versions
- [2015](https://www.visualstudio.com/vs/older-downloads/)
- [2017](https://www.visualstudio.com/vs/older-downloads/)
- [2019](https://www.visualstudio.com/vs/downloads/)
- [2022](https://www.visualstudio.com/vs/downloads/)
- [2019](https://www.visualstudio.com/vs/older-downloads/)
- The Community Edition of each of the above versions is sufficient, as
well as any more capable edition.
- [CMake 3.10.2](https://cmake.org/files/v3.10/cmake-3.10.2-win64-x64.zip) is recommended.
- [CMake 3.17.2](https://cmake.org/files/v3.17/cmake-3.17.2-win64-x64.zip) is recommended.
- Use the installer option to add CMake to the system PATH
- Git Client Support
- [Git for Windows](http://git-scm.com/download/win) is a popular solution
@ -271,7 +294,7 @@ Open a developer command prompt and enter:
cd Vulkan-Loader
mkdir build
cd build
cmake -A x64 -DVULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir ..
cmake -A x64 -D UPDATE_DEPS=ON ..
cmake --build .
The above commands instruct CMake to find and use the default Visual Studio
@ -279,10 +302,6 @@ installation to generate a Visual Studio solution and projects for the x64
architecture. The second CMake command builds the Debug (default)
configuration of the solution.
Note that if you do not wish to use a developer command prompt, you may either
run either `vcvars64.bat` or `vcvars32.bat` to set the required environment
variables.
#### Use `CMake` to Create the Visual Studio Project Files
Change your current directory to the top of the cloned repository directory,
@ -291,26 +310,24 @@ create a build directory and generate the Visual Studio project files:
cd Vulkan-Loader
mkdir build
cd build
cmake -A x64 -DVULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir ..
cmake -D UPDATE_DEPS=ON -G "Visual Studio 16 2019" -A x64 ..
> Note: The `..` parameter tells `cmake` the location of the top of the
> repository. If you place your build directory someplace else, you'll need to
> specify the location of the repository top differently.
> specify the location of the repository differently.
The `-A` option is used to select either the "Win32" or "x64" architecture.
The `-G` option is used to select the generator
If a generator for a specific version of Visual Studio is required, you can
specify it for Visual Studio 2015, for example, with:
Supported Visual Studio generators:
* `Visual Studio 17 2022`
* `Visual Studio 16 2019`
64-bit: -G "Visual Studio 14 2015 Win64"
32-bit: -G "Visual Studio 14 2015"
See this [list](#cmake-visual-studio-generators) of other possible generators
for Visual Studio.
The `-A` option is used to select either the "Win32", "x64", or "ARM64 architecture.
When generating the project files, the absolute path to a Vulkan-Headers
install directory must be provided. This can be done by setting the
`VULKAN_HEADERS_INSTALL_DIR` environment variable or by setting the
install directory must be provided. This can be done automatically by the
`-D UPDATE_DEPS=ON` option, by directly setting the
`VULKAN_HEADERS_INSTALL_DIR` environment variable, or by setting the
`VULKAN_HEADERS_INSTALL_DIR` CMake variable with the `-D` CMake option. In
either case, the variable should point to the installation directory of a
Vulkan-Headers repository built with the install target.
@ -347,8 +364,8 @@ the primary build artifacts to a specific location using a "bin, include, lib"
style directory structure. This may be useful for collecting the artifacts and
providing them to another project that is dependent on them.
The default location is `$CMAKE_BINARY_DIR\install`, but can be changed with
the `CMAKE_INSTALL_PREFIX` variable when first generating the project build
The default location is `$CMAKE_CURRENT_BINARY_DIR\install`, but can be changed
with the `CMAKE_INSTALL_PREFIX` variable when first generating the project build
files with CMake.
You can build the install target from the command line with:
@ -357,81 +374,15 @@ You can build the install target from the command line with:
or build the `INSTALL` target from the Visual Studio solution explorer.
### Windows Tests
The Vulkan-Loader repository contains some simple unit tests for the loader
but no other test clients.
To run the loader test script, open a Powershell Console, change to the
`build\tests` directory, and run:
For Release builds:
.\run_all_tests.ps1
For Debug builds:
.\run_all_tests.ps1 -Debug
This script will run the following tests:
- `vk_loader_validation_tests`:
Vulkan loader handle wrapping, allocation callback, and loader/layer interface tests
You can also change to either `build\tests\Debug` or `build\tests\Release`
(depending on which one you built) and run the executable tests (`*.exe`)
files from there.
### Windows Notes
#### CMake Visual Studio Generators
The chosen generator should match one of the Visual Studio versions that you
have installed. Generator strings that correspond to versions of Visual Studio
include:
| Build Platform | 64-bit Generator | 32-bit Generator |
| ---------------------------- | ----------------------------- | ----------------------- |
| Microsoft Visual Studio 2015 | "Visual Studio 14 2015 Win64" | "Visual Studio 14 2015" |
| Microsoft Visual Studio 2017 | "Visual Studio 15 2017 Win64" | "Visual Studio 15 2017" |
| Microsoft Visual Studio 2019 | "Visual Studio 16 2019" | "Visual Studio 16 2019" |
Note that with Visual Studio 2019, the architecture will need to be specified with the `-A`
flag for 64-bit builds.
#### Using The Vulkan Loader Library in this Repository on Windows
Vulkan programs must be able to find and use the Vulkan loader
(`vulkan-1.dll`) library as well as any other libraries the program requires.
One convenient way to do this is to copy the required libraries into the same
directory as the program. The projects in this solution copy the Vulkan loader
library and the "googletest" libraries to the `build\tests\Debug` or the
`build\tests\Release` directory, which is where the
`vk_loader_validation_test.exe` executable is found, depending on what
configuration you built. (The loader validation tests use the "googletest"
testing framework.)
Other techniques include placing the library in a system folder
(C:\Windows\System32) or in a directory that appears in the `PATH` environment
variable.
See the `LoaderAndLayerInterface` document in the `loader` folder in this
repository for more information on how the loader finds driver libraries and
layer libraries. The document also describes both how ICDs and layers should
be packaged, and how developers can point to ICDs and layers within their
builds.
## Building On Linux
### Linux Development Environment Requirements
This repository has been built and tested on the two most recent Ubuntu LTS
versions. Currently, the oldest supported version is Ubuntu 16.04, meaning
that the minimum officially supported C++11 compiler version is GCC 5.4.0,
although earlier versions may work. It should be straightforward to adapt this
repository to other Linux distributions.
versions, although earlier versions may work.
It is be straightforward to adapt this repository to other Linux distributions.
[CMake 3.10.2](https://cmake.org/files/v3.10/cmake-3.10.2-Linux-x86_64.tar.gz) is recommended.
[CMake 3.17.2](https://cmake.org/files/v3.17/cmake-3.17.2-Linux-x86_64.tar.gz) is recommended.
#### Required Package List
@ -448,7 +399,7 @@ CMake with the `--build` option or `make` to build from the command line.
cd Vulkan-Loader
mkdir build
cd build
cmake -DVULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir ..
cmake -D UPDATE_DEPS=ON ..
make
See below for the details.
@ -461,21 +412,22 @@ create a build directory and generate the make files.
cd Vulkan-Loader
mkdir build
cd build
cmake -DCMAKE_BUILD_TYPE=Debug \
-DVULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir \
-DCMAKE_INSTALL_PREFIX=install ..
cmake -D CMAKE_BUILD_TYPE=Debug \
-D VULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir \
-D CMAKE_INSTALL_PREFIX=install ..
> Note: The `..` parameter tells `cmake` the location of the top of the
> repository. If you place your `build` directory someplace else, you'll need
> to specify the location of the repository top differently.
Use `-DCMAKE_BUILD_TYPE` to specify a Debug or Release build.
Use `-D CMAKE_BUILD_TYPE` to specify a Debug or Release build.
When generating the project files, the absolute path to a Vulkan-Headers
install directory must be provided. This can be done by setting the
`VULKAN_HEADERS_INSTALL_DIR` environment variable or by setting the
`VULKAN_HEADERS_INSTALL_DIR` CMake variable with the `-D` CMake option. In
either case, the variable should point to the installation directory of a
install directory must be provided. This can be done automatically by the
`-D UPDATE_DEPS=ON` option, by directly setting the `VULKAN_HEADERS_INSTALL_DIR`
environment variable, or by setting the `VULKAN_HEADERS_INSTALL_DIR` CMake
variable with the `-D` CMake option.
In either case, the variable should point to the installation directory of a
Vulkan-Headers repository built with the install target.
> Note: For Linux, the default value for `CMAKE_INSTALL_PREFIX` is
@ -496,25 +448,8 @@ You can also use
cmake --build .
If your build system supports ccache, you can enable that via CMake option
`-DUSE_CCACHE=On`
### Linux Notes
#### Using The Vulkan Loader Library in this Repository on Linux
The `vk_loader_validation_tests` executable is linked with an RPATH setting to
allow it to find the Vulkan loader library in the repository's build
directory. This allows the test executable to run and find this Vulkan loader
library without installing the loader library to a directory searched by the
system loader or in the `LD_LIBRARY_PATH`.
If you want to test a Vulkan application that is not built within this
repository with the loader you just built from this repository, you can direct
the application to load it from your build directory:
export LD_LIBRARY_PATH=<path to your repository root>/build/loader
#### WSI Support Build Options
By default, the Vulkan Loader is built with support for the Vulkan-defined WSI
@ -550,7 +485,7 @@ CMake variables to override their defaults. For example, if you would like to
install to `/tmp/build` instead of `/usr/local`, on your CMake command line
specify:
-DCMAKE_INSTALL_PREFIX=/tmp/build
-D CMAKE_INSTALL_PREFIX=/tmp/build
Then run `make install` as before. The install step places the files in
`/tmp/build`. This may be useful for collecting the artifacts and providing
@ -573,76 +508,43 @@ variables `CMAKE_INSTALL_SYSCONFDIR` to rename the `etc` directory and
See the CMake documentation for more details on using these variables to
further customize your installation.
Also see the `LoaderAndLayerInterface` document in the `loader` folder in this
Also see the `LoaderInterfaceArchitecture.md` document in the `docs` folder in this
repository for more information about loader operation.
Note that some executables in this repository (e.g.,
`vk_loader_validation_tests`) use the RPATH linker directive to load the
Vulkan loader from the build directory, `build` in this example. This means
that even after installing the loader to the system directories, these
executables still use the loader from the build directory.
#### Linux Uninstall
To uninstall the files from the system directories, you can execute:
sudo make uninstall
#### Linux Tests
The Vulkan-Loader repository contains some simple unit tests for the loader
but no other test clients.
To run the loader test script, change to the `build/tests` directory, and run:
./run_all_tests.sh
This script will run the following tests:
- `vk_loader_validation_tests`: Vulkan loader handle wrapping, allocation
callback, and loader/layer interface tests
#### Linux 32-bit support
Usage of this repository's contents in 32-bit Linux environments is not
officially supported. However, since this repository is supported on 32-bit
Windows, these modules should generally work on 32-bit Linux.
Here are some notes for building 32-bit targets on a 64-bit Ubuntu "reference"
platform:
The loader supports building in 32-bit Linux environments.
However, it is not nearly as straightforward as it is for Windows.
Here are some notes for building this repo as 32-bit on a 64-bit Ubuntu
"reference" platform:
If not already installed, install the following 32-bit development libraries:
`gcc-multilib g++-multilib libx11-dev:i386`
`gcc-multilib gcc-multilib g++-multilib libc6:i386 libc6-dev-i386 libgcc-s1:i386 libwayland-dev:i386 libxrandr-dev:i386`
This list may vary depending on your distribution and which windowing systems
you are building for.
Set up your environment for building 32-bit targets:
export ASFLAGS=--32
export CFLAGS=-m32
export CXXFLAGS=-m32
export PKG_CONFIG_LIBDIR=/usr/lib/i386-linux-gnu
export LDFLAGS=-m32
export ASFLAGS=--32
Again, your PKG_CONFIG configuration may be different, depending on your
distribution.
Your PKG_CONFIG configuration may be different, depending on your distribution.
Finally, rebuild the repository using `cmake` and `make`, as explained above.
Finally, build the repository normally as explained above.
These notes are taken from the Github Actions workflow `linux-32` which is run
regularly as a part of CI.
## Building on MacOS
### MacOS Development Environment Requirements
Tested on OSX version 10.12.6
Setup Homebrew and components
- Follow instructions on [brew.sh](http://brew.sh) to get Homebrew installed.
/usr/bin/ruby -e "$(curl -fsSL \
https://raw.githubusercontent.com/Homebrew/install/master/install)"
- Ensure Homebrew is at the beginning of your PATH:
export PATH=/usr/local/bin:$PATH
@ -653,37 +555,29 @@ Setup Homebrew and components
### Clone the Repository
Clone the Vulkan-ValidationLayers repository:
Clone the Vulkan-Loader repository:
git clone https://github.com/KhronosGroup/Vulkan-ValidationLayers.git
git clone https://github.com/KhronosGroup/Vulkan-Loader.git
### MacOS build
[CMake 3.10.2](https://cmake.org/files/v3.10/cmake-3.10.2-Darwin-x86_64.tar.gz) is recommended.
#### CMake Generators
This repository uses CMake to generate build or project files that are then
used to build the repository. The CMake generators explicitly supported in
this repository are:
- Unix Makefiles
- Xcode
[CMake 3.17.2](https://cmake.org/files/v3.17/cmake-3.17.2-Darwin-x86_64.tar.gz) is recommended.
#### Building with the Unix Makefiles Generator
This generator is the default generator.
When generating the project files, the absolute path to a Vulkan-Headers
install directory must be provided. This can be done by setting the
`VULKAN_HEADERS_INSTALL_DIR` environment variable or by setting the
install directory must be provided. This can be done automatically by the
`-D UPDATE_DEPS=ON` option, by directly setting the
`VULKAN_HEADERS_INSTALL_DIR` environment variable, or by setting the
`VULKAN_HEADERS_INSTALL_DIR` CMake variable with the `-D` CMake option. In
either case, the variable should point to the installation directory of a
Vulkan-Headers repository built with the install target.
mkdir build
cd build
cmake -DVULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir -DCMAKE_BUILD_TYPE=Debug ..
cmake -D UPDATE_DEPS=ON -D VULKAN_HEADERS_INSTALL_DIR=absolute_path_to_install_dir -D CMAKE_BUILD_TYPE=Debug ..
make
To speed up the build on a multi-core machine, use the `-j` option for `make`
@ -703,44 +597,59 @@ To create and open an Xcode project:
Within Xcode, you can select Debug or Release builds in the project's Build
Settings.
### Using the new macOS loader
If you want to test a Vulkan application with the loader you just built, you
can direct the application to load it from your build directory:
export DYLD_LIBRARY_PATH=<path to your repository>/build/loader
### MacOS Tests
The Vulkan-Loader repository contains some simple unit tests for the loader
but no other test clients.
Before you run these tests, you will need to clone and build the
[MoltenVK](https://github.com/KhronosGroup/MoltenVK) repository.
You will also need to direct your new loader to the MoltenVK ICD:
export VK_DRIVER_FILES=<path to MoltenVK repository>/Package/Latest/MoltenVK/macOS/MoltenVK_icd.json
To run the loader test script, change to the `build/tests` directory in your
Vulkan-Loader repository, and run:
./vk_loader_validation_tests
## Building on Fuchsia
Fuchsia uses the project's GN build system to integrate with the Fuchsia platform build.
### SDK Symbols
The Vulkan Loader is a component of the Fuchsia SDK, so it must explicitly declare its exported symbols in
the file vulkan.symbols.api; see [SDK](https://fuchsia.dev/fuchsia-src/development/sdk).
## Building on QNX
QNX is using its own build system. The proper build environment must be set
under the QNX host development system (Linux, Win64, MacOS) by invoking
the shell/batch script provided with QNX installation.
Then change working directory to the "build-qnx" in this project and type "make".
Then change working directory to the "scripts/qnx" in this project and type "make".
It will build the ICD loader for all CPU targets supported by QNX.
### SDK Symbols
## Cross Compilation
The Vulkan Loader is a component of the Fuchsia SDK, so it must explicitly declare its exported symbols in
the file vulkan.symbols.api; see [SDK](https://fuchsia.dev/fuchsia-src/development/sdk).
While this repo is capable of cross compilation, there are a handful of caveats.
### Unknown function handling which requires explicit assembly implementations
Unknown function handling is only fully supported on select platforms due to the
need for assembly in the implementation.
Platforms not fully supported will have assembly disabled automatically, or
can be manually disabled by setting `USE_GAS` or `USE_MASM` to `OFF`.
#### Platforms which fully support unknown function handling
* 64 bit Windows (x64)
* 32 bit Windows (x86)
* 64 bit Linux (x64)
* 32 bit Linux (x86)
* 64 bit Arm (aarch64)
Platforms not listed will use a fallback C Code path that relies on tail-call optimization to work.
No guarantees are made about the use of the fallback code paths.
### Link Time Optimization
When cross compiling, the use of Link Time Optimization (LTO) and unknown function handling
is not supported. Either LTO needs to be turned off, or the assembly should be disabled.
## Tests
To build tests, make sure that the `BUILD_TESTS` option is set to true. Using
the command line, this looks like `-D BUILD_TESTS=ON`.
This project is configured to run with `ctest`, which makes it easy to run the
tests. To run the tests, change the directory to that of the build direction, and
execute `ctest`.
More details can be found in the [README.md](./tests/README.md) for the tests
directory of this project.

View File

@ -1,6 +1,8 @@
# ~~~
# Copyright (c) 2014-2022 Valve Corporation
# Copyright (c) 2014-2022 LunarG, Inc.
# Copyright (c) 2014-2023 Valve Corporation
# Copyright (c) 2014-2023 LunarG, 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.
@ -14,89 +16,27 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ~~~
cmake_minimum_required(VERSION 3.17.2)
cmake_minimum_required(VERSION 3.10.2)
project(VULKAN_LOADER VERSION 1.3.275 LANGUAGES C)
# Apple: Must be set before enable_language() or project() as it may influence configuration of the toolchain and flags.
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.12" CACHE STRING "Minimum OS X deployment version")
# This variable enables downstream users to customize the target API
# variant (e.g. Vulkan SC)
set(API_TYPE "vulkan")
# If we are building in Visual Studio 2015 and with a CMake version 3.19 or greater, we need to set this variable
# so that CMake will choose a Windows SDK version higher than 10.0.14393.0, as dxgi1_6.h is only found in Windows SDK
# 10.0.17763 and higher.
set(CMAKE_VS_WINDOWS_TARGET_PLATFORM_VERSION_MAXIMUM OFF)
add_subdirectory(scripts)
project(Vulkan-Loader)
set(CMAKE_C_STANDARD 99)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_C_EXTENSIONS OFF)
set(CMAKE_C_VISIBILITY_PRESET "hidden")
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
if (UPDATE_DEPS)
find_package(PythonInterp 3 REQUIRED)
if (CMAKE_GENERATOR_PLATFORM)
set(_target_arch ${CMAKE_GENERATOR_PLATFORM})
else()
if (MSVC_IDE)
message(WARNING "CMAKE_GENERATOR_PLATFORM not set. Using x64 as target architecture.")
endif()
set(_target_arch x64)
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()
set(_build_tests_arg "")
if (NOT BUILD_TESTS)
set(_build_tests_arg "--optional=tests")
endif()
message("********************************************************************************")
message("* NOTE: Adding target vl_update_deps to run as needed for updating *")
message("* dependencies. *")
message("********************************************************************************")
# Add a target so that update_deps.py will run when necessary
# NOTE: This is triggered off of the timestamps of known_good.json and helper.cmake
add_custom_command(OUTPUT ${CMAKE_CURRENT_LIST_DIR}/external/helper.cmake
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scripts/update_deps.py --dir ${CMAKE_CURRENT_LIST_DIR}/external --arch ${_target_arch} --config ${_build_type} --generator "${CMAKE_GENERATOR}" ${_build_tests_arg}
DEPENDS ${CMAKE_CURRENT_LIST_DIR}/scripts/known_good.json)
add_custom_target(vl_update_deps DEPENDS ${CMAKE_CURRENT_LIST_DIR}/external/helper.cmake)
# Check if update_deps.py needs to be run on first cmake run
if (${CMAKE_CURRENT_LIST_DIR}/scripts/known_good.json IS_NEWER_THAN ${CMAKE_CURRENT_LIST_DIR}/external/helper.cmake)
execute_process(
COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_LIST_DIR}/scripts/update_deps.py --dir ${CMAKE_CURRENT_LIST_DIR}/external --arch ${_target_arch} --config ${_build_type} --generator "${CMAKE_GENERATOR}" ${_build_tests_arg}
WORKING_DIRECTORY ${CMAKE_CURRENT_LIST_DIR}
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()
endif()
include(${CMAKE_CURRENT_LIST_DIR}/external/helper.cmake)
else()
message("********************************************************************************")
message("* NOTE: Not adding target to run update_deps.py automatically. *")
message("********************************************************************************")
find_package(PythonInterp 3 QUIET)
endif()
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake")
find_package(PythonInterp 3 QUIET)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
option(BUILD_TESTS "Build Tests" OFF)
if(BUILD_TESTS)
enable_testing()
endif()
if(APPLE)
option(BUILD_STATIC_LOADER "Build a loader that can be statically linked" OFF)
# By default, loader & tests are built without sanitizers
# Use these options to force a specific sanitizer on the loader and test executables
if (UNIX)
option(LOADER_ENABLE_ADDRESS_SANITIZER "Linux & macOS only: Advanced memory checking" OFF)
option(LOADER_ENABLE_THREAD_SANITIZER "Linux & macOS only: Advanced thread checking" OFF)
endif()
if(WIN32)
@ -105,51 +45,10 @@ if(WIN32)
set(BUILD_DLL_VERSIONINFO "" CACHE STRING "Set the version to be used in the loader.rc file. Default value is the currently generated header version")
endif()
if(BUILD_STATIC_LOADER)
message(WARNING "The BUILD_STATIC_LOADER option has been set. Note that this will only work on MacOS and is not supported "
"or tested as part of the loader. Use it at your own risk.")
endif()
if (TARGET Vulkan::Headers)
message(STATUS "Using Vulkan headers from Vulkan::Headers target")
get_target_property(VulkanHeaders_INCLUDE_DIRS Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES)
get_target_property(VulkanRegistry_DIR Vulkan::Registry INTERFACE_INCLUDE_DIRECTORIES)
else()
find_package(VulkanHeaders)
if(NOT ${VulkanHeaders_FOUND})
message(FATAL_ERROR "Could not find Vulkan headers path. This can be fixed by setting VULKAN_HEADERS_INSTALL_DIR to an "
"installation of the Vulkan-Headers repository.")
endif()
if(NOT ${VulkanRegistry_FOUND})
message(FATAL_ERROR "Could not find Vulkan registry path. This can be fixed by setting VULKAN_HEADERS_INSTALL_DIR to an "
"installation of the Vulkan-Headers repository.")
endif()
# set up the Vulkan::Headers target for consistency
add_library(vulkan-headers INTERFACE)
target_include_directories(vulkan-headers SYSTEM INTERFACE "${VulkanHeaders_INCLUDE_DIRS}")
add_library(Vulkan::Headers ALIAS vulkan-headers)
endif()
option(USE_CCACHE "Use ccache" OFF)
if(USE_CCACHE)
find_program(CCACHE_FOUND ccache)
if(CCACHE_FOUND)
set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ccache)
endif()
endif()
find_package(VulkanHeaders CONFIG QUIET)
include(GNUInstallDirs)
if(UNIX AND NOT APPLE) # i.e.: Linux
include(FindPkgConfig)
endif()
if(APPLE)
# CMake versions 3 or later need CMAKE_MACOSX_RPATH defined. This avoids the CMP0042 policy message.
set(CMAKE_MACOSX_RPATH 1)
endif()
set(GIT_BRANCH_NAME "--unknown--")
set(GIT_TAG_INFO "--unknown--")
find_package (Git)
@ -172,11 +71,6 @@ if (GIT_FOUND AND EXISTS "${CMAKE_CURRENT_LIST_DIR}/.git/HEAD")
endif()
endif()
if(WIN32 AND CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
# Windows: if install locations not set by user, set install prefix to "<build_dir>\install".
set(CMAKE_INSTALL_PREFIX "${CMAKE_BINARY_DIR}/install" CACHE PATH "default install path" FORCE)
endif()
# Enable IDE GUI folders. "Helper targets" that don't have interesting source code should set their FOLDER property to this
set_property(GLOBAL PROPERTY USE_FOLDERS ON)
set(LOADER_HELPER_FOLDER "Helper Targets")
@ -190,145 +84,104 @@ if(UNIX)
"System-wide search directory. If not set or empty, CMAKE_INSTALL_FULL_SYSCONFDIR and /etc are used.")
endif()
# Because we use CMake 3.10.2, we can't use the policy which would disable adding /W3 by default. In the interim, replace the flags
# When this project is updated to 3.15 and above, use the following line.
# cmake_policy(SET CMP0092 NEW)
string(REGEX REPLACE "/W3" "" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}")
string(REGEX REPLACE "/W3" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
# For MSVC/Windows, replace /GR with an empty string, this prevents warnings of /GR being overriden by /GR-
# Newer CMake versions (3.20) have better solutions for this through policy - using the old
# way while waiting for when updating can occur
string(REPLACE "/GR" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
if(UNIX AND NOT APPLE) # i.e.: Linux
option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON)
option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON)
option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" ON)
option(BUILD_WSI_DIRECTFB_SUPPORT "Build DirectFB WSI support" OFF)
option(BUILD_WSI_SCREEN_QNX_SUPPORT "Build QNX Screen WSI support" OFF)
if(BUILD_WSI_XCB_SUPPORT)
find_package(XCB REQUIRED)
include_directories(SYSTEM ${XCB_INCLUDE_DIR})
endif()
if(BUILD_WSI_XLIB_SUPPORT)
find_package(X11 REQUIRED)
endif()
if(BUILD_WSI_DIRECTFB_SUPPORT)
find_package(DirectFB REQUIRED)
include_directories(SYSTEM ${DIRECTFB_INCLUDE_DIR})
endif()
if(BUILD_WSI_SCREEN_QNX_SUPPORT)
# Part of OS, no additional include directories are required
endif()
endif()
if(WIN32)
option(ENABLE_WIN10_ONECORE "Link the loader with OneCore umbrella libraries" OFF)
endif()
add_library(platform_wsi_defines INTERFACE)
add_library(platform_wsi INTERFACE)
if(WIN32)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_WIN32_KHR)
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_WIN32_KHR)
elseif(ANDROID)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_ANDROID_KHR)
message(FATAL_ERROR "Android build not supported!")
elseif(APPLE)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_MACOS_MVK VK_USE_PLATFORM_METAL_EXT)
elseif(UNIX AND NOT APPLE) # i.e.: Linux
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_METAL_EXT)
if (IOS)
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_IOS_MVK)
endif()
if (CMAKE_SYSTEM_NAME STREQUAL "Darwin")
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_MACOS_MVK)
endif()
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux|BSD|DragonFly|GNU")
option(BUILD_WSI_XCB_SUPPORT "Build XCB WSI support" ON)
option(BUILD_WSI_XLIB_SUPPORT "Build Xlib WSI support" ON)
option(BUILD_WSI_WAYLAND_SUPPORT "Build Wayland WSI support" ON)
option(BUILD_WSI_DIRECTFB_SUPPORT "Build DirectFB WSI support" OFF)
find_package(PkgConfig REQUIRED QUIET) # Use PkgConfig to find Linux system libraries
if(BUILD_WSI_XCB_SUPPORT)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_XCB_KHR)
pkg_check_modules(XCB REQUIRED QUIET IMPORTED_TARGET xcb)
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_XCB_KHR)
target_link_libraries(platform_wsi INTERFACE PkgConfig::XCB)
endif()
if(BUILD_WSI_XLIB_SUPPORT)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_XLIB_KHR VK_USE_PLATFORM_XLIB_XRANDR_EXT)
pkg_check_modules(X11 REQUIRED QUIET IMPORTED_TARGET x11)
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_XLIB_KHR VK_USE_PLATFORM_XLIB_XRANDR_EXT)
target_link_libraries(platform_wsi INTERFACE PkgConfig::X11)
endif()
if(BUILD_WSI_WAYLAND_SUPPORT)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_WAYLAND_KHR)
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_WAYLAND_KHR)
endif()
if(BUILD_WSI_DIRECTFB_SUPPORT)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_DIRECTFB_EXT)
endif()
if(BUILD_WSI_SCREEN_QNX_SUPPORT)
target_compile_definitions(platform_wsi_defines INTERFACE VK_USE_PLATFORM_SCREEN_QNX)
pkg_check_modules(DirectFB QUIET REQUIRED IMPORTED_TARGET directfb)
target_compile_definitions(platform_wsi INTERFACE VK_USE_PLATFORM_DIRECTFB_EXT)
target_link_libraries(platform_wsi INTERFACE PkgConfig::DirectFB)
endif()
elseif(CMAKE_SYSTEM_NAME MATCHES "QNX")
message(FATAL_ERROR "See BUILD.md for QNX build")
elseif(CMAKE_SYSTEM_NAME MATCHES "Fuchsia")
message(FATAL_ERROR "Fuchsia uses Chromium build. See BUILD.gn")
else()
message(FATAL_ERROR "Unsupported Platform!")
endif()
add_library(loader_common_options INTERFACE)
target_compile_definitions(loader_common_options INTERFACE API_NAME="Vulkan")
target_link_libraries(loader_common_options INTERFACE platform_wsi_defines)
target_link_libraries(loader_common_options INTERFACE platform_wsi)
# Enable beta Vulkan extensions
target_compile_definitions(loader_common_options INTERFACE VK_ENABLE_BETA_EXTENSIONS)
target_compile_features(loader_common_options INTERFACE c_std_99)
target_compile_features(loader_common_options INTERFACE cxx_std_11)
set(LOADER_STANDARD_C_PROPERTIES PROPERTIES C_STANDARD 99 C_STANDARD_REQUIRED YES C_EXTENSIONS OFF)
set(LOADER_STANDARD_CXX_PROPERTIES PROPERTIES CXX_STANDARD 11 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS OFF)
option(ENABLE_WERROR "Enable warnings as errors" ON)
option(BUILD_WERROR "Enable warnings as errors")
# Set warnings as errors and the main diagnostic flags
# Must be set first so the warning silencing later on works properly
# Note that clang-cl.exe should use MSVC flavor flags, not GNU
if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC"))
if (ENABLE_WERROR)
if (CMAKE_C_COMPILER_ID STREQUAL "MSVC" OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "MSVC"))
if (BUILD_WERROR)
target_compile_options(loader_common_options INTERFACE /WX)
endif()
target_compile_options(loader_common_options INTERFACE /W4)
elseif(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
elseif(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
# using GCC or Clang with the regular front end
if (ENABLE_WERROR)
if (BUILD_WERROR)
target_compile_options(loader_common_options INTERFACE -Werror)
endif()
target_compile_options(loader_common_options INTERFACE -Wall -Wextra)
endif()
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU" OR CMAKE_CXX_COMPILER_ID STREQUAL "Clang")
target_compile_options(loader_common_options INTERFACE -Wno-unused-parameter -Wno-unused-function -Wno-missing-field-initializers)
if(CMAKE_C_COMPILER_ID MATCHES "GNU|Clang")
target_compile_options(loader_common_options INTERFACE -Wno-missing-field-initializers)
# need to prepend /clang: to compiler arguments when using clang-cl
if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC")
target_compile_options(loader_common_options INTERFACE /clang:-fno-strict-aliasing /clang:-fno-builtin-memcmp)
else()
target_compile_options(loader_common_options INTERFACE -fno-strict-aliasing -fno-builtin-memcmp)
endif()
# For GCC version 7.1 or greater, we need to disable the implicit fallthrough warning since there's no consistent way to satisfy
# all compilers until they all accept the C++17 standard
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
target_compile_options(loader_common_options INTERFACE -Wno-stringop-truncation -Wno-stringop-overflow)
if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 7.1)
target_compile_options(loader_common_options INTERFACE -Wimplicit-fallthrough=0)
if (CMAKE_C_COMPILER_VERSION VERSION_GREATER_EQUAL 7.1)
target_compile_options(loader_common_options INTERFACE -Wshadow=local) #only added in GCC 7
endif()
endif()
if(UNIX)
target_compile_options(loader_common_options INTERFACE -fvisibility=hidden)
endif()
target_compile_options(loader_common_options INTERFACE -Wpointer-arith)
endif()
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC" OR (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC"))
if(CMAKE_C_COMPILER_ID MATCHES "MSVC" OR (CMAKE_C_COMPILER_ID STREQUAL "Clang" AND CMAKE_C_COMPILER_FRONTEND_VARIANT MATCHES "MSVC"))
# /sdl: Enable additional security checks
# /GR-: Disable RTTI
# /guard:cf: Enable control flow guard
# /wd4100: Disable warning on unreferenced formal parameter
# /wd4152: Disable warning on conversion of a function pointer to a data pointer
# /wd4201: Disable warning on anonymous struct/unions
target_compile_options(loader_common_options INTERFACE /GR- /guard:cf /wd4100 /wd4152 /wd4201)
target_compile_options(loader_common_options INTERFACE /sdl /GR- /guard:cf /wd4152 /wd4201)
# Enable control flow guard
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.13.0")
target_link_options(loader_common_options INTERFACE "LINKER:/guard:cf")
else()
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /guard:cf")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /guard:cf")
endif()
# Prevent <windows.h> from polluting the code. guards against things like MIN and MAX
target_compile_definitions(loader_common_options INTERFACE WIN32_LEAN_AND_MEAN)
@ -338,34 +191,34 @@ endif()
# Add git branch and tag info in debug mode
target_compile_definitions(loader_common_options INTERFACE $<$<CONFIG:DEBUG>:DEBUG;GIT_BRANCH_NAME="${GIT_BRANCH_NAME}";GIT_TAG_INFO="${GIT_TAG_INFO}">)
# Check for the existance of the secure_getenv or __secure_getenv commands
include(CheckFunctionExists)
include(CheckIncludeFile)
if (NOT (WIN32 OR APPLE))
# Check for the existance of the secure_getenv or __secure_getenv commands
include(CheckFunctionExists)
check_function_exists(secure_getenv HAVE_SECURE_GETENV)
check_function_exists(__secure_getenv HAVE___SECURE_GETENV)
check_function_exists(secure_getenv HAVE_SECURE_GETENV)
check_function_exists(__secure_getenv HAVE___SECURE_GETENV)
if (HAVE_SECURE_GETENV)
if (HAVE_SECURE_GETENV)
target_compile_definitions(loader_common_options INTERFACE HAVE_SECURE_GETENV)
endif()
if (HAVE___SECURE_GETENV)
endif()
if (HAVE___SECURE_GETENV)
target_compile_definitions(loader_common_options INTERFACE HAVE___SECURE_GETENV)
endif()
if(NOT MSVC AND NOT (HAVE_SECURE_GETENV OR HAVE___SECURE_GETENV))
endif()
if (NOT (HAVE_SECURE_GETENV OR HAVE___SECURE_GETENV))
message(WARNING "Using non-secure environmental lookups. This loader will not properly disable environent variables when run with elevated permissions.")
endif()
endif()
# Optional codegen target
if(PYTHONINTERP_FOUND)
add_custom_target(VulkanLoader_generated_source
COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/generate_source.py
${VulkanRegistry_DIR} --incremental
option(LOADER_CODEGEN "Enable vulkan loader code generation")
if(LOADER_CODEGEN)
find_package(Python3 REQUIRED)
add_custom_target(loader_codegen
COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/generate_source.py
"${VULKAN_HEADERS_INSTALL_DIR}/${CMAKE_INSTALL_DATADIR}/vulkan/registry"
--generated-version ${VulkanHeaders_VERSION} --incremental --api ${API_TYPE}
)
else()
message("WARNING: VulkanLoader_generated_source target requires python 3")
endif()
if(UNIX)
target_compile_definitions(loader_common_options INTERFACE FALLBACK_CONFIG_DIRS="${FALLBACK_CONFIG_DIRS}" FALLBACK_DATA_DIRS="${FALLBACK_DATA_DIRS}")
@ -382,120 +235,10 @@ if(UNIX)
endif()
endif()
# uninstall target
if(NOT TARGET uninstall)
configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/cmake_uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake"
IMMEDIATE
@ONLY)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake)
set_target_properties(uninstall PROPERTIES FOLDER ${LOADER_HELPER_FOLDER})
endif()
add_subdirectory(loader)
if(BUILD_TESTS)
# Set gtest build configuration
# Attempt to enable if it is available.
if(TARGET gtest)
# Already enabled as a target (perhaps by a project enclosing this one)
message(STATUS "Vulkan-Loader/external: " "googletest already configured - using it")
elseif(IS_DIRECTORY "${GOOGLETEST_INSTALL_DIR}/googletest")
set(BUILD_GTEST ON CACHE BOOL "Builds the googletest subproject")
set(BUILD_GMOCK OFF CACHE BOOL "Builds the googlemock subproject")
set(gtest_force_shared_crt ON CACHE BOOL "Link gtest runtimes dynamically" FORCE)
set(BUILD_SHARED_LIBS ON CACHE BOOL "Build shared libraries")
# The googletest directory exists, so enable it as a target.
message(STATUS "Vulkan-Loader/external: " "googletest found - configuring it for tests")
add_subdirectory("${GOOGLETEST_INSTALL_DIR}")
else()
message(SEND_ERROR "Could not find googletest directory. Be sure to run update_deps.py with the --tests option to download the appropriate version of googletest")
set(BUILD_TESTS OFF)
endif()
if (WIN32)
if(TARGET detours)
# Already enabled as a target (perhaps by a project enclosing this one)
message(STATUS "Vulkan-Loader/external: " "detours already configured - using it")
else()
if(IS_DIRECTORY ${DETOURS_INSTALL_DIR})
# The detours directory exists, so enable it as a target.
message(STATUS "Vulkan-Loader/external: " "detours found - configuring it for tests")
else()
message(SEND_ERROR "Could not find detours directory. Be sure to run update_deps.py with the --tests option to download the appropriate version of detours")
set(BUILD_TESTS OFF)
endif()
add_library(detours STATIC
${DETOURS_INSTALL_DIR}/src/creatwth.cpp
${DETOURS_INSTALL_DIR}/src/detours.cpp
${DETOURS_INSTALL_DIR}/src/detours.h
${DETOURS_INSTALL_DIR}/src/detver.h
${DETOURS_INSTALL_DIR}/src/disasm.cpp
${DETOURS_INSTALL_DIR}/src/disolarm.cpp
${DETOURS_INSTALL_DIR}/src/disolarm64.cpp
${DETOURS_INSTALL_DIR}/src/disolia64.cpp
${DETOURS_INSTALL_DIR}/src/disolx64.cpp
${DETOURS_INSTALL_DIR}/src/disolx86.cpp
${DETOURS_INSTALL_DIR}/src/image.cpp
${DETOURS_INSTALL_DIR}/src/modules.cpp
)
target_include_directories(detours PUBLIC ${DETOURS_INSTALL_DIR}/src)
macro(GET_WIN32_WINNT version)
if(WIN32 AND CMAKE_SYSTEM_VERSION)
set(ver ${CMAKE_SYSTEM_VERSION})
string(REGEX MATCH "^([0-9]+).([0-9])" ver ${ver})
string(REGEX MATCH "^([0-9]+)" verMajor ${ver})
# Check for Windows 10, b/c we'll need to convert to hex 'A'.
if("${verMajor}" MATCHES "10")
set(verMajor "A")
string(REGEX REPLACE "^([0-9]+)" ${verMajor} ver ${ver})
endif("${verMajor}" MATCHES "10")
# Remove all remaining '.' characters.
string(REPLACE "." "" ver ${ver})
# Prepend each digit with a zero.
string(REGEX REPLACE "([0-9A-Z])" "0\\1" ver ${ver})
set(${version} "0x${ver}")
endif()
endmacro()
set(DETOURS_MAJOR_VERSION "4")
set(DETOURS_MINOR_VERSION "0")
set(DETOURS_PATCH_VERSION "1")
set(DETOURS_VERSION "${DETOURS_MAJOR_VERSION}.${DETOURS_MINOR_VERSION}.${DETOURS_PATCH_VERSION}")
target_include_directories(detours PUBLIC ${DETOURS_INSTALL_DIR}/src)
if(MSVC_VERSION GREATER_EQUAL 1700)
target_compile_definitions(detours PUBLIC DETOURS_CL_17_OR_NEWER)
endif(MSVC_VERSION GREATER_EQUAL 1700)
GET_WIN32_WINNT(ver)
if(ver EQUAL 0x0700)
target_compile_definitions(detours PUBLIC _USING_V110_SDK71_ DETOURS_WIN_7)
endif(ver EQUAL 0x0700)
target_compile_definitions(detours PUBLIC "_WIN32_WINNT=${ver}")
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
target_compile_definitions(detours PUBLIC "DETOURS_TARGET_PROCESSOR=X64" DETOURS_X64 DETOURS_64BIT _AMD64_)
else("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
target_compile_definitions(detours PUBLIC "DETOURS_TARGET_PROCESSOR=X86" DETOURS_X86 _X86_)
endif("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
target_compile_definitions(detours PUBLIC "DETOURS_VERSION=0x4c0c1" WIN32_LEAN_AND_MEAN)
if(MSVC)
target_compile_definitions(detours PUBLIC "_CRT_SECURE_NO_WARNINGS=1")
set_target_properties(detours PROPERTIES COMPILE_FLAGS /EHsc)
endif()
# Silence errors found in clang-cl
if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang" AND "${CMAKE_CXX_SIMULATE_ID}" MATCHES "MSVC")
target_compile_options(detours PRIVATE -Wno-sizeof-pointer-memaccess -Wno-microsoft-goto -Wno-microsoft-cast)
endif()
endif()
endif()
if (BUILD_TESTS)
add_subdirectory(tests ${CMAKE_BINARY_DIR}/tests)
endif()
option(BUILD_TESTS "Build Tests")
if (BUILD_TESTS)
enable_testing()
add_subdirectory(tests)
endif()

View File

@ -42,7 +42,7 @@ current assignee.
[submitting a pull request](https://help.github.com/articles/using-pull-requests/).
* Please read and adhere to the style and process
[guidelines](#coding-conventions-and-formatting) enumerated below.
* Please base your fixes on the master branch.
* Please base your fixes on the `main` branch.
SDK branches are generally not updated except for critical fixes needed to
repair an SDK release.
* Provide one or more tests which show a failure for the issue before your changes
@ -74,7 +74,7 @@ current assignee.
clang-format settings which are found and used automatically by clang-format.
* **clang-format** binaries are available from the LLVM orginization, here:
[LLVM](https://clang.llvm.org/).
Our CI system (Travis-CI) currently uses clang-format version 5.0.0 to
Our CI system currently uses clang-format version 16 to
check that the lines of code you have changed are formatted properly.
It is recommended that you use the same version to format your code prior
to submission.
@ -107,7 +107,7 @@ Please ensure that the repository compiles and passes tests without
error for each commit in your pull request.
Note that to be accepted into the repository, the pull request must
pass all tests on all supported platforms.
The automatic Github Travis and AppVeyor continuous integration features
The automatic Github continuous integration features
will assist in enforcing this requirement.*
#### Generated Source Code
@ -115,9 +115,8 @@ will assist in enforcing this requirement.*
The `loader/generated` directory contains source code that is created by several
generator scripts in the `scripts` directory. All changes to these scripts _must_ be submitted with the
corresponding generated output to keep the repository self-consistent. This requirement is enforced by both
Travis CI and AppVeyor test configurations. Regenerate source files after modifying any of the generator
scripts and before building and testing your changes. More details can be found in
[BUILD.md](https://github.com/KhronosGroup/Vulkan-Loader/blob/master/BUILD.md#generated-source-code).
GitHub actions. Regenerate source files after modifying any of the generator scripts and before building
and testing your changes. More details can be found in [BUILD.md](BUILD.md#generated-source-code).
#### Testing Your Changes
@ -139,21 +138,6 @@ scripts and before building and testing your changes. More details can be found
* The indent is 4 spaces.
* CMake functions are lower-case.
* Variable and keyword names are upper-case.
* The format is defined by
[cmake-format](https://github.com/cheshirekow/cmake_format)
using the `.cmake-format.py` file in the repository to define the settings.
See the cmake-format page for information about its simple markup for comments.
* Disable reformatting of a block of comment lines by inserting
a `# ~~~` comment line before and after that block.
* Disable any formatting of a block of lines by surrounding that block with
`# cmake-format: off` and `# cmake-format: on` comment lines.
* To install: `sudo pip install cmake_format`
* To run: `cmake-format --in-place $FILENAME`
* **IMPORTANT (June 2018)** cmake-format v0.3.6 has a
[bug]( https://github.com/cheshirekow/cmake_format/issues/50)
that can corrupt the formatting of comment lines in CMake files.
A workaround is to use the following command _before_ running cmake-format:
`sed --in-place='' 's/^ *#/#/' $FILENAME`
### Contributor License Agreement (CLA)

View File

@ -1,10 +1,6 @@
# Vulkan Ecosystem Components
# Vulkan Loader
This project provides the Khronos official Vulkan ICD desktop loader for Windows, Linux, and MacOS.
## CI Build Status
[![Build Status](https://github.com/KhronosGroup/Vulkan-Loader/workflows/CI%20Build/badge.svg?branch=master)](https://github.com/KhronosGroup/Vulkan-Loader/actions)
This project provides the Khronos official Vulkan Loader for all platforms except [Android](https://android.googlesource.com/platform/frameworks/native/+/master/vulkan/)
## Introduction
@ -31,29 +27,25 @@ The following components are available in this repository:
## Information for Developing or Contributing
Please see the [CONTRIBUTING.md](CONTRIBUTING.md) file in this repository for more details.
Please see the [GOVERNANCE.md](GOVERNANCE.md) file in this repository for repository
management details.
Please see the [GOVERNANCE.md](GOVERNANCE.md) file in this repository for repository management details.
## How to Build and Run
[BUILD.md](BUILD.md)
Includes directions for building all components.
[BUILD.md](BUILD.md) includes directions for building all components.
Architecture and interface information for the loader is in
[docs/LoaderInterfaceArchitecture.md](docs/LoaderInterfaceArchitecture.md).
Architecture and interface information for the loader is in [docs/LoaderInterfaceArchitecture.md](docs/LoaderInterfaceArchitecture.md).
## Version Tagging Scheme
Updates to the `Vulkan-Loader` repository which correspond to a new Vulkan specification release are tagged using the following format: `v<`_`version`_`>` (e.g., `v1.1.96`).
Updates to this repository which correspond to a new Vulkan specification release are tagged using the following format: `v<`_`version`_`>` (e.g., `v1.3.266`).
**Note**: Marked version releases have undergone thorough testing but do not imply the same quality level as SDK tags. SDK tags follow the `sdk-<`_`version`_`>.<`_`patch`_`>` format (e.g., `sdk-1.1.92.0`).
**Note**: Marked version releases have undergone thorough testing but do not imply the same quality level as SDK tags. SDK tags follow the `vulkan-sdk-<`_`version`_`>.<`_`patch`_`>` format (e.g., `vulkan-sdk-1.3.266.0`).
This scheme was adopted following the 1.1.96 Vulkan specification release.
This scheme was adopted following the `1.3.266` Vulkan specification release.
## License
This work is released as open source under a Apache-style license from Khronos
including a Khronos copyright.
This work is released as open source under a Apache-style license from Khronos including a Khronos copyright.
## Acknowledgements

13
SECURITY.md Normal file
View File

@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
Security updates are applied only to the latest release.
## Reporting a Vulnerability
If you have discovered a security vulnerability in this project, please report it privately. **Do not disclose it as a public issue.** This gives us time to work with you to fix the issue before public exposure, reducing the chance that the exploit will be used before a patch is released.
Please disclose it at [security advisory](https://github.com/KhronosGroup/Vulkan-Loader/security/advisories/new).
This project is maintained by a team of volunteers on a reasonable-effort basis. As such, please give us at least 90 days to work on a fix before public exposure.

View File

@ -1,57 +0,0 @@
vars = {
'chromium_git': 'https://chromium.googlesource.com',
}
deps = {
'build': {
'url': '{chromium_git}/chromium/src/build.git@45ab3c89af6fc3126b0ca5a7836f0db85ad1ba0e',
},
'buildtools': {
'url': '{chromium_git}/chromium/src/buildtools.git@204a35a2a64f7179f8b76d7a0385653690839e21',
},
'testing': {
'url': '{chromium_git}/chromium/src/testing@3993ef1f527b206d8d3bf3f9824f4fe0e4bbdb0e',
},
'tools/clang': {
'url': '{chromium_git}/chromium/src/tools/clang.git@04b99e7bf9160d551c3a5562f583014b6afc90f9',
},
}
hooks = [
# Pull clang-format binaries using checked-in hashes.
{
'name': 'clang_format_linux',
'pattern': '.',
'condition': 'host_os == "linux"',
'action': [ 'download_from_google_storage',
'--no_resume',
'--platform=linux*',
'--no_auth',
'--bucket', 'chromium-clang-format',
'-s', 'buildtools/linux64/clang-format.sha1',
],
},
{
'name': 'sysroot_x64',
'pattern': '.',
'condition': 'checkout_linux and checkout_x64',
'action': ['python', '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': ['python', 'tools/clang/scripts/update.py'],
},
]
recursedeps = [
# buildtools provides clang_format.
'buildtools',
]

View File

@ -1,18 +0,0 @@
# Copyright (c) 2019 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

View File

@ -1,15 +0,0 @@
# Copyright (c) 2020 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

View File

@ -1,23 +0,0 @@
# Copyright (c) 2019 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 loader dependencies
vulkan_headers_dir = "//external/Vulkan-Headers"
# Subdirectories for generated files
vulkan_gen_subdir = ""
# Vulkan loader build options
vulkan_loader_shared = true

View File

@ -1,2 +0,0 @@
LIST=OS
include recurse.mk

View File

@ -1,8 +0,0 @@
LIST=CPU
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -1,8 +0,0 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -1 +0,0 @@
include ../../../common.mk

View File

@ -1,8 +0,0 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -1 +0,0 @@
include ../../../common.mk

View File

@ -1,8 +0,0 @@
LIST=VARIANT
ifndef QRECURSE
QRECURSE=recurse.mk
ifdef QCONFIG
QRDIR=$(dir $(QCONFIG))
endif
endif
include $(QRDIR)$(QRECURSE)

View File

@ -1 +0,0 @@
include ../../../common.mk

View File

@ -1,126 +0,0 @@
CMake - Cross Platform Makefile Generator
Copyright 2000-2018 Kitware, Inc. and Contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Kitware, Inc. nor the names of Contributors
may be used to endorse or promote products derived from this
software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
------------------------------------------------------------------------------
The following individuals and institutions are among the Contributors:
* Aaron C. Meadows <cmake@shadowguarddev.com>
* Adriaan de Groot <groot@kde.org>
* Aleksey Avdeev <solo@altlinux.ru>
* Alexander Neundorf <neundorf@kde.org>
* Alexander Smorkalov <alexander.smorkalov@itseez.com>
* Alexey Sokolov <sokolov@google.com>
* Alex Turbov <i.zaufi@gmail.com>
* Andreas Pakulat <apaku@gmx.de>
* Andreas Schneider <asn@cryptomilk.org>
* André Rigland Brodtkorb <Andre.Brodtkorb@ifi.uio.no>
* Axel Huebl, Helmholtz-Zentrum Dresden - Rossendorf
* Benjamin Eikel
* Bjoern Ricks <bjoern.ricks@gmail.com>
* Brad Hards <bradh@kde.org>
* Christopher Harvey
* Christoph Grüninger <foss@grueninger.de>
* Clement Creusot <creusot@cs.york.ac.uk>
* Daniel Blezek <blezek@gmail.com>
* Daniel Pfeifer <daniel@pfeifer-mail.de>
* Enrico Scholz <enrico.scholz@informatik.tu-chemnitz.de>
* Eran Ifrah <eran.ifrah@gmail.com>
* Esben Mose Hansen, Ange Optimization ApS
* Geoffrey Viola <geoffrey.viola@asirobots.com>
* Google Inc
* Gregor Jasny
* Helio Chissini de Castro <helio@kde.org>
* Ilya Lavrenov <ilya.lavrenov@itseez.com>
* Insight Software Consortium <insightsoftwareconsortium.org>
* Jan Woetzel
* Kelly Thompson <kgt@lanl.gov>
* Konstantin Podsvirov <konstantin@podsvirov.pro>
* Mario Bensi <mbensi@ipsquad.net>
* Mathieu Malaterre <mathieu.malaterre@gmail.com>
* Matthaeus G. Chajdas
* Matthias Kretz <kretz@kde.org>
* Matthias Maennich <matthias@maennich.net>
* Michael Stürmer
* Miguel A. Figueroa-Villanueva
* Mike Jackson
* Mike McQuaid <mike@mikemcquaid.com>
* Nicolas Bock <nicolasbock@gmail.com>
* Nicolas Despres <nicolas.despres@gmail.com>
* Nikita Krupen'ko <krnekit@gmail.com>
* NVIDIA Corporation <www.nvidia.com>
* OpenGamma Ltd. <opengamma.com>
* Patrick Stotko <stotko@cs.uni-bonn.de>
* Per Øyvind Karlsen <peroyvind@mandriva.org>
* Peter Collingbourne <peter@pcc.me.uk>
* Petr Gotthard <gotthard@honeywell.com>
* Philip Lowman <philip@yhbt.com>
* Philippe Proulx <pproulx@efficios.com>
* Raffi Enficiaud, Max Planck Society
* Raumfeld <raumfeld.com>
* Roger Leigh <rleigh@codelibre.net>
* Rolf Eike Beer <eike@sf-mail.de>
* Roman Donchenko <roman.donchenko@itseez.com>
* Roman Kharitonov <roman.kharitonov@itseez.com>
* Ruslan Baratov
* Sebastian Holtermann <sebholt@xwmw.org>
* Stephen Kelly <steveire@gmail.com>
* Sylvain Joubert <joubert.sy@gmail.com>
* Thomas Sondergaard <ts@medical-insight.com>
* Tobias Hunger <tobias.hunger@qt.io>
* Todd Gamblin <tgamblin@llnl.gov>
* Tristan Carel
* University of Dundee
* Vadim Zhukov
* Will Dicharry <wdicharry@stellarscience.com>
See version control history for details of individual contributions.
The above copyright and license notice applies to distributions of
CMake in source and binary form. Third-party software packages supplied
with CMake under compatible licenses provide their own copyright notices
documented in corresponding subdirectories or source files.
------------------------------------------------------------------------------
CMake was initially developed by Kitware with the following sponsorship:
* National Library of Medicine at the National Institutes of Health
as part of the Insight Segmentation and Registration Toolkit (ITK).
* US National Labs (Los Alamos, Livermore, Sandia) ASC Parallel
Visualization Initiative.
* National Alliance for Medical Image Computing (NAMIC) is funded by the
National Institutes of Health through the NIH Roadmap for Medical Research,
Grant U54 EB005149.
* Kitware, Inc.

View File

@ -1,28 +0,0 @@
# Try to find DirectFB
#
# This will define:
#
# DIRECTFB_FOUND - True if DirectFB is found
# DIRECTFB_LIBRARIES - Link these to use DirectFB
# DIRECTFB_INCLUDE_DIR - Include directory for DirectFB
# DIRECTFB_DEFINITIONS - Compiler flags for using DirectFB
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
IF (NOT WIN32)
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PKG_DIRECTFB QUIET directfb)
SET(DIRECTFB_DEFINITIONS ${PKG_DIRECTFB_CFLAGS})
FIND_PATH(DIRECTFB_INCLUDE_DIR NAMES directfb.h HINTS ${PKG_DIRECTFB_INCLUDE_DIRS})
FIND_LIBRARY(DIRECTFB_LIBRARIES NAMES directfb HINTS ${PKG_DIRECTFB_LIBRARY_DIRS})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(DIRECTFB DEFAULT_MSG DIRECTFB_LIBRARIES DIRECTFB_INCLUDE_DIR)
MARK_AS_ADVANCED(DIRECTFB_INCLUDE_DIR DIRECTFB_LIBRARIES)
ENDIF ()

View File

@ -1,28 +0,0 @@
# - FindPCIAccess
#
# Copyright 2015 Valve Corporation
find_package(PkgConfig)
pkg_check_modules(PC_PCIACCESS QUIET pciaccess)
find_path(PCIACCESS_INCLUDE_DIR NAMES pciaccess.h
HINTS
${PC_PCIACCESS_INCLUDEDIR}
${PC_PCIACCESS_INCLUDE_DIRS}
)
find_library(PCIACCESS_LIBRARY NAMES pciaccess
HINTS
${PC_PCIACCESS_LIBDIR}
${PC_PCIACCESS_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PCIAccess DEFAULT_MSG
PCIACCESS_INCLUDE_DIR PCIACCESS_LIBRARY)
mark_as_advanced(PCIACCESS_INCLUDE_DIR PCIACCESS_LIBRARY)
set(PCIACCESS_INCLUDE_DIRS ${PCIACCESS_INCLUDE_DIR})
set(PCIACCESS_LIBRARIES ${PCIACCESS_LIBRARY})

View File

@ -1,14 +0,0 @@
# - FindPthreadStubs
#
# Copyright (C) 2015 Valve Corporation
find_package(PkgConfig)
pkg_check_modules(PC_PTHREADSTUBS QUIET pthread-stubs)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(PthreadStubs DEFAULT_MSG
PC_PTHREADSTUBS_FOUND)
set(PTHREADSTUBS_INCLUDE_DIRS "")
set(PTHREADSTUBS_LIBRARIES "")

View File

@ -1,28 +0,0 @@
# - FindUDev
#
# Copyright (C) 2015 Valve Corporation
find_package(PkgConfig)
pkg_check_modules(PC_LIBUDEV QUIET libudev)
find_path(UDEV_INCLUDE_DIR NAMES libudev.h
HINTS
${PC_LIBUDEV_INCLUDEDIR}
${PC_LIBUDEV_INCLUDE_DIRS}
)
find_library(UDEV_LIBRARY NAMES udev
HINTS
${PC_LIBUDEV_LIBDIR}
${PC_LIBUDEV_LIBRARY_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(UDev DEFAULT_MSG
UDEV_INCLUDE_DIR UDEV_LIBRARY)
mark_as_advanced(UDEV_INCLUDE_DIR UDEV_LIBRARY)
set(UDEV_INCLUDE_DIRS ${UDEV_INCLUDE_DIR})
set(UDEV_LIBRARIES ${UDEV_LIBRARY})

View File

@ -1,22 +0,0 @@
# - FindValgrind
#
# Copyright (C) 2015 Valve Corporation
find_package(PkgConfig)
pkg_check_modules(PC_VALGRIND QUIET valgrind)
find_path(VALGRIND_INCLUDE_DIR NAMES valgrind.h memcheck.h
HINTS
${PC_VALGRIND_INCLUDEDIR}
${PC_VALGRIND_INCLUDE_DIRS}
)
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(Valgrind DEFAULT_MSG
VALGRIND_INCLUDE_DIR)
mark_as_advanced(VALGRIND_INCLUDE_DIR)
set(VALGRIND_INCLUDE_DIRS ${VALGRIND_INCLUDE_DIR})
set(VALGRIND_LIBRARIES "")

View File

@ -1,154 +0,0 @@
#.rst:
# FindVulkanHeaders
# -----------------
#
# Try to find Vulkan Headers and Registry.
#
# This module is intended to be used by projects that build Vulkan
# "system" components such as the loader and layers.
# Vulkan applications should instead use the FindVulkan (or similar)
# find module that locates the headers and the loader library.
#
# When using this find module to locate the headers and registry
# in a Vulkan-Headers repository, the Vulkan-Headers repository
# should be built with 'install' target and the following environment
# or CMake variable set to the location of the install directory.
#
# VULKAN_HEADERS_INSTALL_DIR
#
# IMPORTED Targets
# ^^^^^^^^^^^^^^^^
#
# This module defines no IMPORTED targets
#
# Result Variables
# ^^^^^^^^^^^^^^^^
#
# This module defines the following variables::
#
# VulkanHeaders_FOUND - True if VulkanHeaders was found
# VulkanHeaders_INCLUDE_DIRS - include directories for VulkanHeaders
#
# VulkanRegistry_FOUND - True if VulkanRegistry was found
# VulkanRegistry_DIRS - directories for VulkanRegistry
#
# VulkanHeaders_VERSION_MAJOR - The Major API version of the latest version
# contained in the Vulkan header
# VulkanHeaders_VERSION_MINOR - The Minor API version of the latest version
# contained in the Vulkan header
# VulkanHeaders_VERSION_PATCH - The Patch API version of the latest version
# contained in the Vulkan header
#
# The module will also define two cache variables::
#
# VulkanHeaders_INCLUDE_DIR - the VulkanHeaders include directory
# VulkanRegistry_DIR - the VulkanRegistry directory
#
# Probe command-line arguments and the environment to see if they specify the
# Vulkan headers installation path.
if(NOT DEFINED VULKAN_HEADERS_INSTALL_DIR)
if (DEFINED ENV{VULKAN_HEADERS_INSTALL_DIR})
set(VULKAN_HEADERS_INSTALL_DIR "$ENV{VULKAN_HEADERS_INSTALL_DIR}")
elseif(DEFINED ENV{VULKAN_SDK})
set(VULKAN_HEADERS_INSTALL_DIR "$ENV{VULKAN_SDK}/include")
endif()
endif()
if(DEFINED VULKAN_HEADERS_INSTALL_DIR)
# When CMAKE_FIND_ROOT_PATH_INCLUDE is set to ONLY, the HINTS in find_path()
# are re-rooted, which prevents VULKAN_HEADERS_INSTALL_DIR to work as
# expected. So use NO_CMAKE_FIND_ROOT_PATH to avoid it.
# Use HINTS instead of PATH to search these locations before
# searching system environment variables like $PATH that may
# contain SDK directories.
find_path(VulkanHeaders_INCLUDE_DIR
NAMES vulkan/vulkan.h
HINTS ${VULKAN_HEADERS_INSTALL_DIR}/include
NO_CMAKE_FIND_ROOT_PATH)
find_path(VulkanRegistry_DIR
NAMES vk.xml
HINTS ${VULKAN_HEADERS_INSTALL_DIR}/share/vulkan/registry
NO_CMAKE_FIND_ROOT_PATH)
else()
# If VULKAN_HEADERS_INSTALL_DIR, or one of its variants was not specified,
# do a normal search without hints.
find_path(VulkanHeaders_INCLUDE_DIR NAMES vulkan/vulkan.h HINTS "${CMAKE_CURRENT_SOURCE_DIR}/external/Vulkan-Headers/include" NO_CMAKE_FIND_ROOT_PATH)
get_filename_component(VULKAN_REGISTRY_PATH_HINT ${VulkanHeaders_INCLUDE_DIR} DIRECTORY)
find_path(VulkanRegistry_DIR NAMES vk.xml HINTS ${VULKAN_REGISTRY_PATH_HINT}/share/vulkan/registry
"${VULKAN_REGISTRY_PATH_HINT}/registry" NO_CMAKE_FIND_ROOT_PATH)
endif()
set(VulkanHeaders_INCLUDE_DIRS ${VulkanHeaders_INCLUDE_DIR})
set(VulkanRegistry_DIRS ${VulkanRegistry_DIR})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(VulkanHeaders
DEFAULT_MSG
VulkanHeaders_INCLUDE_DIR)
set(FPHSA_NAME_MISMATCHED TRUE)
find_package_handle_standard_args(VulkanRegistry
DEFAULT_MSG
VulkanRegistry_DIR)
unset(FPHSA_NAME_MISMATCHED)
mark_as_advanced(VulkanHeaders_INCLUDE_DIR VulkanRegistry_DIR)
# Determine the major/minor/patch version from the vulkan header
set(VulkanHeaders_VERSION_MAJOR "0")
set(VulkanHeaders_VERSION_MINOR "0")
set(VulkanHeaders_VERSION_PATCH "0")
# First, determine which header we need to grab the version information from.
# Starting with Vulkan 1.1, we should use vulkan_core.h, but prior to that,
# the information was in vulkan.h.
if (EXISTS "${VulkanHeaders_INCLUDE_DIR}/vulkan/vulkan_core.h")
set(VulkanHeaders_main_header ${VulkanHeaders_INCLUDE_DIR}/vulkan/vulkan_core.h)
else()
set(VulkanHeaders_main_header ${VulkanHeaders_INCLUDE_DIR}/vulkan/vulkan.h)
endif()
# Find all lines in the header file that contain any version we may be interested in
# NOTE: They start with #define and then have other keywords
file(STRINGS
${VulkanHeaders_main_header}
VulkanHeaders_lines
REGEX "^#define VK_HEADER_VERSION(_COMPLETE)? ")
foreach(VulkanHeaders_line ${VulkanHeaders_lines})
# First, handle the case where we have a major/minor version
# Format is:
# #define VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION(0, X, Y, VK_HEADER_VERSION)
# We grab the major version (X) and minor version (Y) out of the parentheses
string(REGEX MATCH "VK_HEADER_VERSION_COMPLETE VK_MAKE_API_VERSION\\(.*\\)" VulkanHeaders_out ${VulkanHeaders_line})
string(REGEX MATCHALL "[0-9]+" VulkanHeaders_MAJOR_MINOR "${VulkanHeaders_out}")
if (VulkanHeaders_MAJOR_MINOR)
list (GET VulkanHeaders_MAJOR_MINOR 1 VulkanHeaders_cur_major)
list (GET VulkanHeaders_MAJOR_MINOR 2 VulkanHeaders_cur_minor)
if (${VulkanHeaders_cur_major} GREATER ${VulkanHeaders_VERSION_MAJOR})
set(VulkanHeaders_VERSION_MAJOR ${VulkanHeaders_cur_major})
set(VulkanHeaders_VERSION_MINOR ${VulkanHeaders_cur_minor})
endif()
if (${VulkanHeaders_cur_major} EQUAL ${VulkanHeaders_VERSION_MAJOR} AND
${VulkanHeaders_cur_minor} GREATER ${VulkanHeaders_VERSION_MINOR})
set(VulkanHeaders_VERSION_MINOR ${VulkanHeaders_cur_minor})
endif()
endif()
# Second, handle the case where we have the patch version
# Format is:
# #define VK_HEADER_VERSION Z
# Where Z is the patch version which we just grab off the end
string(REGEX MATCH "define.*VK_HEADER_VERSION[^_].*[0-9]+" VulkanHeaders_out ${VulkanHeaders_line})
list(LENGTH VulkanHeaders_out VulkanHeaders_len)
if (VulkanHeaders_len)
string(REGEX MATCH "[0-9]+" VulkanHeaders_VERSION_PATCH "${VulkanHeaders_out}")
endif()
endforeach()
MESSAGE(STATUS
"Detected Vulkan Version ${VulkanHeaders_VERSION_MAJOR}."
"${VulkanHeaders_VERSION_MINOR}."
"${VulkanHeaders_VERSION_PATCH}")

View File

@ -1,32 +0,0 @@
# - Try to find libX11-xcb
# Once done this will define
#
# X11_XCB_FOUND - system has libX11-xcb
# X11_XCB_LIBRARIES - Link these to use libX11-xcb
# X11_XCB_INCLUDE_DIR - the libX11-xcb include dir
# X11_XCB_DEFINITIONS - compiler switches required for using libX11-xcb
# Copyright (c) 2011 Fredrik Höglund <fredrik@kde.org>
# Copyright (c) 2008 Helio Chissini de Castro, <helio@kde.org>
# Copyright (c) 2007 Matthias Kretz, <kretz@kde.org>
#
# Redistribution and use is allowed according to the terms of the BSD license.
# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
IF (NOT WIN32)
# use pkg-config to get the directories and then use these values
# in the FIND_PATH() and FIND_LIBRARY() calls
FIND_PACKAGE(PkgConfig)
PKG_CHECK_MODULES(PKG_X11_XCB QUIET x11-xcb)
SET(X11_XCB_DEFINITIONS ${PKG_X11_XCB_CFLAGS})
FIND_PATH(X11_XCB_INCLUDE_DIR NAMES X11/Xlib-xcb.h HINTS ${PKG_X11_XCB_INCLUDE_DIRS})
FIND_LIBRARY(X11_XCB_LIBRARIES NAMES X11-xcb HINTS ${PKG_X11_XCB_LIBRARY_DIRS})
include(FindPackageHandleStandardArgs)
FIND_PACKAGE_HANDLE_STANDARD_ARGS(X11_XCB DEFAULT_MSG X11_XCB_LIBRARIES X11_XCB_INCLUDE_DIR)
MARK_AS_ADVANCED(X11_XCB_INCLUDE_DIR X11_XCB_LIBRARIES)
ENDIF (NOT WIN32)

View File

@ -1,54 +0,0 @@
# - FindXCB
#
# Copyright (C) 2015 Valve Corporation
find_package(PkgConfig)
if(NOT XCB_FIND_COMPONENTS)
set(XCB_FIND_COMPONENTS xcb)
endif()
include(FindPackageHandleStandardArgs)
set(XCB_FOUND true)
set(XCB_INCLUDE_DIRS "")
set(XCB_LIBRARIES "")
foreach(comp ${XCB_FIND_COMPONENTS})
# component name
string(TOUPPER ${comp} compname)
string(REPLACE "-" "_" compname ${compname})
# header name
string(REPLACE "xcb-" "" headername xcb/${comp}.h)
# library name
set(libname ${comp})
pkg_check_modules(PC_${comp} QUIET ${comp})
find_path(${compname}_INCLUDE_DIR NAMES ${headername}
HINTS
${PC_${comp}_INCLUDEDIR}
${PC_${comp}_INCLUDE_DIRS}
)
find_library(${compname}_LIBRARY NAMES ${libname}
HINTS
${PC_${comp}_LIBDIR}
${PC_${comp}_LIBRARY_DIRS}
)
set(FPHSA_NAME_MISMATCHED TRUE)
find_package_handle_standard_args(${comp}
FOUND_VAR ${comp}_FOUND
REQUIRED_VARS ${compname}_INCLUDE_DIR ${compname}_LIBRARY)
unset(FPHSA_NAME_MISMATCHED)
mark_as_advanced(${compname}_INCLUDE_DIR ${compname}_LIBRARY)
list(APPEND XCB_INCLUDE_DIRS ${${compname}_INCLUDE_DIR})
list(APPEND XCB_LIBRARIES ${${compname}_LIBRARY})
if(NOT ${comp}_FOUND)
set(XCB_FOUND false)
endif()
endforeach()
list(REMOVE_DUPLICATES XCB_INCLUDE_DIRS)

View File

@ -1,21 +0,0 @@
if(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
endif(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt")
file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif(NOT "${rm_retval}" STREQUAL 0)
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
endforeach(file)

View File

@ -4,15 +4,15 @@
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Application Interface to Loader
# Application Interface to Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
<!-- Copyright &copy; 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
## Table of Contents
## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Interfacing with Vulkan Functions](#interfacing-with-vulkan-functions)
@ -36,9 +36,6 @@
- [Forcing Layers to be Enabled on Windows, Linux and macOS](#forcing-layers-to-be-enabled-on-windows-linux-and-macos)
- [Overall Layer Ordering](#overall-layer-ordering)
- [Debugging Possible Layer Issues](#debugging-possible-layer-issues)
- [Enable Loader Debug Layer Output](#enable-loader-debug-layer-output)
- [Disable All Layers](#disable-all-layers)
- [Enable More Loader Debug Output](#enable-more-loader-debug-output)
- [Application Usage of Extensions](#application-usage-of-extensions)
- [Instance and Device Extensions](#instance-and-device-extensions)
- [WSI Extensions](#wsi-extensions)
@ -376,7 +373,7 @@ layer, dropping the need for meta layers.
While not necessary for validation anymore, VkConfig does use meta layers to
group layers together based on user's preferences.
More can be found out about this functionality through both the
[VkConfig documentation](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
[VkConfig documentation](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
and the section later on the [Override Layer](#override-layer).
Meta-layers are detailed more in the
@ -411,7 +408,7 @@ On Desktop platforms (Windows, Linux, and macOS), these enable/disable settings
are defined in the layer's JSON file.
Discovery of system-installed implicit and explicit layers is described later
in the [Layer discovery](LoaderLayerInterface#layer-discovery)
in the [Layer discovery](LoaderLayerInterface.md#layer-discovery)
section in the
[LoaderLayerInterface.md](LoaderLayerInterface.md) document.
@ -449,7 +446,7 @@ The table below details more information:
#### Override Layer
The "Override Layer" is a special implicit meta-layer created by the
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
tool and available by default when the tool is running.
Once VkConfig exits, the override layer is removed, and the system should
return to standard Vulkan behavior.
@ -472,9 +469,9 @@ the system-installed layers.
This can be accomplished in one of two ways:
1. Selecting specific layer paths using the
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
tool shipped with the Vulkan SDK.
2. Directing the loader to look for layers in specific folders by using the
2. Directing the loader to look for layers in specific files and/or folders by using the
`VK_LAYER_PATH` environment variable.
The `VK_LAYER_PATH` environment variable can contain multiple paths separated by
@ -482,7 +479,7 @@ the operating-system specific path separator.
On Windows, this is a semicolon (`;`), while on Linux and macOS it is a colon
(`:`).
If `VK_LAYER_PATH` exists, the folders listed in it will be scanned for explicit
If `VK_LAYER_PATH` exists, the files and/or folders listed will be scanned for explicit
layer manifest files.
Implicit layer discovery is unaffected by this environment variable.
Each directory listed should be the full pathname of a folder containing layer
@ -515,7 +512,7 @@ application they are using.
This can be also be accomplished in one of two ways:
1. Selecting specific layers using the
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
tool shipped with the Vulkan SDK.
2. Directing the loader to look for additional layers by name using the
`VK_INSTANCE_LAYERS` environment variable.
@ -572,140 +569,10 @@ make to function.
### Debugging Possible Layer Issues
If it is possible that a layer is causing issues, there are several things that
can be tried.
#### Enable Loader Debug Layer Output
First, enable the "layer" debug output option (`VK_LOADER_DEBUG`) in the loader,
See the
[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md##table-of-debug-environment-variables)
for more info.
When enabled, the loader will output information on:
* Where it looks for implicit layers
* Where it looks for explicit layers
* What manifest files it finds
* Which layer manifest files are loaded
* What libraries are associated with a layer
* What the layer callstack looks like for both the instance and device chain
For example, the layer output for searching for implicit layers on Linux may
look like:
```
LAYER: Searching for layer manifest files
LAYER: In following folders:
LAYER: /home/linust/.config/vulkan/implicit_layer.d
LAYER: /etc/xdg/vulkan/implicit_layer.d
LAYER: /usr/local/etc/vulkan/implicit_layer.d
LAYER: /etc/vulkan/implicit_layer.d
LAYER: /home/linust/.local/share/vulkan/implicit_layer.d
LAYER: /home/linust/.local/share/flatpak/exports/share/vulkan/implicit_layer.d
LAYER: /var/lib/flatpak/exports/share/vulkan/implicit_layer.d
LAYER: /usr/local/share/vulkan/implicit_layer.d
LAYER: /usr/share/vulkan/implicit_layer.d
LAYER: Found the following files:
LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/renderdoc_capture.json
LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamfossilize_i386.json
LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamfossilize_x86_64.json
LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamoverlay_i386.json
LAYER: /home/linust/.local/share/vulkan/implicit_layer.d/steamoverlay_x86_64.json
LAYER: /usr/share/vulkan/implicit_layer.d/nvidia_layers.json
LAYER: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
```
In the above scenario, seven implicit layers were discovered in two different
folders.
Just because they were found does not mean that they will be loaded, but this
information can be used to make sure a layer JSON file was properly discovered.
When the loader actually loads a layer, the messages may look like the
following:
```
LAYER | DEBUG: Loading layer library libVkLayer_khronos_validation.so
LAYER | INFO: Insert instance layer VK_LAYER_KHRONOS_validation (libVkLayer_khronos_validation.so)
LAYER | DEBUG: Loading layer library libVkLayer_MESA_device_select.so
LAYER | INFO: Insert instance layer VK_LAYER_MESA_device_select (libVkLayer_MESA_device_select.so)
```
This information does not indicate the order the layers are used in.
That information is displayed later showing all the callstack during both
`vkCreateInstance` and `vkCreateDevice`.
In the same sample above, the callstack for `vkCreateInstance` looks like the
following:
```
LAYER: vkCreateInstance layer callstack setup to:
LAYER: <Application>
LAYER: ||
LAYER: <Loader>
LAYER: ||
LAYER: VK_LAYER_MESA_device_select
LAYER: Type: Implicit
LAYER: Disable Env Var: NODEVICE_SELECT
LAYER: Manifest: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
LAYER: Library: libVkLayer_MESA_device_select.so
LAYER: ||
LAYER: VK_LAYER_KHRONOS_validation
LAYER: Type: Explicit
LAYER: Manifest: /usr/share/vulkan/explicit_layer.d/VkLayer_khronos_validation.json
LAYER: Library: libVkLayer_khronos_validation.so
LAYER: ||
LAYER: <Drivers>
```
In this scenario, two layers were used (the same two that were loaded earlier):
* `VK_LAYER_MESA_device_select`
* `VK_LAYER_KHRONOS_validation`
This information now shows us that the `VK_LAYER_MESA_device_select` is loaded
first, followed by `VK_LAYER_KHRONOS_validation` which will then continue into
any available drivers.
It also shows that `VK_LAYER_MESA_device_select` is an implicit layer which
implies that it wasn't directly enabled by the application.
On the other hand, `VK_LAYER_KHRONOS_validation` is shown as an explicit layer
which indicates that it was likely enabled by the application.
Sometimes, implicit layers can cause issues with an application.
Because of this, the next step is to try to disable one or more of the listed
implicit layers.
This can be done by defining the disable environment variable for that layer.
Each layer has it's own disable environment variable as mentioned in the
[Layer Manifest File Format](LoaderLayerInterface.md#layer-manifest-file-format).
However, it can be difficult to find this variable in the manifest files, so
the loader now outputs it as part of the callstack information.
Looking at the above `vkCreateInstance` callstack output, under the
section for `VK_LAYER_MESA_device_select` exists a section listed as
"Disable Env Var:".
This is the disable environment variable that can be used to disable the
`VK_LAYER_MESA_device_select` layer from being loaded by the loader.
In the above output, the disable environment variable is listed as
"NODEVICE_SELECT" which can be defined to a non-zero value to cause the loader
to ignore this layer.
#### Disable All Layers
Because implicit layers are virtually unknown to the application, it is best to
next try to disable each one of them.
Using the above debug output, define each environment variable to disable the
corresponding implicit layer that was used.
Once all are disabled, re-run the application again.
If the failure still occurs, try disabling all explicit layers loaded by the
application by modifying the application or using a tool such as
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md).
#### Enable More Loader Debug Output
If the failure continues after disabling all layers, then enable all loader
debug warnings and errors by setting `VK_LOADER_DEBUG` to "error,warn" or
even "all".
This will output any other issues that the loader has encountered.
can be tried which are documented in the
[Debugging Possible Layer Issues](LoaderDebugging.md#debugging-possible-layer-issues)
section of the [LoaderDebugging.mg](LoaderDebugging.md) document in the docs
folder.
## Application Usage of Extensions

361
docs/LoaderDebugging.md Normal file
View File

@ -0,0 +1,361 @@
<!-- markdownlint-disable MD041 -->
[![Khronos Vulkan][1]][2]
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Debugging The Vulkan Desktop Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
<!-- Copyright &copy; 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
## Table of Contents <!-- omit from toc -->
- [Debugging Issues](#debugging-issues)
- [Loader Logging](#loader-logging)
- [Debugging Possible Layer Issues](#debugging-possible-layer-issues)
- [Enable Layer Logging](#enable-layer-logging)
- [Disable Layers](#disable-layers)
- [Selectively Re-enable Layers](#selectively-re-enable-layers)
- [Allow specific layers to be ignored by VK\_LOADER\_LAYERS\_DISABLE](#allow-specific-layers-to-be-ignored-by-vk_loader_layers_disable)
- [Debugging Possible Driver Issues](#debugging-possible-driver-issues)
- [Enable Driver Logging](#enable-driver-logging)
- [Selectively Enable Specific Drivers](#selectively-enable-specific-drivers)
## Debugging Issues
If your application is crashing or behaving weirdly, the loader provides
several mechanisms for you to debug the issues.
**NOTE**: This functionality is all specific to the desktop Vulkan loader and
does not work for the Android loader.
## Loader Logging
The Vulkan desktop loader has added logging functionality that can be enabled by
using the `VK_LOADER_DEBUG` environment variable.
The results will be output to the standard output, but will also be passed to
any `VK_EXT_debug_utils` messengers present as well.
The variable can be set to a comma-delimited list of debug level options which
include:
* error&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report any errors encountered by
the loader
* warn&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report any warnings encountered by
the loader
* info&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report info-level
messages generated by the loader
* debug&nbsp;&nbsp;&nbsp;&nbsp;Report debug-level messages generated by the
loader
* layer&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report all layer-specific messages
generated by the loader
* driver&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report all driver-specific messages
generated by the loader
* all&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Report all
messages generated by the loader (includes all of the above)
If you're not sure where the issue comes from, at least set it to output all
messages through the "info" level:
```
set VK_LOADER_DEBUG=error,warn,info
```
Then, you can search the list for any errors or warnings that might provide a
hint at why you're seeing issues.
For more info on enabling loader logging, refer to the
[Enable Loader Debug Layer Output](LoaderApplicationInterface.md#enable-loader-debug-layer-output)
and the
[Table of Debug Environment Variables](LoaderInterfaceArchitecture.md#table-of-debug-environment-variables)
below.
## Debugging Possible Layer Issues
### Enable Layer Logging
If you suspect a layer issue, set the loader logging to specifically output
layer messages in addition to warnings and errors:
```
set VK_LOADER_DEBUG=error,warn,layer
```
Most important layer messages should go out with error or warning levels set,
but this will provide more layer-specific info as well such as:
* What layers are found
* Where they were found
* If they are implicit, what environment variables can be used to disable them
* If there is any incompatibility with a given layer, this could include:
* The layer library file (.so/.dll) wasn't found
* The layer library is the wrong bit-depth for the executing application
(i.e. 32-bit vs 64-bit)
* The layer itself doesn't support the application desired version of Vulkan
* If any environment variables are disabling any layers
For example, the output of the loader looking for implicit layers may look like
the following:
```
LAYER: Searching for layer manifest files
LAYER: In following locations:
LAYER: /home/${USER}/.config/vulkan/implicit_layer.d
LAYER: /etc/xdg/vulkan/implicit_layer.d
LAYER: /usr/local/etc/vulkan/implicit_layer.d
LAYER: /etc/vulkan/implicit_layer.d
LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d
LAYER: /home/${USER}/.local/share/flatpak/exports/share/vulkan/implicit_layer.d
LAYER: /var/lib/flatpak/exports/share/vulkan/implicit_layer.d
LAYER: /usr/local/share/vulkan/implicit_layer.d
LAYER: /usr/share/vulkan/implicit_layer.d
LAYER: Found the following files:
LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/renderdoc_capture.json
LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamfossilize_i386.json
LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamfossilize_x86_64.json
LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamoverlay_i386.json
LAYER: /home/${USER}/.local/share/vulkan/implicit_layer.d/steamoverlay_x86_64.json
LAYER: /usr/share/vulkan/implicit_layer.d/nvidia_layers.json
LAYER: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
```
Then, the loading of layer libraries is reported similar to this:
```
LAYER | DEBUG: Loading layer library libVkLayer_khronos_validation.so
LAYER | INFO: Insert instance layer VK_LAYER_KHRONOS_validation (libVkLayer_khronos_validation.so)
LAYER | DEBUG: Loading layer library libVkLayer_MESA_device_select.so
LAYER | INFO: Insert instance layer VK_LAYER_MESA_device_select (libVkLayer_MESA_device_select.so)
```
Finally, when the Vulkan instance is created, you can see the full instance
call-chain from a functional standpoint with output like this:
```
LAYER: vkCreateInstance layer callstack setup to:
LAYER: <Application>
LAYER: ||
LAYER: <Loader>
LAYER: ||
LAYER: VK_LAYER_MESA_device_select
LAYER: Type: Implicit
LAYER: Disable Env Var: NODEVICE_SELECT
LAYER: Manifest: /usr/share/vulkan/implicit_layer.d/VkLayer_MESA_device_select.json
LAYER: Library: libVkLayer_MESA_device_select.so
LAYER: ||
LAYER: VK_LAYER_KHRONOS_validation
LAYER: Type: Explicit
LAYER: Manifest: /usr/share/vulkan/explicit_layer.d/VkLayer_khronos_validation.json
LAYER: Library: libVkLayer_khronos_validation.so
LAYER: ||
LAYER: <Drivers>
```
In this scenario, two layers were used (the same two that were loaded earlier):
* `VK_LAYER_MESA_device_select`
* `VK_LAYER_KHRONOS_validation`
This information now shows us that the `VK_LAYER_MESA_device_select` is loaded
first, followed by `VK_LAYER_KHRONOS_validation` which will then continue into
any available drivers.
It also shows that `VK_LAYER_MESA_device_select` is an implicit layer which
implies that it wasn't directly enabled by the application.
On the other hand, `VK_LAYER_KHRONOS_validation` is shown as an explicit layer
which indicates that it was likely enabled by the application.
### Disable Layers
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
Sometimes, implicit layers can cause issues with an application.
Because of this, the next step is to try to disable one or more of the listed
implicit layers.
You can use the filtering environment variables
(`VK_LOADER_LAYERS_ENABLE` and `VK_LOADER_LAYERS_DISABLE`) to selectively enable
or disable various layers.
If you're not sure what to do, try disabling all implicit layers manually by
setting `VK_LOADER_LAYERS_DISABLE` to `~implicit~`.
```
set VK_LOADER_LAYERS_DISABLE=~implicit~
```
This will disable all implicit layers and the loader will report any disabled
layers to the logging output when layer logging is enabled in the following way:
```
WARNING | LAYER: Implicit layer "VK_LAYER_MESA_device_select" forced disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'.
WARNING | LAYER: Implicit layer "VK_LAYER_AMD_switchable_graphics_64" forced disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'.
WARNING | LAYER: Implicit layer "VK_LAYER_Twitch_Overlay" forced disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'.
```
### Selectively Re-enable Layers
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
When trying to diagnose problems caused by layers, it is useful to first disable
all layers and re-enable each layer individually.
If the problem reappears, then it is immediately clear which layer is the source
of the issue.
For example, from the above given list of disabled layers, lets selectively
re-enable one:
```
set VK_LOADER_LAYERS_DISABLE=~implicit~
set VK_LOADER_LAYERS_ENABLE=*AMD*
```
This would keep both the "VK_LAYER_MESA_device_select" and
"VK_LAYER_Twitch_Overlay" layers disabled, while enabling the
"VK_LAYER_AMD_switchable_graphics_64" layer.
If everything continues to work, then the evidence seems to suggest the issue is
likely not related to the AMD layer.
This would lead to enabling one other layer and trying again:
```
set VK_LOADER_LAYERS_DISABLE=~implicit~
set VK_LOADER_LAYERS_ENABLE=*AMD*,*twitch*
```
And so forth.
For more info on how to use the filtering environment variables, refer to the
[Layer Filtering](LoaderLayerInterface.md#layer-filtering) section of the
[LoaderLayerInterface](LoaderLayerInterface.md) document.
## Allow specific layers to be ignored by VK_LOADER_LAYERS_DISABLE
**NOTE:** VK_LOADER_LAYERS_DISABLE is only available with Loaders built with version
1.3.262 of the Vulkan headers and later.
When using `VK_LOADER_LAYERS_DISABLE` to disable implicit layers, it is possible
to allow specific layers to be enabled using `VK_LOADER_LAYERS_ENABLE`.
However, this has the effect of *forcing* layers to be enabled, which is not
always desired.
Implicit layers have the ability to only be enabled when a layer specified
environment variable is set, allow for context dependent enablement.
`VK_LOADER_LAYERS_ENABLE` ignores that context.
Thus, a different environment variable is needed: `VK_LOADER_LAYERS_ALLOW`
The behavior of `VK_LOADER_LAYERS_ALLOW` is similar to `VK_LOADER_LAYERS_ENABLE`
except that it does not force a layer to be enabled.
The way to think about this environment variable is that every layer matching
`VK_LOADER_LAYERS_ALLOW` is excluded from being forcibly disabled by
`VK_LOADER_LAYERS_DISABLE`.
this allows for implicit layers that are context dependent to be enabled
depending on the relevant context instead of force enabling them.
Example: Disable all implicit layers except for any layers that have steam or
mesa in their name.
```
set VK_LOADER_LAYERS_DISABLE=~implicit~
set VK_LOADER_LAYERS_ALLOW=*steam*,*Mesa*
```
## Debugging Possible Driver Issues
### Enable Driver Logging
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
If you suspect a driver issue, set the loader logging to specifically output
driver messages:
```
set VK_LOADER_DEBUG=error,warn,driver
```
Most important driver messages should go out with error or warning levels set,
but this will provide more driver-specific info as well such as:
* What drivers are found
* Where they were found
* If there is any incompatibility with a given driver
* If any environment variables are disabling any of the drivers
For example, the output of the loader looking for drivers on a Linux system may
look like the following (NOTE: additional spaces have been removed from the
output for easier reading):
```
DRIVER: Searching for driver manifest files
DRIVER: In following folders:
DRIVER: /home/$(USER)/.config/vulkan/icd.d
DRIVER: /etc/xdg/vulkan/icd.d
DRIVER: /etc/vulkan/icd.d
DRIVER: /home/$(USER)/.local/share/vulkan/icd.d
DRIVER: /home/$(USER)/.local/share/flatpak/exports/share/vulkan/icd.d
DRIVER: /var/lib/flatpak/exports/share/vulkan/icd.d
DRIVER: /usr/local/share/vulkan/icd.d
DRIVER: /usr/share/vulkan/icd.d
DRIVER: Found the following files:
DRIVER: /usr/share/vulkan/icd.d/intel_icd.x86_64.json
DRIVER: /usr/share/vulkan/icd.d/lvp_icd.x86_64.json
DRIVER: /usr/share/vulkan/icd.d/radeon_icd.x86_64.json
DRIVER: /usr/share/vulkan/icd.d/lvp_icd.i686.json
DRIVER: /usr/share/vulkan/icd.d/radeon_icd.i686.json
DRIVER: /usr/share/vulkan/icd.d/intel_icd.i686.json
DRIVER: /usr/share/vulkan/icd.d/nvidia_icd.json
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/intel_icd.x86_64.json, version "1.0.0"
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/lvp_icd.x86_64.json, version "1.0.0"
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/radeon_icd.x86_64.json, version "1.0.0"
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/lvp_icd.i686.json, version "1.0.0"
DRIVER: Requested driver /usr/lib/libvulkan_lvp.so was wrong bit-type. Ignoring this JSON
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/radeon_icd.i686.json, version "1.0.0"
DRIVER: Requested driver /usr/lib/libvulkan_radeon.so was wrong bit-type. Ignoring this JSON
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/intel_icd.i686.json, version "1.0.0"
DRIVER: Requested driver /usr/lib/libvulkan_intel.so was wrong bit-type. Ignoring this JSON
DRIVER: Found ICD manifest file /usr/share/vulkan/icd.d/nvidia_icd.json, version "1.0.0"
```
Then when the application selects the device to use, you will see the Vulkan
device call chain reported in the following way (NOTE: additional spaces have
been removed from the output for easier reading):
```
DRIVER: vkCreateDevice layer callstack setup to:
DRIVER: <Application>
DRIVER: ||
DRIVER: <Loader>
DRIVER: ||
DRIVER: <Device>
DRIVER: Using "Intel(R) UHD Graphics 630 (CFL GT2)" with driver: "/usr/lib64/libvulkan_intel.so"
```
### Selectively Enable Specific Drivers
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
You can now use the filtering environment variables
(`VK_LOADER_DRIVERS_SELECT` and `VK_LOADER_DRIVERS_DISABLE`) to control what
drivers the loader will attempt to load.
For drivers, the string globs passed into the above environment variables will
be compared against the driver JSON file name since there is no driver name
known to the loader until much later in the Vulkan initialization process.
For example, to disable all drivers except Nvidia you could do the following:
```
set VK_LOADER_DRIVERS_DISABLE=*
set VK_LOADER_DRIVERS_SELECT=*nvidia*
```
The loader outputs messages like the following when the environment variables
are used:
```
WARNING | DRIVER: Driver "intel_icd.x86_64.json" ignored because not selected by env var 'VK_LOADER_DRIVERS_SELECT'
WARNING | DRIVER: Driver "radeon_icd.x86_64.json" ignored because it was disabled by env var 'VK_LOADER_DRIVERS_DISABLE'
```
For more info on how to use the filtering environment variables, refer to the
[Driver Filtering](LoaderDriverInterface.md#driver-filtering) section of the
[LoaderDriverInterface](LoaderDriverInterface.md) document.

View File

@ -4,21 +4,24 @@
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Driver interface to the Vulkan Loader
# Driver interface to the Vulkan Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
<!-- Copyright &copy; 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
## Table of Contents
## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Driver Discovery](#driver-discovery)
- [Overriding the Default Driver Discovery](#overriding-the-default-driver-discovery)
- [Additional Driver Discovery](#additional-driver-discovery)
- [Driver Filtering](#driver-filtering)
- [Driver Select Filtering](#driver-select-filtering)
- [Driver Disable Filtering](#driver-disable-filtering)
- [Exception for Elevated Privileges](#exception-for-elevated-privileges)
- [Examples](#examples)
- [On Windows](#on-windows)
@ -32,6 +35,10 @@
- [Driver Discovery on macOS](#driver-discovery-on-macos)
- [Example macOS Driver Search Path](#example-macos-driver-search-path)
- [Additional Settings For Driver Debugging](#additional-settings-for-driver-debugging)
- [Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension](#driver-discovery-using-thevk_lunarg_direct_driver_loading-extension)
- [How to use `VK_LUNARG_direct_driver_loading`](#how-to-use-vk_lunarg_direct_driver_loading)
- [Interactions with other driver discovery mechanisms](#interactions-with-other-driver-discovery-mechanisms)
- [Limitations of `VK_LUNARG_direct_driver_loading`](#limitations-of-vk_lunarg_direct_driver_loading)
- [Using Pre-Production ICDs or Software Drivers](#using-pre-production-icds-or-software-drivers)
- [Driver Discovery on Android](#driver-discovery-on-android)
- [Driver Manifest File Format](#driver-manifest-file-format)
@ -50,18 +57,19 @@
- [Handling KHR Surface Objects in WSI Extensions](#handling-khr-surface-objects-in-wsi-extensions)
- [Loader and Driver Interface Negotiation](#loader-and-driver-interface-negotiation)
- [Windows, Linux and macOS Driver Negotiation](#windows-linux-and-macos-driver-negotiation)
- [Version Negotiation Between Loader and Drivers](#version-negotiation-between-loader-and-drivers)
- [Version Negotiation Between the Loader and Drivers](#version-negotiation-between-the-loader-and-drivers)
- [Interfacing With Legacy Drivers or Loaders](#interfacing-with-legacy-drivers-or-loaders)
- [Loader Version 6 Interface Requirements](#loader-version-6-interface-requirements)
- [Loader Version 5 Interface Requirements](#loader-version-5-interface-requirements)
- [Loader Version 4 Interface Requirements](#loader-version-4-interface-requirements)
- [Loader Version 3 Interface Requirements](#loader-version-3-interface-requirements)
- [Loader Version 2 Interface Requirements](#loader-version-2-interface-requirements)
- [Loader Version 1 Interface Requirements](#loader-version-1-interface-requirements)
- [Loader Version 0 Interface Requirements](#loader-version-0-interface-requirements)
- [Loader and Driver Interface Version 7 Requirements](#loader-and-driver-interface-version-7-requirements)
- [Loader and Driver Interface Version 6 Requirements](#loader-and-driver-interface-version-6-requirements)
- [Loader and Driver Interface Version 5 Requirements](#loader-and-driver-interface-version-5-requirements)
- [Loader and Driver Interface Version 4 Requirements](#loader-and-driver-interface-version-4-requirements)
- [Loader and Driver Interface Version 3 Requirements](#loader-and-driver-interface-version-3-requirements)
- [Loader and Driver Interface Version 2 Requirements](#loader-and-driver-interface-version-2-requirements)
- [Loader and Driver Interface Version 1 Requirements](#loader-and-driver-interface-version-1-requirements)
- [Loader and Driver Interface Version 0 Requirements](#loader-and-driver-interface-version-0-requirements)
- [Additional Interface Notes:](#additional-interface-notes)
- [Android Driver Negotiation](#android-driver-negotiation)
- [Loader implementation of VK_KHR_portability_enumeration](#loader-implementation-of-vk_khr_portability_enumeration)
- [Loader implementation of VK\_KHR\_portability\_enumeration](#loader-implementation-of-vk_khr_portability_enumeration)
- [Loader and Driver Policy](#loader-and-driver-policy)
- [Number Format](#number-format)
- [Android Differences](#android-differences)
@ -112,8 +120,9 @@ If both `VK_DRIVER_FILES` and `VK_ICD_FILENAMES` environment variables are
present, then the newer `VK_DRIVER_FILES` will be used, and the values in
`VK_ICD_FILENAMES` will be ignored.
The `VK_DRIVER_FILES` environment variable is a list of Driver Manifest
files, containing the full path to the driver JSON Manifest file.
The `VK_DRIVER_FILES` environment variable is a list of paths to Driver Manifest
files, containing the full path to the driver JSON Manifest file, and/or paths
to folders containing Driver Manifest files.
This list is colon-separated on Linux and macOS, and semicolon-separated on
Windows.
Typically, `VK_DRIVER_FILES` will only contain a full pathname to one info
@ -126,7 +135,8 @@ There may be times that a developer wishes to force the loader to use a specific
Driver in addition to the standard drivers (without replacing the standard
search paths.
The `VK_ADD_DRIVER_FILES` environment variable can be used to add a list of
Driver Manifest files, containing the full path to the driver JSON Manifest file.
Driver Manifest files, containing the full path to the driver JSON Manifest
file, and/or paths to folders containing Driver Manifest files.
This list is colon-separated on Linux and macOS, and semicolon-separated on
Windows.
It will be added prior to the standard driver search files.
@ -134,11 +144,65 @@ If `VK_DRIVER_FILES` or `VK_ICD_FILENAMES` is present, then
`VK_ADD_DRIVER_FILES` will not be used by the loader and any values will be
ignored.
#### Exception for Elevated Privileges
### Driver Filtering
For security reasons, `VK_ICD_FILENAMES`, `VK_DRIVER_FILES` and
`VK_ADD_DRIVER_FILES` are all ignored if running the Vulkan application with
elevated privileges.
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
The loader supports filter environment variables which can forcibly select and
disable known drivers.
Known driver manifests are those files that are already found by the loader
taking into account default search paths and other environment variables (like
`VK_ICD_FILENAMES` or `VK_ADD_DRIVER_FILES`).
The filter variables will be compared against the driver's manifest filename.
The filters must also follow the behaviors define in the
[Filter Environment Variable Behaviors](LoaderInterfaceArchitecture.md#filter-environment-variable-behaviors)
section of the [LoaderLayerInterface](LoaderLayerInterface.md) document.
#### Driver Select Filtering
The driver select environment variable `VK_LOADER_DRIVERS_SELECT` is a
comma-delimited list of globs to search for in known drivers.
If a driver is not selected when using the `VK_LOADER_DRIVERS_SELECT` filter,
and loader logging is set to emit either warnings or driver messages, then a
message will show for each driver that has been ignored.
This message will look like the following:
```
WARNING | DRIVER: Driver "intel_icd.x86_64.json" ignored because not selected by env var 'VK_LOADER_DRIVERS_SELECT'
```
If no drivers are found with a manifest filename that matches any of the
provided globs, then no driver is enabled and may result in failures for
any Vulkan application that is run.
#### Driver Disable Filtering
The driver disable environment variable `VK_LOADER_DRIVERS_DISABLE` is a
comma-delimited list of globs to search for in known drivers.
When a driver is disabled using the `VK_LOADER_DRIVERS_DISABLE` filter, and
loader logging is set to emit either warnings or driver messages, then a message
will show for each driver that has been forcibly disabled.
This message will look like the following:
```
WARNING | DRIVER: Driver "radeon_icd.x86_64.json" ignored because it was disabled by env var 'VK_LOADER_DRIVERS_DISABLE'
```
If no drivers are found with a manifest filename that matches any of the
provided globs, then no driver is disabled.
### Exception for Elevated Privileges
For security reasons, `VK_ICD_FILENAMES`, `VK_DRIVER_FILES`, and
`VK_ADD_DRIVER_FILES` are all ignored if running the Vulkan application
with elevated privileges.
This is because they may insert new libraries into the executable process that
are not normally found by the loader.
Because of this, these environment variables can only be used for applications
that do not use elevated privileges.
@ -292,9 +356,10 @@ middle.
This is because the value of 1 for vendor_b_vk.json disables the driver.
Additionally, the Vulkan loader will scan the system for well-known Windows
AppX/MSIX packages. If a package is found, the loader will scan the root directory
of this installed package for JSON manifest files. At this time, the only package
that is known is Microsoft's
AppX/MSIX packages.
If a package is found, the loader will scan the root directory of this installed
package for JSON manifest files. At this time, the only package that is known is
Microsoft's
[OpenCL™ and OpenGL® Compatibility Pack](https://apps.microsoft.com/store/detail/9NQPSL29BFFF?hl=en-us&gl=US).
The Vulkan loader will open each enabled manifest file found to obtain the name
@ -386,7 +451,7 @@ The loader then selects each path, and applies the "/vulkan/icd.d" suffix onto
each and looks in that specific folder for manifest files.
The Vulkan loader will open each manifest file found to obtain the name or
pathname of a driver's shared library (".dylib") file.
pathname of a driver's shared library (".so") file.
**NOTE** While the order of folders searched for manifest files is well
defined, the order contents are read by the loader in each directory is
@ -447,6 +512,17 @@ The order is similar to the search path on Linux with the exception that
the application's bundle resources are searched first:
`(bundle)/Contents/Resources/`.
System installed drivers will be ignored if drivers are found inside of the app
bundle.
This is because there is not a standard mechanism in which to distinguish drivers
that happen to be duplicates.
For example, MoltenVK is commonly placed inside application bundles.
If there exists a system installed MoltenVK, the loader will load both the app
bundled and the system installed MoltenVK, leading to potential issues or crashes.
Drivers found through environment variables, such as `VK_DRIVER_FILES`, will be
used regardless of whether there are bundled drivers present or not.
#### Example macOS Driver Search Path
For a fictional user "Me" the Driver Manifest search path might look
@ -475,6 +551,117 @@ will expose it and cause the Vulkan loader to fail on loading the driver.
It is recommended that `LD_BIND_NOW` along with `VK_LOADER_DEBUG=error,warn`
to expose any issues.
### Driver Discovery using the`VK_LUNARG_direct_driver_loading` extension
The `VK_LUNARG_direct_driver_loading` extension allows for applications to
provide a driver or drivers to the Loader during vkCreateInstance.
This allows drivers to be included with an application without requiring
installation and is capable of being used in any execution environment, such as
a process running with elevated privileges.
When calling `vkEnumeratePhysicalDevices` with the
`VK_LUNARG_direct_driver_loading` extension enabled, the `VkPhysicalDevice`s
from system installed drivers and environment variable specified drivers will
appear before any `VkPhysicalDevice`s that originate from drivers from the
`VkDirectDriverLoadingListLUNARG::pDrivers` list.
#### How to use `VK_LUNARG_direct_driver_loading`
To use this extension, it must first be enabled on the VkInstance.
This requires enabling the `VK_LUNARG_direct_driver_loading` extension through
the `enabledExtensionCount` and `ppEnabledExtensionNames`members of
`VkInstanceCreateInfo`.
```c
const char* extensions[] = {VK_LUNARG_DIRECT_DRIVER_LOADING_EXTENSION_NAME, <other extensions>};
VkInstanceCreateInfo instance_create_info = {};
instance_create_info.enabledExtensionCount = <size of extension list>;
instance_create_info.ppEnabledExtensionNames = extensions;
```
The `VkDirectDriverLoadingInfoLUNARG` structure contains a
`VkDirectDriverLoadingFlagsLUNARG` member (reserved for future use) and a
`PFN_vkGetInstanceProcAddrLUNARG` member which provides the loader with the
function pointer for the driver's `vkGetInstanceProcAddr`.
The `VkDirectDriverLoadingListLUNARG` structure contains a count and pointer
members which provide the size of and pointer to an application provided array of
`VkDirectDriverLoadingInfoLUNARG` structures.
Creating those structures looks like the following
```c
VkDirectDriverLoadingInfoLUNARG direct_loading_info = {};
direct_loading_info.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_INFO_LUNARG
direct_loading_info.pfnGetInstanceProcAddr = <put the PFN_vkGetInstanceProcAddr of the driver here>
VkDirectDriverLoadingListLUNARG direct_driver_list = {};
direct_driver_list.sType = VK_STRUCTURE_TYPE_DIRECT_DRIVER_LOADING_LIST_LUNARG;
direct_driver_list.mode = VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG; // or VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG
direct_driver_list.driverCount = 1;
direct_driver_list.pDrivers = &direct_loading_info; // can include multiple drivers here if so desired
```
The `VkDirectDriverLoadingListLUNARG` structure contains the enum
`VkDirectDriverLoadingModeLUNARG`.
There are two modes:
* `VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG` - specifies that the only drivers
to be loaded will come from the `VkDirectDriverLoadingListLUNARG` structure.
* `VK_DIRECT_DRIVER_LOADING_MODE_INCLUSIVE_LUNARG` - specifies that drivers
from the `VkDirectDriverLoadingModeLUNARG` structure will be used in addition to
any system installed drivers and environment variable specified drivers.
Then, the `VkDirectDriverLoadingListLUNARG` structure *must* be appended to the
`pNext` chain of `VkInstanceCreateInfo`.
```c
instance_create_info.pNext = (const void*)&direct_driver_list;
```
Finally, create the instance like normal.
#### Interactions with other driver discovery mechanisms
If the `VK_DIRECT_DRIVER_LOADING_MODE_EXCLUSIVE_LUNARG` mode is specified in the
`VkDirectDriverLoadingListLUNARG` structure, then no system installed drivers
are loaded.
This applies equally to all platforms.
Additionally, the following environment variables have no effect:
* `VK_DRIVER_FILES`
* `VK_ICD_FILENAMES`
* `VK_ADD_DRIVER_FILES`
* `VK_LOADER_DRIVERS_SELECT`
* `VK_LOADER_DRIVERS_DISABLE`
Exclusive mode will also disable MacOS bundle manifest discovery of drivers.
#### Limitations of `VK_LUNARG_direct_driver_loading`
Because `VkDirectDriverLoadingListLUNARG` is provided to the loader at instance
creation, there is no mechanism for the loader to query the list of instance
extensions that originate from `VkDirectDriverLoadingListLUNARG` drivers during
`vkEnumerateInstanceExtensionProperties`.
Applications can instead manually load the `vkEnumerateInstanceExtensionProperties`
function pointer directly from the drivers the application provides to the loader
using the `pfnGetInstanceProcAddrLUNARG` for each driver.
Then the application can call each driver's
`vkEnumerateInstanceExtensionProperties` and append non-duplicate entriees to the
list from the loader's `vkEnumerateInstanceExtensionProperties` to get the full
list of supported instance extensions.
Alternatively, because the Application is providing drivers, it is reasonable for
the application to already know which instance extensions are available with the
provided drivers, preventing the need to manually query them.
However, there are limitations.
If there are any active implicit layers which intercept
`vkEnumerateInstanceExtensionProperties` to remove unsupported extensions, then
those layers will not be able to remove unsupported extensions from drivers that
are provided by the application.
This is due to `vkEnumerateInstanceExtensionProperties` not having a mechanism
to extend it.
### Using Pre-Production ICDs or Software Drivers
@ -510,7 +697,8 @@ The loader will load the driver via `hw_get_module` with the ID of "vulkan".
## Driver Manifest File Format
The following section discusses the details of the Driver Manifest JSON file format.
The following section discusses the details of the Driver Manifest JSON file
format.
The JSON file itself does not have any requirements for naming.
The only requirement is that the extension suffix of the file is ".json".
@ -569,18 +757,18 @@ Here is an example driver JSON Manifest file:
<td>"api_version" </td>
<td>The major.minor.patch version number of the maximum Vulkan API supported
by the driver.
However, just because the driver supports the specific Vulkan API version,
it does not guarantee that the hardware on a user's system can support
that version.
However, just because the driver supports the specific Vulkan API
version, it does not guarantee that the hardware on a user's system can
support that version.
Information on what the underlying physical device can support must be
queried by the user using the <i>vkGetPhysicalDeviceProperties</i> API call.
<br/>
queried by the user using the <i>vkGetPhysicalDeviceProperties</i> API
call.<br/>
For example: 1.0.33.</td>
</tr>
<tr>
<td>"is_portability_driver" </td>
<td>Defines whether the driver contains any VkPhysicalDevices which implement
the VK_KHR_portability_subset extension.<br/>
<td>Defines whether the driver contains any VkPhysicalDevices which
implement the VK_KHR_portability_subset extension.<br/>
</td>
</tr>
</table>
@ -742,11 +930,17 @@ missing support for this extension.
## Driver Unknown Physical Device Extensions
Drivers that implement entrypoints which take a `VkPhysicalDevice` as the first
parameter *should* support `vk_icdGetPhysicalDeviceProcAddr`. This function
is added to the Driver Interface Version 4 and allows the loader to distinguish
between entrypoints which take `VkDevice` and `VkPhysicalDevice` as the first
parameter. This allows the loader to properly support entrypoints that are
unknown to it gracefully.
parameter *should* support `vk_icdGetPhysicalDeviceProcAddr`.
This function is added to the Loader and Driver Driver Interface Version 4,
allowing the loader to distinguish between entrypoints which take `VkDevice`
and `VkPhysicalDevice` as the first parameter.
This allows the loader to properly support entrypoints that are unknown to it
gracefully.
This entry point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers.
Note: Loader and Driver Interface Version 7 makes exporting
`vk_icdGetPhysicalDeviceProcAddr` optional.
Instead, drivers *must* expose it through `vk_icdGetInstanceProcAddr`.
```cpp
PFN_vkVoidFunction
@ -762,13 +956,13 @@ In this way, it compares "pName" to every physical device function supported in
the driver.
Implementations of the function should have the following behavior:
* If `pName` is the name of a Vulkan API entrypoint that takes a `VkPhysicalDevice`
as its primary dispatch handle, and the driver supports the entrypoint, then
the driver **must** return the valid function pointer to the driver's
implementation of that entrypoint.
* If `pName` is the name of a Vulkan API entrypoint that takes something other than
a `VkPhysicalDevice` as its primary dispatch handle, then the driver **must**
return `NULL`.
* If `pName` is the name of a Vulkan API entrypoint that takes a
`VkPhysicalDevice` as its primary dispatch handle, and the driver supports the
entrypoint, then the driver **must** return the valid function pointer to the
driver's implementation of that entrypoint.
* If `pName` is the name of a Vulkan API entrypoint that takes something other
than a `VkPhysicalDevice` as its primary dispatch handle, then the driver
**must** return `NULL`.
* If the driver is unaware of any entrypoint with the name `pName`, it **must**
return `NULL`.
@ -782,7 +976,9 @@ function.
If a driver does implement this support, it must export the function from the
driver library using the name `vk_icdGetPhysicalDeviceProcAddr` so that the
symbol can be located through the platform's dynamic linking utilities.
symbol can be located through the platform's dynamic linking utilities, or if
the driver supports Loader and Driver Interface Version 7, exposed through
`vk_icdGetInstanceProcAddr` instead.
The behavior of the loader's `vkGetInstanceProcAddr` with support for the
`vk_icdGetPhysicalDeviceProcAddr` function is as follows:
@ -848,10 +1044,15 @@ preference will be listed first.
This mechanism does not force an application to use any particular GPU &mdash;
it merely changes the order in which they are presented.
This mechanism requires that a driver provide version 6 of the loader/driver
interface.
Version 6 of this interface defines a new exported function that the driver may
provide on Windows:
This mechanism requires that a driver provide The Loader and Driver Interface
Version 6.
This version defines a new exported function, `vk_icdEnumerateAdapterPhysicalDevices`,
detailed below, that Drivers may provide on Windows.
This entry point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers.
Note: Loader and Driver Interface Version 7 makes exporting
`vk_icdEnumerateAdapterPhysicalDevices` optional.
Instead, drivers *must* expose it through `vk_icdGetInstanceProcAddr`.
```c
VKAPI_ATTR VkResult VKAPI_CALL
@ -862,6 +1063,7 @@ VKAPI_ATTR VkResult VKAPI_CALL
VkPhysicalDevice* pPhysicalDevices);
```
This function takes an adapter LUID as input, and enumerates all Vulkan physical
devices that are associated with that LUID.
This works in the same way as other Vulkan enumerations &mdash; if
@ -886,6 +1088,14 @@ of Windows 10 that support GPU selection through the OS.
Other platforms may be included in the future, but they will require separate
platform-specific interfaces.
A requirement of `vk_icdEnumerateAdapterPhysicalDevices` is that it *must*
return the same `VkPhysicalDevice` handle values for the same physical
devices that are returned by `vkEnumeratePhysicalDevices`.
This is because the loader calls both functions on the driver then
de-duplicates the physical devices using the `VkPhysicalDevice` handles.
Since not all physical devices in a driver will have a LUID, such as for
software implementations, this step is necessary to allow drivers to
enumerate all available physical devices.
## Driver Dispatchable Object Creation
@ -966,8 +1176,8 @@ appropriate `VkIcdSurfaceXXX` structure.
The driver may choose to handle `VkSurfaceKHR` object creation instead.
If a driver desires to handle creating and destroying it must do the following:
1. Support version 3 or newer of the loader/driver interface.
2. Export and handle all functions that take in a `VkSurfaceKHR` object,
1. Support Loader and Driver Interface Version 3 or newer.
2. Expose and handle all functions that take in a `VkSurfaceKHR` object,
including:
* `vkCreateXXXSurfaceKHR`
* `vkGetPhysicalDeviceSurfaceSupportKHR`
@ -1010,13 +1220,16 @@ These additional requirements are versioned to allow flexibility in the future.
### Windows, Linux and macOS Driver Negotiation
#### Version Negotiation Between Loader and Drivers
#### Version Negotiation Between the Loader and Drivers
All drivers (supporting interface version 2 or higher) must export the
following function that is used for determination of the interface version that
will be used.
All drivers supporting Loader and Driver Interface Version 2 or higher must
export the following function that is used for determination of the interface
version that will be used.
This entry point is not a part of the Vulkan API itself, only a private
interface between the loader and drivers.
Note: Loader and Driver Interface Version 7 makes exporting
`vk_icdNegotiateLoaderICDInterfaceVersion` optional.
Instead, drivers *must* expose it through `vk_icdGetInstanceProcAddr`.
```cpp
VKAPI_ATTR VkResult VKAPI_CALL
@ -1060,19 +1273,50 @@ during enumeration.
#### Interfacing With Legacy Drivers or Loaders
If a loader sees that a driver does not export the
If a loader sees that a driver does not export or expose the
`vk_icdNegotiateLoaderICDInterfaceVersion` function, then the loader assumes the
corresponding driver only supports either interface version 0 or 1.
From the other side of the interface, if a driver sees a call to
`vk_icdGetInstanceProcAddr` before a call to
`vk_icdNegotiateLoaderICDInterfaceVersion`, then it knows that loader making the
calls is a legacy loader supporting version 0 or 1.
If the loader calls `vk_icdGetInstanceProcAddr` first, it supports at least
version 1.
`vk_icdNegotiateLoaderICDInterfaceVersion`, then the loader is either a legacy
loader with only support for interface version 0 or 1, or the loader is using
interface version 7 or newer.
If the first call to `vk_icdGetInstanceProcAddr` is to query for
`vk_icdNegotiateLoaderICDInterfaceVersion`, then that means the loader is using
interface version 7.
This only occurs when the driver does not export
`vk_icdNegotiateLoaderICDInterfaceVersion`.
Drivers which export `vk_icdNegotiateLoaderICDInterfaceVersion` will have it
called first.
If the first call to `vk_icdGetInstanceProcAddr` is **not** querying for
`vk_icdNegotiateLoaderICDInterfaceVersion`, then loader is a legacy loader only
which supports version 0 or 1.
In this case, if the loader calls `vk_icdGetInstanceProcAddr` first, it supports
at least interface version 1.
Otherwise, the loader only supports version 0.
#### Loader Version 6 Interface Requirements
#### Loader and Driver Interface Version 7 Requirements
Version 7 relaxes the requirement that Loader and Driver Interface functions
must be exported.
Instead, it only requires that those functions be queryable through
`vk_icdGetInstanceProcAddr`.
The functions are:
`vk_icdNegotiateLoaderICDInterfaceVersion`
`vk_icdGetPhysicalDeviceProcAddr`
`vk_icdEnumerateAdapterPhysicalDevices` (Windows only)
These functions are considered global for the purposes of retrieval, so the
`VkInstance` parameter of `vk_icdGetInstanceProcAddr` will be **NULL**.
While exporting these functions is no longer a requirement, drivers may still
export them for compatibility with older loaders.
The changes in this version allow drivers provided through the
`VK_LUNARG_direct_driver_loading` extension to support the entire Loader and
Driver Interface.
#### Loader and Driver Interface Version 6 Requirements
Version 6 provides a mechanism to allow the loader to sort physical devices.
The loader will only attempt to sort physical devices on a driver if version 6
@ -1080,9 +1324,9 @@ of the interface is supported.
This version provides the `vk_icdEnumerateAdapterPhysicalDevices` function
defined earlier in this document.
#### Loader Version 5 Interface Requirements
#### Loader and Driver Interface Version 5 Requirements
Version 5 of the loader/driver interface has no changes to the actual interface.
This interface version has no changes to the actual interface.
If the loader requests interface version 5 or greater, it is simply
an indication to drivers that the loader is now evaluating whether the API
Version info passed into vkCreateInstance is a valid version for the loader.
@ -1139,10 +1383,9 @@ Here is a table of the expected behaviors:
</tr>
</table>
#### Loader Version 4 Interface Requirements
#### Loader and Driver Interface Version 4 Requirements
The major change to version 4 of the loader/driver interface is the
support of
The major change to version 4 of this interface version is the support of
[Unknown Physical Device Extensions](#driver-unknown-physical-device-extensions)
using the `vk_icdGetPhysicalDeviceProcAddr` function.
This function is purely optional.
@ -1152,16 +1395,16 @@ Otherwise, the loader will continue to treat any unknown functions as VkDevice
functions and cause invalid behavior.
#### Loader Version 3 Interface Requirements
#### Loader and Driver Interface Version 3 Requirements
The primary change that occurred in version 3 of the loader/driver interface was
to allow a driver to handle creation/destruction of their own KHR_surfaces.
The primary change that occurred in this interface version is to allow a driver
to handle creation and destruction of their own KHR_surfaces.
Up until this point, the loader created a surface object that was used by all
drivers.
However, some drivers may want to provide their own surface handles.
If a driver chooses to enable this support, it must export support for version 3
of the loader/driver interface, as well as any Vulkan function that uses a
KHR_surface handle, such as:
However, some drivers *may* want to provide their own surface handles.
If a driver chooses to enable this support, it must support Loader and Driver
Interface Version 3, as well as any Vulkan function that uses a `VkSurfaceKHR`
handle, such as:
- `vkCreateXXXSurfaceKHR` (where XXX is the platform-specific identifier [i.e.
`vkCreateWin32SurfaceKHR` for Windows])
- `vkDestroySurfaceKHR`
@ -1171,25 +1414,24 @@ KHR_surface handle, such as:
- `vkGetPhysicalDeviceSurfaceFormatsKHR`
- `vkGetPhysicalDeviceSurfacePresentModesKHR`
A driver can still choose to not take advantage of this functionality
by simply not exposing the above `vkCreateXXXSurfaceKHR` and
A driver which does not participate in this functionality can opt out by
simply not exposing the above `vkCreateXXXSurfaceKHR` and
`vkDestroySurfaceKHR` functions.
#### Loader Version 2 Interface Requirements
#### Loader and Driver Interface Version 2 Requirements
Version 2 interface is the first to implement the new
`vk_icdNegotiateLoaderICDInterfaceVersion` functionality, see
[Version Negotiation Between Loader and Drivers](#version-negotiation-between-loader-and-drivers) for more details
on that function.
Interface Version 2 requires that drivers export
`vk_icdNegotiateLoaderICDInterfaceVersion`.
For more information, see [Version Negotiation Between Loader and Drivers](#version-negotiation-between-loader-and-drivers).
Additional, version 2 was the first to define that Vulkan dispatchable objects
created by drivers must now be created in accordance to the
Additional, version 2 requires that Vulkan dispatchable objects created by
drivers must be created in accordance to the
[Driver Dispatchable Object Creation](#driver-dispatchable-object-creation)
section.
#### Loader Version 1 Interface Requirements
#### Loader and Driver Interface Version 1 Requirements
Version 1 of the interface added the driver-specific entry-point
`vk_icdGetInstanceProcAddr`.
@ -1204,14 +1446,14 @@ No other entry-points need to be exported by the driver as the loader will query
the appropriate function pointers using that.
#### Loader Version 0 Interface Requirements
#### Loader and Driver Interface Version 0 Requirements
Version 0 interface does not support either `vk_icdGetInstanceProcAddr` or
Version 0 does not support either `vk_icdGetInstanceProcAddr` or
`vk_icdNegotiateLoaderICDInterfaceVersion`.
Because of this, the loader will assume the driver supports only version 0 of
the interface unless one of those functions exists.
Additionally, for version 0, the driver must expose at least the following core
Additionally, for Version 0, the driver must expose at least the following core
Vulkan entry-points so the loader may build up the interface to the driver:
- The function `vkGetInstanceProcAddr` **must be exported** in the driver
@ -1257,12 +1499,13 @@ manifest files used by the Windows, Linux and macOS loaders.
The loader implements the `VK_KHR_portability_enumeration` instance extension,
which filters out any drivers that report support for the portability subset
device extension. Unless the application explicitly requests enumeration of
portability devices by setting the VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR
bit in the VkInstanceCreateInfo::flags, the loader does not load any drivers
that declare themselves to be portability drivers.
portability devices by setting the
`VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR` bit in the
VkInstanceCreateInfo::flags, the loader does not load any drivers that declare
themselves to be portability drivers.
Drivers declare whether they are portability drivers or not in the Driver Manifest
Json file, with the `is_portability_driver` boolean field.
Drivers declare whether they are portability drivers or not in the Driver
Manifest Json file, with the `is_portability_driver` boolean field.
[More information here](#driver-manifest-file-version-101)
The initial support for this extension only reported errors when an application
@ -1292,8 +1535,8 @@ best experience to end-users and developers.
### Number Format
Loader/Driver policy items start with the prefix `LDP_` (short for
Loader/Driver Policy) which is followed by an identifier based on what
Loader and Driver policy items start with the prefix `LDP_` (short for
Loader and Driver Policy) which is followed by an identifier based on what
component the policy is targeted against.
In this case there are only two possible components:
- Drivers: which will have the string `DRIVER_` as part of the policy number.
@ -1355,7 +1598,7 @@ Android Vulkan documentation</a>.
<tr>
<td><small><b>LDP_DRIVER_3</b></small></td>
<td>A driver <b>must</b> be able to negotiate a supported version of the
loader/driver interface with the loader in accordance with the stated
Loader and Driver Interface with the loader in accordance with the stated
negotiation process.
</td>
<td>The driver will not be loaded.</td>
@ -1397,14 +1640,15 @@ Android Vulkan documentation</a>.
possibly including crashes or corruption.
</td>
<td><small>
<a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/master/external/openglcts/README.md">
<a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/main/external/openglcts/README.md">
Vulkan CTS Documentation</a>
</small>
</td>
</tr>
<tr>
<td><small><b>LDP_DRIVER_6</b></small></td>
<td>Removed - See <a href="#removed-driver-policies">Removed Driver Policies</a>
<td>Removed - See
<a href="#removed-driver-policies">Removed Driver Policies</a>
</td>
<td>-</td>
<td>-</td>
@ -1414,7 +1658,7 @@ Android Vulkan documentation</a>.
<tr>
<td><small><b>LDP_DRIVER_7</b></small></td>
<td>If a driver desires to support Vulkan API 1.1 or newer, it <b>must</b>
expose support of Vulkan loader/driver interface 5 or newer.
expose support for Loader and Driver Interface Version 5 or newer.
</td>
<td>The driver will be used when it shouldn't be and will cause
undefined behavior possibly including crashes or corruption.
@ -1429,7 +1673,7 @@ Android Vulkan documentation</a>.
<tr>
<td><small><b>LDP_DRIVER_8</b></small></td>
<td>If a driver wishes to handle its own <i>VkSurfaceKHR</i> object
creation, it <b>must</b> implement loader/driver interface version 3 or
creation, it <b>must</b> implement the Loader and Driver Interface Version 3 or
newer and support querying all the relevant surface functions via
<i>vk_icdGetInstanceProcAddr</i>.
</td>
@ -1443,15 +1687,15 @@ Android Vulkan documentation</a>.
</tr>
<tr>
<td><small><b>LDP_DRIVER_9</b></small></td>
<td>If a driver negotiation results in it using loader/driver interface
version 4 or earlier, the driver <b>must</b> verify that the Vulkan API
version passed into <i>vkCreateInstance</i> (through
<td>If version negotiation results in a driver using the Loader
and Driver Interface Version 4 or earlier, the driver <b>must</b> verify
that the Vulkan API version passed into <i>vkCreateInstance</i> (through
<i>VkInstanceCreateInfo</i>s <i>VkApplicationInfo</i>'s
<i>apiVersion</i>) is supported.
If the requested Vulkan API version can not be supported by the driver,
it <b>must</b> return <b>VK_ERROR_INCOMPATIBLE_DRIVER</b>. <br/>
This is not required if the interface version is 5 or newer because the
responsibility for this check then falls on the loader.
loader is responsible for this check.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
@ -1463,11 +1707,13 @@ Android Vulkan documentation</a>.
</tr>
<tr>
<td><small><b>LDP_DRIVER_10</b></small></td>
<td>If a driver negotiation results in it using loader/driver interface
version 5 or newer, the driver <b>must</b> ignore the Vulkan API version
<td>If version negotiation results in a driver using the Loader and Driver Interface
Version 5 or newer, the driver <b>must</b> not return
<b>VK_ERROR_INCOMPATIBLE_DRIVER</b> if the Vulkan API version
passed into <i>vkCreateInstance</i> (through
<i>VkInstanceCreateInfo</i>s <i>VkApplicationInfo</i>'s
<i>apiVersion</i>).
<i>apiVersion</i>) is not supported by the driver. This check is performed
by the loader on the drivers behalf.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>
@ -1515,7 +1761,8 @@ Android Vulkan documentation</a>.
#### Removed Driver Policies
These policies were in the loader source at some point but later removed. They are documented here for reference.
These policies were in the loader source at some point but later removed.
They are documented here for reference.
<table>
<tr>
@ -1525,7 +1772,7 @@ These policies were in the loader source at some point but later removed. They a
</tr>
<tr>
<td><small><b>LDP_DRIVER_6</b></small></td>
<td>A driver supporting loader/driver interface version 1 or newer <b>must
<td>A driver supporting Loader and Driver Interface Version 1 or newer <b>must
not</b> directly export standard Vulkan entry-points.
<br/>
Instead, it <b>must</b> export only the loader interface functions
@ -1611,7 +1858,7 @@ These policies were in the loader source at some point but later removed. They a
<tr>
<td><small><b>LDP_LOADER_5</b></small></td>
<td>A loader <b>must</b> ignore any driver for which a compatible
loader/driver interface version can not be negotiated.
Loader and Driver Interface Version can not be negotiated.
</td>
<td>The loader would load a driver improperly resulting in undefined
behavior possibly including crashes or corruption.
@ -1624,16 +1871,16 @@ These policies were in the loader source at some point but later removed. They a
</tr>
<tr>
<td><small><b>LDP_LOADER_6</b></small></td>
<td>If a driver negotiation results in it using loader/driver interface
version 5 or newer, a loader <b>must</b> verify that the Vulkan API
version passed into <i>vkCreateInstance</i> (through
<td>If a driver negotiation results in the loader using Loader and Driver
Interface Version 5 or newer, a loader <b>must</b> verify that the Vulkan
API version passed into <i>vkCreateInstance</i> (through
<i>VkInstanceCreateInfo</i>s <i>VkApplicationInfo</i>'s
<i>apiVersion</i>) is supported by at least one driver.
If the requested Vulkan API version can not be supported by any
driver, the loader <b>must</b> return
<b>VK_ERROR_INCOMPATIBLE_DRIVER</b>.<br/>
This is not required if the interface version is 4 or earlier because
the responsibility for this check then falls on the drivers.
This is not required if the Loader and Driver Interface Version is 4 or
earlier because the responsibility for this check falls on the drivers.
</td>
<td>The behavior is undefined and may result in crashes or corruption.</td>
<td>No</td>

View File

@ -4,14 +4,14 @@
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Architecture of the Vulkan Loader Interfaces
# Architecture of the Vulkan Loader Interfaces <!-- omit from toc -->
[![Creative Commons][3]][4]
<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
<!-- Copyright &copy; 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
## Table of Contents
## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Who Should Read This Document](#who-should-read-this-document)
@ -38,8 +38,17 @@
- [Application Interface to the Loader](#application-interface-to-the-loader)
- [Layer Interface with the Loader](#layer-interface-with-the-loader)
- [Driver Interface With the Loader](#driver-interface-with-the-loader)
- [Debugging Issues](#debugging-issues)
- [Loader Policies](#loader-policies)
- [Filter Environment Variable Behaviors](#filter-environment-variable-behaviors)
- [Comparison Strings](#comparison-strings)
- [Comma-Delimited Lists](#comma-delimited-lists)
- [Globs](#globs)
- [Case-Insensitive](#case-insensitive)
- [Environment Variable Priority](#environment-variable-priority)
- [Table of Debug Environment Variables](#table-of-debug-environment-variables)
- [Active Environment Variables](#active-environment-variables)
- [Deprecated Environment Variables](#deprecated-environment-variables)
- [Glossary of Terms](#glossary-of-terms)
## Overview
@ -217,7 +226,7 @@ In the future, VkConfig may have additional interactions with the Vulkan
loader.
More details on VkConfig can be found in its
[GitHub documentation](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md).
[GitHub documentation](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md).
<br/>
<br/>
@ -374,7 +383,7 @@ layers to marshall the appropriate information to all available drivers.
For example, the diagram below represents what happens in the call chain for
`vkCreateInstance`.
After initializing the chain, the loader calls into the first layer's
`vkCreateInstance`, which will call the next layer's `vkCreateInstance
`vkCreateInstance`, which will call the next layer's `vkCreateInstance`
before finally terminating in the loader again where it will call
every driver's `vkCreateInstance`.
This allows every enabled layer in the chain to set up what it needs based on
@ -458,6 +467,17 @@ directory as this file.
<br/>
## Debugging Issues
If your application is crashing or behaving weirdly, the loader provides
several mechanisms for you to debug the issues.
These are detailed in the [LoaderDebugging.md](LoaderDebugging.md) document
found in the same directory as this file.
<br/>
<br/>
## Loader Policies
Loader policies with regards to the loader interaction with drivers and layers
@ -478,6 +498,62 @@ sections listed below:
<br/>
<br/>
## Filter Environment Variable Behaviors
The filter environment variables provided in certain areas have some common
restrictions and behaviors that should be listed.
### Comparison Strings
The filter variables will be compared against the appropriate strings for either
drivers or layers.
The appropriate string for layers is the layer name provided in the layer's
manifest file.
Since drivers dont have a name like layers, this substring is used to compare
against the driver manifest's filename.
### Comma-Delimited Lists
All of the filter environment variables accept comma-delimited input.
Therefore, you can chain multiple strings together and it will use the strings
to individually enable or disable the appropriate item in the current list of
available items.
### Globs
To provide enough flexibility to limit name searches to only those wanted by the
developer, the loader uses a limited glob format for strings.
Acceptable globs are:
- Prefixes: `"string*"`
- Suffixes: `"*string"`
- Substrings: `"*string*"`
- Whole strings: `"string"`
- In the case of whole strings, the string will be compared against each
layer or driver file name in its entirety.
- Because of this, it will only match the specific target such as:
`VK_LAYER_KHRONOS_validation` will match the layer name
`VK_LAYER_KHRONOS_validation`, but **not** a layer named
`VK_LAYER_KHRONOS_validation2` (not that there is such a layer).
This is especially useful because it is difficult sometimes to determine the
full name of a driver manifest file or even some commonly used layers
such as `VK_LAYER_KHRONOS_validation`.
### Case-Insensitive
All of the filter environment variables assume the strings inside of the glob
are not case-sensitive.
Therefore, “Bob”, “bob”, and “BOB” all amount to the same thing.
### Environment Variable Priority
The values from the *disable* environment variable will be considered
**before** the *enable* or *select* environment variable.
Because of this, it is possible to disable a layer/driver using the *disable*
environment variable, only to have it be re-enabled by the *enable*/*select*
environment variable.
This is useful if you disable all layers/drivers with the intent of only
enabling a smaller subset of specific layers/drivers for issue triaging.
## Table of Debug Environment Variables
@ -556,14 +632,15 @@ discovery.
<td><small>
Force the loader to use the specific driver JSON files.
The value contains a list of delimited full path listings to
driver JSON Manifest files.<br/>
driver JSON Manifest files and/or
paths to folders containing driver JSON files.<br/>
<br/>
This has replaced the older deprecated environment variable
<i>VK_ICD_FILENAMES</i>, however the older environment variable will
continue to work for some time.
continue to work.
</small></td>
<td><small>
If a global path to the JSON file is not used, issues may be encountered.
If a relative path not used, issues may be encountered.
<br/> <br/>
<a href="#elevated-privilege-caveats">
Ignored when running Vulkan application with elevated privileges.
@ -580,35 +657,12 @@ discovery.
</small>
</td>
</tr>
<tr>
<td><small>
<i>VK_INSTANCE_LAYERS</i>
</small></td>
<td><small>
Force the loader to add the given layers to the list of Enabled layers
normally passed into <b>vkCreateInstance</b>.
These layers are added first, and the loader will remove any duplicate
layers that appear in both this list as well as that passed into
<i>ppEnabledLayerNames</i>.
</small></td>
<td><small>
None
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;:&lt;layer_b&gt;<br/><br/>
set<br/>
&nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;;&lt;layer_b&gt;
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LAYER_PATH</i></small></td>
<td><small>
Override the loader's standard Layer library search folders and use the
provided delimited folders to search for explicit layer manifest files.
provided delimited file and/or folders to locate explicit layer manifest files.
</small></td>
<td><small>
<a href="#elevated-privilege-caveats">
@ -624,6 +678,34 @@ discovery.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;path_a&gt;;&lt;path_b&gt;
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_DEBUG</i>
</small></td>
<td><small>
Enable loader debug messages using a comma-delimited list of level
options. These options are:<br/>
&nbsp;&nbsp;* error (only errors)<br/>
&nbsp;&nbsp;* warn (only warnings)<br/>
&nbsp;&nbsp;* info (only info)<br/>
&nbsp;&nbsp;* debug (only debug)<br/>
&nbsp;&nbsp;* layer (layer-specific output)<br/>
&nbsp;&nbsp;* driver (driver-specific output)<br/>
&nbsp;&nbsp;* all (report out all messages)<br/><br/>
To enable multiple options (outside of "all") like info, warning and
error messages, set the value to "error,warn,info".
</small></td>
<td><small>
None
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_DEBUG=all<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_DEBUG=warn
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_DEVICE_SELECT</i>
@ -679,30 +761,179 @@ discovery.
</tr>
<tr>
<td><small>
<i>VK_LOADER_DEBUG</i>
<i>VK_LOADER_DRIVERS_SELECT</i>
</small></td>
<td><small>
Enable loader debug messages using a comma-delimited list of level
options. These options are:<br/>
&nbsp;&nbsp;* error (only errors)<br/>
&nbsp;&nbsp;* warn (only warnings)<br/>
&nbsp;&nbsp;* info (only info)<br/>
&nbsp;&nbsp;* debug (only debug)<br/>
&nbsp;&nbsp;* layer (layer-specific output)<br/>
&nbsp;&nbsp;* driver (driver-specific output)<br/>
&nbsp;&nbsp;* all (report out all messages)<br/><br/>
To enable multiple options (outside of "all") like info, warning and
error messages, set the value to "error,warn,info".
A comma-delimited list of globs to search for in known drivers and
used to select only the drivers whose manifest file names match one or
more of the provided globs.<br/>
Since drivers dont have a name like layers, this glob is used to
compare against the manifest filename.
Known driver manifests being those files that are already found by the
loader taking into account default search paths and other environment
variables (like <i>VK_ICD_FILENAMES</i> or <i>VK_ADD_DRIVER_FILES</i>).
</small></td>
<td><small>
None
This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.<br/>
If no drivers are found with a manifest filename that matches any of the
provided globs, then no driver is enabled and it <b>may</b> result
in Vulkan applications failing to run properly.
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_DEBUG=all<br/>
&nbsp;&nbsp;VK_LOADER_DRIVERS_SELECT=nvidia*<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_DEBUG=warn
&nbsp;&nbsp;VK_LOADER_DRIVERS_SELECT=nvidia*<br/><br/>
The above would select only the Nvidia driver if it was present on the
system and already visible to the loader.
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_DRIVERS_DISABLE</i>
</small></td>
<td><small>
A comma-delimited list of globs to search for in known drivers and
used to disable only the drivers whose manifest file names match one or
more of the provided globs.<br/>
Since drivers dont have a name like layers, this glob is used to
compare against the manifest filename.
Known driver manifests being those files that are already found by the
loader taking into account default search paths and other environment
variables (like <i>VK_ICD_FILENAMES</i> or <i>VK_ADD_DRIVER_FILES</i>).
</small></td>
<td><small>
This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.<br/>
If all available drivers are disabled using this environment variable,
then no drivers will be found by the loader and <b>will</b> result
in Vulkan applications failing to run properly.<br/>
This is also checked before other driver environment variables (such as
<i>VK_LOADER_DRIVERS_SELECT</i>) so that a user may easily disable all
drivers and then selectively re-enable individual drivers using the
enable environment variable.
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_DRIVERS_DISABLE=*amd*,*intel*<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_DRIVERS_DISABLE=*amd*,*intel*<br/><br/>
The above would disable both Intel and AMD drivers if both were present
on the system and already visible to the loader.
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_LAYERS_ENABLE</i>
</small></td>
<td><small>
A comma-delimited list of globs to search for in known layers and
used to select only the layers whose layer name matches one or more of
the provided globs.<br/>
Known layers are those which are found by the loader taking into account
default search paths and other environment variables
(like <i>VK_LAYER_PATH</i>).
<br/>
This has replaced the older deprecated environment variable
<i>VK_INSTANCE_LAYERS</i>
</small></td>
<td><small>
This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_LAYERS_ENABLE=*validation,*recon*<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_LAYERS_ENABLE=*validation,*recon*<br/><br/>
The above would enable the Khronos validation layer and the
GfxReconstruct layer, if both were present on the system and already
visible to the loader.
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_LAYERS_DISABLE</i>
</small></td>
<td><small>
A comma-delimited list of globs to search for in known layers and
used to disable only the layers whose layer name matches one or more of
the provided globs.<br/>
Known layers are those which are found by the loader taking into account
default search paths and other environment variables
(like <i>VK_LAYER_PATH</i>).
</small></td>
<td><small>
This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.<br/>
Disabling a layer that an application intentionally enables as an
explicit layer <b>may</b> cause the application to not function
properly.<br/>
This is also checked before other layer environment variables (such as
<i>VK_LOADER_LAYERS_ENABLE</i>) so that a user may easily disable all
layers and then selectively re-enable individual layers using the
enable environment variable.
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_LAYERS_DISABLE=*MESA*,~implicit~<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_LAYERS_DISABLE=*MESA*,~implicit~<br/><br/>
The above would disable any Mesa layer and all other implicit layers
that would normally be enabled on the system.
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_LAYERS_ALLOW</i>
</small></td>
<td><small>
A comma-delimited list of globs to search for in known layers and
used to prevent layers whose layer name matches one or more of
the provided globs from being disabled by <i>VK_LOADER_LAYERS_DISABLE</i>.<br/>
Known layers are those which are found by the loader taking into account
default search paths and other environment variables
(like <i>VK_LAYER_PATH</i>).
</small></td>
<td><small>
This functionality is only available with Loaders built with version
1.3.262 of the Vulkan headers and later.<br/>
This will not cause layers to be enabled if the normal mechanism to
enable them
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_LAYERS_ALLOW=*validation*,*recon*<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_LAYERS_ALLOW=*validation*,*recon*<br/><br/>
The above would allow any layer whose name is validation or recon to be
enabled regardless of the value of <i>VK_LOADER_LAYERS_DISABLE</i>.
</small></td>
</tr>
<tr>
<td><small>
<i>VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING</i>
</small></td>
<td><small>
If set to "1", causes the loader to not unload dynamic libraries during vkDestroyInstance.
This option allows leak sanitizers to have full stack traces.
</small></td>
<td><small>
This functionality is only available with Loaders built with version
1.3.259 of the Vulkan headers and later.<br/>
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING=1<br/>
<br/>
set<br/>
&nbsp;&nbsp;VK_LOADER_DISABLE_DYNAMIC_LIBRARY_UNLOADING=1<br/><br/>
</small></td>
</tr>
</table>
@ -750,6 +981,34 @@ may be removed in a future loader release.
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<folder_a>\nvidia.json;<folder_b>\mesa.json
</small></td>
</tr>
<tr>
<td><small>
<i>VK_INSTANCE_LAYERS</i>
</small></td>
<td><small>
Force the loader to add the given layers to the list of Enabled layers
normally passed into <b>vkCreateInstance</b>.
These layers are added first, and the loader will remove any duplicate
layers that appear in both this list as well as that passed into
<i>ppEnabledLayerNames</i>.
</small></td>
<td><small>
This has been deprecated by <i>VK_LOADER_LAYERS_ENABLE</i>.
It also overrides any layers disabled with
<i>VK_LOADER_LAYERS_DISABLE</i>.
</small></td>
<td><small>
None
</small></td>
<td><small>
export<br/>
&nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;;&lt;layer_b&gt;<br/><br/>
set<br/>
&nbsp;&nbsp;VK_INSTANCE_LAYERS=<br/>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&lt;layer_a&gt;;&lt;layer_b&gt;
</small></td>
</tr>
</table>
<br/>
<br/>
@ -814,8 +1073,8 @@ may be removed in a future loader release.
<td>Discovery</td>
<td>The process of the loader searching for driver and layer files to set up
the internal list of Vulkan objects available.<br/>
On <i>Windows/Linux/macOS</i>, the discovery process typically focuses on
searching for Manifest files.<br/>
On <i>Windows/Linux/macOS</i>, the discovery process typically focuses
on searching for Manifest files.<br/>
On <i>Android</i>, the process focuses on searching for library files.
</td>
</tr>
@ -982,4 +1241,31 @@ may be removed in a future loader release.
for more information.
</td>
</tr>
<tr>
<td>Exported Function</td>
<td>A function which is intended to be obtained through the platform specific
dynamic linker, specifically from a Driver or a Layer library.
Functions that are required to be exported are primarily the very first
functions the Loader calls on a Layer or Driver library. <br/>
</td>
</tr>
<tr>
<td>Exposed Function</td>
<td>A function which is intended to be obtained through a Querying Function, such as
`vkGetInstanceProcAddr`.
The exact Querying Function required for a specific exposed function varies
between Layers and Drivers, as well as between interface versions. <br/>
</td>
</tr>
<tr>
<td>Querying Functions</td>
<td>These are functions which allow the Loader to query other functions from
drivers and layers. These functions may be in the Vulkan API but also may be
from the private Loader and Driver Interface or the Loader and Layer Interface. <br/>
These functions are:
`vkGetInstanceProcAddr`, `vkGetDeviceProcAddr`,
`vk_icdGetInstanceProcAddr`, `vk_icdGetPhysicalDeviceProcAddr`, and
`vk_layerGetPhysicalDeviceProcAddr`.
</td>
</tr>
</table>

View File

@ -4,16 +4,16 @@
[1]: https://vulkan.lunarg.com/img/Vulkan_100px_Dec16.png "https://www.khronos.org/vulkan/"
[2]: https://www.khronos.org/vulkan/
# Layer Interface to the Loader
# Layer Interface to the Loader <!-- omit from toc -->
[![Creative Commons][3]][4]
<!-- Copyright &copy; 2015-2021 LunarG, Inc. -->
<!-- Copyright &copy; 2015-2023 LunarG, Inc. -->
[3]: https://i.creativecommons.org/l/by-nd/4.0/88x31.png "Creative Commons License"
[4]: https://creativecommons.org/licenses/by-nd/4.0/
## Table of Contents
## Table of Contents <!-- omit from toc -->
- [Overview](#overview)
- [Layer Discovery](#layer-discovery)
@ -25,6 +25,13 @@
- [Fuchsia Layer Discovery](#fuchsia-layer-discovery)
- [macOS Layer Discovery](#macos-layer-discovery)
- [Example macOS Implicit Layer Search Path](#example-macos-implicit-layer-search-path)
- [Layer Filtering](#layer-filtering)
- [Layer Enable Filtering](#layer-enable-filtering)
- [Layer Disable Filtering](#layer-disable-filtering)
- [Layer Special Case Disable](#layer-special-case-disable)
- [Layer Disable Warning](#layer-disable-warning)
- [Allow certain Layers to ignore Layer Disabling](#allow-certain-layers-to-ignore-layer-disabling)
- [`VK_INSTANCE_LAYERS`](#vk_instance_layers)
- [Exception for Elevated Privileges](#exception-for-elevated-privileges)
- [Layer Version Negotiation](#layer-version-negotiation)
- [Layer Call Chains and Distributed Dispatch](#layer-call-chains-and-distributed-dispatch)
@ -48,6 +55,7 @@
- [Versioning and Activation Interactions](#versioning-and-activation-interactions)
- [Layer Manifest File Format](#layer-manifest-file-format)
- [Layer Manifest File Version History](#layer-manifest-file-version-history)
- [Layer Manifest File Version 1.2.1](#layer-manifest-file-version-121)
- [Layer Manifest File Version 1.2.0](#layer-manifest-file-version-120)
- [Layer Manifest File Version 1.1.2](#layer-manifest-file-version-112)
- [Layer Manifest File Version 1.1.1](#layer-manifest-file-version-111)
@ -335,6 +343,9 @@ provided by the standard explicit layer paths mentioned above.
The paths provided by `VK_ADD_LAYER_PATH` are added before the standard list
of search folders and will therefore be searched first.
If `VK_LAYER_PATH` is present, then `VK_ADD_LAYER_PATH` will not be used by the
loader and any values will be ignored.
For security reasons, both `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` are ignored
if running with elevated privileges.
See [Exception for Elevated Privileges](#exception-for-elevated-privileges)
@ -412,14 +423,130 @@ following:
/usr/share/vulkan/implicit_layer.d
```
### Layer Filtering
**NOTE:** This functionality is only available with Loaders built with version
1.3.234 of the Vulkan headers and later.
The loader supports filter environment variables which can forcibly enable and
disable known layers.
Known layers are those that are already found by the loader taking into account
default search paths and other environment variables
(like `VK_LAYER_PATH` or `VK_ADD_LAYER_PATH`).
The filter variables will be compared against the layer name provided in the
layer's manifest file.
The filters must also follow the behaviors define in the
[Filter Environment Variable Behaviors](LoaderInterfaceArchitecture.md#filter-environment-variable-behaviors)
section of the [LoaderLayerInterface](LoaderLayerInterface.md) document.
#### Layer Enable Filtering
The layer enable environment variable `VK_LOADER_LAYERS_ENABLE` is a
comma-delimited list of globs to search for in known layers.
The layer names are compared against the globs listed in the environment
variable, and if they match, they will automatically be added to the enabled
layer list in the loader for each application.
These layers are enabled after implicit layers but before other explicit layers.
When a layer is enabled using the `VK_LOADER_LAYERS_ENABLE` filter, and
loader logging is set to emit either warnings or layer messages, then a message
will show for each layer that has been forced on.
This message will look like the following:
```
WARNING | LAYER: Layer "VK_LAYER_LUNARG_wrap_objects" force enabled due to env var 'VK_LOADER_LAYERS_ENABLE'
```
#### Layer Disable Filtering
The layer disable environment variable `VK_LOADER_LAYERS_DISABLE` is a
comma-delimited list of globs to search for in known layers.
The layer names are compared against the globs listed in the environment
variable, and if they match, they will automatically be disabled (whether or not
the layer is Implicit or Explicit).
This means that they will not be added to the enabled layer list in the loader
for each application.
This could mean that layers requested by an application are also not enabled
such as `VK_KHRONOS_LAYER_synchronization2` which could cause some applications
to misbehave.
When a layer is disabled using the `VK_LOADER_LAYERS_DISABLE` filter, and
loader logging is set to emit either warnings or layer messages, then a message
will show for each layer that has been forcibly disabled.
This message will look like the following:
```
WARNING | LAYER: Layer "VK_LAYER_LUNARG_wrap_objects" disabled because name matches filter of env var 'VK_LOADER_LAYERS_DISABLE'
```
#### Layer Special Case Disable
Because there are different types of layers, there are 3 additional special
disable options available when using the `VK_LOADER_LAYERS_DISABLE` environment
variable.
These are:
* `~all~`
* `~implicit~`
* `~explicit~`
`~all~` will effectively disable every layer.
This enables a developer to disable all layers on the system.
`~implicit~` will effectively disable every implicit layer (leaving explicit
layers still present in the application call chain).
`~explicit~` will effectively disable every explicit layer (leaving implicit
layers still present in the application call chain).
#### Layer Disable Warning
Disabling layers, whether just through normal usage of
`VK_LOADER_LAYERS_DISABLE` or by evoking one of the special disable options like
`~all~` or `~explicit~` could cause application breakage if the application is
relying on features provided by one or more explicit layers.
#### Allow certain Layers to ignore Layer Disabling
**NOTE:** VK_LOADER_LAYERS_DISABLE is only available with Loaders built with version
1.3.262 of the Vulkan headers and later.
The layer allow environment variable `VK_LOADER_LAYERS_ALLOW` is a
comma-delimited list of globs to search for in known layers.
The layer names are compared against the globs listed in the environment
variable, and if they match, they will not be able to be disabled by
`VK_LOADER_LAYERS_DISABLE`.
Implicit layers have the ability to only be enabled when a layer specified
environment variable is set, allow for context dependent enablement.
`VK_LOADER_LAYERS_ENABLE` ignores that context.
`VK_LOADER_LAYERS_ALLOW` behaves similar to `VK_LOADER_LAYERS_ENABLE` while
also respecting the context which is normally used to determine whether an
implicit layer should be enabled.
`VK_LOADER_LAYERS_ALLOW` effectively negates the behavior of
`VK_LOADER_LAYERS_DISABLE`.
Explicit layers listed by `VK_LOADER_LAYERS_ALLOW` will not be enabled.
Implicit layers listed by ``VK_LOADER_LAYERS_ALLOW` which are always active,
i.e. they do not require any external context to be enabled, will be enabled.
##### `VK_INSTANCE_LAYERS`
The original `VK_INSTANCE_LAYERS` can be viewed as a special case of the new
`VK_LOADER_LAYERS_ENABLE`.
Because of this, any layers enabled via `VK_INSTANCE_LAYERS` will be treated the
same as layers enabled with `VK_LOADER_LAYERS_ENABLE` and will therefore
override any disables supplied in `VK_LOADER_LAYERS_DISABLE`.
### Exception for Elevated Privileges
There is an exception to when either `VK_LAYER_PATH` or `VK_ADD_LAYER_PATH` are
available for use.
For security reasons, both `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` are ignored
if running the Vulkan application with elevated privileges.
Because of this, both `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` can only be used
for applications that do not use elevated privileges.
For security reasons, `VK_LAYER_PATH` and `VK_ADD_LAYER_PATH` are ignored if
running the Vulkan application with elevated privileges.
This is because they may insert new libraries into the executable process that
are not normally found by the loader.
Because of this, these environment variables can only be used for applications
that do not use elevated privileges.
For more information see
[Elevated Privilege Caveats](LoaderInterfaceArchitecture.md#elevated-privilege-caveats)
@ -630,7 +757,8 @@ chain_info->u.pLayerInfo->pfnNextGetPhysicalDeviceProcAddr
`vk_layerGetPhysicalDeviceProcAddr`.
If a layer intends to support functions that take VkPhysicalDevice as the
dispatchable parameter, then layer should support `vk_layerGetPhysicalDeviceProcAddr`.
dispatchable parameter, then layer should support
`vk_layerGetPhysicalDeviceProcAddr`.
This is because if these functions aren't known to the loader, such as those
from unreleased extensions or because the loader is an older build thus doesn't
know about them _yet_, the loader won't be able to distinguish whether this is
@ -658,8 +786,8 @@ function, and set up a generic terminator which will pass it to the proper
driver.
4. Call down using `GetInstanceProcAddr`
- If it returns non-NULL, treat it as an unknown logical device command.
This means setting up a generic trampoline function that takes in a `VkDevice` as
the first parameter and adjusting the dispatch table to call the
This means setting up a generic trampoline function that takes in a `VkDevice`
as the first parameter and adjusting the dispatch table to call the
driver/layer's function after getting the dispatch table from the `VkDevice`.
Then, return the pointer to corresponding trampoline function.
5. Return NULL
@ -714,7 +842,8 @@ function.
corresponding Vulkan function in the next entity.
* The common behavior for a layer is to intercept a call, perform some
behavior, then pass it down to the next entity.
* If a layer doesn't pass the information down, undefined behavior may occur.
* If a layer doesn't pass the information down, undefined behavior may
occur.
* This is because the function will not be received by layers further
down the chain, or any drivers.
* One function that **must never call down the chain** is:
@ -1074,7 +1203,7 @@ If any component layer is not present in the provided override paths, the meta
layer is disabled.
The override meta-layer is primarily enabled when using the
[VkConfig](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
[VkConfig](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
tool included in the Vulkan SDK.
It is typically only available while the VkConfig tool is actually executing.
Please refer to that documentation for more information.
@ -1083,8 +1212,8 @@ Please refer to that documentation for more information.
Vulkan includes a small number of functions which are called without any
dispatchable object.
<b>Most layers do not intercept these functions</b>, as layers are enabled when an
instance is created.
<b>Most layers do not intercept these functions</b>, as layers are enabled when
an instance is created.
However, under certain conditions it is possible for a layer to intercept
these functions.
@ -1411,7 +1540,8 @@ are in the blacklist will not be enabled.
* The `app_keys` member of the override meta layer will make a meta layer apply
to only applications found in this list.
If there are any items in the app keys list, the meta layer isn't enabled for any application except those found in the list.
If there are any items in the app keys list, the meta layer isn't enabled for
any application except those found in the list.
* The `override_paths` member of the override meta layer, if present, will
replace the search paths the loader uses to find component layers.
@ -1539,7 +1669,7 @@ Here's an example of a meta-layer manifest file:
supports.
It does not require the application to make use of that API version.
It simply is an indication that the layer can support Vulkan API
instance and device functions up to and including that API version. </br>
instance and device functions up to and including that API version.</br>
For example: 1.0.33.
</td>
<td>None</td>
@ -1792,7 +1922,7 @@ application.
#### Layer Manifest File Version 1.2.0
The ability to define the layer settings as defined by the
[layer manifest schema](https://github.com/LunarG/VulkanTools/blob/master/vkconfig_core/layers/layers_schema.json).
[layer manifest schema](https://github.com/LunarG/VulkanTools/blob/main/vkconfig_core/layers/layers_schema.json).
The ability to briefly document the layer thanks to the fields:
* "introduction": Presentation of the purpose of the layer in a paragraph.
@ -1802,7 +1932,7 @@ The ability to briefly document the layer thanks to the fields:
These changes were made to enable third-party layers to expose their features
within
[Vulkan Configurator](https://github.com/LunarG/VulkanTools/blob/master/vkconfig/README.md)
[Vulkan Configurator](https://github.com/LunarG/VulkanTools/blob/main/vkconfig/README.md)
or other tools.
#### Layer Manifest File Version 1.1.2
@ -1837,8 +1967,8 @@ loader needs to query using OS-specific calls.
- NOTE: This is an optional field and, as the two previous fields, only
needed if the layer requires changing the name of the function for some reason.
The layer manifest file does not need to to be updated if the names of any listed
functions has not changed.
The layer manifest file does not need to to be updated if the names of any
listed functions has not changed.
#### Layer Manifest File Version 1.0.1
@ -1878,7 +2008,7 @@ The following sections detail the differences between the various versions.
### Layer Interface Version 2
Introduced the concept of
[loader and layer interface](#layer-version-negotiation) using the new
[loader and layer interface](#layer-version-negotiation) using the
`vkNegotiateLoaderLayerInterfaceVersion` function.
Additionally, it introduced the concept of
[Layer Unknown Physical Device Extensions](#layer-unknown-physical-device-extensions)
@ -1891,7 +2021,7 @@ Note: If a layer wraps the VkInstance handle, support for
### Layer Interface Version 1
A layer supporting interface version 1 had the following behavior:
1. `GetInstanceProcAddr` and `GetDeviceProcAddr` were directly exported
1. `vkGetInstanceProcAddr` and `vkGetDeviceProcAddr` were directly exported
2. The layer manifest file was able to override the names of the
`GetInstanceProcAddr` and `GetDeviceProcAddr`functions.
@ -2090,7 +2220,7 @@ Android Vulkan documentation</a>.
<td>A layer <b>must</b> have a valid JSON manifest file for the
loader to process that ends with the ".json" suffix.
It is recommended validating the layer manifest file against
<a href="https://github.com/LunarG/VulkanTools/blob/master/vkconfig_core/layers/layers_schema.json">
<a href="https://github.com/LunarG/VulkanTools/blob/main/vkconfig_core/layers/layers_schema.json">
the layer schema</a> prior to publication.</br>
The <b>only</b> exception is on Android which determines layer
functionality through the introspection functions defined in
@ -2168,7 +2298,7 @@ Android Vulkan documentation</a>.
<td>Yes</td>
<td>No</td>
<td><small>
<a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/master/external/openglcts/README.md">
<a href="https://github.com/KhronosGroup/VK-GL-CTS/blob/main/external/openglcts/README.md">
Vulkan CTS Documentation</a>
</small>
</td>
@ -2370,6 +2500,22 @@ Android Vulkan documentation</a>.
<td>Yes</td>
<td><small>N/A</small></td>
</tr>
<tr>
<td><small><b>LLP_LAYER_22</b></small></td>
<td>During <i>vkCreateDevice</i>, a layer <b>must not</b> modify the
<i>pDevice</i> pointer during prior to calling down to the lower
layers.<br/>
This is because the loader passes information in this pointer that is
necessary for the initialization code in the loader's terminator
function.<br/>
Instead, if the layer is overriding the <i>pDevice</i> pointer, it
<b>must</b> do so only after the call to the lower layers returns.
</td>
<td>The loader will likely crash.</td>
<td>No</td>
<td>Yes</td>
<td><small>N/A</small></td>
</tr>
</table>

View File

@ -1,8 +1,9 @@
# ~~~
# Copyright (c) 2014-2021 The Khronos Group Inc.
# Copyright (c) 2014-2021 Valve Corporation
# Copyright (c) 2014-2021 LunarG, Inc.
# Copyright (c) 2014-2023 The Khronos Group Inc.
# Copyright (c) 2014-2023 Valve Corporation
# Copyright (c) 2014-2023 LunarG, Inc.
# Copyright (c) 2021 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.
@ -16,45 +17,20 @@
# See the License for the specific language governing permissions and
# limitations under the License.
# ~~~
# Get version of the API the generated code used and put it into a cmake variable LOADER_GENERATED_HEADER_VERSION
include(generated/loader_generated_header_version.cmake)
include(CheckIncludeFile)
add_library(loader_specific_options INTERFACE)
target_link_libraries(loader_specific_options INTERFACE loader_common_options Vulkan::Headers)
target_include_directories(loader_specific_options INTERFACE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/generated ${CMAKE_CURRENT_BINARY_DIR})
if(WIN32)
if(MSVC)
# Use static MSVCRT libraries
foreach(configuration
in
CMAKE_C_FLAGS_DEBUG
CMAKE_C_FLAGS_MINSIZEREL
CMAKE_C_FLAGS_RELEASE
CMAKE_C_FLAGS_RELWITHDEBINFO
CMAKE_CXX_FLAGS_DEBUG
CMAKE_CXX_FLAGS_MINSIZEREL
CMAKE_CXX_FLAGS_RELEASE
CMAKE_CXX_FLAGS_RELWITHDEBINFO)
if(${configuration} MATCHES "/MD")
string(REGEX
REPLACE "/MD"
"/MT"
${configuration}
"${${configuration}}")
endif()
endforeach()
endif()
if(ENABLE_WIN10_ONECORE)
# Note: When linking your app or driver to OneCore.lib, be sure to remove any links to non-umbrella libs (such as
# kernel32.lib).
set(CMAKE_CXX_STANDARD_LIBRARIES " ") # space is intentional
set(CMAKE_C_STANDARD_LIBRARIES ${CMAKE_CXX_STANDARD_LIBRARIES})
set(CMAKE_C_STANDARD_LIBRARIES " ") # space is intentional
endif()
target_compile_options(loader_specific_options INTERFACE -D_CRT_SECURE_NO_WARNINGS)
# ~~~
# Build dev_ext_trampoline.c and unknown_ext_chain.c with /O2 to allow tail-call optimization.
# Setup two CMake targets (loader-norm and loader-opt) for the different compilation flags.
@ -68,27 +44,24 @@ if(WIN32)
separate_arguments(MODIFIED_C_FLAGS_DEBUG WINDOWS_COMMAND ${MODIFIED_C_FLAGS_DEBUG})
# ~~~
# Setup the loader.rc flie to contain the correct info
# Optionally uses the BUILD_DLL_VERSIONINFO build option to allow setting the exact build version
# Adds "Dev Build" to any build without the BUILD_DLL_VERSIONINFO option set
# Only generate the loader.rc file with CMake if BUILD_DLL_VERSIONINFO was set.
# This feature is for the Vulkan Runtime build
# Otherwise rely on the checked in loader.rc from the python script
# ~~~
if ("$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "")
# default case - use 0 as the BUILDNO
set(LOADER_RC_VERSION "1.0.1111.2222")
set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}.Dev Build\"")
set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader - Dev Build\"")
else()
if (NOT "$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "")
string(TIMESTAMP CURRENT_YEAR "%Y")
set(LOADER_CUR_COPYRIGHT_YEAR "${CURRENT_YEAR}")
set(LOADER_RC_VERSION "$CACHE{BUILD_DLL_VERSIONINFO}")
set(LOADER_VER_FILE_VERSION_STR "\"${LOADER_RC_VERSION}\"")
set(LOADER_VER_FILE_DESCRIPTION_STR "\"Vulkan Loader\"")
endif()
# RC file wants the value of FILEVERSION to separated by commas
string(REPLACE "." ", " LOADER_VER_FILE_VERSION "${LOADER_RC_VERSION}")
# Configure the file to include the versioning info
# Place it in the current directory for check-in - so the GN build has up to date info
configure_file(loader.rc.in ${CMAKE_CURRENT_LIST_DIR}/loader.rc)
# Place it in the build directory - the GN build will use the checked in file
configure_file(loader.rc.in ${CMAKE_CURRENT_BINARY_DIR}/loader.rc)
endif()
else()
# Used to make alloca() and secure_getenv() available
target_compile_definitions(loader_specific_options INTERFACE _GNU_SOURCE)
@ -103,26 +76,46 @@ endif()
set(NORMAL_LOADER_SRCS
allocation.c
allocation.h
cJSON.c
cJSON.h
debug_utils.c
debug_utils.h
extension_manual.c
get_environment.c
extension_manual.h
loader_environment.c
loader_environment.h
gpa_helper.c
gpa_helper.h
loader.c
loader.h
log.c
log.h
settings.c
settings.h
terminator.c
trampoline.c
unknown_function_handling.c
unknown_function_handling.h
wsi.c
wsi.h
)
if(WIN32)
list(APPEND NORMAL_LOADER_SRCS loader_windows.c dirent_on_windows.c)
elseif(UNIX AND NOT APPLE) # i.e.: Linux
elseif(CMAKE_SYSTEM_NAME MATCHES "Linux|BSD|DragonFly|GNU")
list(APPEND NORMAL_LOADER_SRCS loader_linux.c)
target_compile_definitions(loader_specific_options INTERFACE LOADER_ENABLE_LINUX_SORT)
endif()
if ("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";")
set(APPLE_UNIVERSAL_BINARY ON)
# When building a universal binary we cannot enable USE_GAS
# Since USE_GAS assumes only 1 architecture (arm64, x64, etc).
set(USE_GAS OFF)
endif()
set(OPT_LOADER_SRCS dev_ext_trampoline.c phys_dev_ext.c)
# Check for assembler support
@ -130,9 +123,13 @@ set(ASM_FAILURE_MSG "The build will fall back on building with C code\n")
set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG}Note that this may be unsafe, as the C code requires tail-call optimizations to remove")
set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} the stack frame for certain calls. If the compiler does not do this, then unknown device")
set(ASM_FAILURE_MSG "${ASM_FAILURE_MSG} extensions will suffer from a corrupted stack.")
if(WIN32)
if(MINGW)
find_program(JWASM_FOUND jwasm)
if (APPLE_UNIVERSAL_BINARY)
set(USE_ASSEMBLY_FALLBACK ON)
elseif(WIN32)
option(USE_MASM "Use MASM" ON)
if(USE_MASM AND MINGW)
find_program(JWASM_FOUND NAMES jwasm uasm)
if (JWASM_FOUND)
set(CMAKE_ASM_MASM_COMPILER ${JWASM_FOUND})
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpmachine OUTPUT_VARIABLE COMPILER_VERSION_OUTPUT)
@ -140,57 +137,101 @@ if(WIN32)
if (COMPILER_VERSION_OUTPUT MATCHES "x86_64")
set(JWASM_FLAGS -win64)
else()
set(JWASM_FLAGS -coff)
# jwasm requires setting the cpu to at least 386 for setting a flat model
set(JWASM_FLAGS -3 -coff)
endif()
endif()
endif()
endif()
option(USE_MASM "Use MASM" ON)
if (USE_MASM)
enable_language(ASM_MASM)
endif()
# Test if the detected compiler actually works.
# Unfortunately, CMake's detection of ASM_MASM is not reliable, so we need to do this ourselves.
if (CMAKE_SIZEOF_VOID_P EQUAL 4)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[
.model flat
.code
extrn _start:near
xor eax, eax
ret
end
]=])
else()
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm [=[
.code
extrn start:near
xor rax, rax
ret
end
]=])
endif ()
if(CMAKE_ASM_MASM_COMPILER_WORKS OR JWASM_FOUND)
if(MINGW)
set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} ${JWASM_FLAGS})
elseif(NOT CMAKE_CL_64 AND NOT JWASM_FOUND)
set(CMAKE_ASM_MASM_FLAGS ${CMAKE_ASM_MASM_FLAGS} /safeseh)
endif()
# try_compile does not work here due to the same reasons as static above.
execute_process(COMMAND ${CMAKE_ASM_MASM_COMPILER} ${CMAKE_ASM_MASM_FLAGS} -c -Fo ${CMAKE_CURRENT_BINARY_DIR}/masm_check.obj ${CMAKE_CURRENT_BINARY_DIR}/masm_check.asm
RESULT_VARIABLE CMAKE_ASM_MASM_COMPILER_WORKS
OUTPUT_QUIET ERROR_QUIET)
# Convert the return code to a boolean
if(CMAKE_ASM_MASM_COMPILER_WORKS EQUAL 0)
set(CMAKE_ASM_MASM_COMPILER_WORKS true)
else()
set(CMAKE_ASM_MASM_COMPILER_WORKS false)
endif()
if(CMAKE_ASM_MASM_COMPILER_WORKS)
add_executable(asm_offset asm_offset.c)
target_link_libraries(asm_offset loader_specific_options)
target_link_libraries(asm_offset PRIVATE loader_specific_options)
# If am emulator is provided (Like Wine), or running on native, run asm_offset to generate gen_defines.asm
if (CMAKE_CROSSCOMPILING_EMULATOR OR NOT CMAKE_CROSSCOMPILING)
add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset MASM)
else()
# Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
target_compile_options(asm_offset PRIVATE "/Fa$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" /FA)
# Force off optimization so that the output assembly includes all the necessary info - optimizer would get rid of it otherwise.
target_compile_options(asm_offset PRIVATE /Od)
find_package(Python3 REQUIRED QUIET)
# Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
add_custom_command(TARGET asm_offset POST_BUILD
COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm"
"$<TARGET_FILE_DIR:asm_offset>/asm_offset.asm" "MASM" "${CMAKE_C_COMPILER_ID}" "${CMAKE_SYSTEM_PROCESSOR}"
BYPRODUCTS gen_defines.asm
)
endif()
add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
set_target_properties(loader_asm_gen_files PROPERTIES FOLDER ${LOADER_HELPER_FOLDER})
add_library(loader-unknown-chain OBJECT unknown_ext_chain_masm.asm)
target_link_libraries(loader-unknown-chain Vulkan::Headers)
target_include_directories(loader-unknown-chain PUBLIC $<TARGET_PROPERTY:loader_asm_gen_files,BINARY_DIR>)
target_include_directories(loader-unknown-chain PUBLIC ${CMAKE_CURRENT_BINARY_DIR})
add_dependencies(loader-unknown-chain loader_asm_gen_files)
else()
set(USE_ASSEMBLY_FALLBACK ON)
message(WARNING "Could not find working MASM assembler\n${ASM_FAILURE_MSG}")
add_custom_target(loader_asm_gen_files)
add_library(loader-unknown-chain OBJECT unknown_ext_chain.c)
target_link_libraries(loader-unknown-chain loader_specific_options)
set_target_properties(loader-unknown-chain PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}")
endif()
elseif(APPLE)
# For MacOS, use the C code and force the compiler's tail-call optimization instead of using assembly code.
set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
set_source_files_properties(${OPT_LOADER_SRCS} PROPERTIES COMPILE_FLAGS -O)
add_custom_target(loader_asm_gen_files) # This causes no assembly files to be generated.
else() # i.e.: Linux
elseif(UNIX) # i.e.: Linux & Apple
option(USE_GAS "Use GAS" ON)
if(USE_GAS)
if (APPLE_UNIVERSAL_BINARY)
message(FATAL_ERROR "USE_GAS cannot be used when compiling a universal binary!")
endif()
enable_language(ASM)
set(CMAKE_ASM_FLAGS "${CMAKE_C_FLAGS}")
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
if (${CMAKE_SYSTEM_PROCESSOR} STREQUAL "aarch64")
if (${CMAKE_SYSTEM_PROCESSOR} MATCHES "aarch64|arm64")
try_compile(ASSEMBLER_WORKS ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/asm_test_aarch64.S)
if(ASSEMBLER_WORKS)
set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain_gas_aarch64.S)
endif()
elseif(${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86_64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "amd64" OR ${CMAKE_SYSTEM_PROCESSOR} STREQUAL "x86" OR ${CMAKE_SYSTEM_PROCESSOR} MATCHES "^i.86$")
# Covers x86_64, amd64, x86, i386, i686, I386, I686
elseif(${CMAKE_SYSTEM_PROCESSOR} MATCHES "amd64|86")
check_include_file("cet.h" HAVE_CET_H)
if(HAVE_CET_H)
target_compile_definitions(loader_specific_options INTERFACE HAVE_CET_H)
@ -203,19 +244,70 @@ else() # i.e.: Linux
endif()
endif()
# When compiling for x86 on x64, we can't use CMAKE_SYSTEM_PROCESSOR to determine which architecture to use,
# Instead, check the size of void* and if its 4, set ASM_OFFSET_SYSTEM_PROCESSOR to x86
# Note - there is no 32 bit arm assembly code, so this only applies to x86 currently.
if("${CMAKE_SIZEOF_VOID_P}" EQUAL "8")
set(ASM_OFFSET_SYSTEM_PROCESSOR ${CMAKE_SYSTEM_PROCESSOR}) # x86_64 or aarch64/arm64
else()
set(ASM_OFFSET_SYSTEM_PROCESSOR "x86")
endif()
if(ASSEMBLER_WORKS)
add_executable(asm_offset asm_offset.c)
target_link_libraries(asm_offset loader_specific_options)
# If not cross compiling, run asm_offset to generage gen_defines.asm
if (NOT CMAKE_CROSSCOMPILING)
add_custom_command(OUTPUT gen_defines.asm DEPENDS asm_offset COMMAND asm_offset GAS)
add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
else()
# Forces compiler to write the intermediate asm file, needed so that we can get sizeof/offset of info out of it.
target_compile_options(asm_offset PRIVATE -save-temps=obj)
if(CMAKE_C_COMPILER_ID STREQUAL "GNU")
set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm")
set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.c.s")
elseif(CMAKE_C_COMPILER_ID STREQUAL "Clang")
set(ASM_OFFSET_EXECUTABLE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/gen_defines.asm")
set(ASM_OFFSET_INTERMEDIATE_LOCATION "$<TARGET_FILE_DIR:asm_offset>/CMakeFiles/asm_offset.dir/asm_offset.s")
elseif(CMAKE_C_COMPILER_ID STREQUAL "AppleClang")
# Need to use the current binary dir since the asm_offset.s file is in that folder rather than the bundle
set(ASM_OFFSET_EXECUTABLE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/gen_defines.asm")
set(ASM_OFFSET_INTERMEDIATE_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/CMakeFiles/asm_offset.dir/asm_offset.s")
else()
message(FATAL_ERROR "C_COMPILER_ID not supported!")
endif()
find_package(Python3 REQUIRED QUIET)
# Run parse_asm_values.py on asm_offset's assembly file to generate the gen_defines.asm, which the asm code depends on
add_custom_command(TARGET asm_offset POST_BUILD
COMMAND Python3::Interpreter ${PROJECT_SOURCE_DIR}/scripts/parse_asm_values.py "${ASM_OFFSET_EXECUTABLE_LOCATION}"
"${ASM_OFFSET_INTERMEDIATE_LOCATION}" "GAS" "${CMAKE_C_COMPILER_ID}" "${ASM_OFFSET_SYSTEM_PROCESSOR}"
BYPRODUCTS gen_defines.asm
)
endif()
add_custom_target(loader_asm_gen_files DEPENDS gen_defines.asm)
if (APPLE)
set(MODIFY_UNKNOWN_FUNCTION_DECLS ON)
endif()
else()
set(USE_ASSEMBLY_FALLBACK ON)
if(USE_GAS)
message(WARNING "Could not find working ${CMAKE_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}")
message(WARNING "Could not find working ${ASM_OFFSET_SYSTEM_PROCESSOR} GAS assembler\n${ASM_FAILURE_MSG}")
else()
message(WARNING "Assembly sources have been disabled\n${ASM_FAILURE_MSG}")
endif()
set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
endif()
endif()
if(USE_ASSEMBLY_FALLBACK)
add_custom_target(loader_asm_gen_files)
if (MSVC)
add_library(loader-unknown-chain OBJECT unknown_ext_chain.c)
target_link_libraries(loader-unknown-chain loader_specific_options)
set_target_properties(loader-unknown-chain PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}")
else()
set(OPT_LOADER_SRCS ${OPT_LOADER_SRCS} unknown_ext_chain.c)
set_source_files_properties(${OPT_LOADER_SRCS} PROPERTIES COMPILE_FLAGS -O)
endif()
endif()
@ -225,25 +317,29 @@ if(WIN32)
add_dependencies(loader-opt loader_asm_gen_files)
set_target_properties(loader-opt PROPERTIES CMAKE_C_FLAGS_DEBUG "${MODIFIED_C_FLAGS_DEBUG}")
# If BUILD_DLL_VERSIONINFO was set, use the loader.rc in the build dir, otherwise use the checked in file
set(RC_FILE_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/loader.rc)
if (NOT "$CACHE{BUILD_DLL_VERSIONINFO}" STREQUAL "")
set(RC_FILE_LOCATION ${CMAKE_CURRENT_BINARY_DIR}/loader.rc)
endif()
set(LOADER_UNKNOWN_CHAIN_LIBRARY $<$<TARGET_EXISTS:loader-unknown-chain>:$<TARGET_OBJECTS:loader-unknown-chain>>)
add_library(vulkan
SHARED
${NORMAL_LOADER_SRCS}
$<TARGET_OBJECTS:loader-unknown-chain>
${CMAKE_CURRENT_SOURCE_DIR}/vulkan-1.def
${CMAKE_CURRENT_LIST_DIR}/loader.rc)
${LOADER_UNKNOWN_CHAIN_LIBRARY}
${CMAKE_CURRENT_SOURCE_DIR}/${API_TYPE}-1.def
${RC_FILE_LOCATION})
target_link_libraries(vulkan PRIVATE loader_specific_options loader-opt)
if (UPDATE_DEPS)
add_dependencies(vulkan vl_update_deps)
endif()
# when adding the suffix the import and runtime library names must be consistent
# mingw: libvulkan-1.dll.a / vulkan-1.dll
# msvc: vulkan-1.lib / vulkan-1.dll
set_target_properties(vulkan
PROPERTIES
OUTPUT_NAME vulkan-1)
OUTPUT_NAME ${API_TYPE}-1)
if(MINGW)
# generate the same DLL with mingw
set_target_properties(vulkan
@ -261,20 +357,48 @@ if(WIN32)
add_dependencies(vulkan loader_asm_gen_files)
else()
if(APPLE AND BUILD_STATIC_LOADER)
add_library(vulkan STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
target_compile_definitions(vulkan PRIVATE BUILD_STATIC_LOADER)
else()
add_library(vulkan SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
if(APPLE)
option(APPLE_STATIC_LOADER "Build a loader that can be statically linked. Intended for Chromium usage/testing.")
mark_as_advanced(APPLE_STATIC_LOADER)
endif()
if(APPLE_STATIC_LOADER)
add_library(vulkan STATIC)
target_compile_definitions(vulkan PRIVATE APPLE_STATIC_LOADER)
message(WARNING "The APPLE_STATIC_LOADER option has been set. Note that this will only work on MacOS and is not supported "
"or tested as part of the loader. Use it at your own risk.")
else()
add_library(vulkan SHARED)
endif()
target_sources(vulkan PRIVATE ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
add_dependencies(vulkan loader_asm_gen_files)
# set version based on LOADER_GENERATED_HEADER_VERSION used to generate the code
set_target_properties(vulkan
PROPERTIES SOVERSION "1"
VERSION ${LOADER_GENERATED_HEADER_VERSION})
target_link_libraries(vulkan PRIVATE ${CMAKE_DL_LIBS} m)
if (NOT ANDROID)
target_link_libraries(vulkan PRIVATE Threads::Threads)
set_target_properties(vulkan PROPERTIES
SOVERSION "1"
VERSION "${VULKAN_LOADER_VERSION}"
)
set(THREADS_PREFER_PTHREAD_FLAG ON)
find_package(Threads REQUIRED)
target_link_libraries(vulkan PRIVATE ${CMAKE_DL_LIBS} m Threads::Threads)
set_target_properties(vulkan PROPERTIES OUTPUT_NAME ${API_TYPE})
if (LOADER_ENABLE_ADDRESS_SANITIZER)
target_compile_options(vulkan PUBLIC -fsanitize=address)
target_link_options(vulkan PUBLIC -fsanitize=address)
endif()
if (LOADER_ENABLE_THREAD_SANITIZER)
target_compile_options(vulkan PUBLIC -fsanitize=thread)
target_link_options(vulkan PUBLIC -fsanitize=thread)
endif()
if (LOADER_ENABLE_UNDEFINED_BEHAVIOR_SANITIZER)
target_compile_options(vulkan PUBLIC -fsanitize=undefined)
target_link_options(vulkan PUBLIC -fsanitize=undefined)
endif()
if(APPLE)
@ -284,83 +408,106 @@ else()
# Build vulkan.framework
# Use GLOB_RECURSE to find all the header files and populate the vulkan.framework headers with them
# Use CONFIGURE_DEPENDS to ensure that if the header files are updated, this list is also updated
# Note: CONFIGURE_DEPENDS is a 3.12 feature - gate it for now and remove when CMake minimum version is higher
if(${CMAKE_VERSION} VERSION_GREATER_EQUAL "3.12.0")
get_target_property(VulkanHeaders_INCLUDE_DIRS Vulkan::Headers INTERFACE_INCLUDE_DIRECTORIES)
file(GLOB_RECURSE CONFIGURE_DEPENDS FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS})
else()
file(GLOB_RECURSE FRAMEWORK_HEADERS ${VulkanHeaders_INCLUDE_DIRS})
endif()
if(BUILD_STATIC_LOADER)
add_library(vulkan-framework STATIC ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
else()
add_library(vulkan-framework SHARED ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
endif()
add_library(vulkan-framework SHARED)
target_sources(vulkan-framework PRIVATE ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS} ${FRAMEWORK_HEADERS})
add_dependencies(vulkan-framework loader_asm_gen_files)
target_link_libraries(vulkan-framework ${CMAKE_DL_LIBS} Threads::Threads -lm "-framework CoreFoundation")
target_link_libraries(vulkan-framework loader_specific_options)
if (MODIFY_UNKNOWN_FUNCTION_DECLS)
# Modifies the names of functions as they appearin the assembly code so that the
# unknown function handling will work
target_compile_definitions(vulkan PRIVATE MODIFY_UNKNOWN_FUNCTION_DECLS)
target_compile_definitions(vulkan-framework PRIVATE MODIFY_UNKNOWN_FUNCTION_DECLS)
endif()
# The FRAMEWORK_VERSION needs to be "A" here so that Xcode code-signing works when a user adds their framework to an Xcode
# project and does "Sign on Copy". It would have been nicer to use "1" to denote Vulkan 1. Although Apple docs say that a
# framework version does not have to be "A", this part of the Apple toolchain expects it.
# https://forums.developer.apple.com/thread/65963
# cmake-format: off
set_target_properties(vulkan-framework PROPERTIES
OUTPUT_NAME vulkan
FRAMEWORK TRUE
FRAMEWORK_VERSION A
VERSION "${LOADER_GENERATED_HEADER_VERSION}" # "current version"
SOVERSION "1.0.0" # "compatibility version"
VERSION "${VULKAN_LOADER_VERSION}"
SOVERSION "1.0.0"
MACOSX_FRAMEWORK_IDENTIFIER com.lunarg.vulkanFramework
PUBLIC_HEADER "${FRAMEWORK_HEADERS}"
)
# Workaround linker warning: https://github.com/KhronosGroup/Vulkan-Loader/issues/1332
#
# MACHO_CURRENT_VERSION specifically applies to the -current_version linker option which is the
# linker warning we are trying to address.
set(APPLE_VULKAN_LOADER_VERSION "${VULKAN_LOADER_VERSION_MAJOR}.${VULKAN_LOADER_VERSION_MINOR}.0")
set_target_properties(vulkan PROPERTIES MACHO_CURRENT_VERSION "${APPLE_VULKAN_LOADER_VERSION}")
set_target_properties(vulkan-framework PROPERTIES MACHO_CURRENT_VERSION "${APPLE_VULKAN_LOADER_VERSION}")
install(TARGETS vulkan-framework
PUBLIC_HEADER DESTINATION vulkan
FRAMEWORK DESTINATION loader
)
# cmake-format: on
endif()
endif()
option(LOADER_USE_UNSAFE_FILE_SEARCH "Allows the loader to search in unsafe locations")
if (LOADER_USE_UNSAFE_FILE_SEARCH)
target_compile_definitions(vulkan PRIVATE LOADER_USE_UNSAFE_FILE_SEARCH)
endif()
# common attributes of the vulkan library
target_link_libraries(vulkan PRIVATE loader_specific_options)
set_target_properties(vulkan ${LOADER_STANDARD_C_PROPERTIES})
if (TARGET asm_offset)
set_target_properties(asm_offset ${LOADER_STANDARD_C_PROPERTIES})
target_link_libraries(vulkan PRIVATE Vulkan::Headers)
add_library(Vulkan::Loader ALIAS vulkan)
if (APPLE_STATIC_LOADER)
# TLDR: This feature only exists at the request of Google for Chromium. No other project should use this!
message(NOTICE "Apple STATIC lib: it will be built but not installed, and vulkan.pc and VulkanLoaderConfig.cmake won't be generated!")
return()
endif()
# Generate pkg-config file.
include(FindPkgConfig QUIET)
if(PKG_CONFIG_FOUND)
set(VK_API_VERSION "${LOADER_GENERATED_HEADER_VERSION}")
foreach(LIB ${CMAKE_CXX_IMPLICIT_LINK_LIBRARIES} ${PLATFORM_LIBS})
set(PRIVATE_LIBS "${PRIVATE_LIBS} -l${LIB}")
endforeach()
# Generate CMake Configuration File (IE: VulkanLoaderConfig.cmake)
install(TARGETS vulkan EXPORT VulkanLoaderConfig)
set_target_properties(vulkan PROPERTIES EXPORT_NAME "Loader")
install(EXPORT VulkanLoaderConfig DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanLoader NAMESPACE Vulkan::)
# Generate CMake Version File (IE: VulkanLoaderConfigVersion.cmake)
include(CMakePackageConfigHelpers)
set(version_config "${CMAKE_CURRENT_BINARY_DIR}/generated/VulkanLoaderConfigVersion.cmake")
write_basic_package_version_file("${version_config}" COMPATIBILITY SameMajorVersion)
install(FILES "${version_config}" DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/VulkanLoader)
# Generate PkgConfig File (IE: vulkan.pc)
# NOTE: Hopefully in the future CMake can generate .pc files natively.
# https://gitlab.kitware.com/cmake/cmake/-/issues/22621
find_package(PkgConfig)
if (PKG_CONFIG_FOUND)
if(WIN32)
if(MINGW)
set(VULKAN_LIB_SUFFIX "-1.dll")
else()
set(VULKAN_LIB_SUFFIX "-1")
endif()
# Set libdir path as in cmake's FindVulkan.cmake
# https://github.com/KhronosGroup/Vulkan-Loader/issues/668
if(CMAKE_SIZEOF_VOID_P EQUAL 8)
string(REPLACE "lib" "Lib" CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
else()
string(REPLACE "lib" "Lib32" CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
endif()
# BUG: The following code will NOT work well with `cmake --install ... --prefix <dir>`
# due to this code relying on CMAKE_INSTALL_PREFIX being defined at configure time.
#
# NOTE: vulkan.pc essentially cover both Vulkan-Loader and Vulkan-Headers for legacy reasons.
if ("${CMAKE_INSTALL_PREFIX}" STREQUAL "")
set(CMAKE_INSTALL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
set(CMAKE_INSTALL_INCLUDEDIR_PC ${CMAKE_INSTALL_FULL_INCLUDEDIR})
else()
set(CMAKE_INSTALL_FULL_LIBDIR_PC ${CMAKE_INSTALL_FULL_LIBDIR})
endif ()
file(RELATIVE_PATH CMAKE_INSTALL_LIBDIR_PC ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_FULL_LIBDIR})
file(RELATIVE_PATH CMAKE_INSTALL_INCLUDEDIR_PC ${CMAKE_INSTALL_PREFIX} ${CMAKE_INSTALL_FULL_INCLUDEDIR})
endif()
configure_file("vulkan.pc.in" "vulkan.pc" @ONLY)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/vulkan.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig" RENAME "${API_TYPE}.pc")
endif()
target_link_libraries(vulkan PRIVATE Vulkan::Headers)
add_library(Vulkan::Vulkan ALIAS vulkan)
install(TARGETS vulkan
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

View File

@ -28,7 +28,7 @@ typedef struct LoaderEnumAdapters2 {
LUID luid;
ULONG source_count;
BOOL present_move_regions_preferred;
} * adapters;
} *adapters;
} LoaderEnumAdapters2;
typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderEnumAdapters2)(const LoaderEnumAdapters2 *);

View File

@ -22,14 +22,54 @@
// This code generates an assembly file which provides offsets to get struct members from assembly code.
// __USE_MINGW_ANSI_STDIO is needed to use the %zu format specifier with mingw-w64.
// Otherwise the compiler will complain about an unknown format specifier.
#if defined(__MINGW32__) && !defined(__USE_MINGW_ANSI_STDIO)
#define __USE_MINGW_ANSI_STDIO 1
#endif
#include <stdio.h>
#include "loader_common.h"
#include "log.h"
#if defined(__GNUC__) || defined(__clang__)
void produce_asm_define() {
// GCC and clang make it easy to print easy to regex for values
__asm__("# VULKAN_LOADER_ERROR_BIT = %c0" : : "i"(VULKAN_LOADER_ERROR_BIT));
__asm__("# PTR_SIZE = %c0" : : "i"(sizeof(void *)));
__asm__("# CHAR_PTR_SIZE = %c0" : : "i"(sizeof(char *)));
__asm__("# FUNCTION_OFFSET_INSTANCE = %c0" : : "i"(offsetof(struct loader_instance, phys_dev_ext_disp_functions)));
__asm__("# PHYS_DEV_OFFSET_INST_DISPATCH = %c0" : : "i"(offsetof(struct loader_instance_dispatch_table, phys_dev_ext)));
__asm__("# PHYS_DEV_OFFSET_PHYS_DEV_TRAMP = %c0" : : "i"(offsetof(struct loader_physical_device_tramp, phys_dev)));
__asm__("# ICD_TERM_OFFSET_PHYS_DEV_TERM = %c0" : : "i"(offsetof(struct loader_physical_device_term, this_icd_term)));
__asm__("# PHYS_DEV_OFFSET_PHYS_DEV_TERM = %c0" : : "i"(offsetof(struct loader_physical_device_term, phys_dev)));
__asm__("# INSTANCE_OFFSET_ICD_TERM = %c0" : : "i"(offsetof(struct loader_icd_term, this_instance)));
__asm__("# DISPATCH_OFFSET_ICD_TERM = %c0" : : "i"(offsetof(struct loader_icd_term, phys_dev_ext)));
__asm__("# EXT_OFFSET_DEVICE_DISPATCH = %c0" : : "i"(offsetof(struct loader_dev_dispatch_table, ext_dispatch)));
}
#elif defined(_WIN32)
// MSVC will print the name of the value and the value in hex
// Must disable optimization for this translation unit, otherwise the compiler strips out the variables
static const uint32_t PTR_SIZE = sizeof(void *);
static const uint32_t CHAR_PTR_SIZE = sizeof(char *);
static const uint32_t FUNCTION_OFFSET_INSTANCE = offsetof(struct loader_instance, phys_dev_ext_disp_functions);
static const uint32_t PHYS_DEV_OFFSET_INST_DISPATCH = offsetof(struct loader_instance_dispatch_table, phys_dev_ext);
static const uint32_t PHYS_DEV_OFFSET_PHYS_DEV_TRAMP = offsetof(struct loader_physical_device_tramp, phys_dev);
static const uint32_t ICD_TERM_OFFSET_PHYS_DEV_TERM = offsetof(struct loader_physical_device_term, this_icd_term);
static const uint32_t PHYS_DEV_OFFSET_PHYS_DEV_TERM = offsetof(struct loader_physical_device_term, phys_dev);
static const uint32_t INSTANCE_OFFSET_ICD_TERM = offsetof(struct loader_icd_term, this_instance);
static const uint32_t DISPATCH_OFFSET_ICD_TERM = offsetof(struct loader_icd_term, phys_dev_ext);
static const uint32_t EXT_OFFSET_DEVICE_DISPATCH = offsetof(struct loader_dev_dispatch_table, ext_dispatch);
#else
#warning asm_offset.c variable declarations need to be defined for this platform
#endif
#if !defined(_MSC_VER) || (_MSC_VER >= 1900)
#define SIZE_T_FMT "%-8zu"
#else
#elif defined(__GNUC__) || defined(__clang__)
#define SIZE_T_FMT "%-8lu"
#else
#warning asm_offset.c SIZE_T_FMT must be defined for this platform
#endif
struct ValueInfo {
@ -38,6 +78,8 @@ struct ValueInfo {
const char *comment;
};
// This file can both be executed to produce gen_defines.asm and contains all the relevant data which
// the parse_asm_values.py script needs to write gen_defines.asm, necessary for cross compilation
int main(int argc, char **argv) {
const char *assembler = NULL;
for (int i = 0; i < argc; ++i) {
@ -78,7 +120,7 @@ int main(int argc, char **argv) {
// clang-format on
};
FILE *file = fopen("gen_defines.asm", "w");
FILE *file = loader_fopen("gen_defines.asm", "w");
fprintf(file, "\n");
if (!strcmp(assembler, "MASM")) {
for (size_t i = 0; i < sizeof(values) / sizeof(values[0]); ++i) {

File diff suppressed because it is too large Load Diff

View File

@ -25,11 +25,9 @@
#pragma once
#include "loader_common.h"
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif
#include <vulkan/vulkan_core.h>
/* cJSON Types: */
#define cJSON_False 0
@ -64,96 +62,50 @@ typedef struct cJSON {
VkAllocationCallbacks *pAllocator;
} cJSON;
/* Supply a block of JSON, and this returns a cJSON object you can interrogate.
* Call cJSON_Delete when finished. */
cJSON *cJSON_Parse(const VkAllocationCallbacks *pAllocator, const char *value);
/* Render a cJSON entity to text for transfer/storage. Free the char* when
* finished. */
char *cJSON_Print(cJSON *item);
char *loader_cJSON_Print(cJSON *item);
/* Render a cJSON entity to text for transfer/storage without any formatting.
* Free the char* when finished. */
char *cJSON_PrintUnformatted(cJSON *item);
/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess
* at the final size. guessing well reduces reallocation. fmt=0 gives
* unformatted, =1 gives formatted */
char *cJSON_PrintBuffered(cJSON *item, int prebuffer, int fmt);
char *loader_cJSON_PrintUnformatted(cJSON *item);
/* Delete a cJSON entity and all subentities. */
void cJSON_Delete(cJSON *c);
/* Delete an item allocated inside the JSON parser*/
void cJSON_Free(const VkAllocationCallbacks *pAllocator, void *p);
void loader_cJSON_Delete(cJSON *c);
/* Returns the number of items in an array (or object). */
int cJSON_GetArraySize(cJSON *array);
int loader_cJSON_GetArraySize(cJSON *array);
/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful.
*/
cJSON *cJSON_GetArrayItem(cJSON *array, int item);
cJSON *loader_cJSON_GetArrayItem(cJSON *array, int item);
/* Get item "string" from object. Case insensitive. */
cJSON *cJSON_GetObjectItem(cJSON *object, const char *string);
/* For analysing failed parses. This returns a pointer to the parse error.
* You'll probably need to look a few chars back to make sense of it. Defined
* when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
const char *cJSON_GetErrorPtr(void);
/* These calls create a cJSON item of the appropriate type. */
cJSON *cJSON_CreateNull(const VkAllocationCallbacks *pAllocator);
cJSON *cJSON_CreateTrue(const VkAllocationCallbacks *pAllocator);
cJSON *cJSON_CreateFalse(const VkAllocationCallbacks *pAllocator);
cJSON *cJSON_CreateBool(const VkAllocationCallbacks *pAllocator, int b);
cJSON *cJSON_CreateNumber(const VkAllocationCallbacks *pAllocator, double num);
cJSON *cJSON_CreateString(const VkAllocationCallbacks *pAllocator, const char *string);
cJSON *cJSON_CreateArray(const VkAllocationCallbacks *pAllocator);
cJSON *cJSON_CreateObject(const VkAllocationCallbacks *pAllocator);
/* These utilities create an Array of count items. */
cJSON *cJSON_CreateIntArray(const VkAllocationCallbacks *pAllocator, const int *numbers, int count);
cJSON *cJSON_CreateFloatArray(const VkAllocationCallbacks *pAllocator, const float *numbers, int count);
cJSON *cJSON_CreateDoubleArray(const VkAllocationCallbacks *pAllocator, const double *numbers, int count);
cJSON *cJSON_CreateStringArray(const VkAllocationCallbacks *pAllocator, const char **strings, int count);
/* Append item to the specified array/object. */
void cJSON_AddItemToArray(cJSON *array, cJSON *item);
void cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
/* Use this when string is definitely const (i.e. a literal, or as good as), and
* will definitely survive the cJSON object */
void cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
/* Append reference to item to the specified array/object. Use this when you
* want to add an existing cJSON to a new cJSON, but don't want to corrupt your
* existing cJSON. */
void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
void cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
/* Remove/Detach items from Arrays/Objects. */
cJSON *cJSON_DetachItemFromArray(cJSON *array, int which);
void cJSON_DeleteItemFromArray(cJSON *array, int which);
cJSON *cJSON_DetachItemFromObject(cJSON *object, const char *string);
void cJSON_DeleteItemFromObject(cJSON *object, const char *string);
/* Update array items. */
void cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
void cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
void cJSON_ReplaceItemInObject(cJSON *object, const char *string, cJSON *newitem);
/* Duplicate a cJSON item */
cJSON *cJSON_Duplicate(cJSON *item, int recurse);
/* Duplicate will create a new, identical cJSON item to the one you pass, in new
memory that will
need to be released. With recurse!=0, it will duplicate any children connected
to the item.
The item->next and ->prev pointers are always zero on return from Duplicate. */
/* ParseWithOpts allows you to require (and check) that the JSON is null
* terminated, and to retrieve the pointer to the final byte parsed. */
cJSON *cJSON_ParseWithOpts(const VkAllocationCallbacks *pAllocator, const char *value, const char **return_parse_end,
int require_null_terminated);
void cJSON_Minify(char *json);
cJSON *loader_cJSON_GetObjectItem(cJSON *object, const char *string);
/* When assigning an integer value, it needs to be propagated to valuedouble
* too. */
#define cJSON_SetIntValue(object, val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
#define cJSON_SetNumberValue(object, val) ((object) ? (object)->valueint = (object)->valuedouble = (val) : (val))
#ifdef __cplusplus
}
#endif
// Helper functions to using JSON
struct loader_instance;
struct loader_string_list;
// Read a JSON file into a buffer.
//
// @return - A pointer to a cJSON object representing the JSON parse tree.
// This returned buffer should be freed by caller.
VkResult loader_get_json(const struct loader_instance *inst, const char *filename, cJSON **json);
// Given a cJSON object, find the string associated with the key and puts an pre-allocated string into out_string.
// Length is given by out_str_len, and this function truncates the string with a null terminator if it the provided space isn't
// large enough.
VkResult loader_parse_json_string_to_existing_str(const struct loader_instance *inst, cJSON *object, const char *key,
size_t out_str_len, char *out_string);
// Given a cJSON object, find the string associated with the key and puts an allocated string into out_string.
// It is the callers responsibility to free out_string.
VkResult loader_parse_json_string(cJSON *object, const char *key, char **out_string);
// Given a cJSON object, find the array of strings associated with they key and writes the count into out_count and data into
// out_array_of_strings. It is the callers responsibility to free out_array_of_strings.
VkResult loader_parse_json_array_of_strings(const struct loader_instance *inst, cJSON *object, const char *key,
struct loader_string_list *string_list);

View File

@ -27,9 +27,8 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#ifndef WIN32
#if !defined(WIN32)
#include <signal.h>
#else
#endif
#include "vulkan/vk_layer.h"
@ -45,30 +44,32 @@
VkResult util_CreateDebugUtilsMessenger(struct loader_instance *inst, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT messenger) {
VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
VkLayerDbgFunctionNode *new_dbg_function_node = NULL;
pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
new_dbg_function_node = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
pAllocator, inst, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!pNewDbgFuncNode) {
if (!new_dbg_function_node) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
pNewDbgFuncNode->is_messenger = true;
pNewDbgFuncNode->messenger.messenger = messenger;
pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
inst->DbgFunctionHead = pNewDbgFuncNode;
new_dbg_function_node->is_messenger = true;
new_dbg_function_node->messenger.messenger = messenger;
new_dbg_function_node->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
new_dbg_function_node->messenger.messageSeverity = pCreateInfo->messageSeverity;
new_dbg_function_node->messenger.messageType = pCreateInfo->messageType;
new_dbg_function_node->pUserData = pCreateInfo->pUserData;
new_dbg_function_node->pNext = inst->instance_only_dbg_function_head;
inst->instance_only_dbg_function_head = new_dbg_function_node;
inst->current_dbg_function_head = inst->instance_only_dbg_function_head;
return VK_SUCCESS;
}
static VKAPI_ATTR VkResult VKAPI_CALL
debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugUtilsMessengerEXT *pMessenger) {
VKAPI_ATTR VkResult VKAPI_CALL debug_utils_CreateDebugUtilsMessengerEXT(VkInstance instance,
const VkDebugUtilsMessengerCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDebugUtilsMessengerEXT *pMessenger) {
struct loader_instance *inst = loader_get_instance(instance);
loader_platform_thread_lock_mutex(&loader_lock);
VkResult result = inst->disp->layer_inst_disp.CreateDebugUtilsMessengerEXT(inst->instance, pCreateInfo, pAllocator, pMessenger);
@ -82,7 +83,7 @@ VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkD
VkBool32 bail = false;
if (NULL != pCallbackData) {
VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
VkDebugReportObjectTypeEXT object_type = VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
VkDebugReportFlagsEXT object_flags = 0;
uint64_t object_handle = 0;
@ -115,13 +116,14 @@ VkBool32 util_SubmitDebugUtilsMessageEXT(const struct loader_instance *inst, VkD
void util_DestroyDebugUtilsMessenger(struct loader_instance *inst, VkDebugUtilsMessengerEXT messenger,
const VkAllocationCallbacks *pAllocator) {
VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
VkLayerDbgFunctionNode *pPrev = pTrav;
while (pTrav) {
if (pTrav->is_messenger && pTrav->messenger.messenger == messenger) {
pPrev->pNext = pTrav->pNext;
if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
if (inst->current_dbg_function_head == pTrav) inst->current_dbg_function_head = pTrav->pNext;
if (inst->instance_only_dbg_function_head == pTrav) inst->instance_only_dbg_function_head = pTrav->pNext;
loader_free_with_instance_fallback(pAllocator, inst, pTrav);
break;
}
@ -149,15 +151,16 @@ VkResult util_CreateDebugUtilsMessengers(struct loader_instance *inst, const voi
return VK_SUCCESS;
}
static VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(
VkInstance instance, VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity, VkDebugUtilsMessageTypeFlagsEXT messageTypes,
VKAPI_ATTR void VKAPI_CALL debug_utils_SubmitDebugUtilsMessageEXT(VkInstance instance,
VkDebugUtilsMessageSeverityFlagBitsEXT messageSeverity,
VkDebugUtilsMessageTypeFlagsEXT messageTypes,
const VkDebugUtilsMessengerCallbackDataEXT *pCallbackData) {
struct loader_instance *inst = loader_get_instance(instance);
inst->disp->layer_inst_disp.SubmitDebugUtilsMessageEXT(inst->instance, messageSeverity, messageTypes, pCallbackData);
}
static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugUtilsMessengerEXT(VkInstance instance, VkDebugUtilsMessengerEXT messenger,
const VkAllocationCallbacks *pAllocator) {
struct loader_instance *inst = loader_get_instance(instance);
loader_platform_thread_lock_mutex(&loader_lock);
@ -177,7 +180,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
struct loader_instance *inst = (struct loader_instance *)instance;
VkResult res = VK_SUCCESS;
uint32_t storage_idx;
VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
icd_info = (VkDebugUtilsMessengerEXT *)loader_calloc_with_instance_fallback(
pAllocator, inst, inst->total_icd_count * sizeof(VkDebugUtilsMessengerEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
@ -204,23 +207,23 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugUtilsMessengerEXT(VkInstanc
// Setup the debug report callback in the terminator since a layer may want
// to grab the information itself (RenderDoc) and then return back to the
// user callback a sub-set of the messages.
pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
new_dbg_func_node = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
pAllocator, inst, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!pNewDbgFuncNode) {
if (!new_dbg_func_node) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
pNewDbgFuncNode->is_messenger = true;
pNewDbgFuncNode->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
pNewDbgFuncNode->messenger.messageSeverity = pCreateInfo->messageSeverity;
pNewDbgFuncNode->messenger.messageType = pCreateInfo->messageType;
pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
inst->DbgFunctionHead = pNewDbgFuncNode;
new_dbg_func_node->is_messenger = true;
new_dbg_func_node->messenger.pfnUserCallback = pCreateInfo->pfnUserCallback;
new_dbg_func_node->messenger.messageSeverity = pCreateInfo->messageSeverity;
new_dbg_func_node->messenger.messageType = pCreateInfo->messageType;
new_dbg_func_node->pUserData = pCreateInfo->pUserData;
new_dbg_func_node->pNext = inst->current_dbg_function_head;
inst->current_dbg_function_head = new_dbg_func_node;
*(VkDebugUtilsMessengerEXT **)pMessenger = icd_info;
pNewDbgFuncNode->messenger.messenger = *pMessenger;
*pMessenger = (VkDebugUtilsMessengerEXT)(uintptr_t)icd_info;
new_dbg_func_node->messenger.messenger = *pMessenger;
out:
@ -237,8 +240,8 @@ out:
}
storage_idx++;
}
loader_free(pAllocator, pNewDbgFuncNode);
loader_free(pAllocator, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, new_dbg_func_node);
loader_free_with_instance_fallback(pAllocator, inst, icd_info);
}
return res;
@ -252,7 +255,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance i
const struct loader_icd_term *icd_term;
struct loader_instance *inst = (struct loader_instance *)instance;
icd_info = *(VkDebugUtilsMessengerEXT **)&messenger;
icd_info = (VkDebugUtilsMessengerEXT *)(uintptr_t)messenger;
storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (NULL == icd_term->dispatch.DestroyDebugUtilsMessengerEXT) {
@ -267,7 +270,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugUtilsMessengerEXT(VkInstance i
util_DestroyDebugUtilsMessenger(inst, messenger, pAllocator);
loader_free(pAllocator, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, icd_info);
}
// This is the instance chain terminator function for SubmitDebugUtilsMessageEXT
@ -289,28 +292,30 @@ VKAPI_ATTR void VKAPI_CALL terminator_SubmitDebugUtilsMessageEXT(VkInstance inst
VkResult util_CreateDebugReportCallback(struct loader_instance *inst, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT callback) {
VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
new_dbg_func_node = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
pAllocator, inst, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!pNewDbgFuncNode) {
if (!new_dbg_func_node) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
pNewDbgFuncNode->is_messenger = false;
pNewDbgFuncNode->report.msgCallback = callback;
pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
inst->DbgFunctionHead = pNewDbgFuncNode;
new_dbg_func_node->is_messenger = false;
new_dbg_func_node->report.msgCallback = callback;
new_dbg_func_node->report.pfnMsgCallback = pCreateInfo->pfnCallback;
new_dbg_func_node->report.msgFlags = pCreateInfo->flags;
new_dbg_func_node->pUserData = pCreateInfo->pUserData;
new_dbg_func_node->pNext = inst->instance_only_dbg_function_head;
inst->instance_only_dbg_function_head = new_dbg_func_node;
inst->current_dbg_function_head = inst->instance_only_dbg_function_head;
return VK_SUCCESS;
}
static VKAPI_ATTR VkResult VKAPI_CALL
debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
VKAPI_ATTR VkResult VKAPI_CALL debug_utils_CreateDebugReportCallbackEXT(VkInstance instance,
const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkDebugReportCallbackEXT *pCallback) {
struct loader_instance *inst = loader_get_instance(instance);
loader_platform_thread_lock_mutex(&loader_lock);
VkResult result = inst->disp->layer_inst_disp.CreateDebugReportCallbackEXT(inst->instance, pCreateInfo, pAllocator, pCallback);
@ -322,7 +327,7 @@ debug_utils_CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugRepor
VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
VkBool32 bail = false;
VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
VkDebugUtilsMessageSeverityFlagBitsEXT severity;
VkDebugUtilsMessageTypeFlagsEXT types;
VkDebugUtilsMessengerCallbackDataEXT callback_data;
@ -365,13 +370,15 @@ VkBool32 util_DebugReportMessage(const struct loader_instance *inst, VkFlags msg
void util_DestroyDebugReportCallback(struct loader_instance *inst, VkDebugReportCallbackEXT callback,
const VkAllocationCallbacks *pAllocator) {
VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
VkLayerDbgFunctionNode *pPrev = pTrav;
while (pTrav) {
if (!pTrav->is_messenger && pTrav->report.msgCallback == callback) {
pPrev->pNext = pTrav->pNext;
if (inst->DbgFunctionHead == pTrav) inst->DbgFunctionHead = pTrav->pNext;
if (inst->current_dbg_function_head == pTrav) inst->current_dbg_function_head = pTrav->pNext;
if (inst->instance_only_dbg_function_head == pTrav) inst->instance_only_dbg_function_head = pTrav->pNext;
if (inst->current_dbg_function_head == pTrav) inst->current_dbg_function_head = pTrav->pNext;
loader_free_with_instance_fallback(pAllocator, inst, pTrav);
break;
}
@ -399,7 +406,7 @@ VkResult util_CreateDebugReportCallbacks(struct loader_instance *inst, const voi
return VK_SUCCESS;
}
static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback,
const VkAllocationCallbacks *pAllocator) {
struct loader_instance *inst = loader_get_instance(instance);
loader_platform_thread_lock_mutex(&loader_lock);
@ -409,10 +416,9 @@ static VKAPI_ATTR void VKAPI_CALL debug_utils_DestroyDebugReportCallbackEXT(VkIn
loader_platform_thread_unlock_mutex(&loader_lock);
}
static VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objType, uint64_t object,
size_t location, int32_t msgCode, const char *pLayerPrefix,
const char *pMsg) {
VKAPI_ATTR void VKAPI_CALL debug_utils_DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags,
VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location,
int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
struct loader_instance *inst = loader_get_instance(instance);
inst->disp->layer_inst_disp.DebugReportMessageEXT(inst->instance, flags, objType, object, location, msgCode, pLayerPrefix,
@ -430,10 +436,10 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
struct loader_instance *inst = (struct loader_instance *)instance;
VkResult res = VK_SUCCESS;
uint32_t storage_idx;
VkLayerDbgFunctionNode *pNewDbgFuncNode = NULL;
VkLayerDbgFunctionNode *new_dbg_func_node = NULL;
icd_info = ((VkDebugReportCallbackEXT *)loader_calloc(pAllocator, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT),
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
icd_info = ((VkDebugReportCallbackEXT *)loader_calloc_with_instance_fallback(
pAllocator, inst, inst->total_icd_count * sizeof(VkDebugReportCallbackEXT), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT));
if (!icd_info) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
@ -456,23 +462,23 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDebugReportCallbackEXT(VkInstanc
// Setup the debug report callback in the terminator since a layer may want
// to grab the information itself (RenderDoc) and then return back to the
// user callback a sub-set of the messages.
pNewDbgFuncNode = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
new_dbg_func_node = (VkLayerDbgFunctionNode *)loader_calloc_with_instance_fallback(
pAllocator, inst, sizeof(VkLayerDbgFunctionNode), VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
if (!pNewDbgFuncNode) {
if (!new_dbg_func_node) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
pNewDbgFuncNode->is_messenger = false;
pNewDbgFuncNode->report.pfnMsgCallback = pCreateInfo->pfnCallback;
pNewDbgFuncNode->report.msgFlags = pCreateInfo->flags;
pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
pNewDbgFuncNode->pNext = inst->DbgFunctionHead;
inst->DbgFunctionHead = pNewDbgFuncNode;
new_dbg_func_node->is_messenger = false;
new_dbg_func_node->report.pfnMsgCallback = pCreateInfo->pfnCallback;
new_dbg_func_node->report.msgFlags = pCreateInfo->flags;
new_dbg_func_node->pUserData = pCreateInfo->pUserData;
new_dbg_func_node->pNext = inst->current_dbg_function_head;
inst->current_dbg_function_head = new_dbg_func_node;
*(VkDebugReportCallbackEXT **)pCallback = icd_info;
pNewDbgFuncNode->report.msgCallback = *pCallback;
*pCallback = (VkDebugReportCallbackEXT)(uintptr_t)icd_info;
new_dbg_func_node->report.msgCallback = *pCallback;
out:
@ -489,8 +495,8 @@ out:
}
storage_idx++;
}
loader_free(pAllocator, pNewDbgFuncNode);
loader_free(pAllocator, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, new_dbg_func_node);
loader_free_with_instance_fallback(pAllocator, inst, icd_info);
}
return res;
@ -504,7 +510,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance i
const struct loader_icd_term *icd_term;
struct loader_instance *inst = (struct loader_instance *)instance;
icd_info = *(VkDebugReportCallbackEXT **)&callback;
icd_info = (VkDebugReportCallbackEXT *)(uintptr_t)callback;
storage_idx = 0;
for (icd_term = inst->icd_terms; icd_term; icd_term = icd_term->next) {
if (NULL == icd_term->dispatch.DestroyDebugReportCallbackEXT) {
@ -519,7 +525,7 @@ VKAPI_ATTR void VKAPI_CALL terminator_DestroyDebugReportCallbackEXT(VkInstance i
util_DestroyDebugReportCallback(inst, callback, pAllocator);
loader_free(pAllocator, icd_info);
loader_free_with_instance_fallback(pAllocator, inst, icd_info);
}
// This is the instance chain terminator function for DebugReportMessage
@ -548,24 +554,24 @@ VKAPI_ATTR void VKAPI_CALL terminator_DebugReportMessageEXT(VkInstance instance,
// General utilities
static const VkExtensionProperties debug_utils_extension_info[] = {
const VkExtensionProperties debug_utils_extension_info[] = {
{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION},
{VK_EXT_DEBUG_UTILS_EXTENSION_NAME, VK_EXT_DEBUG_UTILS_SPEC_VERSION},
};
void destroy_debug_callbacks_chain(struct loader_instance *inst, const VkAllocationCallbacks *pAllocator) {
VkLayerDbgFunctionNode *pTrav = inst->DbgFunctionHead;
VkLayerDbgFunctionNode *pTrav = inst->current_dbg_function_head;
VkLayerDbgFunctionNode *pNext = NULL;
while (pTrav) {
pNext = pTrav->pNext;
loader_free_with_instance_fallback(pAllocator, inst, pTrav);
pTrav = pNext;
}
inst->DbgFunctionHead = NULL;
inst->current_dbg_function_head = NULL;
}
void add_debug_extensions_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
VkResult add_debug_extensions_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list) {
return loader_add_to_ext_list(inst, ext_list, sizeof(debug_utils_extension_info) / sizeof(VkExtensionProperties),
debug_utils_extension_info);
}

View File

@ -28,7 +28,7 @@
// General utilities
void add_debug_extensions_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list);
VkResult add_debug_extensions_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list);
void check_for_enabled_debug_extensions(struct loader_instance *ptr_instance, const VkInstanceCreateInfo *pCreateInfo);
bool debug_extensions_InstanceGpa(struct loader_instance *ptr_instance, const char *name, void **addr);
bool debug_utils_ReportFlagsToAnnotFlags(VkDebugReportFlagsEXT dr_flags, bool default_flag_is_spec,

View File

@ -24,259 +24,266 @@
#pragma GCC optimize(3) // force gcc to use tail-calls
#endif
// The asm declaration prevents name mangling which is necessary for macOS
#if defined(MODIFY_UNKNOWN_FUNCTION_DECLS)
#define ASM_NAME(name) __asm(name)
#else
#define ASM_NAME(name)
#endif
// Clang-format does not understand macros.
// clang-format off
VKAPI_ATTR void VKAPI_CALL vkdev_ext0(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext1(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext2(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext3(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext4(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext5(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext6(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext7(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext8(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext9(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext10(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext11(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext12(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext13(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext14(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext15(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext16(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext17(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext18(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext19(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext20(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext21(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext22(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext23(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext24(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext25(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext26(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext27(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext28(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext29(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext30(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext31(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext32(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext33(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext34(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext35(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext36(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext37(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext38(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext39(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext40(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext41(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext42(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext43(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext44(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext45(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext46(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext47(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext48(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext49(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext50(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext51(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext52(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext53(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext54(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext55(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext56(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext57(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext58(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext59(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext60(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext61(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext62(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext63(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext64(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext65(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext66(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext67(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext68(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext69(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext70(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext71(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext72(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext73(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext74(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext75(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext76(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext77(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext78(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext79(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext80(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext81(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext82(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext83(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext84(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext85(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext86(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext87(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext88(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext89(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext90(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext91(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext92(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext93(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext94(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext95(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext96(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext97(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext98(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext99(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext100(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext101(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext102(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext103(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext104(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext105(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext106(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext107(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext108(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext109(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext110(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext111(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext112(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext113(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext114(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext115(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext116(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext117(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext118(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext119(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext120(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext121(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext122(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext123(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext124(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext125(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext126(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext127(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext128(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext129(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext130(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext131(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext132(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext133(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext134(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext135(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext136(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext137(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext138(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext139(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext140(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext141(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext142(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext143(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext144(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext145(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext146(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext147(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext148(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext149(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext150(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext151(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext152(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext153(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext154(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext155(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext156(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext157(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext158(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext159(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext160(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext161(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext162(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext163(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext164(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext165(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext166(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext167(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext168(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext169(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext170(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext171(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext172(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext173(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext174(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext175(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext176(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext177(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext178(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext179(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext180(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext181(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext182(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext183(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext184(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext185(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext186(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext187(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext188(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext189(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext190(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext191(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext192(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext193(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext194(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext195(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext196(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext197(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext198(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext199(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext200(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext201(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext202(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext203(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext204(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext205(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext206(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext207(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext208(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext209(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext210(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext211(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext212(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext213(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext214(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext215(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext216(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext217(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext218(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext219(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext220(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext221(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext222(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext223(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext224(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext225(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext226(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext227(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext228(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext229(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext230(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext231(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext232(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext233(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext234(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext235(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext236(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext237(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext238(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext239(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext240(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext241(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext242(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext243(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext244(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext245(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext246(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext247(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext248(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext249(VkDevice device);
VKAPI_ATTR void VKAPI_CALL vkdev_ext0(VkDevice device) ASM_NAME("vkdev_ext0");
VKAPI_ATTR void VKAPI_CALL vkdev_ext1(VkDevice device) ASM_NAME("vkdev_ext1");
VKAPI_ATTR void VKAPI_CALL vkdev_ext2(VkDevice device) ASM_NAME("vkdev_ext2");
VKAPI_ATTR void VKAPI_CALL vkdev_ext3(VkDevice device) ASM_NAME("vkdev_ext3");
VKAPI_ATTR void VKAPI_CALL vkdev_ext4(VkDevice device) ASM_NAME("vkdev_ext4");
VKAPI_ATTR void VKAPI_CALL vkdev_ext5(VkDevice device) ASM_NAME("vkdev_ext5");
VKAPI_ATTR void VKAPI_CALL vkdev_ext6(VkDevice device) ASM_NAME("vkdev_ext6");
VKAPI_ATTR void VKAPI_CALL vkdev_ext7(VkDevice device) ASM_NAME("vkdev_ext7");
VKAPI_ATTR void VKAPI_CALL vkdev_ext8(VkDevice device) ASM_NAME("vkdev_ext8");
VKAPI_ATTR void VKAPI_CALL vkdev_ext9(VkDevice device) ASM_NAME("vkdev_ext9");
VKAPI_ATTR void VKAPI_CALL vkdev_ext10(VkDevice device) ASM_NAME("vkdev_ext10");
VKAPI_ATTR void VKAPI_CALL vkdev_ext11(VkDevice device) ASM_NAME("vkdev_ext11");
VKAPI_ATTR void VKAPI_CALL vkdev_ext12(VkDevice device) ASM_NAME("vkdev_ext12");
VKAPI_ATTR void VKAPI_CALL vkdev_ext13(VkDevice device) ASM_NAME("vkdev_ext13");
VKAPI_ATTR void VKAPI_CALL vkdev_ext14(VkDevice device) ASM_NAME("vkdev_ext14");
VKAPI_ATTR void VKAPI_CALL vkdev_ext15(VkDevice device) ASM_NAME("vkdev_ext15");
VKAPI_ATTR void VKAPI_CALL vkdev_ext16(VkDevice device) ASM_NAME("vkdev_ext16");
VKAPI_ATTR void VKAPI_CALL vkdev_ext17(VkDevice device) ASM_NAME("vkdev_ext17");
VKAPI_ATTR void VKAPI_CALL vkdev_ext18(VkDevice device) ASM_NAME("vkdev_ext18");
VKAPI_ATTR void VKAPI_CALL vkdev_ext19(VkDevice device) ASM_NAME("vkdev_ext19");
VKAPI_ATTR void VKAPI_CALL vkdev_ext20(VkDevice device) ASM_NAME("vkdev_ext20");
VKAPI_ATTR void VKAPI_CALL vkdev_ext21(VkDevice device) ASM_NAME("vkdev_ext21");
VKAPI_ATTR void VKAPI_CALL vkdev_ext22(VkDevice device) ASM_NAME("vkdev_ext22");
VKAPI_ATTR void VKAPI_CALL vkdev_ext23(VkDevice device) ASM_NAME("vkdev_ext23");
VKAPI_ATTR void VKAPI_CALL vkdev_ext24(VkDevice device) ASM_NAME("vkdev_ext24");
VKAPI_ATTR void VKAPI_CALL vkdev_ext25(VkDevice device) ASM_NAME("vkdev_ext25");
VKAPI_ATTR void VKAPI_CALL vkdev_ext26(VkDevice device) ASM_NAME("vkdev_ext26");
VKAPI_ATTR void VKAPI_CALL vkdev_ext27(VkDevice device) ASM_NAME("vkdev_ext27");
VKAPI_ATTR void VKAPI_CALL vkdev_ext28(VkDevice device) ASM_NAME("vkdev_ext28");
VKAPI_ATTR void VKAPI_CALL vkdev_ext29(VkDevice device) ASM_NAME("vkdev_ext29");
VKAPI_ATTR void VKAPI_CALL vkdev_ext30(VkDevice device) ASM_NAME("vkdev_ext30");
VKAPI_ATTR void VKAPI_CALL vkdev_ext31(VkDevice device) ASM_NAME("vkdev_ext31");
VKAPI_ATTR void VKAPI_CALL vkdev_ext32(VkDevice device) ASM_NAME("vkdev_ext32");
VKAPI_ATTR void VKAPI_CALL vkdev_ext33(VkDevice device) ASM_NAME("vkdev_ext33");
VKAPI_ATTR void VKAPI_CALL vkdev_ext34(VkDevice device) ASM_NAME("vkdev_ext34");
VKAPI_ATTR void VKAPI_CALL vkdev_ext35(VkDevice device) ASM_NAME("vkdev_ext35");
VKAPI_ATTR void VKAPI_CALL vkdev_ext36(VkDevice device) ASM_NAME("vkdev_ext36");
VKAPI_ATTR void VKAPI_CALL vkdev_ext37(VkDevice device) ASM_NAME("vkdev_ext37");
VKAPI_ATTR void VKAPI_CALL vkdev_ext38(VkDevice device) ASM_NAME("vkdev_ext38");
VKAPI_ATTR void VKAPI_CALL vkdev_ext39(VkDevice device) ASM_NAME("vkdev_ext39");
VKAPI_ATTR void VKAPI_CALL vkdev_ext40(VkDevice device) ASM_NAME("vkdev_ext40");
VKAPI_ATTR void VKAPI_CALL vkdev_ext41(VkDevice device) ASM_NAME("vkdev_ext41");
VKAPI_ATTR void VKAPI_CALL vkdev_ext42(VkDevice device) ASM_NAME("vkdev_ext42");
VKAPI_ATTR void VKAPI_CALL vkdev_ext43(VkDevice device) ASM_NAME("vkdev_ext43");
VKAPI_ATTR void VKAPI_CALL vkdev_ext44(VkDevice device) ASM_NAME("vkdev_ext44");
VKAPI_ATTR void VKAPI_CALL vkdev_ext45(VkDevice device) ASM_NAME("vkdev_ext45");
VKAPI_ATTR void VKAPI_CALL vkdev_ext46(VkDevice device) ASM_NAME("vkdev_ext46");
VKAPI_ATTR void VKAPI_CALL vkdev_ext47(VkDevice device) ASM_NAME("vkdev_ext47");
VKAPI_ATTR void VKAPI_CALL vkdev_ext48(VkDevice device) ASM_NAME("vkdev_ext48");
VKAPI_ATTR void VKAPI_CALL vkdev_ext49(VkDevice device) ASM_NAME("vkdev_ext49");
VKAPI_ATTR void VKAPI_CALL vkdev_ext50(VkDevice device) ASM_NAME("vkdev_ext50");
VKAPI_ATTR void VKAPI_CALL vkdev_ext51(VkDevice device) ASM_NAME("vkdev_ext51");
VKAPI_ATTR void VKAPI_CALL vkdev_ext52(VkDevice device) ASM_NAME("vkdev_ext52");
VKAPI_ATTR void VKAPI_CALL vkdev_ext53(VkDevice device) ASM_NAME("vkdev_ext53");
VKAPI_ATTR void VKAPI_CALL vkdev_ext54(VkDevice device) ASM_NAME("vkdev_ext54");
VKAPI_ATTR void VKAPI_CALL vkdev_ext55(VkDevice device) ASM_NAME("vkdev_ext55");
VKAPI_ATTR void VKAPI_CALL vkdev_ext56(VkDevice device) ASM_NAME("vkdev_ext56");
VKAPI_ATTR void VKAPI_CALL vkdev_ext57(VkDevice device) ASM_NAME("vkdev_ext57");
VKAPI_ATTR void VKAPI_CALL vkdev_ext58(VkDevice device) ASM_NAME("vkdev_ext58");
VKAPI_ATTR void VKAPI_CALL vkdev_ext59(VkDevice device) ASM_NAME("vkdev_ext59");
VKAPI_ATTR void VKAPI_CALL vkdev_ext60(VkDevice device) ASM_NAME("vkdev_ext60");
VKAPI_ATTR void VKAPI_CALL vkdev_ext61(VkDevice device) ASM_NAME("vkdev_ext61");
VKAPI_ATTR void VKAPI_CALL vkdev_ext62(VkDevice device) ASM_NAME("vkdev_ext62");
VKAPI_ATTR void VKAPI_CALL vkdev_ext63(VkDevice device) ASM_NAME("vkdev_ext63");
VKAPI_ATTR void VKAPI_CALL vkdev_ext64(VkDevice device) ASM_NAME("vkdev_ext64");
VKAPI_ATTR void VKAPI_CALL vkdev_ext65(VkDevice device) ASM_NAME("vkdev_ext65");
VKAPI_ATTR void VKAPI_CALL vkdev_ext66(VkDevice device) ASM_NAME("vkdev_ext66");
VKAPI_ATTR void VKAPI_CALL vkdev_ext67(VkDevice device) ASM_NAME("vkdev_ext67");
VKAPI_ATTR void VKAPI_CALL vkdev_ext68(VkDevice device) ASM_NAME("vkdev_ext68");
VKAPI_ATTR void VKAPI_CALL vkdev_ext69(VkDevice device) ASM_NAME("vkdev_ext69");
VKAPI_ATTR void VKAPI_CALL vkdev_ext70(VkDevice device) ASM_NAME("vkdev_ext70");
VKAPI_ATTR void VKAPI_CALL vkdev_ext71(VkDevice device) ASM_NAME("vkdev_ext71");
VKAPI_ATTR void VKAPI_CALL vkdev_ext72(VkDevice device) ASM_NAME("vkdev_ext72");
VKAPI_ATTR void VKAPI_CALL vkdev_ext73(VkDevice device) ASM_NAME("vkdev_ext73");
VKAPI_ATTR void VKAPI_CALL vkdev_ext74(VkDevice device) ASM_NAME("vkdev_ext74");
VKAPI_ATTR void VKAPI_CALL vkdev_ext75(VkDevice device) ASM_NAME("vkdev_ext75");
VKAPI_ATTR void VKAPI_CALL vkdev_ext76(VkDevice device) ASM_NAME("vkdev_ext76");
VKAPI_ATTR void VKAPI_CALL vkdev_ext77(VkDevice device) ASM_NAME("vkdev_ext77");
VKAPI_ATTR void VKAPI_CALL vkdev_ext78(VkDevice device) ASM_NAME("vkdev_ext78");
VKAPI_ATTR void VKAPI_CALL vkdev_ext79(VkDevice device) ASM_NAME("vkdev_ext79");
VKAPI_ATTR void VKAPI_CALL vkdev_ext80(VkDevice device) ASM_NAME("vkdev_ext80");
VKAPI_ATTR void VKAPI_CALL vkdev_ext81(VkDevice device) ASM_NAME("vkdev_ext81");
VKAPI_ATTR void VKAPI_CALL vkdev_ext82(VkDevice device) ASM_NAME("vkdev_ext82");
VKAPI_ATTR void VKAPI_CALL vkdev_ext83(VkDevice device) ASM_NAME("vkdev_ext83");
VKAPI_ATTR void VKAPI_CALL vkdev_ext84(VkDevice device) ASM_NAME("vkdev_ext84");
VKAPI_ATTR void VKAPI_CALL vkdev_ext85(VkDevice device) ASM_NAME("vkdev_ext85");
VKAPI_ATTR void VKAPI_CALL vkdev_ext86(VkDevice device) ASM_NAME("vkdev_ext86");
VKAPI_ATTR void VKAPI_CALL vkdev_ext87(VkDevice device) ASM_NAME("vkdev_ext87");
VKAPI_ATTR void VKAPI_CALL vkdev_ext88(VkDevice device) ASM_NAME("vkdev_ext88");
VKAPI_ATTR void VKAPI_CALL vkdev_ext89(VkDevice device) ASM_NAME("vkdev_ext89");
VKAPI_ATTR void VKAPI_CALL vkdev_ext90(VkDevice device) ASM_NAME("vkdev_ext90");
VKAPI_ATTR void VKAPI_CALL vkdev_ext91(VkDevice device) ASM_NAME("vkdev_ext91");
VKAPI_ATTR void VKAPI_CALL vkdev_ext92(VkDevice device) ASM_NAME("vkdev_ext92");
VKAPI_ATTR void VKAPI_CALL vkdev_ext93(VkDevice device) ASM_NAME("vkdev_ext93");
VKAPI_ATTR void VKAPI_CALL vkdev_ext94(VkDevice device) ASM_NAME("vkdev_ext94");
VKAPI_ATTR void VKAPI_CALL vkdev_ext95(VkDevice device) ASM_NAME("vkdev_ext95");
VKAPI_ATTR void VKAPI_CALL vkdev_ext96(VkDevice device) ASM_NAME("vkdev_ext96");
VKAPI_ATTR void VKAPI_CALL vkdev_ext97(VkDevice device) ASM_NAME("vkdev_ext97");
VKAPI_ATTR void VKAPI_CALL vkdev_ext98(VkDevice device) ASM_NAME("vkdev_ext98");
VKAPI_ATTR void VKAPI_CALL vkdev_ext99(VkDevice device) ASM_NAME("vkdev_ext99");
VKAPI_ATTR void VKAPI_CALL vkdev_ext100(VkDevice device) ASM_NAME("vkdev_ext100");
VKAPI_ATTR void VKAPI_CALL vkdev_ext101(VkDevice device) ASM_NAME("vkdev_ext101");
VKAPI_ATTR void VKAPI_CALL vkdev_ext102(VkDevice device) ASM_NAME("vkdev_ext102");
VKAPI_ATTR void VKAPI_CALL vkdev_ext103(VkDevice device) ASM_NAME("vkdev_ext103");
VKAPI_ATTR void VKAPI_CALL vkdev_ext104(VkDevice device) ASM_NAME("vkdev_ext104");
VKAPI_ATTR void VKAPI_CALL vkdev_ext105(VkDevice device) ASM_NAME("vkdev_ext105");
VKAPI_ATTR void VKAPI_CALL vkdev_ext106(VkDevice device) ASM_NAME("vkdev_ext106");
VKAPI_ATTR void VKAPI_CALL vkdev_ext107(VkDevice device) ASM_NAME("vkdev_ext107");
VKAPI_ATTR void VKAPI_CALL vkdev_ext108(VkDevice device) ASM_NAME("vkdev_ext108");
VKAPI_ATTR void VKAPI_CALL vkdev_ext109(VkDevice device) ASM_NAME("vkdev_ext109");
VKAPI_ATTR void VKAPI_CALL vkdev_ext110(VkDevice device) ASM_NAME("vkdev_ext110");
VKAPI_ATTR void VKAPI_CALL vkdev_ext111(VkDevice device) ASM_NAME("vkdev_ext111");
VKAPI_ATTR void VKAPI_CALL vkdev_ext112(VkDevice device) ASM_NAME("vkdev_ext112");
VKAPI_ATTR void VKAPI_CALL vkdev_ext113(VkDevice device) ASM_NAME("vkdev_ext113");
VKAPI_ATTR void VKAPI_CALL vkdev_ext114(VkDevice device) ASM_NAME("vkdev_ext114");
VKAPI_ATTR void VKAPI_CALL vkdev_ext115(VkDevice device) ASM_NAME("vkdev_ext115");
VKAPI_ATTR void VKAPI_CALL vkdev_ext116(VkDevice device) ASM_NAME("vkdev_ext116");
VKAPI_ATTR void VKAPI_CALL vkdev_ext117(VkDevice device) ASM_NAME("vkdev_ext117");
VKAPI_ATTR void VKAPI_CALL vkdev_ext118(VkDevice device) ASM_NAME("vkdev_ext118");
VKAPI_ATTR void VKAPI_CALL vkdev_ext119(VkDevice device) ASM_NAME("vkdev_ext119");
VKAPI_ATTR void VKAPI_CALL vkdev_ext120(VkDevice device) ASM_NAME("vkdev_ext120");
VKAPI_ATTR void VKAPI_CALL vkdev_ext121(VkDevice device) ASM_NAME("vkdev_ext121");
VKAPI_ATTR void VKAPI_CALL vkdev_ext122(VkDevice device) ASM_NAME("vkdev_ext122");
VKAPI_ATTR void VKAPI_CALL vkdev_ext123(VkDevice device) ASM_NAME("vkdev_ext123");
VKAPI_ATTR void VKAPI_CALL vkdev_ext124(VkDevice device) ASM_NAME("vkdev_ext124");
VKAPI_ATTR void VKAPI_CALL vkdev_ext125(VkDevice device) ASM_NAME("vkdev_ext125");
VKAPI_ATTR void VKAPI_CALL vkdev_ext126(VkDevice device) ASM_NAME("vkdev_ext126");
VKAPI_ATTR void VKAPI_CALL vkdev_ext127(VkDevice device) ASM_NAME("vkdev_ext127");
VKAPI_ATTR void VKAPI_CALL vkdev_ext128(VkDevice device) ASM_NAME("vkdev_ext128");
VKAPI_ATTR void VKAPI_CALL vkdev_ext129(VkDevice device) ASM_NAME("vkdev_ext129");
VKAPI_ATTR void VKAPI_CALL vkdev_ext130(VkDevice device) ASM_NAME("vkdev_ext130");
VKAPI_ATTR void VKAPI_CALL vkdev_ext131(VkDevice device) ASM_NAME("vkdev_ext131");
VKAPI_ATTR void VKAPI_CALL vkdev_ext132(VkDevice device) ASM_NAME("vkdev_ext132");
VKAPI_ATTR void VKAPI_CALL vkdev_ext133(VkDevice device) ASM_NAME("vkdev_ext133");
VKAPI_ATTR void VKAPI_CALL vkdev_ext134(VkDevice device) ASM_NAME("vkdev_ext134");
VKAPI_ATTR void VKAPI_CALL vkdev_ext135(VkDevice device) ASM_NAME("vkdev_ext135");
VKAPI_ATTR void VKAPI_CALL vkdev_ext136(VkDevice device) ASM_NAME("vkdev_ext136");
VKAPI_ATTR void VKAPI_CALL vkdev_ext137(VkDevice device) ASM_NAME("vkdev_ext137");
VKAPI_ATTR void VKAPI_CALL vkdev_ext138(VkDevice device) ASM_NAME("vkdev_ext138");
VKAPI_ATTR void VKAPI_CALL vkdev_ext139(VkDevice device) ASM_NAME("vkdev_ext139");
VKAPI_ATTR void VKAPI_CALL vkdev_ext140(VkDevice device) ASM_NAME("vkdev_ext140");
VKAPI_ATTR void VKAPI_CALL vkdev_ext141(VkDevice device) ASM_NAME("vkdev_ext141");
VKAPI_ATTR void VKAPI_CALL vkdev_ext142(VkDevice device) ASM_NAME("vkdev_ext142");
VKAPI_ATTR void VKAPI_CALL vkdev_ext143(VkDevice device) ASM_NAME("vkdev_ext143");
VKAPI_ATTR void VKAPI_CALL vkdev_ext144(VkDevice device) ASM_NAME("vkdev_ext144");
VKAPI_ATTR void VKAPI_CALL vkdev_ext145(VkDevice device) ASM_NAME("vkdev_ext145");
VKAPI_ATTR void VKAPI_CALL vkdev_ext146(VkDevice device) ASM_NAME("vkdev_ext146");
VKAPI_ATTR void VKAPI_CALL vkdev_ext147(VkDevice device) ASM_NAME("vkdev_ext147");
VKAPI_ATTR void VKAPI_CALL vkdev_ext148(VkDevice device) ASM_NAME("vkdev_ext148");
VKAPI_ATTR void VKAPI_CALL vkdev_ext149(VkDevice device) ASM_NAME("vkdev_ext149");
VKAPI_ATTR void VKAPI_CALL vkdev_ext150(VkDevice device) ASM_NAME("vkdev_ext150");
VKAPI_ATTR void VKAPI_CALL vkdev_ext151(VkDevice device) ASM_NAME("vkdev_ext151");
VKAPI_ATTR void VKAPI_CALL vkdev_ext152(VkDevice device) ASM_NAME("vkdev_ext152");
VKAPI_ATTR void VKAPI_CALL vkdev_ext153(VkDevice device) ASM_NAME("vkdev_ext153");
VKAPI_ATTR void VKAPI_CALL vkdev_ext154(VkDevice device) ASM_NAME("vkdev_ext154");
VKAPI_ATTR void VKAPI_CALL vkdev_ext155(VkDevice device) ASM_NAME("vkdev_ext155");
VKAPI_ATTR void VKAPI_CALL vkdev_ext156(VkDevice device) ASM_NAME("vkdev_ext156");
VKAPI_ATTR void VKAPI_CALL vkdev_ext157(VkDevice device) ASM_NAME("vkdev_ext157");
VKAPI_ATTR void VKAPI_CALL vkdev_ext158(VkDevice device) ASM_NAME("vkdev_ext158");
VKAPI_ATTR void VKAPI_CALL vkdev_ext159(VkDevice device) ASM_NAME("vkdev_ext159");
VKAPI_ATTR void VKAPI_CALL vkdev_ext160(VkDevice device) ASM_NAME("vkdev_ext160");
VKAPI_ATTR void VKAPI_CALL vkdev_ext161(VkDevice device) ASM_NAME("vkdev_ext161");
VKAPI_ATTR void VKAPI_CALL vkdev_ext162(VkDevice device) ASM_NAME("vkdev_ext162");
VKAPI_ATTR void VKAPI_CALL vkdev_ext163(VkDevice device) ASM_NAME("vkdev_ext163");
VKAPI_ATTR void VKAPI_CALL vkdev_ext164(VkDevice device) ASM_NAME("vkdev_ext164");
VKAPI_ATTR void VKAPI_CALL vkdev_ext165(VkDevice device) ASM_NAME("vkdev_ext165");
VKAPI_ATTR void VKAPI_CALL vkdev_ext166(VkDevice device) ASM_NAME("vkdev_ext166");
VKAPI_ATTR void VKAPI_CALL vkdev_ext167(VkDevice device) ASM_NAME("vkdev_ext167");
VKAPI_ATTR void VKAPI_CALL vkdev_ext168(VkDevice device) ASM_NAME("vkdev_ext168");
VKAPI_ATTR void VKAPI_CALL vkdev_ext169(VkDevice device) ASM_NAME("vkdev_ext169");
VKAPI_ATTR void VKAPI_CALL vkdev_ext170(VkDevice device) ASM_NAME("vkdev_ext170");
VKAPI_ATTR void VKAPI_CALL vkdev_ext171(VkDevice device) ASM_NAME("vkdev_ext171");
VKAPI_ATTR void VKAPI_CALL vkdev_ext172(VkDevice device) ASM_NAME("vkdev_ext172");
VKAPI_ATTR void VKAPI_CALL vkdev_ext173(VkDevice device) ASM_NAME("vkdev_ext173");
VKAPI_ATTR void VKAPI_CALL vkdev_ext174(VkDevice device) ASM_NAME("vkdev_ext174");
VKAPI_ATTR void VKAPI_CALL vkdev_ext175(VkDevice device) ASM_NAME("vkdev_ext175");
VKAPI_ATTR void VKAPI_CALL vkdev_ext176(VkDevice device) ASM_NAME("vkdev_ext176");
VKAPI_ATTR void VKAPI_CALL vkdev_ext177(VkDevice device) ASM_NAME("vkdev_ext177");
VKAPI_ATTR void VKAPI_CALL vkdev_ext178(VkDevice device) ASM_NAME("vkdev_ext178");
VKAPI_ATTR void VKAPI_CALL vkdev_ext179(VkDevice device) ASM_NAME("vkdev_ext179");
VKAPI_ATTR void VKAPI_CALL vkdev_ext180(VkDevice device) ASM_NAME("vkdev_ext180");
VKAPI_ATTR void VKAPI_CALL vkdev_ext181(VkDevice device) ASM_NAME("vkdev_ext181");
VKAPI_ATTR void VKAPI_CALL vkdev_ext182(VkDevice device) ASM_NAME("vkdev_ext182");
VKAPI_ATTR void VKAPI_CALL vkdev_ext183(VkDevice device) ASM_NAME("vkdev_ext183");
VKAPI_ATTR void VKAPI_CALL vkdev_ext184(VkDevice device) ASM_NAME("vkdev_ext184");
VKAPI_ATTR void VKAPI_CALL vkdev_ext185(VkDevice device) ASM_NAME("vkdev_ext185");
VKAPI_ATTR void VKAPI_CALL vkdev_ext186(VkDevice device) ASM_NAME("vkdev_ext186");
VKAPI_ATTR void VKAPI_CALL vkdev_ext187(VkDevice device) ASM_NAME("vkdev_ext187");
VKAPI_ATTR void VKAPI_CALL vkdev_ext188(VkDevice device) ASM_NAME("vkdev_ext188");
VKAPI_ATTR void VKAPI_CALL vkdev_ext189(VkDevice device) ASM_NAME("vkdev_ext189");
VKAPI_ATTR void VKAPI_CALL vkdev_ext190(VkDevice device) ASM_NAME("vkdev_ext190");
VKAPI_ATTR void VKAPI_CALL vkdev_ext191(VkDevice device) ASM_NAME("vkdev_ext191");
VKAPI_ATTR void VKAPI_CALL vkdev_ext192(VkDevice device) ASM_NAME("vkdev_ext192");
VKAPI_ATTR void VKAPI_CALL vkdev_ext193(VkDevice device) ASM_NAME("vkdev_ext193");
VKAPI_ATTR void VKAPI_CALL vkdev_ext194(VkDevice device) ASM_NAME("vkdev_ext194");
VKAPI_ATTR void VKAPI_CALL vkdev_ext195(VkDevice device) ASM_NAME("vkdev_ext195");
VKAPI_ATTR void VKAPI_CALL vkdev_ext196(VkDevice device) ASM_NAME("vkdev_ext196");
VKAPI_ATTR void VKAPI_CALL vkdev_ext197(VkDevice device) ASM_NAME("vkdev_ext197");
VKAPI_ATTR void VKAPI_CALL vkdev_ext198(VkDevice device) ASM_NAME("vkdev_ext198");
VKAPI_ATTR void VKAPI_CALL vkdev_ext199(VkDevice device) ASM_NAME("vkdev_ext199");
VKAPI_ATTR void VKAPI_CALL vkdev_ext200(VkDevice device) ASM_NAME("vkdev_ext200");
VKAPI_ATTR void VKAPI_CALL vkdev_ext201(VkDevice device) ASM_NAME("vkdev_ext201");
VKAPI_ATTR void VKAPI_CALL vkdev_ext202(VkDevice device) ASM_NAME("vkdev_ext202");
VKAPI_ATTR void VKAPI_CALL vkdev_ext203(VkDevice device) ASM_NAME("vkdev_ext203");
VKAPI_ATTR void VKAPI_CALL vkdev_ext204(VkDevice device) ASM_NAME("vkdev_ext204");
VKAPI_ATTR void VKAPI_CALL vkdev_ext205(VkDevice device) ASM_NAME("vkdev_ext205");
VKAPI_ATTR void VKAPI_CALL vkdev_ext206(VkDevice device) ASM_NAME("vkdev_ext206");
VKAPI_ATTR void VKAPI_CALL vkdev_ext207(VkDevice device) ASM_NAME("vkdev_ext207");
VKAPI_ATTR void VKAPI_CALL vkdev_ext208(VkDevice device) ASM_NAME("vkdev_ext208");
VKAPI_ATTR void VKAPI_CALL vkdev_ext209(VkDevice device) ASM_NAME("vkdev_ext209");
VKAPI_ATTR void VKAPI_CALL vkdev_ext210(VkDevice device) ASM_NAME("vkdev_ext210");
VKAPI_ATTR void VKAPI_CALL vkdev_ext211(VkDevice device) ASM_NAME("vkdev_ext211");
VKAPI_ATTR void VKAPI_CALL vkdev_ext212(VkDevice device) ASM_NAME("vkdev_ext212");
VKAPI_ATTR void VKAPI_CALL vkdev_ext213(VkDevice device) ASM_NAME("vkdev_ext213");
VKAPI_ATTR void VKAPI_CALL vkdev_ext214(VkDevice device) ASM_NAME("vkdev_ext214");
VKAPI_ATTR void VKAPI_CALL vkdev_ext215(VkDevice device) ASM_NAME("vkdev_ext215");
VKAPI_ATTR void VKAPI_CALL vkdev_ext216(VkDevice device) ASM_NAME("vkdev_ext216");
VKAPI_ATTR void VKAPI_CALL vkdev_ext217(VkDevice device) ASM_NAME("vkdev_ext217");
VKAPI_ATTR void VKAPI_CALL vkdev_ext218(VkDevice device) ASM_NAME("vkdev_ext218");
VKAPI_ATTR void VKAPI_CALL vkdev_ext219(VkDevice device) ASM_NAME("vkdev_ext219");
VKAPI_ATTR void VKAPI_CALL vkdev_ext220(VkDevice device) ASM_NAME("vkdev_ext220");
VKAPI_ATTR void VKAPI_CALL vkdev_ext221(VkDevice device) ASM_NAME("vkdev_ext221");
VKAPI_ATTR void VKAPI_CALL vkdev_ext222(VkDevice device) ASM_NAME("vkdev_ext222");
VKAPI_ATTR void VKAPI_CALL vkdev_ext223(VkDevice device) ASM_NAME("vkdev_ext223");
VKAPI_ATTR void VKAPI_CALL vkdev_ext224(VkDevice device) ASM_NAME("vkdev_ext224");
VKAPI_ATTR void VKAPI_CALL vkdev_ext225(VkDevice device) ASM_NAME("vkdev_ext225");
VKAPI_ATTR void VKAPI_CALL vkdev_ext226(VkDevice device) ASM_NAME("vkdev_ext226");
VKAPI_ATTR void VKAPI_CALL vkdev_ext227(VkDevice device) ASM_NAME("vkdev_ext227");
VKAPI_ATTR void VKAPI_CALL vkdev_ext228(VkDevice device) ASM_NAME("vkdev_ext228");
VKAPI_ATTR void VKAPI_CALL vkdev_ext229(VkDevice device) ASM_NAME("vkdev_ext229");
VKAPI_ATTR void VKAPI_CALL vkdev_ext230(VkDevice device) ASM_NAME("vkdev_ext230");
VKAPI_ATTR void VKAPI_CALL vkdev_ext231(VkDevice device) ASM_NAME("vkdev_ext231");
VKAPI_ATTR void VKAPI_CALL vkdev_ext232(VkDevice device) ASM_NAME("vkdev_ext232");
VKAPI_ATTR void VKAPI_CALL vkdev_ext233(VkDevice device) ASM_NAME("vkdev_ext233");
VKAPI_ATTR void VKAPI_CALL vkdev_ext234(VkDevice device) ASM_NAME("vkdev_ext234");
VKAPI_ATTR void VKAPI_CALL vkdev_ext235(VkDevice device) ASM_NAME("vkdev_ext235");
VKAPI_ATTR void VKAPI_CALL vkdev_ext236(VkDevice device) ASM_NAME("vkdev_ext236");
VKAPI_ATTR void VKAPI_CALL vkdev_ext237(VkDevice device) ASM_NAME("vkdev_ext237");
VKAPI_ATTR void VKAPI_CALL vkdev_ext238(VkDevice device) ASM_NAME("vkdev_ext238");
VKAPI_ATTR void VKAPI_CALL vkdev_ext239(VkDevice device) ASM_NAME("vkdev_ext239");
VKAPI_ATTR void VKAPI_CALL vkdev_ext240(VkDevice device) ASM_NAME("vkdev_ext240");
VKAPI_ATTR void VKAPI_CALL vkdev_ext241(VkDevice device) ASM_NAME("vkdev_ext241");
VKAPI_ATTR void VKAPI_CALL vkdev_ext242(VkDevice device) ASM_NAME("vkdev_ext242");
VKAPI_ATTR void VKAPI_CALL vkdev_ext243(VkDevice device) ASM_NAME("vkdev_ext243");
VKAPI_ATTR void VKAPI_CALL vkdev_ext244(VkDevice device) ASM_NAME("vkdev_ext244");
VKAPI_ATTR void VKAPI_CALL vkdev_ext245(VkDevice device) ASM_NAME("vkdev_ext245");
VKAPI_ATTR void VKAPI_CALL vkdev_ext246(VkDevice device) ASM_NAME("vkdev_ext246");
VKAPI_ATTR void VKAPI_CALL vkdev_ext247(VkDevice device) ASM_NAME("vkdev_ext247");
VKAPI_ATTR void VKAPI_CALL vkdev_ext248(VkDevice device) ASM_NAME("vkdev_ext248");
VKAPI_ATTR void VKAPI_CALL vkdev_ext249(VkDevice device) ASM_NAME("vkdev_ext249");
void *loader_get_dev_ext_trampoline(uint32_t index) {
switch (index) {

View File

@ -16,7 +16,7 @@
#include "allocation.h"
#ifdef __cplusplus
#if defined(__cplusplus)
extern "C" {
#endif
@ -36,11 +36,12 @@ DIR *opendir(const VkAllocationCallbacks *pAllocator, const char *name) {
size_t base_length = strlen(name);
const char *all = /* search pattern must end with suitable wildcard */
strchr("/\\", name[base_length - 1]) ? "*" : "/*";
size_t full_length = base_length + strlen(all) + 1;
if ((dir = (DIR *)loader_alloc(pAllocator, sizeof *dir, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)) != 0 &&
(dir->name = (char *)loader_alloc(pAllocator, base_length + strlen(all) + 1, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)) !=
0) {
strcat(strcpy(dir->name, name), all);
(dir->name = (char *)loader_calloc(pAllocator, full_length, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND)) != 0) {
loader_strncpy(dir->name, full_length, name, base_length);
loader_strncat(dir->name, full_length, all, strlen(all));
if ((dir->handle = (handle_type)_findfirst(dir->name, &dir->info)) != -1) {
dir->result.d_name = 0;
@ -108,7 +109,7 @@ void rewinddir(DIR *dir) {
}
}
#ifdef __cplusplus
#if defined(__cplusplus)
}
#endif

View File

@ -12,7 +12,7 @@
#include <vulkan/vulkan.h>
#ifdef __cplusplus
#if defined(__cplusplus)
extern "C" {
#endif
@ -46,6 +46,6 @@ void rewinddir(DIR *);
*/
#ifdef __cplusplus
#if defined(__cplusplus)
}
#endif

View File

@ -46,7 +46,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceExternalImageFormatPropertiesNV(
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetPhysicalDeviceExternalImageFormatPropertiesNV: Invalid physicalDevice "
"[VUID-vkGetPhysicalDeviceExternalImageFormatPropertiesNV-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
@ -92,7 +92,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfaceCapabilities2EXT(VkPhysic
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetPhysicalDeviceExternalImageFormatPropertiesNV: Invalid physicalDevice "
"[VUID-vkGetPhysicalDeviceSurfaceCapabilities2EXT-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
@ -157,7 +157,7 @@ VKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkReleaseDisplayEXT: Invalid physicalDevice [VUID-vkReleaseDisplayEXT-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
@ -170,7 +170,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice phy
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
if (icd_term->dispatch.ReleaseDisplayEXT == NULL) {
loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
loader_log(icd_term->this_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
"ICD \"%s\" associated with VkPhysicalDevice does not support vkReleaseDisplayEXT - Consequently, the call is "
"invalid because it should not be possible to acquire a display on this device",
icd_term->scanned_icd->lib_name);
@ -181,12 +181,12 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice phy
// ---- VK_EXT_acquire_xlib_display extension trampoline/terminators
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
VKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display *dpy, VkDisplayKHR display) {
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkAcquireXlibDisplayEXT: Invalid physicalDevice [VUID-vkAcquireXlibDisplayEXT-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
@ -217,7 +217,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetRandROutputDisplayEXT(VkPhysicalDevice physica
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetRandROutputDisplayEXT: Invalid physicalDevice [VUID-vkGetRandROutputDisplayEXT-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
@ -247,7 +247,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDev
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceSurfaceInfo2KHR *pSurfaceInfo,
uint32_t *pPresentModeCount,
@ -255,7 +255,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysic
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetPhysicalDeviceSurfacePresentModes2EXT: Invalid physicalDevice "
"[VUID-vkGetPhysicalDeviceSurfacePresentModes2EXT-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
@ -270,7 +270,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModes2E
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
if (NULL == icd_term->dispatch.GetPhysicalDeviceSurfacePresentModes2EXT) {
loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
loader_log(icd_term->this_instance, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT, 0,
"ICD associated with VkPhysicalDevice does not support GetPhysicalDeviceSurfacePresentModes2EXT");
abort();
}
@ -293,7 +293,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetDeviceGroupSurfacePresentModes2EXT(VkDevice de
VkDeviceGroupPresentModeFlagsKHR *pModes) {
const VkLayerDispatchTable *disp = loader_get_dispatch(device);
if (NULL == disp) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetDeviceGroupSurfacePresentModes2EXT: Invalid device "
"[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-device-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
@ -307,18 +307,30 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModes2EXT(
uint32_t icd_index = 0;
struct loader_device *dev;
struct loader_icd_term *icd_term = loader_get_icd_and_device(device, &dev, &icd_index);
if (NULL != icd_term && NULL != icd_term->dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
if (NULL == icd_term || NULL == dev ||
NULL == dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT) {
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetDeviceGroupSurfacePresentModes2EXT Terminator: Invalid device handle. This is likely the result of a "
"layer wrapping device handles and failing to unwrap them in all functions. "
"[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-device-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
if (NULL == pSurfaceInfo) {
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetDeviceGroupSurfacePresentModes2EXT: Invalid pSurfaceInfo pointer "
"[VUID-vkGetDeviceGroupSurfacePresentModes2EXT-pSurfaceInfo-parameter]");
abort(); /* Intentionally fail so user can correct issue. */
}
VkIcdSurface *icd_surface = (VkIcdSurface *)(uintptr_t)pSurfaceInfo->surface;
if (NULL != icd_surface->real_icd_surfaces && (VkSurfaceKHR)NULL != icd_surface->real_icd_surfaces[icd_index]) {
if (NULL != icd_surface->real_icd_surfaces && NULL != (void *)(uintptr_t)icd_surface->real_icd_surfaces[icd_index]) {
VkPhysicalDeviceSurfaceInfo2KHR surface_info_copy;
surface_info_copy.sType = pSurfaceInfo->sType;
surface_info_copy.pNext = pSurfaceInfo->pNext;
surface_info_copy.surface = icd_surface->real_icd_surfaces[icd_index];
return icd_term->dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy, pModes);
return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, &surface_info_copy,
pModes);
}
return icd_term->dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
}
return VK_SUCCESS;
return dev->loader_dispatch.extension_terminator_dispatch.GetDeviceGroupSurfacePresentModes2EXT(device, pSurfaceInfo, pModes);
}
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -330,7 +342,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceToolPropertiesEXT(VkPhysicalDevi
const VkLayerInstanceDispatchTable *disp;
VkPhysicalDevice unwrapped_phys_dev = loader_unwrap_physical_device(physicalDevice);
if (VK_NULL_HANDLE == unwrapped_phys_dev) {
loader_log(NULL, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
loader_log(NULL, VULKAN_LOADER_FATAL_ERROR_BIT | VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_VALIDATION_BIT, 0,
"vkGetPhysicalDeviceToolPropertiesEXT: Invalid physicalDevice "
"[VUID-vkGetPhysicalDeviceToolPropertiesEXT-physicalDevice-parameter]");
abort(); /* Intentionally fail so user can correct issue. */

View File

@ -49,7 +49,7 @@ VKAPI_ATTR VkResult VKAPI_CALL ReleaseDisplayEXT(VkPhysicalDevice physicalDevice
VKAPI_ATTR VkResult VKAPI_CALL terminator_ReleaseDisplayEXT(VkPhysicalDevice physicalDevice, VkDisplayKHR display);
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
VKAPI_ATTR VkResult VKAPI_CALL AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display* dpy, VkDisplayKHR display);
VKAPI_ATTR VkResult VKAPI_CALL terminator_AcquireXlibDisplayEXT(VkPhysicalDevice physicalDevice, Display* dpy,
@ -62,7 +62,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetRandROutputDisplayEXT(VkPhysicalDev
VkDisplayKHR* pDisplay);
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VKAPI_ATTR VkResult VKAPI_CALL GetPhysicalDeviceSurfacePresentModes2EXT(VkPhysicalDevice physicalDevice,
const VkPhysicalDeviceSurfaceInfo2KHR* pSurfaceInfo,
uint32_t* pPresentModeCount,

View File

@ -1,5 +0,0 @@
---
# Disable clang-format for generated code
DisableFormat: true
SortIncludes: false
...

View File

@ -1,28 +0,0 @@
# *** THIS FILE IS GENERATED - DO NOT EDIT ***
# See loader_versioning_generator.py for modifications
############################################################################
#
# Copyright (c) 2021 The Khronos Group Inc.
# Copyright (c) 2021 Valve Corporation
# Copyright (c) 2021 LunarG, Inc.
# Copyright (c) 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: Charles Giessen <charles@lunarg.com>
#
############################################################################
set(LOADER_GENERATED_HEADER_VERSION "1.3.231")

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@
* Copyright (c) 2015-2022 The Khronos Group Inc.
* Copyright (c) 2015-2022 Valve Corporation
* Copyright (c) 2015-2022 LunarG, Inc.
* Copyright (c) 2021-2023 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.
@ -22,16 +24,19 @@
* Author: Mark Young <marky@lunarg.com>
*/
// clang-format off
#pragma once
#if !defined(PFN_GetPhysicalDeviceProcAddr)
typedef PFN_vkVoidFunction (VKAPI_PTR *PFN_GetPhysicalDeviceProcAddr)(VkInstance instance, const char* pName);
#endif
// Instance function pointer dispatch table
typedef struct VkLayerInstanceDispatchTable_ {
// Manually add in GetPhysicalDeviceProcAddr entry
PFN_GetPhysicalDeviceProcAddr GetPhysicalDeviceProcAddr;
// ---- Core 1_0 commands
// ---- Core Vulkan 1.0 commands
PFN_vkCreateInstance CreateInstance;
PFN_vkDestroyInstance DestroyInstance;
PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
@ -49,7 +54,7 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
// ---- Core 1_1 commands
// ---- Core Vulkan 1.1 commands
PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion;
PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
@ -63,7 +68,7 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
// ---- Core 1_3 commands
// ---- Core Vulkan 1.3 commands
PFN_vkGetPhysicalDeviceToolProperties GetPhysicalDeviceToolProperties;
// ---- VK_KHR_surface extension commands
@ -86,49 +91,45 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
// ---- VK_KHR_xlib_surface extension commands
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
#endif // VK_USE_PLATFORM_XLIB_KHR
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR;
#endif // VK_USE_PLATFORM_XLIB_KHR
// ---- VK_KHR_xcb_surface extension commands
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
#endif // VK_USE_PLATFORM_XCB_KHR
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR;
#endif // VK_USE_PLATFORM_XCB_KHR
// ---- VK_KHR_wayland_surface extension commands
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
#endif // VK_USE_PLATFORM_WAYLAND_KHR
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR;
#endif // VK_USE_PLATFORM_WAYLAND_KHR
// ---- VK_KHR_android_surface extension commands
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
#endif // VK_USE_PLATFORM_ANDROID_KHR
// ---- VK_KHR_win32_surface extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
// ---- VK_KHR_video_queue extension commands
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR GetPhysicalDeviceVideoCapabilitiesKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR GetPhysicalDeviceVideoFormatPropertiesKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
// ---- VK_KHR_get_physical_device_properties2 extension commands
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR;
@ -168,13 +169,22 @@ typedef struct VkLayerInstanceDispatchTable_ {
// ---- VK_KHR_fragment_shading_rate extension commands
PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR GetPhysicalDeviceFragmentShadingRatesKHR;
// ---- VK_KHR_video_encode_queue extension commands
PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR;
// ---- VK_KHR_cooperative_matrix extension commands
PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR GetPhysicalDeviceCooperativeMatrixPropertiesKHR;
// ---- VK_KHR_calibrated_timestamps extension commands
PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR GetPhysicalDeviceCalibrateableTimeDomainsKHR;
// ---- VK_EXT_debug_report extension commands
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
// ---- VK_GGP_stream_descriptor_surface extension commands
#ifdef VK_USE_PLATFORM_GGP
#if defined(VK_USE_PLATFORM_GGP)
PFN_vkCreateStreamDescriptorSurfaceGGP CreateStreamDescriptorSurfaceGGP;
#endif // VK_USE_PLATFORM_GGP
@ -182,7 +192,7 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV;
// ---- VK_NN_vi_surface extension commands
#ifdef VK_USE_PLATFORM_VI_NN
#if defined(VK_USE_PLATFORM_VI_NN)
PFN_vkCreateViSurfaceNN CreateViSurfaceNN;
#endif // VK_USE_PLATFORM_VI_NN
@ -190,10 +200,10 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkReleaseDisplayEXT ReleaseDisplayEXT;
// ---- VK_EXT_acquire_xlib_display extension commands
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
PFN_vkAcquireXlibDisplayEXT AcquireXlibDisplayEXT;
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
PFN_vkGetRandROutputDisplayEXT GetRandROutputDisplayEXT;
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
@ -201,12 +211,12 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT GetPhysicalDeviceSurfaceCapabilities2EXT;
// ---- VK_MVK_ios_surface extension commands
#ifdef VK_USE_PLATFORM_IOS_MVK
#if defined(VK_USE_PLATFORM_IOS_MVK)
PFN_vkCreateIOSSurfaceMVK CreateIOSSurfaceMVK;
#endif // VK_USE_PLATFORM_IOS_MVK
// ---- VK_MVK_macos_surface extension commands
#ifdef VK_USE_PLATFORM_MACOS_MVK
#if defined(VK_USE_PLATFORM_MACOS_MVK)
PFN_vkCreateMacOSSurfaceMVK CreateMacOSSurfaceMVK;
#endif // VK_USE_PLATFORM_MACOS_MVK
@ -222,12 +232,12 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCalibrateableTimeDomainsEXT;
// ---- VK_FUCHSIA_imagepipe_surface extension commands
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkCreateImagePipeSurfaceFUCHSIA CreateImagePipeSurfaceFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
// ---- VK_EXT_metal_surface extension commands
#ifdef VK_USE_PLATFORM_METAL_EXT
#if defined(VK_USE_PLATFORM_METAL_EXT)
PFN_vkCreateMetalSurfaceEXT CreateMetalSurfaceEXT;
#endif // VK_USE_PLATFORM_METAL_EXT
@ -241,7 +251,7 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
// ---- VK_EXT_full_screen_exclusive extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT GetPhysicalDeviceSurfacePresentModes2EXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -253,26 +263,26 @@ typedef struct VkLayerInstanceDispatchTable_ {
PFN_vkGetDrmDisplayEXT GetDrmDisplayEXT;
// ---- VK_NV_acquire_winrt_display extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkAcquireWinrtDisplayNV AcquireWinrtDisplayNV;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetWinrtDisplayNV GetWinrtDisplayNV;
#endif // VK_USE_PLATFORM_WIN32_KHR
// ---- VK_EXT_directfb_surface extension commands
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
PFN_vkCreateDirectFBSurfaceEXT CreateDirectFBSurfaceEXT;
#endif // VK_USE_PLATFORM_DIRECTFB_EXT
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT GetPhysicalDeviceDirectFBPresentationSupportEXT;
#endif // VK_USE_PLATFORM_DIRECTFB_EXT
// ---- VK_QNX_screen_surface extension commands
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
PFN_vkCreateScreenSurfaceQNX CreateScreenSurfaceQNX;
#endif // VK_USE_PLATFORM_SCREEN_QNX
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX GetPhysicalDeviceScreenPresentationSupportQNX;
#endif // VK_USE_PLATFORM_SCREEN_QNX
@ -290,7 +300,7 @@ typedef struct VkLayerInstanceDispatchTable_ {
typedef struct VkLayerDispatchTable_ {
uint64_t magic; // Should be DEVICE_DISP_TABLE_MAGIC_NUMBER
// ---- Core 1_0 commands
// ---- Core Vulkan 1.0 commands
PFN_vkGetDeviceProcAddr GetDeviceProcAddr;
PFN_vkDestroyDevice DestroyDevice;
PFN_vkGetDeviceQueue GetDeviceQueue;
@ -413,7 +423,7 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCmdEndRenderPass CmdEndRenderPass;
PFN_vkCmdExecuteCommands CmdExecuteCommands;
// ---- Core 1_1 commands
// ---- Core Vulkan 1.1 commands
PFN_vkBindBufferMemory2 BindBufferMemory2;
PFN_vkBindImageMemory2 BindImageMemory2;
PFN_vkGetDeviceGroupPeerMemoryFeatures GetDeviceGroupPeerMemoryFeatures;
@ -431,7 +441,7 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkUpdateDescriptorSetWithTemplate UpdateDescriptorSetWithTemplate;
PFN_vkGetDescriptorSetLayoutSupport GetDescriptorSetLayoutSupport;
// ---- Core 1_2 commands
// ---- Core Vulkan 1.2 commands
PFN_vkCmdDrawIndirectCount CmdDrawIndirectCount;
PFN_vkCmdDrawIndexedIndirectCount CmdDrawIndexedIndirectCount;
PFN_vkCreateRenderPass2 CreateRenderPass2;
@ -446,7 +456,7 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetBufferOpaqueCaptureAddress GetBufferOpaqueCaptureAddress;
PFN_vkGetDeviceMemoryOpaqueCaptureAddress GetDeviceMemoryOpaqueCaptureAddress;
// ---- Core 1_3 commands
// ---- Core Vulkan 1.3 commands
PFN_vkCreatePrivateDataSlot CreatePrivateDataSlot;
PFN_vkDestroyPrivateDataSlot DestroyPrivateDataSlot;
PFN_vkSetPrivateData SetPrivateData;
@ -498,41 +508,19 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
// ---- VK_KHR_video_queue extension commands
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkCreateVideoSessionKHR CreateVideoSessionKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkDestroyVideoSessionKHR DestroyVideoSessionKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkGetVideoSessionMemoryRequirementsKHR GetVideoSessionMemoryRequirementsKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkBindVideoSessionMemoryKHR BindVideoSessionMemoryKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkCreateVideoSessionParametersKHR CreateVideoSessionParametersKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkUpdateVideoSessionParametersKHR UpdateVideoSessionParametersKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkDestroyVideoSessionParametersKHR DestroyVideoSessionParametersKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkCmdBeginVideoCodingKHR CmdBeginVideoCodingKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkCmdEndVideoCodingKHR CmdEndVideoCodingKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkCmdControlVideoCodingKHR CmdControlVideoCodingKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
// ---- VK_KHR_video_decode_queue extension commands
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkCmdDecodeVideoKHR CmdDecodeVideoKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
// ---- VK_KHR_dynamic_rendering extension commands
PFN_vkCmdBeginRenderingKHR CmdBeginRenderingKHR;
@ -547,10 +535,10 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkTrimCommandPoolKHR TrimCommandPoolKHR;
// ---- VK_KHR_external_memory_win32 extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetMemoryWin32HandleKHR GetMemoryWin32HandleKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetMemoryWin32HandlePropertiesKHR GetMemoryWin32HandlePropertiesKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -559,10 +547,10 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetMemoryFdPropertiesKHR GetMemoryFdPropertiesKHR;
// ---- VK_KHR_external_semaphore_win32 extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkImportSemaphoreWin32HandleKHR ImportSemaphoreWin32HandleKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetSemaphoreWin32HandleKHR GetSemaphoreWin32HandleKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -589,10 +577,10 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetSwapchainStatusKHR GetSwapchainStatusKHR;
// ---- VK_KHR_external_fence_win32 extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkImportFenceWin32HandleKHR ImportFenceWin32HandleKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetFenceWin32HandleKHR GetFenceWin32HandleKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -652,10 +640,13 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetPipelineExecutableStatisticsKHR GetPipelineExecutableStatisticsKHR;
PFN_vkGetPipelineExecutableInternalRepresentationsKHR GetPipelineExecutableInternalRepresentationsKHR;
// ---- VK_KHR_map_memory2 extension commands
PFN_vkMapMemory2KHR MapMemory2KHR;
PFN_vkUnmapMemory2KHR UnmapMemory2KHR;
// ---- VK_KHR_video_encode_queue extension commands
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkGetEncodedVideoSessionParametersKHR GetEncodedVideoSessionParametersKHR;
PFN_vkCmdEncodeVideoKHR CmdEncodeVideoKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
// ---- VK_KHR_synchronization2 extension commands
PFN_vkCmdSetEvent2KHR CmdSetEvent2KHR;
@ -683,6 +674,23 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetDeviceImageMemoryRequirementsKHR GetDeviceImageMemoryRequirementsKHR;
PFN_vkGetDeviceImageSparseMemoryRequirementsKHR GetDeviceImageSparseMemoryRequirementsKHR;
// ---- VK_KHR_maintenance5 extension commands
PFN_vkCmdBindIndexBuffer2KHR CmdBindIndexBuffer2KHR;
PFN_vkGetRenderingAreaGranularityKHR GetRenderingAreaGranularityKHR;
PFN_vkGetDeviceImageSubresourceLayoutKHR GetDeviceImageSubresourceLayoutKHR;
PFN_vkGetImageSubresourceLayout2KHR GetImageSubresourceLayout2KHR;
// ---- VK_KHR_calibrated_timestamps extension commands
PFN_vkGetCalibratedTimestampsKHR GetCalibratedTimestampsKHR;
// ---- VK_KHR_maintenance6 extension commands
PFN_vkCmdBindDescriptorSets2KHR CmdBindDescriptorSets2KHR;
PFN_vkCmdPushConstants2KHR CmdPushConstants2KHR;
PFN_vkCmdPushDescriptorSet2KHR CmdPushDescriptorSet2KHR;
PFN_vkCmdPushDescriptorSetWithTemplate2KHR CmdPushDescriptorSetWithTemplate2KHR;
PFN_vkCmdSetDescriptorBufferOffsets2EXT CmdSetDescriptorBufferOffsets2EXT;
PFN_vkCmdBindDescriptorBufferEmbeddedSamplers2EXT CmdBindDescriptorBufferEmbeddedSamplers2EXT;
// ---- VK_EXT_debug_marker extension commands
PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
@ -717,7 +725,7 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetShaderInfoAMD GetShaderInfoAMD;
// ---- VK_NV_external_memory_win32 extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetMemoryWin32HandleNV GetMemoryWin32HandleNV;
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -740,6 +748,8 @@ typedef struct VkLayerDispatchTable_ {
// ---- VK_EXT_discard_rectangles extension commands
PFN_vkCmdSetDiscardRectangleEXT CmdSetDiscardRectangleEXT;
PFN_vkCmdSetDiscardRectangleEnableEXT CmdSetDiscardRectangleEnableEXT;
PFN_vkCmdSetDiscardRectangleModeEXT CmdSetDiscardRectangleModeEXT;
// ---- VK_EXT_hdr_metadata extension commands
PFN_vkSetHdrMetadataEXT SetHdrMetadataEXT;
@ -755,13 +765,36 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT;
// ---- VK_ANDROID_external_memory_android_hardware_buffer extension commands
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
PFN_vkGetAndroidHardwareBufferPropertiesANDROID GetAndroidHardwareBufferPropertiesANDROID;
#endif // VK_USE_PLATFORM_ANDROID_KHR
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
PFN_vkGetMemoryAndroidHardwareBufferANDROID GetMemoryAndroidHardwareBufferANDROID;
#endif // VK_USE_PLATFORM_ANDROID_KHR
// ---- VK_AMDX_shader_enqueue extension commands
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkCreateExecutionGraphPipelinesAMDX CreateExecutionGraphPipelinesAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkGetExecutionGraphPipelineScratchSizeAMDX GetExecutionGraphPipelineScratchSizeAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkGetExecutionGraphPipelineNodeIndexAMDX GetExecutionGraphPipelineNodeIndexAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkCmdInitializeGraphScratchMemoryAMDX CmdInitializeGraphScratchMemoryAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkCmdDispatchGraphAMDX CmdDispatchGraphAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkCmdDispatchGraphIndirectAMDX CmdDispatchGraphIndirectAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
#if defined(VK_ENABLE_BETA_EXTENSIONS)
PFN_vkCmdDispatchGraphIndirectCountAMDX CmdDispatchGraphIndirectCountAMDX;
#endif // VK_ENABLE_BETA_EXTENSIONS
// ---- VK_EXT_sample_locations extension commands
PFN_vkCmdSetSampleLocationsEXT CmdSetSampleLocationsEXT;
@ -809,6 +842,7 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCmdDrawMeshTasksIndirectCountNV CmdDrawMeshTasksIndirectCountNV;
// ---- VK_NV_scissor_exclusive extension commands
PFN_vkCmdSetExclusiveScissorEnableNV CmdSetExclusiveScissorEnableNV;
PFN_vkCmdSetExclusiveScissorNV CmdSetExclusiveScissorNV;
// ---- VK_NV_device_diagnostic_checkpoints extension commands
@ -833,13 +867,13 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetBufferDeviceAddressEXT GetBufferDeviceAddressEXT;
// ---- VK_EXT_full_screen_exclusive extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkAcquireFullScreenExclusiveModeEXT AcquireFullScreenExclusiveModeEXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkReleaseFullScreenExclusiveModeEXT ReleaseFullScreenExclusiveModeEXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
@ -863,6 +897,16 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCmdSetStencilTestEnableEXT CmdSetStencilTestEnableEXT;
PFN_vkCmdSetStencilOpEXT CmdSetStencilOpEXT;
// ---- VK_EXT_host_image_copy extension commands
PFN_vkCopyMemoryToImageEXT CopyMemoryToImageEXT;
PFN_vkCopyImageToMemoryEXT CopyImageToMemoryEXT;
PFN_vkCopyImageToImageEXT CopyImageToImageEXT;
PFN_vkTransitionImageLayoutEXT TransitionImageLayoutEXT;
PFN_vkGetImageSubresourceLayout2EXT GetImageSubresourceLayout2EXT;
// ---- VK_EXT_swapchain_maintenance1 extension commands
PFN_vkReleaseSwapchainImagesEXT ReleaseSwapchainImagesEXT;
// ---- VK_NV_device_generated_commands extension commands
PFN_vkGetGeneratedCommandsMemoryRequirementsNV GetGeneratedCommandsMemoryRequirementsNV;
PFN_vkCmdPreprocessGeneratedCommandsNV CmdPreprocessGeneratedCommandsNV;
@ -871,23 +915,44 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCreateIndirectCommandsLayoutNV CreateIndirectCommandsLayoutNV;
PFN_vkDestroyIndirectCommandsLayoutNV DestroyIndirectCommandsLayoutNV;
// ---- VK_EXT_depth_bias_control extension commands
PFN_vkCmdSetDepthBias2EXT CmdSetDepthBias2EXT;
// ---- VK_EXT_private_data extension commands
PFN_vkCreatePrivateDataSlotEXT CreatePrivateDataSlotEXT;
PFN_vkDestroyPrivateDataSlotEXT DestroyPrivateDataSlotEXT;
PFN_vkSetPrivateDataEXT SetPrivateDataEXT;
PFN_vkGetPrivateDataEXT GetPrivateDataEXT;
// ---- VK_NV_cuda_kernel_launch extension commands
PFN_vkCreateCudaModuleNV CreateCudaModuleNV;
PFN_vkGetCudaModuleCacheNV GetCudaModuleCacheNV;
PFN_vkCreateCudaFunctionNV CreateCudaFunctionNV;
PFN_vkDestroyCudaModuleNV DestroyCudaModuleNV;
PFN_vkDestroyCudaFunctionNV DestroyCudaFunctionNV;
PFN_vkCmdCudaLaunchKernelNV CmdCudaLaunchKernelNV;
// ---- VK_EXT_metal_objects extension commands
#ifdef VK_USE_PLATFORM_METAL_EXT
#if defined(VK_USE_PLATFORM_METAL_EXT)
PFN_vkExportMetalObjectsEXT ExportMetalObjectsEXT;
#endif // VK_USE_PLATFORM_METAL_EXT
// ---- VK_EXT_descriptor_buffer extension commands
PFN_vkGetDescriptorSetLayoutSizeEXT GetDescriptorSetLayoutSizeEXT;
PFN_vkGetDescriptorSetLayoutBindingOffsetEXT GetDescriptorSetLayoutBindingOffsetEXT;
PFN_vkGetDescriptorEXT GetDescriptorEXT;
PFN_vkCmdBindDescriptorBuffersEXT CmdBindDescriptorBuffersEXT;
PFN_vkCmdSetDescriptorBufferOffsetsEXT CmdSetDescriptorBufferOffsetsEXT;
PFN_vkCmdBindDescriptorBufferEmbeddedSamplersEXT CmdBindDescriptorBufferEmbeddedSamplersEXT;
PFN_vkGetBufferOpaqueCaptureDescriptorDataEXT GetBufferOpaqueCaptureDescriptorDataEXT;
PFN_vkGetImageOpaqueCaptureDescriptorDataEXT GetImageOpaqueCaptureDescriptorDataEXT;
PFN_vkGetImageViewOpaqueCaptureDescriptorDataEXT GetImageViewOpaqueCaptureDescriptorDataEXT;
PFN_vkGetSamplerOpaqueCaptureDescriptorDataEXT GetSamplerOpaqueCaptureDescriptorDataEXT;
PFN_vkGetAccelerationStructureOpaqueCaptureDescriptorDataEXT GetAccelerationStructureOpaqueCaptureDescriptorDataEXT;
// ---- VK_NV_fragment_shading_rate_enums extension commands
PFN_vkCmdSetFragmentShadingRateEnumNV CmdSetFragmentShadingRateEnumNV;
// ---- VK_EXT_image_compression_control extension commands
PFN_vkGetImageSubresourceLayout2EXT GetImageSubresourceLayout2EXT;
// ---- VK_EXT_device_fault extension commands
PFN_vkGetDeviceFaultInfoEXT GetDeviceFaultInfoEXT;
@ -895,35 +960,35 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCmdSetVertexInputEXT CmdSetVertexInputEXT;
// ---- VK_FUCHSIA_external_memory extension commands
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkGetMemoryZirconHandleFUCHSIA GetMemoryZirconHandleFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkGetMemoryZirconHandlePropertiesFUCHSIA GetMemoryZirconHandlePropertiesFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
// ---- VK_FUCHSIA_external_semaphore extension commands
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkImportSemaphoreZirconHandleFUCHSIA ImportSemaphoreZirconHandleFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkGetSemaphoreZirconHandleFUCHSIA GetSemaphoreZirconHandleFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
// ---- VK_FUCHSIA_buffer_collection extension commands
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkCreateBufferCollectionFUCHSIA CreateBufferCollectionFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkSetBufferCollectionImageConstraintsFUCHSIA SetBufferCollectionImageConstraintsFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkSetBufferCollectionBufferConstraintsFUCHSIA SetBufferCollectionBufferConstraintsFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkDestroyBufferCollectionFUCHSIA DestroyBufferCollectionFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkGetBufferCollectionPropertiesFUCHSIA GetBufferCollectionPropertiesFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
@ -970,6 +1035,10 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetDeviceMicromapCompatibilityEXT GetDeviceMicromapCompatibilityEXT;
PFN_vkGetMicromapBuildSizesEXT GetMicromapBuildSizesEXT;
// ---- VK_HUAWEI_cluster_culling_shader extension commands
PFN_vkCmdDrawClusterHUAWEI CmdDrawClusterHUAWEI;
PFN_vkCmdDrawClusterIndirectHUAWEI CmdDrawClusterIndirectHUAWEI;
// ---- VK_EXT_pageable_device_local_memory extension commands
PFN_vkSetDeviceMemoryPriorityEXT SetDeviceMemoryPriorityEXT;
@ -977,6 +1046,19 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkGetDescriptorSetLayoutHostMappingInfoVALVE GetDescriptorSetLayoutHostMappingInfoVALVE;
PFN_vkGetDescriptorSetHostMappingVALVE GetDescriptorSetHostMappingVALVE;
// ---- VK_NV_copy_memory_indirect extension commands
PFN_vkCmdCopyMemoryIndirectNV CmdCopyMemoryIndirectNV;
PFN_vkCmdCopyMemoryToImageIndirectNV CmdCopyMemoryToImageIndirectNV;
// ---- VK_NV_memory_decompression extension commands
PFN_vkCmdDecompressMemoryNV CmdDecompressMemoryNV;
PFN_vkCmdDecompressMemoryIndirectCountNV CmdDecompressMemoryIndirectCountNV;
// ---- VK_NV_device_generated_commands_compute extension commands
PFN_vkGetPipelineIndirectMemoryRequirementsNV GetPipelineIndirectMemoryRequirementsNV;
PFN_vkCmdUpdatePipelineIndirectBufferNV CmdUpdatePipelineIndirectBufferNV;
PFN_vkGetPipelineIndirectDeviceAddressNV GetPipelineIndirectDeviceAddressNV;
// ---- VK_EXT_extended_dynamic_state3 extension commands
PFN_vkCmdSetTessellationDomainOriginEXT CmdSetTessellationDomainOriginEXT;
PFN_vkCmdSetDepthClampEnableEXT CmdSetDepthClampEnableEXT;
@ -1020,28 +1102,30 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkBindOpticalFlowSessionImageNV BindOpticalFlowSessionImageNV;
PFN_vkCmdOpticalFlowExecuteNV CmdOpticalFlowExecuteNV;
// ---- VK_EXT_shader_object extension commands
PFN_vkCreateShadersEXT CreateShadersEXT;
PFN_vkDestroyShaderEXT DestroyShaderEXT;
PFN_vkGetShaderBinaryDataEXT GetShaderBinaryDataEXT;
PFN_vkCmdBindShadersEXT CmdBindShadersEXT;
// ---- VK_QCOM_tile_properties extension commands
PFN_vkGetFramebufferTilePropertiesQCOM GetFramebufferTilePropertiesQCOM;
PFN_vkGetDynamicRenderingTilePropertiesQCOM GetDynamicRenderingTilePropertiesQCOM;
// ---- VK_OHOS_native_buffer extension commands
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkGetSwapchainGrallocUsageOHOS GetSwapchainGrallocUsageOHOS;
#endif // VK_USE_PLATFORM_OHOS
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkAcquireImageOHOS AcquireImageOHOS;
#endif // VK_USE_PLATFORM_OHOS
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkQueueSignalReleaseImageOHOS QueueSignalReleaseImageOHOS;
#endif // VK_USE_PLATFORM_OHOS
// ---- VK_NV_low_latency2 extension commands
PFN_vkSetLatencySleepModeNV SetLatencySleepModeNV;
PFN_vkLatencySleepNV LatencySleepNV;
PFN_vkSetLatencyMarkerNV SetLatencyMarkerNV;
PFN_vkGetLatencyTimingsNV GetLatencyTimingsNV;
PFN_vkQueueNotifyOutOfBandNV QueueNotifyOutOfBandNV;
// ---- VK_OHOS_external_memory extension commands
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkGetNativeBufferPropertiesOHOS GetNativeBufferPropertiesOHOS;
#endif // VK_USE_PLATFORM_OHOS
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkGetMemoryNativeBufferOHOS GetMemoryNativeBufferOHOS;
#endif // VK_USE_PLATFORM_OHOS
// ---- VK_EXT_attachment_feedback_loop_dynamic_state extension commands
PFN_vkCmdSetAttachmentFeedbackLoopEnableEXT CmdSetAttachmentFeedbackLoopEnableEXT;
// ---- VK_QNX_external_memory_screen_buffer extension commands
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
PFN_vkGetScreenBufferPropertiesQNX GetScreenBufferPropertiesQNX;
#endif // VK_USE_PLATFORM_SCREEN_QNX
// ---- VK_KHR_acceleration_structure extension commands
PFN_vkCreateAccelerationStructureKHR CreateAccelerationStructureKHR;
@ -1073,6 +1157,25 @@ typedef struct VkLayerDispatchTable_ {
PFN_vkCmdDrawMeshTasksEXT CmdDrawMeshTasksEXT;
PFN_vkCmdDrawMeshTasksIndirectEXT CmdDrawMeshTasksIndirectEXT;
PFN_vkCmdDrawMeshTasksIndirectCountEXT CmdDrawMeshTasksIndirectCountEXT;
// ---- VK_OHOS_native_buffer extension commands
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkGetSwapchainGrallocUsageOHOS GetSwapchainGrallocUsageOHOS;
#endif // VK_USE_PLATFORM_OHOS
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkAcquireImageOHOS AcquireImageOHOS;
#endif // VK_USE_PLATFORM_OHOS
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkQueueSignalReleaseImageOHOS QueueSignalReleaseImageOHOS;
#endif // VK_USE_PLATFORM_OHOS
// ---- VK_OHOS_external_memory extension commands
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkGetNativeBufferPropertiesOHOS GetNativeBufferPropertiesOHOS;
#endif // VK_USE_PLATFORM_OHOS
#ifdef VK_USE_PLATFORM_OHOS
PFN_vkGetMemoryNativeBufferOHOS GetMemoryNativeBufferOHOS;
#endif // VK_USE_PLATFORM_OHOS
} VkLayerDispatchTable;
// clang-format on

File diff suppressed because it is too large Load Diff

View File

@ -5,6 +5,8 @@
* Copyright (c) 2015-2022 The Khronos Group Inc.
* Copyright (c) 2015-2022 Valve Corporation
* Copyright (c) 2015-2022 LunarG, Inc.
* Copyright (c) 2021-2023 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.
@ -22,6 +24,7 @@
* Author: Mark Young <marky@lunarg.com>
*/
// clang-format off
#pragma once
// Structures defined externally, but used here
@ -45,7 +48,7 @@ void extensions_create_instance(struct loader_instance *ptr_instance, const VkIn
// Extension interception for vkGetDeviceProcAddr function, so we can return
// an appropriate terminator if this is one of those few device commands requiring
// a terminator.
PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *pName);
PFN_vkVoidFunction get_extension_device_proc_terminator(struct loader_device *dev, const char *name, bool* found_name);
// Dispatch table properly filled in with appropriate terminators for the
// supported extensions.
@ -54,8 +57,7 @@ extern const VkLayerInstanceDispatchTable instance_disp;
// Array of extension strings for instance extensions we support.
extern const char *const LOADER_INSTANCE_EXTENSIONS[];
VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_icd_term *icd_term, VkInstance inst,
const PFN_vkGetInstanceProcAddr fp_gipa);
VKAPI_ATTR bool VKAPI_CALL loader_icd_init_entries(struct loader_instance* inst, struct loader_icd_term *icd_term);
// Init Device function pointer dispatch table with core commands
VKAPI_ATTR void VKAPI_CALL loader_init_device_dispatch_table(struct loader_dev_dispatch_table *dev_table, PFN_vkGetDeviceProcAddr gpa,
@ -77,7 +79,7 @@ VKAPI_ATTR void VKAPI_CALL loader_init_instance_extension_dispatch_table(VkLayer
VkInstance inst);
// Device command lookup function
VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table, const char *name);
VKAPI_ATTR void* VKAPI_CALL loader_lookup_device_dispatch_table(const VkLayerDispatchTable *table, const char *name, bool* name_found);
// Instance command lookup function
VKAPI_ATTR void* VKAPI_CALL loader_lookup_instance_dispatch_table(const VkLayerInstanceDispatchTable *table, const char *name,
@ -208,7 +210,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceToolProperties(
// ICD function pointer dispatch table
struct loader_icd_term_dispatch {
// ---- Core 1_0 commands
// ---- Core Vulkan 1.0 commands
PFN_vkCreateInstance CreateInstance;
PFN_vkDestroyInstance DestroyInstance;
PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices;
@ -225,7 +227,7 @@ struct loader_icd_term_dispatch {
PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties;
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties;
// ---- Core 1_1 commands
// ---- Core Vulkan 1.1 commands
PFN_vkEnumerateInstanceVersion EnumerateInstanceVersion;
PFN_vkEnumeratePhysicalDeviceGroups EnumeratePhysicalDeviceGroups;
PFN_vkGetPhysicalDeviceFeatures2 GetPhysicalDeviceFeatures2;
@ -239,7 +241,7 @@ struct loader_icd_term_dispatch {
PFN_vkGetPhysicalDeviceExternalFenceProperties GetPhysicalDeviceExternalFenceProperties;
PFN_vkGetPhysicalDeviceExternalSemaphoreProperties GetPhysicalDeviceExternalSemaphoreProperties;
// ---- Core 1_3 commands
// ---- Core Vulkan 1.3 commands
PFN_vkGetPhysicalDeviceToolProperties GetPhysicalDeviceToolProperties;
// ---- VK_KHR_surface extension commands
@ -250,8 +252,6 @@ struct loader_icd_term_dispatch {
PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR;
// ---- VK_KHR_swapchain extension commands
PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
PFN_vkGetPhysicalDevicePresentRectanglesKHR GetPhysicalDevicePresentRectanglesKHR;
// ---- VK_KHR_display extension commands
@ -263,53 +263,46 @@ struct loader_icd_term_dispatch {
PFN_vkGetDisplayPlaneCapabilitiesKHR GetDisplayPlaneCapabilitiesKHR;
PFN_vkCreateDisplayPlaneSurfaceKHR CreateDisplayPlaneSurfaceKHR;
// ---- VK_KHR_display_swapchain extension commands
PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
// ---- VK_KHR_xlib_surface extension commands
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
PFN_vkCreateXlibSurfaceKHR CreateXlibSurfaceKHR;
#endif // VK_USE_PLATFORM_XLIB_KHR
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
PFN_vkGetPhysicalDeviceXlibPresentationSupportKHR GetPhysicalDeviceXlibPresentationSupportKHR;
#endif // VK_USE_PLATFORM_XLIB_KHR
// ---- VK_KHR_xcb_surface extension commands
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
PFN_vkCreateXcbSurfaceKHR CreateXcbSurfaceKHR;
#endif // VK_USE_PLATFORM_XCB_KHR
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
PFN_vkGetPhysicalDeviceXcbPresentationSupportKHR GetPhysicalDeviceXcbPresentationSupportKHR;
#endif // VK_USE_PLATFORM_XCB_KHR
// ---- VK_KHR_wayland_surface extension commands
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
PFN_vkCreateWaylandSurfaceKHR CreateWaylandSurfaceKHR;
#endif // VK_USE_PLATFORM_WAYLAND_KHR
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR GetPhysicalDeviceWaylandPresentationSupportKHR;
#endif // VK_USE_PLATFORM_WAYLAND_KHR
// ---- VK_KHR_android_surface extension commands
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
PFN_vkCreateAndroidSurfaceKHR CreateAndroidSurfaceKHR;
#endif // VK_USE_PLATFORM_ANDROID_KHR
// ---- VK_KHR_win32_surface extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkCreateWin32SurfaceKHR CreateWin32SurfaceKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetPhysicalDeviceWin32PresentationSupportKHR GetPhysicalDeviceWin32PresentationSupportKHR;
#endif // VK_USE_PLATFORM_WIN32_KHR
// ---- VK_KHR_video_queue extension commands
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkGetPhysicalDeviceVideoCapabilitiesKHR GetPhysicalDeviceVideoCapabilitiesKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
#ifdef VK_ENABLE_BETA_EXTENSIONS
PFN_vkGetPhysicalDeviceVideoFormatPropertiesKHR GetPhysicalDeviceVideoFormatPropertiesKHR;
#endif // VK_ENABLE_BETA_EXTENSIONS
// ---- VK_KHR_get_physical_device_properties2 extension commands
PFN_vkGetPhysicalDeviceFeatures2KHR GetPhysicalDeviceFeatures2KHR;
@ -349,17 +342,22 @@ struct loader_icd_term_dispatch {
// ---- VK_KHR_fragment_shading_rate extension commands
PFN_vkGetPhysicalDeviceFragmentShadingRatesKHR GetPhysicalDeviceFragmentShadingRatesKHR;
// ---- VK_KHR_video_encode_queue extension commands
PFN_vkGetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR GetPhysicalDeviceVideoEncodeQualityLevelPropertiesKHR;
// ---- VK_KHR_cooperative_matrix extension commands
PFN_vkGetPhysicalDeviceCooperativeMatrixPropertiesKHR GetPhysicalDeviceCooperativeMatrixPropertiesKHR;
// ---- VK_KHR_calibrated_timestamps extension commands
PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsKHR GetPhysicalDeviceCalibrateableTimeDomainsKHR;
// ---- VK_EXT_debug_report extension commands
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT;
PFN_vkDebugReportMessageEXT DebugReportMessageEXT;
// ---- VK_EXT_debug_marker extension commands
PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
// ---- VK_GGP_stream_descriptor_surface extension commands
#ifdef VK_USE_PLATFORM_GGP
#if defined(VK_USE_PLATFORM_GGP)
PFN_vkCreateStreamDescriptorSurfaceGGP CreateStreamDescriptorSurfaceGGP;
#endif // VK_USE_PLATFORM_GGP
@ -367,7 +365,7 @@ struct loader_icd_term_dispatch {
PFN_vkGetPhysicalDeviceExternalImageFormatPropertiesNV GetPhysicalDeviceExternalImageFormatPropertiesNV;
// ---- VK_NN_vi_surface extension commands
#ifdef VK_USE_PLATFORM_VI_NN
#if defined(VK_USE_PLATFORM_VI_NN)
PFN_vkCreateViSurfaceNN CreateViSurfaceNN;
#endif // VK_USE_PLATFORM_VI_NN
@ -375,10 +373,10 @@ struct loader_icd_term_dispatch {
PFN_vkReleaseDisplayEXT ReleaseDisplayEXT;
// ---- VK_EXT_acquire_xlib_display extension commands
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
PFN_vkAcquireXlibDisplayEXT AcquireXlibDisplayEXT;
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
#ifdef VK_USE_PLATFORM_XLIB_XRANDR_EXT
#if defined(VK_USE_PLATFORM_XLIB_XRANDR_EXT)
PFN_vkGetRandROutputDisplayEXT GetRandROutputDisplayEXT;
#endif // VK_USE_PLATFORM_XLIB_XRANDR_EXT
@ -386,24 +384,16 @@ struct loader_icd_term_dispatch {
PFN_vkGetPhysicalDeviceSurfaceCapabilities2EXT GetPhysicalDeviceSurfaceCapabilities2EXT;
// ---- VK_MVK_ios_surface extension commands
#ifdef VK_USE_PLATFORM_IOS_MVK
#if defined(VK_USE_PLATFORM_IOS_MVK)
PFN_vkCreateIOSSurfaceMVK CreateIOSSurfaceMVK;
#endif // VK_USE_PLATFORM_IOS_MVK
// ---- VK_MVK_macos_surface extension commands
#ifdef VK_USE_PLATFORM_MACOS_MVK
#if defined(VK_USE_PLATFORM_MACOS_MVK)
PFN_vkCreateMacOSSurfaceMVK CreateMacOSSurfaceMVK;
#endif // VK_USE_PLATFORM_MACOS_MVK
// ---- VK_EXT_debug_utils extension commands
PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT;
PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT;
PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT;
PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT;
PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT;
PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT;
PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT;
PFN_vkCreateDebugUtilsMessengerEXT CreateDebugUtilsMessengerEXT;
PFN_vkDestroyDebugUtilsMessengerEXT DestroyDebugUtilsMessengerEXT;
PFN_vkSubmitDebugUtilsMessageEXT SubmitDebugUtilsMessageEXT;
@ -415,12 +405,12 @@ struct loader_icd_term_dispatch {
PFN_vkGetPhysicalDeviceCalibrateableTimeDomainsEXT GetPhysicalDeviceCalibrateableTimeDomainsEXT;
// ---- VK_FUCHSIA_imagepipe_surface extension commands
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
PFN_vkCreateImagePipeSurfaceFUCHSIA CreateImagePipeSurfaceFUCHSIA;
#endif // VK_USE_PLATFORM_FUCHSIA
// ---- VK_EXT_metal_surface extension commands
#ifdef VK_USE_PLATFORM_METAL_EXT
#if defined(VK_USE_PLATFORM_METAL_EXT)
PFN_vkCreateMetalSurfaceEXT CreateMetalSurfaceEXT;
#endif // VK_USE_PLATFORM_METAL_EXT
@ -434,12 +424,9 @@ struct loader_icd_term_dispatch {
PFN_vkGetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV GetPhysicalDeviceSupportedFramebufferMixedSamplesCombinationsNV;
// ---- VK_EXT_full_screen_exclusive extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetPhysicalDeviceSurfacePresentModes2EXT GetPhysicalDeviceSurfacePresentModes2EXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
// ---- VK_EXT_headless_surface extension commands
PFN_vkCreateHeadlessSurfaceEXT CreateHeadlessSurfaceEXT;
@ -449,26 +436,26 @@ struct loader_icd_term_dispatch {
PFN_vkGetDrmDisplayEXT GetDrmDisplayEXT;
// ---- VK_NV_acquire_winrt_display extension commands
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkAcquireWinrtDisplayNV AcquireWinrtDisplayNV;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
PFN_vkGetWinrtDisplayNV GetWinrtDisplayNV;
#endif // VK_USE_PLATFORM_WIN32_KHR
// ---- VK_EXT_directfb_surface extension commands
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
PFN_vkCreateDirectFBSurfaceEXT CreateDirectFBSurfaceEXT;
#endif // VK_USE_PLATFORM_DIRECTFB_EXT
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
PFN_vkGetPhysicalDeviceDirectFBPresentationSupportEXT GetPhysicalDeviceDirectFBPresentationSupportEXT;
#endif // VK_USE_PLATFORM_DIRECTFB_EXT
// ---- VK_QNX_screen_surface extension commands
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
PFN_vkCreateScreenSurfaceQNX CreateScreenSurfaceQNX;
#endif // VK_USE_PLATFORM_SCREEN_QNX
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
PFN_vkGetPhysicalDeviceScreenPresentationSupportQNX GetPhysicalDeviceScreenPresentationSupportQNX;
#endif // VK_USE_PLATFORM_SCREEN_QNX
@ -496,4 +483,30 @@ struct loader_instance_extension_enables {
uint8_t ext_acquire_drm_display;
};
// Functions that required a terminator need to have a separate dispatch table which contains their corresponding
// device function. This is used in the terminators themselves.
struct loader_device_terminator_dispatch {
// ---- VK_KHR_swapchain extension commands
PFN_vkCreateSwapchainKHR CreateSwapchainKHR;
PFN_vkGetDeviceGroupSurfacePresentModesKHR GetDeviceGroupSurfacePresentModesKHR;
// ---- VK_KHR_display_swapchain extension commands
PFN_vkCreateSharedSwapchainsKHR CreateSharedSwapchainsKHR;
// ---- VK_EXT_debug_marker extension commands
PFN_vkDebugMarkerSetObjectTagEXT DebugMarkerSetObjectTagEXT;
PFN_vkDebugMarkerSetObjectNameEXT DebugMarkerSetObjectNameEXT;
// ---- VK_EXT_debug_utils extension commands
PFN_vkSetDebugUtilsObjectNameEXT SetDebugUtilsObjectNameEXT;
PFN_vkSetDebugUtilsObjectTagEXT SetDebugUtilsObjectTagEXT;
PFN_vkQueueBeginDebugUtilsLabelEXT QueueBeginDebugUtilsLabelEXT;
PFN_vkQueueEndDebugUtilsLabelEXT QueueEndDebugUtilsLabelEXT;
PFN_vkQueueInsertDebugUtilsLabelEXT QueueInsertDebugUtilsLabelEXT;
PFN_vkCmdBeginDebugUtilsLabelEXT CmdBeginDebugUtilsLabelEXT;
PFN_vkCmdEndDebugUtilsLabelEXT CmdEndDebugUtilsLabelEXT;
PFN_vkCmdInsertDebugUtilsLabelEXT CmdInsertDebugUtilsLabelEXT;
#if defined(VK_USE_PLATFORM_WIN32_KHR)
// ---- VK_EXT_full_screen_exclusive extension commands
PFN_vkGetDeviceGroupSurfacePresentModes2EXT GetDeviceGroupSurfacePresentModes2EXT;
#endif // VK_USE_PLATFORM_WIN32_KHR
};
// clang-format on

View File

@ -1,3 +1,4 @@
// clang-format off
// *** THIS FILE IS GENERATED - DO NOT EDIT ***
// See helper_file_generator.py for modifications
@ -80,11 +81,14 @@ typedef enum VulkanObjectType {
kVulkanObjectTypeAccelerationStructureNV = 41,
kVulkanObjectTypePerformanceConfigurationINTEL = 42,
kVulkanObjectTypeIndirectCommandsLayoutNV = 43,
kVulkanObjectTypeBufferCollectionFUCHSIA = 44,
kVulkanObjectTypeMicromapEXT = 45,
kVulkanObjectTypeOpticalFlowSessionNV = 46,
kVulkanObjectTypeAccelerationStructureKHR = 47,
kVulkanObjectTypeMax = 48,
kVulkanObjectTypeCudaModuleNV = 44,
kVulkanObjectTypeCudaFunctionNV = 45,
kVulkanObjectTypeAccelerationStructureKHR = 46,
kVulkanObjectTypeBufferCollectionFUCHSIA = 47,
kVulkanObjectTypeMicromapEXT = 48,
kVulkanObjectTypeOpticalFlowSessionNV = 49,
kVulkanObjectTypeShaderEXT = 50,
kVulkanObjectTypeMax = 51,
// Aliases for backwards compatibilty of "promoted" types
kVulkanObjectTypeDescriptorUpdateTemplateKHR = kVulkanObjectTypeDescriptorUpdateTemplate,
kVulkanObjectTypeSamplerYcbcrConversionKHR = kVulkanObjectTypeSamplerYcbcrConversion,
@ -137,10 +141,13 @@ static const char * const object_string[kVulkanObjectTypeMax] = {
"AccelerationStructureNV",
"PerformanceConfigurationINTEL",
"IndirectCommandsLayoutNV",
"CudaModuleNV",
"CudaFunctionNV",
"AccelerationStructureKHR",
"BufferCollectionFUCHSIA",
"MicromapEXT",
"OpticalFlowSessionNV",
"AccelerationStructureKHR",
"ShaderEXT",
};
// Helper array to get Vulkan VK_EXT_debug_report object type enum from the internal layers version
@ -189,10 +196,13 @@ const VkDebugReportObjectTypeEXT get_debug_report_enum[] = {
VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT, // kVulkanObjectTypeAccelerationStructureNV
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypePerformanceConfigurationINTEL
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeIndirectCommandsLayoutNV
VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV_EXT, // kVulkanObjectTypeCudaModuleNV
VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV_EXT, // kVulkanObjectTypeCudaFunctionNV
VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT, // kVulkanObjectTypeAccelerationStructureKHR
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT, // kVulkanObjectTypeBufferCollectionFUCHSIA
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeMicromapEXT
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeOpticalFlowSessionNV
VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR_EXT, // kVulkanObjectTypeAccelerationStructureKHR
VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, // kVulkanObjectTypeShaderEXT
};
// Helper array to get Official Vulkan VkObjectType enum from the internal layers version
@ -241,10 +251,13 @@ const VkObjectType get_object_type_enum[] = {
VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV, // kVulkanObjectTypeAccelerationStructureNV
VK_OBJECT_TYPE_PERFORMANCE_CONFIGURATION_INTEL, // kVulkanObjectTypePerformanceConfigurationINTEL
VK_OBJECT_TYPE_INDIRECT_COMMANDS_LAYOUT_NV, // kVulkanObjectTypeIndirectCommandsLayoutNV
VK_OBJECT_TYPE_CUDA_MODULE_NV, // kVulkanObjectTypeCudaModuleNV
VK_OBJECT_TYPE_CUDA_FUNCTION_NV, // kVulkanObjectTypeCudaFunctionNV
VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, // kVulkanObjectTypeAccelerationStructureKHR
VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA, // kVulkanObjectTypeBufferCollectionFUCHSIA
VK_OBJECT_TYPE_MICROMAP_EXT, // kVulkanObjectTypeMicromapEXT
VK_OBJECT_TYPE_OPTICAL_FLOW_SESSION_NV, // kVulkanObjectTypeOpticalFlowSessionNV
VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_KHR, // kVulkanObjectTypeAccelerationStructureKHR
VK_OBJECT_TYPE_SHADER_EXT, // kVulkanObjectTypeShaderEXT
};
// Helper function to convert from VkDebugReportObjectTypeEXT to VkObjectType
@ -331,6 +344,10 @@ static inline VkObjectType convertDebugReportObjectToCoreObject(VkDebugReportObj
return VK_OBJECT_TYPE_VALIDATION_CACHE_EXT;
} else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT) {
return VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV;
} else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV_EXT) {
return VK_OBJECT_TYPE_CUDA_MODULE_NV;
} else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV_EXT) {
return VK_OBJECT_TYPE_CUDA_FUNCTION_NV;
} else if (debug_report_obj == VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT) {
return VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA;
}
@ -421,8 +438,13 @@ static inline VkDebugReportObjectTypeEXT convertCoreObjectToDebugReportObject(Vk
return VK_DEBUG_REPORT_OBJECT_TYPE_VALIDATION_CACHE_EXT_EXT;
} else if (core_report_obj == VK_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV) {
return VK_DEBUG_REPORT_OBJECT_TYPE_ACCELERATION_STRUCTURE_NV_EXT;
} else if (core_report_obj == VK_OBJECT_TYPE_CUDA_MODULE_NV) {
return VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_MODULE_NV_EXT;
} else if (core_report_obj == VK_OBJECT_TYPE_CUDA_FUNCTION_NV) {
return VK_DEBUG_REPORT_OBJECT_TYPE_CUDA_FUNCTION_NV_EXT;
} else if (core_report_obj == VK_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA) {
return VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_COLLECTION_FUCHSIA_EXT;
}
return VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT;
}
// clang-format on

View File

@ -1,185 +0,0 @@
/*
*
* Copyright (c) 2014-2021 The Khronos Group Inc.
* Copyright (c) 2014-2021 Valve Corporation
* Copyright (c) 2014-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: Jon Ashburn <jon@lunarg.com>
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: Chia-I Wu <olvaffe@gmail.com>
* Author: Chia-I Wu <olv@lunarg.com>
* Author: Mark Lobodzinski <mark@LunarG.com>
* Author: Lenny Komow <lenny@lunarg.com>
* Author: Charles Giessen <charles@lunarg.com>
*
*/
#include "get_environment.h"
#include "allocation.h"
#include "log.h"
#include "param/sys_param.h"
// Environment variables
#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
bool is_high_integrity() { return geteuid() != getuid() || getegid() != getgid(); }
char *loader_getenv(const char *name, const struct loader_instance *inst) {
#ifdef __OHOS__
CachedHandle g_Handle = CachedParameterCreate(name, "");
int changed = 0;
const char *res = CachedParameterGetChanged(g_Handle, &changed);
loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_INFO_BIT, 0, "loader_getenv name:%s, res:%s", name, res);
if (res == NULL || res[0] == '\0') {
return NULL;
}
return (char *)res;
#else
// No allocation of memory necessary for Linux, but we should at least touch
// the inst pointer to get rid of compiler warnings.
(void)inst;
return getenv(name);
#endif
}
char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
// Apple does not appear to have a secure getenv implementation.
// The main difference between secure getenv and getenv is that secure getenv
// returns NULL if the process is being run with elevated privileges by a normal user.
// The idea is to prevent the reading of malicious environment variables by a process
// that can do damage.
// This algorithm is derived from glibc code that sets an internal
// variable (__libc_enable_secure) if the process is running under setuid or setgid.
return is_high_integrity() ? NULL : loader_getenv(name, inst);
#elif defined(__Fuchsia__)
return loader_getenv(name, inst);
#else
// Linux
char *out;
#if defined(HAVE_SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
(void)inst;
out = secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV) && !defined(USE_UNSAFE_FILE_SEARCH)
(void)inst;
out = __secure_getenv(name);
#else
out = loader_getenv(name, inst);
#if !defined(USE_UNSAFE_FILE_SEARCH)
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
#endif
#endif
return out;
#endif
}
void loader_free_getenv(char *val, const struct loader_instance *inst) {
// No freeing of memory necessary for Linux, but we should at least touch
// the val and inst pointers to get rid of compiler warnings.
(void)val;
(void)inst;
}
#elif defined(WIN32)
bool is_high_integrity() {
HANDLE process_token;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
// Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)];
DWORD buffer_size;
if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer),
&buffer_size) != 0) {
const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer;
const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1);
CloseHandle(process_token);
return integrity_level > SECURITY_MANDATORY_MEDIUM_RID;
}
CloseHandle(process_token);
}
return false;
}
char *loader_getenv(const char *name, const struct loader_instance *inst) {
int name_utf16_size = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
if (name_utf16_size <= 0) {
return NULL;
}
wchar_t *name_utf16 = (wchar_t *)loader_stack_alloc(name_utf16_size * sizeof(wchar_t));
if (MultiByteToWideChar(CP_UTF8, 0, name, -1, name_utf16, name_utf16_size) != name_utf16_size) {
return NULL;
}
DWORD val_size = GetEnvironmentVariableW(name_utf16, NULL, 0);
// val_size DOES include the null terminator, so for any set variable
// will always be at least 1. If it's 0, the variable wasn't set.
if (val_size == 0) {
return NULL;
}
wchar_t *val = (wchar_t *)loader_stack_alloc(val_size * sizeof(wchar_t));
if (GetEnvironmentVariableW(name_utf16, val, val_size) != val_size - 1) {
return NULL;
}
int val_utf8_size = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0, NULL, NULL);
if (val_utf8_size <= 0) {
return NULL;
}
char *val_utf8 = (char *)loader_instance_heap_alloc(inst, val_utf8_size * sizeof(char), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (val_utf8 == NULL) {
return NULL;
}
if (WideCharToMultiByte(CP_UTF8, 0, val, -1, val_utf8, val_utf8_size, NULL, NULL) != val_utf8_size) {
loader_instance_heap_free(inst, val_utf8);
return NULL;
}
return val_utf8;
}
char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
#if !defined(USE_UNSAFE_FILE_SEARCH)
if (is_high_integrity()) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"Loader is running with elevated permissions. Environment variable %s will be ignored", name);
return NULL;
}
#endif
return loader_getenv(name, inst);
}
void loader_free_getenv(char *val, const struct loader_instance *inst) { loader_instance_heap_free(inst, (void *)val); }
#else
char *loader_getenv(const char *name, const struct loader_instance *inst) {
// stub func
(void)inst;
(void)name;
return NULL;
}
void loader_free_getenv(char *val, const struct loader_instance *inst) {
// stub func
(void)val;
(void)inst;
}
#endif

View File

@ -278,17 +278,3 @@ void *globalGetProcAddr(const char *name) {
return NULL;
}
void *loader_non_passthrough_gdpa(const char *name) {
if (!name || name[0] != 'v' || name[1] != 'k') return NULL;
name += 2;
if (!strcmp(name, "GetDeviceProcAddr")) return vkGetDeviceProcAddr;
if (!strcmp(name, "DestroyDevice")) return vkDestroyDevice;
if (!strcmp(name, "GetDeviceQueue")) return vkGetDeviceQueue;
if (!strcmp(name, "GetDeviceQueue2")) return vkGetDeviceQueue2;
if (!strcmp(name, "AllocateCommandBuffers")) return vkAllocateCommandBuffers;
return NULL;
}

View File

@ -27,5 +27,3 @@
void *trampoline_get_proc_addr(struct loader_instance *inst, const char *funcName);
void *globalGetProcAddr(const char *name);
void *loader_non_passthrough_gdpa(const char *name);

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,8 @@
/*
*
* Copyright (c) 2014-2022 The Khronos Group Inc.
* Copyright (c) 2014-2022 Valve Corporation
* Copyright (c) 2014-2022 LunarG, Inc.
* Copyright (c) 2014-2023 The Khronos Group Inc.
* Copyright (c) 2014-2023 Valve Corporation
* Copyright (c) 2014-2023 LunarG, Inc.
* Copyright (C) 2015 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
@ -30,6 +30,7 @@
#pragma once
#include "loader_common.h"
#include "cJSON.h"
// Declare the once_init variable
LOADER_PLATFORM_THREAD_ONCE_EXTERN_DEFINITION(once_init)
@ -68,7 +69,7 @@ static inline struct loader_instance_dispatch_table *loader_get_instance_dispatc
}
static inline void loader_init_dispatch(void *obj, const void *data) {
#ifdef DEBUG
#if defined(DEBUG)
assert(valid_loader_magic_value(obj) &&
"Incompatible ICD, first dword must be initialized to "
"ICD_LOADER_MAGIC. See loader/README.md for details.");
@ -80,7 +81,6 @@ static inline void loader_init_dispatch(void *obj, const void *data) {
// Global variables used across files
extern struct loader_struct loader;
extern loader_platform_thread_mutex loader_lock;
extern loader_platform_thread_mutex loader_json_lock;
extern loader_platform_thread_mutex loader_preload_icd_lock;
extern loader_platform_thread_mutex loader_global_instance_list_lock;
@ -91,58 +91,89 @@ VkResult loader_validate_layers(const struct loader_instance *inst, const uint32
VkResult loader_validate_instance_extensions(struct loader_instance *inst, const struct loader_extension_list *icd_exts,
const struct loader_layer_list *instance_layer,
const struct loader_envvar_all_filters *layer_filters,
const VkInstanceCreateInfo *pCreateInfo);
void loader_initialize(void);
void loader_release(void);
void loader_preload_icds(void);
void loader_unload_preloaded_icds(void);
VkResult loader_init_library_list(struct loader_layer_list *instance_layers, loader_platform_dl_handle **libs);
// Allocate a new string able to hold source_str and place it in dest_str
VkResult loader_copy_to_new_str(const struct loader_instance *inst, const char *source_str, char **dest_str);
// Allocate a loader_string_list with enough space for allocated_count strings inside of it
VkResult create_string_list(const struct loader_instance *inst, uint32_t allocated_count, struct loader_string_list *string_list);
// Resize if there isn't enough space, then add the string str to the end of the loader_string_list
// This function takes ownership of the str passed in - but only when it succeeds
VkResult append_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, char *str);
// Resize if there isn't enough space, then copy the string str to a new string the end of the loader_string_list
// This function does not take ownership of the string, it merely copies it.
// This function appends a null terminator to the string automatically
// The str_len parameter does not include the null terminator
VkResult copy_str_to_string_list(const struct loader_instance *inst, struct loader_string_list *string_list, const char *str,
size_t str_len);
// Free any string inside of loader_string_list and then free the list itself
void free_string_list(const struct loader_instance *inst, struct loader_string_list *string_list);
VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size);
bool has_vk_extension_property_array(const VkExtensionProperties *vk_ext_prop, const uint32_t count,
const VkExtensionProperties *ext_array);
bool has_vk_extension_property(const VkExtensionProperties *vk_ext_prop, const struct loader_extension_list *ext_list);
// This function takes ownership of layer_property in the case that allocation fails
VkResult loader_append_layer_property(const struct loader_instance *inst, struct loader_layer_list *layer_list,
struct loader_layer_properties *layer_property);
VkResult loader_add_layer_properties(const struct loader_instance *inst, struct loader_layer_list *layer_instance_list, cJSON *json,
bool is_implicit, char *filename);
bool loader_find_layer_name_in_list(const char *name, const struct loader_pointer_layer_list *layer_list);
VkResult loader_add_layer_properties_to_list(const struct loader_instance *inst, struct loader_pointer_layer_list *list,
struct loader_layer_properties *props);
void loader_free_layer_properties(const struct loader_instance *inst, struct loader_layer_properties *layer_properties);
bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters,
const struct loader_layer_properties *prop);
VkResult loader_add_meta_layer(const struct loader_instance *inst, const struct loader_envvar_all_filters *filters,
struct loader_layer_properties *prop, struct loader_pointer_layer_list *target_list,
struct loader_pointer_layer_list *expanded_target_list, const struct loader_layer_list *source_list,
bool *out_found_all_component_layers);
VkResult loader_add_to_ext_list(const struct loader_instance *inst, struct loader_extension_list *ext_list,
uint32_t prop_list_count, const VkExtensionProperties *props);
VkResult loader_add_to_dev_ext_list(const struct loader_instance *inst, struct loader_device_extension_list *ext_list,
const VkExtensionProperties *props, uint32_t entry_count, char **entrys);
VkResult loader_add_device_extensions(const struct loader_instance *inst,
PFN_vkEnumerateDeviceExtensionProperties fpEnumerateDeviceExtensionProperties,
VkPhysicalDevice physical_device, const char *lib_name,
struct loader_extension_list *ext_list);
VkResult loader_init_generic_list(const struct loader_instance *inst, struct loader_generic_list *list_info, size_t element_size);
void loader_destroy_generic_list(const struct loader_instance *inst, struct loader_generic_list *list);
void loader_destroy_layer_list(const struct loader_instance *inst, struct loader_device *device,
struct loader_layer_list *layer_list);
void loader_destroy_pointer_layer_list(const struct loader_instance *inst, struct loader_pointer_layer_list *layer_list);
void loader_delete_layer_list_and_properties(const struct loader_instance *inst, struct loader_layer_list *layer_list);
VkResult loader_add_layer_name_to_list(const struct loader_instance *inst, const char *name, const enum layer_type_flags type_flags,
const struct loader_layer_list *source_list, struct loader_layer_list *target_list,
struct loader_layer_list *expanded_target_list);
void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term,
const VkAllocationCallbacks *pAllocator);
void loader_remove_layer_in_list(const struct loader_instance *inst, struct loader_layer_list *layer_list,
uint32_t layer_to_remove);
VkResult loader_scanned_icd_init(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
void loader_scanned_icd_clear(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list);
VkResult loader_icd_scan(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
bool *skipped_portability_drivers);
void loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
void loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers);
bool loader_implicit_layer_is_enabled(const struct loader_instance *inst, const struct loader_layer_properties *prop);
const VkInstanceCreateInfo *pCreateInfo, bool *skipped_portability_drivers);
void loader_icd_destroy(struct loader_instance *ptr_inst, struct loader_icd_term *icd_term,
const VkAllocationCallbacks *pAllocator);
VkResult loader_scan_for_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers,
const struct loader_envvar_all_filters *layer_filters);
VkResult loader_scan_for_implicit_layers(struct loader_instance *inst, struct loader_layer_list *instance_layers,
const struct loader_envvar_all_filters *layer_filters);
VkResult loader_get_icd_loader_instance_extensions(const struct loader_instance *inst, struct loader_icd_tramp_list *icd_tramp_list,
struct loader_extension_list *inst_exts);
struct loader_icd_term *loader_get_icd_and_device(const void *device, struct loader_device **found_dev, uint32_t *icd_index);
struct loader_instance *loader_get_instance(const VkInstance instance);
void loader_deactivate_layers(const struct loader_instance *instance, struct loader_device *device, struct loader_layer_list *list);
struct loader_device *loader_create_logical_device(const struct loader_instance *inst, const VkAllocationCallbacks *pAllocator);
void loader_add_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
struct loader_device *found_dev);
void loader_remove_logical_device(const struct loader_instance *inst, struct loader_icd_term *icd_term,
struct loader_device *found_dev, const VkAllocationCallbacks *pAllocator);
void loader_add_logical_device(struct loader_icd_term *icd_term, struct loader_device *found_dev);
void loader_remove_logical_device(struct loader_icd_term *icd_term, struct loader_device *found_dev,
const VkAllocationCallbacks *pAllocator);
// NOTE: Outside of loader, this entry-point is only provided for error
// cleanup.
void loader_destroy_logical_device(const struct loader_instance *inst, struct loader_device *dev,
const VkAllocationCallbacks *pAllocator);
void loader_destroy_logical_device(struct loader_device *dev, const VkAllocationCallbacks *pAllocator);
VkResult loader_enable_instance_layers(struct loader_instance *inst, const VkInstanceCreateInfo *pCreateInfo,
const struct loader_layer_list *instance_layers);
const struct loader_layer_list *instance_layers,
const struct loader_envvar_all_filters *layer_filters);
VkResult loader_create_instance_chain(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
struct loader_instance *inst, VkInstance *created_instance);
@ -162,7 +193,7 @@ VkResult loader_create_device_chain(const VkPhysicalDevice pd, const VkDeviceCre
PFN_vkGetDeviceProcAddr *layerNextGDPA);
VkResult loader_validate_device_extensions(struct loader_instance *this_instance,
const struct loader_layer_list *activated_device_layers,
const struct loader_pointer_layer_list *activated_device_layers,
const struct loader_extension_list *icd_exts, const VkDeviceCreateInfo *pCreateInfo);
VkResult setup_loader_tramp_phys_devs(struct loader_instance *inst, uint32_t phys_dev_count, VkPhysicalDevice *phys_devs);
@ -171,7 +202,7 @@ VkResult setup_loader_tramp_phys_dev_groups(struct loader_instance *inst, uint32
VkStringErrorFlags vk_string_validate(const int max_length, const char *char_array);
char *loader_get_next_path(char *path);
VkResult add_data_files(const struct loader_instance *inst, char *search_path, struct loader_data_files *out_files,
VkResult add_data_files(const struct loader_instance *inst, char *search_path, struct loader_string_list *out_files,
bool use_first_found_manifest);
loader_api_version loader_make_version(uint32_t version);
@ -181,10 +212,10 @@ loader_api_version loader_combine_version(uint32_t major, uint32_t minor, uint32
bool loader_check_version_meets_required(loader_api_version required, loader_api_version version);
// Convenience macros for common versions
#ifndef LOADER_VERSION_1_0_0
#if !defined(LOADER_VERSION_1_0_0)
#define LOADER_VERSION_1_0_0 loader_combine_version(1, 0, 0)
#endif
#ifndef LOADER_VERSION_1_1_0
#if !defined(LOADER_VERSION_1_1_0)
#define LOADER_VERSION_1_1_0 loader_combine_version(1, 1, 0)
#endif

View File

@ -1,7 +1,7 @@
//
// Copyright (c) 2014-2022 The Khronos Group Inc.
// Copyright (c) 2014-2022 Valve Corporation
// Copyright (c) 2014-2022 LunarG, Inc.
// Copyright (c) 2014-2024 The Khronos Group Inc.
// Copyright (c) 2014-2024 Valve Corporation
// Copyright (c) 2014-2024 LunarG, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -22,9 +22,10 @@
#include "winres.h"
// All set through CMake
#define VER_FILE_VERSION 1, 0, 1111, 2222
#define VER_FILE_DESCRIPTION_STR "Vulkan Loader - Dev Build"
#define VER_FILE_VERSION_STR "1.0.1111.2222.Dev Build"
#define VER_FILE_VERSION 1, 3, 275, 0
#define VER_FILE_DESCRIPTION_STR "1.3.275.Dev Build"
#define VER_FILE_VERSION_STR "Vulkan Loader - Dev Build"
#define VER_COPYRIGHT_STR "Copyright (C) 2015-2024"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILE_VERSION
@ -46,7 +47,7 @@ BEGIN
BEGIN
VALUE "FileDescription", VER_FILE_DESCRIPTION_STR
VALUE "FileVersion", VER_FILE_VERSION_STR
VALUE "LegalCopyright", "Copyright (C) 2015-2022"
VALUE "LegalCopyright", VER_COPYRIGHT_STR
VALUE "ProductName", "Vulkan Runtime"
VALUE "ProductVersion", VER_FILE_VERSION_STR
END

View File

@ -1,7 +1,7 @@
//
// Copyright (c) 2014-2022 The Khronos Group Inc.
// Copyright (c) 2014-2022 Valve Corporation
// Copyright (c) 2014-2022 LunarG, Inc.
// Copyright (c) 2014-${LOADER_CUR_COPYRIGHT_YEAR} The Khronos Group Inc.
// Copyright (c) 2014-${LOADER_CUR_COPYRIGHT_YEAR} Valve Corporation
// Copyright (c) 2014-${LOADER_CUR_COPYRIGHT_YEAR} LunarG, Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@ -25,6 +25,7 @@
#define VER_FILE_VERSION ${LOADER_VER_FILE_VERSION}
#define VER_FILE_DESCRIPTION_STR ${LOADER_VER_FILE_DESCRIPTION_STR}
#define VER_FILE_VERSION_STR ${LOADER_VER_FILE_VERSION_STR}
#define VER_COPYRIGHT_STR "Copyright (C) 2015-${LOADER_CUR_COPYRIGHT_YEAR}"
VS_VERSION_INFO VERSIONINFO
FILEVERSION VER_FILE_VERSION
@ -46,7 +47,7 @@ BEGIN
BEGIN
VALUE "FileDescription", VER_FILE_DESCRIPTION_STR
VALUE "FileVersion", VER_FILE_VERSION_STR
VALUE "LegalCopyright", "Copyright (C) 2015-2022"
VALUE "LegalCopyright", VER_COPYRIGHT_STR
VALUE "ProductName", "Vulkan Runtime"
VALUE "ProductVersion", VER_FILE_VERSION_STR
END

View File

@ -39,6 +39,8 @@
#include "vk_layer_dispatch_table.h"
#include "vk_loader_extensions.h"
#include "settings.h"
typedef enum VkStringErrorFlagBits {
VK_STRING_ERROR_NONE = 0x00000000,
VK_STRING_ERROR_LENGTH = 0x00000001,
@ -65,6 +67,12 @@ struct loader_generic_list {
void *list;
};
struct loader_string_list {
uint32_t allocated_count;
uint32_t count;
char **list;
};
struct loader_extension_list {
size_t capacity;
uint32_t count;
@ -73,8 +81,7 @@ struct loader_extension_list {
struct loader_dev_ext_props {
VkExtensionProperties props;
uint32_t entrypoint_count;
char **entrypoints;
struct loader_string_list entrypoints;
};
struct loader_device_extension_list {
@ -84,28 +91,20 @@ struct loader_device_extension_list {
};
struct loader_name_value {
char name[MAX_STRING_SIZE];
char value[MAX_STRING_SIZE];
char *name;
char *value;
};
struct loader_layer_functions {
char str_gipa[MAX_STRING_SIZE];
char str_gdpa[MAX_STRING_SIZE];
char str_negotiate_interface[MAX_STRING_SIZE];
char *str_gipa;
char *str_gdpa;
char *str_negotiate_interface;
PFN_vkNegotiateLoaderLayerInterfaceVersion negotiate_layer_interface;
PFN_vkGetInstanceProcAddr get_instance_proc_addr;
PFN_vkGetDeviceProcAddr get_device_proc_addr;
PFN_GetPhysicalDeviceProcAddr get_physical_device_proc_addr;
};
struct loader_override_expiration {
uint16_t year;
uint8_t month;
uint8_t day;
uint8_t hour;
uint8_t minute;
};
// This structure is used to store the json file version in a more manageable way.
typedef struct {
uint16_t major;
@ -121,6 +120,7 @@ enum loader_layer_library_status {
LOADER_LAYER_LIB_ERROR_WRONG_BIT_TYPE = 20,
LOADER_LAYER_LIB_ERROR_FAILED_TO_LOAD = 21,
LOADER_LAYER_LIB_ERROR_OUT_OF_MEMORY = 22,
};
enum layer_type_flags {
@ -132,9 +132,11 @@ enum layer_type_flags {
struct loader_layer_properties {
VkLayerProperties info;
enum layer_type_flags type_flags;
enum loader_settings_layer_control settings_control_value;
uint32_t interface_version; // PFN_vkNegotiateLoaderLayerInterfaceVersion
char manifest_file_name[MAX_STRING_SIZE];
char lib_name[MAX_STRING_SIZE];
char *manifest_file_name;
char *lib_name;
enum loader_layer_library_status lib_status;
loader_platform_dl_handle lib_handle;
struct loader_layer_functions functions;
@ -142,36 +144,40 @@ struct loader_layer_properties {
struct loader_device_extension_list device_extension_list;
struct loader_name_value disable_env_var;
struct loader_name_value enable_env_var;
uint32_t num_component_layers;
char (*component_layer_names)[MAX_STRING_SIZE];
struct loader_string_list component_layer_names;
struct {
char enumerate_instance_extension_properties[MAX_STRING_SIZE];
char enumerate_instance_layer_properties[MAX_STRING_SIZE];
char enumerate_instance_version[MAX_STRING_SIZE];
char *enumerate_instance_extension_properties;
char *enumerate_instance_layer_properties;
char *enumerate_instance_version;
} pre_instance_functions;
uint32_t num_override_paths;
char (*override_paths)[MAX_STRING_SIZE];
struct loader_string_list override_paths;
bool is_override;
bool has_expiration;
struct loader_override_expiration expiration;
bool keep;
uint32_t num_blacklist_layers;
char (*blacklist_layer_names)[MAX_STRING_SIZE];
uint32_t num_app_key_paths;
char (*app_key_paths)[MAX_STRING_SIZE];
struct loader_string_list blacklist_layer_names;
struct loader_string_list app_key_paths;
};
// Stores a list of loader_layer_properties
struct loader_layer_list {
size_t capacity;
uint32_t count;
struct loader_layer_properties *list;
};
// Stores a list of pointers to loader_layer_properties
// Used for app_activated_layer_list and expanded_activated_layer_list
struct loader_pointer_layer_list {
size_t capacity;
uint32_t count;
struct loader_layer_properties **list;
};
typedef VkResult(VKAPI_PTR *PFN_vkDevExt)(VkDevice device);
struct loader_dev_dispatch_table {
VkLayerDispatchTable core_dispatch;
PFN_vkDevExt ext_dispatch[MAX_NUM_UNKNOWN_EXTS];
struct loader_device_terminator_dispatch extension_terminator_dispatch;
};
// per CreateDevice structure
@ -181,16 +187,16 @@ struct loader_device {
VkDevice icd_device; // device object from the icd
struct loader_physical_device_term *phys_dev_term;
// List of activated layers.
// app_ is the version based on exactly what the application asked for.
// This is what must be returned to the application on Enumerate calls.
// expanded_ is the version based on expanding meta-layers into their
// individual component layers. This is what is used internally.
struct loader_layer_list app_activated_layer_list;
struct loader_layer_list expanded_activated_layer_list;
VkAllocationCallbacks alloc_callbacks;
// List of activated device extensions that layers support (but not necessarily the driver which have functions that require
// trampolines to work correctly. EX - vkDebugMarkerSetObjectNameEXT can name wrapped handles like instance, physical device,
// or surface
struct {
bool ext_debug_marker_enabled;
bool ext_debug_utils_enabled;
} layer_extensions;
// List of activated device extensions that have terminators implemented in the loader
struct {
bool khr_swapchain_enabled;
@ -199,9 +205,13 @@ struct loader_device {
bool ext_debug_marker_enabled;
bool ext_debug_utils_enabled;
bool ext_full_screen_exclusive_enabled;
} extensions;
} driver_extensions;
struct loader_device *next;
// Makes vkGetDeviceProcAddr check if core functions are supported by the current app_api_version.
// Only set to true if VK_KHR_maintenance5 is enabled.
bool should_ignore_device_commands_from_newer_version;
};
// Per ICD information
@ -243,6 +253,9 @@ struct loader_instance {
struct loader_instance_dispatch_table *disp; // must be first entry in structure
uint64_t magic; // Should be LOADER_MAGIC_NUMBER
// Store all the terminators for instance functions in case a layer queries one *after* vkCreateInstance
VkLayerInstanceDispatchTable terminator_dispatch;
// Vulkan API version the app is intending to use.
loader_api_version app_api_version;
@ -267,6 +280,8 @@ struct loader_instance {
struct loader_icd_term *icd_terms;
struct loader_icd_tramp_list icd_tramp_list;
// Must store the strings inside loader_instance directly - since the asm code will offset into
// loader_instance to get the function name
uint32_t dev_ext_disp_function_count;
char *dev_ext_disp_functions[MAX_NUM_UNKNOWN_EXTS];
uint32_t phys_dev_ext_disp_function_count;
@ -274,6 +289,8 @@ struct loader_instance {
struct loader_msg_callback_map_entry *icd_msg_callback_map;
struct loader_string_list enabled_layer_names;
struct loader_layer_list instance_layer_list;
bool override_layer_present;
@ -282,68 +299,71 @@ struct loader_instance {
// This is what must be returned to the application on Enumerate calls.
// expanded_ is the version based on expanding meta-layers into their
// individual component layers. This is what is used internally.
struct loader_layer_list app_activated_layer_list;
struct loader_layer_list expanded_activated_layer_list;
struct loader_pointer_layer_list app_activated_layer_list;
struct loader_pointer_layer_list expanded_activated_layer_list;
VkInstance instance; // layers/ICD instance returned to trampoline
struct loader_extension_list ext_list; // icds and loaders extensions
struct loader_instance_extension_enables enabled_known_extensions;
// Stores debug callbacks - used in the log
VkLayerDbgFunctionNode *DbgFunctionHead;
// Stores the debug callbacks set during instance creation
// These are kept separate because they aren't to be used outside of instance creation and destruction
// So they are swapped out at the end of instance creation and swapped in at instance destruction
VkLayerDbgFunctionNode *InstanceCreationDeletionDebugFunctionHead;
// Stores debug callbacks - used in the log.
VkLayerDbgFunctionNode *current_dbg_function_head; // Current head
VkLayerDbgFunctionNode *instance_only_dbg_function_head; // Only used for instance create/destroy
VkAllocationCallbacks alloc_callbacks;
// Set to true after vkCreateInstance has returned - necessary for loader_gpa_instance_terminator()
bool instance_finished_creation;
loader_settings settings;
bool portability_enumeration_enabled;
bool portability_enumeration_flag_bit_set;
bool portability_enumeration_extension_enabled;
bool wsi_surface_enabled;
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
bool wsi_win32_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
bool wsi_wayland_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
bool wsi_xcb_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
bool wsi_xlib_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
bool wsi_directfb_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
bool wsi_android_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_OHOS
#if defined(VK_USE_PLATFORM_OHOS)
bool wsi_ohos_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_MACOS_MVK
#if defined(VK_USE_PLATFORM_MACOS_MVK)
bool wsi_macos_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_IOS_MVK
#if defined(VK_USE_PLATFORM_IOS_MVK)
bool wsi_ios_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_GGP
#if defined(VK_USE_PLATFORM_GGP)
bool wsi_ggp_surface_enabled;
#endif
bool wsi_headless_surface_enabled;
#if defined(VK_USE_PLATFORM_METAL_EXT)
bool wsi_metal_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
bool wsi_imagepipe_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
bool wsi_screen_surface_enabled;
#endif
#ifdef VK_USE_PLATFORM_VI_NN
#if defined(VK_USE_PLATFORM_VI_NN)
bool wsi_vi_surface_enabled;
#endif
bool wsi_display_enabled;
@ -384,9 +404,9 @@ struct loader_physical_device_term {
VkPhysicalDevice phys_dev; // object from ICD
};
#ifdef LOADER_ENABLE_LINUX_SORT
// Structure for storing the relevent device information for selecting a device.
// NOTE: Needs to be defined here so we can store this content in the term structrue
#if defined(LOADER_ENABLE_LINUX_SORT)
// Structure for storing the relevant device information for selecting a device.
// NOTE: Needs to be defined here so we can store this content in the term structure
// for quicker sorting.
struct LinuxSortedDeviceInfo {
// Associated Vulkan Physical Device
@ -417,7 +437,7 @@ struct loader_physical_device_group_term {
struct loader_icd_term *this_icd_term;
uint8_t icd_index;
VkPhysicalDeviceGroupProperties group_props;
#ifdef LOADER_ENABLE_LINUX_SORT
#if defined(LOADER_ENABLE_LINUX_SORT)
struct LinuxSortedDeviceInfo internal_device_info[VK_MAX_DEVICE_GROUP_SIZE];
#endif // LOADER_ENABLE_LINUX_SORT
};
@ -447,20 +467,49 @@ enum loader_data_files_type {
LOADER_DATA_FILE_NUM_TYPES // Not a real field, used for possible loop terminator
};
struct loader_data_files {
uint32_t count;
uint32_t alloc_count;
char **filename_list;
};
struct loader_phys_dev_per_icd {
struct loader_icd_physical_devices {
uint32_t device_count;
VkPhysicalDevice *physical_devices;
uint32_t icd_index;
struct loader_icd_term *icd_term;
#if defined(WIN32)
LUID windows_adapter_luid;
#endif
};
struct loader_msg_callback_map_entry {
VkDebugReportCallbackEXT icd_obj;
VkDebugReportCallbackEXT loader_obj;
};
typedef enum loader_filter_string_type {
FILTER_STRING_FULLNAME = 0,
FILTER_STRING_SUBSTRING,
FILTER_STRING_PREFIX,
FILTER_STRING_SUFFIX,
FILTER_STRING_SPECIAL,
} loader_filter_string_type;
struct loader_envvar_filter_value {
char value[VK_MAX_EXTENSION_NAME_SIZE];
size_t length;
loader_filter_string_type type;
};
#define MAX_ADDITIONAL_FILTERS 16
struct loader_envvar_filter {
uint32_t count;
struct loader_envvar_filter_value filters[MAX_ADDITIONAL_FILTERS];
};
struct loader_envvar_disable_layers_filter {
struct loader_envvar_filter additional_filters;
bool disable_all;
bool disable_all_implicit;
bool disable_all_explicit;
};
struct loader_envvar_all_filters {
struct loader_envvar_filter enable_filter;
struct loader_envvar_disable_layers_filter disable_filter;
struct loader_envvar_filter allow_filter;
};

577
loader/loader_environment.c Normal file
View File

@ -0,0 +1,577 @@
/*
*
* Copyright (c) 2014-2023 The Khronos Group Inc.
* Copyright (c) 2014-2023 Valve Corporation
* Copyright (c) 2014-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.
*
* Author: Jon Ashburn <jon@lunarg.com>
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: Chia-I Wu <olvaffe@gmail.com>
* Author: Chia-I Wu <olv@lunarg.com>
* Author: Mark Lobodzinski <mark@LunarG.com>
* Author: Lenny Komow <lenny@lunarg.com>
* Author: Charles Giessen <charles@lunarg.com>
*
*/
#include "loader_environment.h"
#include "allocation.h"
#include "loader.h"
#include "log.h"
#include <ctype.h>
#include "param/sys_param.h"
// Environment variables
#if COMMON_UNIX_PLATFORMS
bool is_high_integrity() { return geteuid() != getuid() || getegid() != getgid(); }
char *loader_getenv(const char *name, const struct loader_instance *inst) {
if (NULL == name) return NULL;
#if defined(__OHOS__)
CachedHandle g_Handle = CachedParameterCreate(name, "");
int changed = 0;
const char *res = CachedParameterGetChanged(g_Handle, &changed);
loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_INFO_BIT, 0, "loader_getenv name:%s, res:%s", name, res);
if (res == NULL || res[0] == '\0') {
return NULL;
}
return (char *)res;
#else
// No allocation of memory necessary for Linux, but we should at least touch
// the inst pointer to get rid of compiler warnings.
(void)inst;
return getenv(name);
#endif
}
char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
// Apple does not appear to have a secure getenv implementation.
// The main difference between secure getenv and getenv is that secure getenv
// returns NULL if the process is being run with elevated privileges by a normal user.
// The idea is to prevent the reading of malicious environment variables by a process
// that can do damage.
// This algorithm is derived from glibc code that sets an internal
// variable (__libc_enable_secure) if the process is running under setuid or setgid.
return is_high_integrity() ? NULL : loader_getenv(name, inst);
#elif defined(__Fuchsia__)
return loader_getenv(name, inst);
#else
// Linux
char *out;
#if defined(HAVE_SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
(void)inst;
out = secure_getenv(name);
#elif defined(HAVE___SECURE_GETENV) && !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
(void)inst;
out = __secure_getenv(name);
#else
out = loader_getenv(name, inst);
#if !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Loader is using non-secure environment variable lookup for %s", name);
#endif
#endif
return out;
#endif
}
void loader_free_getenv(char *val, const struct loader_instance *inst) {
// No freeing of memory necessary for Linux, but we should at least touch
// the val and inst pointers to get rid of compiler warnings.
(void)val;
(void)inst;
}
#elif defined(WIN32)
bool is_high_integrity() {
HANDLE process_token;
if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &process_token)) {
// Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD.
uint8_t mandatory_label_buffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)];
DWORD buffer_size;
if (GetTokenInformation(process_token, TokenIntegrityLevel, mandatory_label_buffer, sizeof(mandatory_label_buffer),
&buffer_size) != 0) {
const TOKEN_MANDATORY_LABEL *mandatory_label = (const TOKEN_MANDATORY_LABEL *)mandatory_label_buffer;
const DWORD sub_authority_count = *GetSidSubAuthorityCount(mandatory_label->Label.Sid);
const DWORD integrity_level = *GetSidSubAuthority(mandatory_label->Label.Sid, sub_authority_count - 1);
CloseHandle(process_token);
return integrity_level >= SECURITY_MANDATORY_HIGH_RID;
}
CloseHandle(process_token);
}
return false;
}
char *loader_getenv(const char *name, const struct loader_instance *inst) {
int name_utf16_size = MultiByteToWideChar(CP_UTF8, 0, name, -1, NULL, 0);
if (name_utf16_size <= 0) {
return NULL;
}
wchar_t *name_utf16 = (wchar_t *)loader_stack_alloc(name_utf16_size * sizeof(wchar_t));
if (MultiByteToWideChar(CP_UTF8, 0, name, -1, name_utf16, name_utf16_size) != name_utf16_size) {
return NULL;
}
DWORD val_size = GetEnvironmentVariableW(name_utf16, NULL, 0);
// val_size DOES include the null terminator, so for any set variable
// will always be at least 1. If it's 0, the variable wasn't set.
if (val_size == 0) {
return NULL;
}
wchar_t *val = (wchar_t *)loader_stack_alloc(val_size * sizeof(wchar_t));
if (GetEnvironmentVariableW(name_utf16, val, val_size) != val_size - 1) {
return NULL;
}
int val_utf8_size = WideCharToMultiByte(CP_UTF8, 0, val, -1, NULL, 0, NULL, NULL);
if (val_utf8_size <= 0) {
return NULL;
}
char *val_utf8 = (char *)loader_instance_heap_alloc(inst, val_utf8_size * sizeof(char), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (val_utf8 == NULL) {
return NULL;
}
if (WideCharToMultiByte(CP_UTF8, 0, val, -1, val_utf8, val_utf8_size, NULL, NULL) != val_utf8_size) {
loader_instance_heap_free(inst, val_utf8);
return NULL;
}
return val_utf8;
}
char *loader_secure_getenv(const char *name, const struct loader_instance *inst) {
if (NULL == name) return NULL;
#if !defined(LOADER_USE_UNSAFE_FILE_SEARCH)
if (is_high_integrity()) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"Loader is running with elevated permissions. Environment variable %s will be ignored", name);
return NULL;
}
#endif
return loader_getenv(name, inst);
}
void loader_free_getenv(char *val, const struct loader_instance *inst) { loader_instance_heap_free(inst, (void *)val); }
#else
#warning \
"This platform does not support environment variables! If this is not intended, please implement the stubs functions loader_getenv and loader_free_getenv"
char *loader_getenv(const char *name, const struct loader_instance *inst) {
// stub func
(void)inst;
(void)name;
return NULL;
}
void loader_free_getenv(char *val, const struct loader_instance *inst) {
// stub func
(void)val;
(void)inst;
}
#endif
// Determine the type of filter string based on the contents of it.
// This will properly check against:
// - substrings "*string*"
// - prefixes "string*"
// - suffixes "*string"
// - full string names "string"
// It will also return the correct start and finish to remove any star '*' characters for the actual string compare
void determine_filter_type(const char *filter_string, enum loader_filter_string_type *filter_type, const char **new_start,
size_t *new_length) {
size_t filter_length = strlen(filter_string);
bool star_begin = false;
bool star_end = false;
if ('~' == filter_string[0]) {
// One of the special identifiers like: ~all~, ~implicit~, or ~explicit~
*filter_type = FILTER_STRING_SPECIAL;
*new_start = filter_string;
*new_length = filter_length;
} else {
if ('*' == filter_string[0]) {
// Only the * means everything
if (filter_length == 1) {
*filter_type = FILTER_STRING_SPECIAL;
*new_start = filter_string;
*new_length = filter_length;
} else {
star_begin = true;
}
}
if ('*' == filter_string[filter_length - 1]) {
// Not really valid, but just catch this case so if someone accidentally types "**" it will also mean everything
if (filter_length == 2) {
*filter_type = FILTER_STRING_SPECIAL;
*new_start = filter_string;
*new_length = filter_length;
} else {
star_end = true;
}
}
if (star_begin && star_end) {
*filter_type = FILTER_STRING_SUBSTRING;
*new_start = &filter_string[1];
*new_length = filter_length - 2;
} else if (star_begin) {
*new_start = &filter_string[1];
*new_length = filter_length - 1;
*filter_type = FILTER_STRING_SUFFIX;
} else if (star_end) {
*filter_type = FILTER_STRING_PREFIX;
*new_start = filter_string;
*new_length = filter_length - 1;
} else {
*filter_type = FILTER_STRING_FULLNAME;
*new_start = filter_string;
*new_length = filter_length;
}
}
}
// Parse the provided filter string provided by the envrionment variable into the appropriate filter
// struct variable.
VkResult parse_generic_filter_environment_var(const struct loader_instance *inst, const char *env_var_name,
struct loader_envvar_filter *filter_struct) {
VkResult result = VK_SUCCESS;
memset(filter_struct, 0, sizeof(struct loader_envvar_filter));
char *parsing_string = NULL;
char *env_var_value = loader_secure_getenv(env_var_name, inst);
if (NULL == env_var_value) {
return result;
}
const size_t env_var_len = strlen(env_var_value);
if (env_var_len == 0) {
goto out;
}
// Allocate a separate string since scan_for_next_comma modifies the original string
parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == parsing_string) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"parse_generic_filter_environment_var: Failed to allocate space for parsing env var \'%s\'", env_var_name);
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
for (uint32_t iii = 0; iii < env_var_len; ++iii) {
parsing_string[iii] = (char)tolower(env_var_value[iii]);
}
parsing_string[env_var_len] = '\0';
char *context = NULL;
char *token = thread_safe_strtok(parsing_string, ",", &context);
while (NULL != token) {
enum loader_filter_string_type cur_filter_type;
const char *actual_start;
size_t actual_len;
determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
if (actual_len > VK_MAX_EXTENSION_NAME_SIZE) {
loader_strncpy(filter_struct->filters[filter_struct->count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start,
VK_MAX_EXTENSION_NAME_SIZE);
} else {
loader_strncpy(filter_struct->filters[filter_struct->count].value, VK_MAX_EXTENSION_NAME_SIZE, actual_start,
actual_len);
}
filter_struct->filters[filter_struct->count].length = actual_len;
filter_struct->filters[filter_struct->count++].type = cur_filter_type;
if (filter_struct->count >= MAX_ADDITIONAL_FILTERS) {
break;
}
token = thread_safe_strtok(NULL, ",", &context);
}
out:
loader_instance_heap_free(inst, parsing_string);
loader_free_getenv(env_var_value, inst);
return result;
}
// Parse the disable layer string. The layer disable has some special behavior because we allow it to disable
// all layers (either with "~all~", "*", or "**"), all implicit layers (with "~implicit~"), and all explicit layers
// (with "~explicit~"), in addition to the other layer filtering behavior.
VkResult parse_layers_disable_filter_environment_var(const struct loader_instance *inst,
struct loader_envvar_disable_layers_filter *disable_struct) {
VkResult result = VK_SUCCESS;
memset(disable_struct, 0, sizeof(struct loader_envvar_disable_layers_filter));
char *parsing_string = NULL;
char *env_var_value = loader_secure_getenv(VK_LAYERS_DISABLE_ENV_VAR, inst);
if (NULL == env_var_value) {
goto out;
}
const size_t env_var_len = strlen(env_var_value);
if (env_var_len == 0) {
goto out;
}
// Allocate a separate string since scan_for_next_comma modifies the original string
parsing_string = loader_instance_heap_calloc(inst, env_var_len + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == parsing_string) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"parse_layers_disable_filter_environment_var: Failed to allocate space for parsing env var "
"\'VK_LAYERS_DISABLE_ENV_VAR\'");
result = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
for (uint32_t iii = 0; iii < env_var_len; ++iii) {
parsing_string[iii] = (char)tolower(env_var_value[iii]);
}
parsing_string[env_var_len] = '\0';
char *context = NULL;
char *token = thread_safe_strtok(parsing_string, ",", &context);
while (NULL != token) {
uint32_t cur_count = disable_struct->additional_filters.count;
enum loader_filter_string_type cur_filter_type;
const char *actual_start;
size_t actual_len;
determine_filter_type(token, &cur_filter_type, &actual_start, &actual_len);
if (cur_filter_type == FILTER_STRING_SPECIAL) {
if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, token) || !strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, token) ||
!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, token)) {
disable_struct->disable_all = true;
} else if (!strcmp(VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR, token)) {
disable_struct->disable_all_implicit = true;
} else if (!strcmp(VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR, token)) {
disable_struct->disable_all_explicit = true;
}
} else {
if (actual_len > VK_MAX_EXTENSION_NAME_SIZE) {
loader_strncpy(disable_struct->additional_filters.filters[cur_count].value, VK_MAX_EXTENSION_NAME_SIZE,
actual_start, VK_MAX_EXTENSION_NAME_SIZE);
} else {
loader_strncpy(disable_struct->additional_filters.filters[cur_count].value, VK_MAX_EXTENSION_NAME_SIZE,
actual_start, actual_len);
}
disable_struct->additional_filters.filters[cur_count].length = actual_len;
disable_struct->additional_filters.filters[cur_count].type = cur_filter_type;
disable_struct->additional_filters.count++;
if (disable_struct->additional_filters.count >= MAX_ADDITIONAL_FILTERS) {
break;
}
}
token = thread_safe_strtok(NULL, ",", &context);
}
out:
loader_instance_heap_free(inst, parsing_string);
loader_free_getenv(env_var_value, inst);
return result;
}
// Parses the filter environment variables to determine if we have any special behavior
VkResult parse_layer_environment_var_filters(const struct loader_instance *inst, struct loader_envvar_all_filters *layer_filters) {
VkResult res = parse_generic_filter_environment_var(inst, VK_LAYERS_ENABLE_ENV_VAR, &layer_filters->enable_filter);
if (VK_SUCCESS != res) {
return res;
}
res = parse_layers_disable_filter_environment_var(inst, &layer_filters->disable_filter);
if (VK_SUCCESS != res) {
return res;
}
res = parse_generic_filter_environment_var(inst, VK_LAYERS_ALLOW_ENV_VAR, &layer_filters->allow_filter);
if (VK_SUCCESS != res) {
return res;
}
return res;
}
// Check to see if the provided layer name matches any of the filter strings.
// This will properly check against:
// - substrings "*string*"
// - prefixes "string*"
// - suffixes "*string"
// - full string names "string"
bool check_name_matches_filter_environment_var(const char *name, const struct loader_envvar_filter *filter_struct) {
bool ret_value = false;
const size_t name_len = strlen(name);
char lower_name[VK_MAX_EXTENSION_NAME_SIZE];
for (uint32_t iii = 0; iii < name_len; ++iii) {
lower_name[iii] = (char)tolower(name[iii]);
}
lower_name[name_len] = '\0';
for (uint32_t filt = 0; filt < filter_struct->count; ++filt) {
// Check if the filter name is longer (this is with all special characters removed), and if it is
// continue since it can't match.
if (filter_struct->filters[filt].length > name_len) {
continue;
}
switch (filter_struct->filters[filt].type) {
case FILTER_STRING_SPECIAL:
if (!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_1, filter_struct->filters[filt].value) ||
!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_2, filter_struct->filters[filt].value) ||
!strcmp(VK_LOADER_DISABLE_ALL_LAYERS_VAR_3, filter_struct->filters[filt].value)) {
ret_value = true;
}
break;
case FILTER_STRING_SUBSTRING:
if (NULL != strstr(lower_name, filter_struct->filters[filt].value)) {
ret_value = true;
}
break;
case FILTER_STRING_SUFFIX:
if (0 == strncmp(lower_name + name_len - filter_struct->filters[filt].length, filter_struct->filters[filt].value,
filter_struct->filters[filt].length)) {
ret_value = true;
}
break;
case FILTER_STRING_PREFIX:
if (0 == strncmp(lower_name, filter_struct->filters[filt].value, filter_struct->filters[filt].length)) {
ret_value = true;
}
break;
case FILTER_STRING_FULLNAME:
if (0 == strncmp(lower_name, filter_struct->filters[filt].value, name_len)) {
ret_value = true;
}
break;
}
if (ret_value) {
break;
}
}
return ret_value;
}
// Get the layer name(s) from the env_name environment variable. If layer is found in
// search_list then add it to layer_list. But only add it to layer_list if type_flags matches.
VkResult loader_add_environment_layers(struct loader_instance *inst, const enum layer_type_flags type_flags,
const struct loader_envvar_all_filters *filters,
struct loader_pointer_layer_list *target_list,
struct loader_pointer_layer_list *expanded_target_list,
const struct loader_layer_list *source_list) {
VkResult res = VK_SUCCESS;
char *layer_env = loader_getenv(ENABLED_LAYERS_ENV, inst);
// If the layer environment variable is present (i.e. VK_INSTANCE_LAYERS), we will always add it to the layer list.
if (layer_env != NULL) {
size_t layer_env_len = strlen(layer_env) + 1;
char *name = loader_stack_alloc(layer_env_len);
if (name != NULL) {
loader_strncpy(name, layer_env_len, layer_env, layer_env_len);
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "env var \'%s\' defined and adding layers \"%s\"",
ENABLED_LAYERS_ENV, name);
// First look for the old-fashion layers forced on with VK_INSTANCE_LAYERS
while (name && *name) {
char *next = loader_get_next_path(name);
if (strlen(name) > 0) {
bool found = false;
for (uint32_t i = 0; i < source_list->count; i++) {
struct loader_layer_properties *source_prop = &source_list->list[i];
if (0 == strcmp(name, source_prop->info.layerName)) {
found = true;
// Only add it if it doesn't already appear in the layer list
if (!loader_find_layer_name_in_list(source_prop->info.layerName, target_list)) {
if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
res = loader_add_layer_properties_to_list(inst, target_list, source_prop);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
res = loader_add_layer_properties_to_list(inst, expanded_target_list, source_prop);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
} else {
res = loader_add_meta_layer(inst, filters, source_prop, target_list, expanded_target_list,
source_list, NULL);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
}
break;
}
}
}
if (!found) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"Layer \"%s\" was not found but was requested by env var VK_INSTANCE_LAYERS!", name);
}
}
name = next;
}
}
}
// Loop through all the layers and check the enable/disable filters
for (uint32_t i = 0; i < source_list->count; i++) {
struct loader_layer_properties *source_prop = &source_list->list[i];
// If it doesn't match the type, or the name isn't what we're looking for, just continue
if ((source_prop->type_flags & type_flags) != type_flags) {
continue;
}
// We found a layer we're interested in, but has it been disabled...
bool adding = true;
bool is_implicit = (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER));
bool disabled_by_type =
(is_implicit) ? (filters->disable_filter.disable_all_implicit) : (filters->disable_filter.disable_all_explicit);
if ((filters->disable_filter.disable_all || disabled_by_type ||
check_name_matches_filter_environment_var(source_prop->info.layerName, &filters->disable_filter.additional_filters)) &&
!check_name_matches_filter_environment_var(source_prop->info.layerName, &filters->allow_filter)) {
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"Layer \"%s\" ignored because it has been disabled by env var \'%s\'", source_prop->info.layerName,
VK_LAYERS_DISABLE_ENV_VAR);
adding = false;
}
// If we are supposed to filter through all layers, we need to compare the layer name against the filter.
// This can override the disable above, so we want to do it second.
// Also make sure the layer isn't already in the output_list, skip adding it if it is.
if (check_name_matches_filter_environment_var(source_prop->info.layerName, &filters->enable_filter) &&
!loader_find_layer_name_in_list(source_prop->info.layerName, target_list)) {
adding = true;
// Only way is_substring is true is if there are enable variables. If that's the case, and we're past the
// above, we should indicate that it was forced on in this way.
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0,
"Layer \"%s\" forced enabled due to env var \'%s\'", source_prop->info.layerName, VK_LAYERS_ENABLE_ENV_VAR);
} else {
adding = false;
}
if (!adding) {
continue;
}
// If not a meta-layer, simply add it.
if (0 == (source_prop->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER)) {
res = loader_add_layer_properties_to_list(inst, target_list, source_prop);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
res = loader_add_layer_properties_to_list(inst, expanded_target_list, source_prop);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
} else {
res = loader_add_meta_layer(inst, filters, source_prop, target_list, expanded_target_list, source_list, NULL);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
}
}
out:
if (layer_env != NULL) {
loader_free_getenv(layer_env, inst);
}
return res;
}

View File

@ -35,10 +35,22 @@
char *loader_getenv(const char *name, const struct loader_instance *inst);
void loader_free_getenv(char *val, const struct loader_instance *inst);
#if defined(WIN32) || defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#if defined(WIN32) || COMMON_UNIX_PLATFORMS
bool is_high_integrity();
char *loader_secure_getenv(const char *name, const struct loader_instance *inst);
#endif
VkResult parse_generic_filter_environment_var(const struct loader_instance *inst, const char *env_var_name,
struct loader_envvar_filter *filter_struct);
VkResult parse_layers_disable_filter_environment_var(const struct loader_instance *inst,
struct loader_envvar_disable_layers_filter *disable_struct);
VkResult parse_layer_environment_var_filters(const struct loader_instance *inst, struct loader_envvar_all_filters *layer_filters);
bool check_name_matches_filter_environment_var(const char *name, const struct loader_envvar_filter *filter_struct);
VkResult loader_add_environment_layers(struct loader_instance *inst, const enum layer_type_flags type_flags,
const struct loader_envvar_all_filters *filters,
struct loader_pointer_layer_list *target_list,
struct loader_pointer_layer_list *expanded_target_list,
const struct loader_layer_list *source_list);

View File

@ -22,7 +22,7 @@
// Non-windows and non-apple only header file, guard it so that accidental
// inclusion doesn't cause unknown header include errors
#ifdef LOADER_ENABLE_LINUX_SORT
#if defined(LOADER_ENABLE_LINUX_SORT)
#include <stdio.h>
#include <stdlib.h>
@ -30,12 +30,12 @@
#include "loader_linux.h"
#include "allocation.h"
#include "get_environment.h"
#include "loader_environment.h"
#include "loader.h"
#include "log.h"
// Determine a priority based on device type with the higher value being higher priority.
static uint32_t determine_priority_type_value(VkPhysicalDeviceType type) {
uint32_t determine_priority_type_value(VkPhysicalDeviceType type) {
switch (type) {
case VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU:
return 10;
@ -55,7 +55,7 @@ static uint32_t determine_priority_type_value(VkPhysicalDeviceType type) {
// Compare the two device types.
// This behaves similar to a qsort compare.
static int32_t device_type_compare(VkPhysicalDeviceType a, VkPhysicalDeviceType b) {
int32_t device_type_compare(VkPhysicalDeviceType a, VkPhysicalDeviceType b) {
uint32_t a_value = determine_priority_type_value(a);
uint32_t b_value = determine_priority_type_value(b);
if (a_value > b_value) {
@ -204,12 +204,12 @@ int32_t compare_device_groups(const void *a, const void *b) {
}
// Search for the default device using the loader environment variable.
static void linux_env_var_default_device(struct loader_instance *inst, uint32_t device_count,
void linux_env_var_default_device(struct loader_instance *inst, uint32_t device_count,
struct LinuxSortedDeviceInfo *sorted_device_info) {
char *selection = loader_getenv("VK_LOADER_DEVICE_SELECT", inst);
if (NULL != selection) {
loader_log(inst, VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_DRIVER_BIT, 0,
"linux_env_var_default_device: Found VK_LOADER_DEVICE_SELECT set to %s", selection);
"linux_env_var_default_device: Found \'VK_LOADER_DEVICE_SELECT\' set to %s", selection);
// The environment variable exists, so grab the vendor ID and device ID of the
// selected default device
@ -233,7 +233,7 @@ static void linux_env_var_default_device(struct loader_instance *inst, uint32_t
// This function allocates an array in sorted_devices which must be freed by the caller if not null
VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32_t icd_count,
struct loader_phys_dev_per_icd *icd_devices, uint32_t phys_dev_count,
struct loader_icd_physical_devices *icd_devices, uint32_t phys_dev_count,
struct loader_physical_device_term **sorted_device_term) {
VkResult res = VK_SUCCESS;
bool app_is_vulkan_1_1 = loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version);
@ -269,7 +269,7 @@ VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32
bool device_is_1_1_capable =
loader_check_version_meets_required(LOADER_VERSION_1_1_0, loader_make_version(dev_props.apiVersion));
if (!sorted_device_info[index].has_pci_bus_info) {
uint32_t ext_count;
uint32_t ext_count = 0;
icd_term->dispatch.EnumerateDeviceExtensionProperties(sorted_device_info[index].physical_device, NULL, &ext_count,
NULL);
if (ext_count > 0) {
@ -437,7 +437,6 @@ VkResult linux_sort_physical_device_groups(struct loader_instance *inst, uint32_
// Sort device groups by PCI info
qsort(sorted_group_term, group_count, sizeof(struct loader_physical_device_group_term), compare_device_groups);
if (loader_get_debug_level() & (VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT)) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, "linux_sort_physical_device_groups: Sorted order:");
for (uint32_t group = 0; group < group_count; ++group) {
loader_log(inst, VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_DRIVER_BIT, 0, " Group %u", group);
@ -448,7 +447,6 @@ VkResult linux_sort_physical_device_groups(struct loader_instance *inst, uint32_
(sorted_group_term[group].internal_device_info[gpu].default_device ? "[default]" : ""));
}
}
}
return res;
}

View File

@ -22,13 +22,13 @@
#pragma once
#ifdef LOADER_ENABLE_LINUX_SORT
#if defined(LOADER_ENABLE_LINUX_SORT)
#include "loader_common.h"
// This function allocates an array in sorted_devices which must be freed by the caller if not null
VkResult linux_read_sorted_physical_devices(struct loader_instance *inst, uint32_t icd_count,
struct loader_phys_dev_per_icd *icd_devices, uint32_t phys_dev_count,
struct loader_icd_physical_devices *icd_devices, uint32_t phys_dev_count,
struct loader_physical_device_term **sorted_device_term);
// This function sorts an array in physical device groups

View File

@ -27,7 +27,7 @@
*
*/
// Windows only header file, guard it so that accidental inclusion doesn't cause unknown header include errors
#ifdef _WIN32
#if defined(_WIN32)
// This needs to be defined first, or else we'll get redefinitions on NTSTATUS values
#define UMDF_USING_NTSTATUS
@ -36,7 +36,7 @@
#include "loader_windows.h"
#include "allocation.h"
#include "get_environment.h"
#include "loader_environment.h"
#include "loader.h"
#include "log.h"
@ -45,13 +45,13 @@
#include <devpkey.h>
#include <winternl.h>
#include <strsafe.h>
#ifdef __MINGW32__
#undef strcpy // fix error with redfined strcpy when building with MinGW-w64
#if defined(__MINGW32__)
#undef strcpy // fix error with redefined strcpy when building with MinGW-w64
#endif
#include <dxgi1_6.h>
#include "adapters.h"
#ifndef __MINGW32__
#if !defined(__MINGW32__)
// not yet available with MinGW-w64 stable
#include <appmodel.h>
#endif
@ -61,7 +61,10 @@
#endif
typedef HRESULT(APIENTRY *PFN_CreateDXGIFactory1)(REFIID riid, void **ppFactory);
static PFN_CreateDXGIFactory1 fpCreateDXGIFactory1;
PFN_CreateDXGIFactory1 fpCreateDXGIFactory1;
// Empty function just so windows_initialization can find the current module location
void function_for_finding_the_current_module(void) {}
void windows_initialization(void) {
char dll_location[MAX_PATH];
@ -69,7 +72,7 @@ void windows_initialization(void) {
// Get a module handle to a static function inside of this source
if (GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS | GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT,
(LPCSTR)&loader_debug_init, &module_handle) != 0 &&
(LPCSTR)&function_for_finding_the_current_module, &module_handle) != 0 &&
GetModuleFileName(module_handle, dll_location, sizeof(dll_location)) != 0) {
loader_log(NULL, VULKAN_LOADER_INFO_BIT, 0, "Using Vulkan Loader %s", dll_location);
}
@ -82,7 +85,8 @@ void windows_initialization(void) {
GetSystemDirectoryW(systemPath, MAX_PATH);
StringCchCatW(systemPath, MAX_PATH, L"\\dxgi.dll");
HMODULE dxgi_module = LoadLibraryW(systemPath);
fpCreateDXGIFactory1 = dxgi_module == NULL ? NULL : (PFN_CreateDXGIFactory1)GetProcAddress(dxgi_module, "CreateDXGIFactory1");
fpCreateDXGIFactory1 =
dxgi_module == NULL ? NULL : (PFN_CreateDXGIFactory1)(void *)GetProcAddress(dxgi_module, "CreateDXGIFactory1");
#if !defined(NDEBUG)
_set_error_mode(_OUT_TO_STDERR);
@ -92,6 +96,7 @@ void windows_initialization(void) {
}
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved) {
(void)hinst;
switch (reason) {
case DLL_PROCESS_ATTACH:
loader_initialize();
@ -227,9 +232,9 @@ out:
VkResult windows_get_device_registry_files(const struct loader_instance *inst, uint32_t log_target_flag, char **reg_data,
PDWORD reg_data_size, LPCSTR value_name) {
static const wchar_t *softwareComponentGUID = L"{5c4c3332-344d-483c-8739-259e934c9cc8}";
static const wchar_t *displayGUID = L"{4d36e968-e325-11ce-bfc1-08002be10318}";
#ifdef CM_GETIDLIST_FILTER_PRESENT
const wchar_t *softwareComponentGUID = L"{5c4c3332-344d-483c-8739-259e934c9cc8}";
const wchar_t *displayGUID = L"{4d36e968-e325-11ce-bfc1-08002be10318}";
#if defined(CM_GETIDLIST_FILTER_PRESENT)
const ULONG flags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT;
#else
const ULONG flags = 0x300;
@ -348,7 +353,7 @@ VkResult windows_get_registry_files(const struct loader_instance *inst, char *lo
PDWORD reg_data_size) {
// This list contains all of the allowed ICDs. This allows us to verify that a device is actually present from the vendor
// specified. This does disallow other vendors, but any new driver should use the device-specific registries anyway.
static const struct {
const struct {
const char *filename;
unsigned int vendor_id;
} known_drivers[] = {
@ -525,8 +530,8 @@ VkResult windows_get_registry_files(const struct loader_instance *inst, char *lo
foundDuplicate = true;
}
}
if (foundDuplicate == false) {
// Only skip if we are adding a driver and a duplicate was found
if (!is_driver || (is_driver && foundDuplicate == false)) {
// Add the new entry to the list.
(void)snprintf(*reg_data + strlen(*reg_data), name_size + 2, "%c%s", PATH_SEPARATOR, name);
found = true;
@ -553,7 +558,8 @@ VkResult windows_get_registry_files(const struct loader_instance *inst, char *lo
}
if (!found && result != VK_ERROR_OUT_OF_HOST_MEMORY) {
loader_log(inst, log_target_flag, 0, "Found no registry files in %s", location);
loader_log(inst, log_target_flag, 0, "Found no registry files in %s\\%s",
(hive == DEFAULT_VK_REGISTRY_HIVE) ? DEFAULT_VK_REGISTRY_HIVE_STR : SECONDARY_VK_REGISTRY_HIVE_STR, location);
result = VK_ERROR_INCOMPATIBLE_DRIVER;
}
@ -581,9 +587,10 @@ VkResult windows_read_manifest_from_d3d_adapters(const struct loader_instance *i
goto out;
}
PFN_LoaderEnumAdapters2 fpLoaderEnumAdapters2 = (PFN_LoaderEnumAdapters2)GetProcAddress(gdi32_dll, "D3DKMTEnumAdapters2");
PFN_LoaderEnumAdapters2 fpLoaderEnumAdapters2 =
(PFN_LoaderEnumAdapters2)(void *)GetProcAddress(gdi32_dll, "D3DKMTEnumAdapters2");
PFN_LoaderQueryAdapterInfo fpLoaderQueryAdapterInfo =
(PFN_LoaderQueryAdapterInfo)GetProcAddress(gdi32_dll, "D3DKMTQueryAdapterInfo");
(PFN_LoaderQueryAdapterInfo)(void *)GetProcAddress(gdi32_dll, "D3DKMTQueryAdapterInfo");
if (fpLoaderEnumAdapters2 == NULL || fpLoaderQueryAdapterInfo == NULL) {
result = VK_ERROR_INCOMPATIBLE_DRIVER;
goto out;
@ -615,7 +622,8 @@ VkResult windows_read_manifest_from_d3d_adapters(const struct loader_instance *i
.value_type = REG_MULTI_SZ,
.physical_adapter_index = 0,
};
wcsncpy(filename_info.value_name, value_name, sizeof(filename_info.value_name) / sizeof(WCHAR));
size_t value_name_size = wcslen(value_name);
wcsncpy_s(filename_info.value_name, MAX_PATH, value_name, value_name_size);
LoaderQueryAdapterInfo query_info;
query_info.handle = adapters.adapters[i].handle;
query_info.type = LOADER_QUERY_TYPE_REGISTRY;
@ -680,7 +688,7 @@ VkResult windows_read_manifest_from_d3d_adapters(const struct loader_instance *i
goto out;
}
// If this is a string and not a multi-string, we don't want to go throught the loop more than once
// If this is a string and not a multi-string, we don't want to go through the loop more than once
if (full_info->value_type == REG_SZ) {
break;
}
@ -698,17 +706,19 @@ out:
// Look for data files in the registry.
VkResult windows_read_data_files_in_registry(const struct loader_instance *inst, enum loader_data_files_type data_file_type,
bool warn_if_not_present, char *registry_location,
struct loader_data_files *out_files) {
struct loader_string_list *out_files) {
VkResult vk_result = VK_SUCCESS;
char *search_path = NULL;
uint32_t log_target_flag = 0;
if (data_file_type == LOADER_DATA_FILE_MANIFEST_DRIVER) {
log_target_flag = VULKAN_LOADER_DRIVER_BIT;
loader_log(inst, log_target_flag, 0, "Checking for Driver Manifest files in Registry at %s", registry_location);
loader_log(inst, log_target_flag, 0, "Checking for Driver Manifest files in Registry at %s\\%s",
DEFAULT_VK_REGISTRY_HIVE_STR, registry_location);
} else {
log_target_flag = VULKAN_LOADER_LAYER_BIT;
loader_log(inst, log_target_flag, 0, "Checking for Layer Manifest files in Registry at %s", registry_location);
loader_log(inst, log_target_flag, 0, "Checking for Layer Manifest files in Registry at %s\\%s",
DEFAULT_VK_REGISTRY_HIVE_STR, registry_location);
}
// These calls look at the PNP/Device section of the registry.
@ -783,12 +793,141 @@ out:
return vk_result;
}
// This function allocates an array in sorted_devices which must be freed by the caller if not null
VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint32_t *sorted_devices_count,
struct loader_phys_dev_per_icd **sorted_devices) {
VkResult enumerate_adapter_physical_devices(struct loader_instance *inst, struct loader_icd_term *icd_term, uint32_t icd_idx,
LUID luid, uint32_t *icd_phys_devs_array_count,
struct loader_icd_physical_devices *icd_phys_devs_array) {
uint32_t count = 0;
VkResult res = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(icd_term->instance, luid, &count, NULL);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
return res;
} else if (res == VK_ERROR_INCOMPATIBLE_DRIVER) {
return VK_SUCCESS; // This driver doesn't support the adapter
} else if (res != VK_SUCCESS) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"Failed to convert DXGI adapter into Vulkan physical device with unexpected error code");
return res;
} else if (0 == count) {
return VK_SUCCESS; // This driver doesn't support the adapter
}
// Take a pointer to the last element of icd_phys_devs_array to simplify usage
struct loader_icd_physical_devices *next_icd_phys_devs = &icd_phys_devs_array[*icd_phys_devs_array_count];
// Get the actual physical devices
do {
next_icd_phys_devs->physical_devices = loader_instance_heap_realloc(
inst, next_icd_phys_devs->physical_devices, next_icd_phys_devs->device_count * sizeof(VkPhysicalDevice),
count * sizeof(VkPhysicalDevice), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (next_icd_phys_devs->physical_devices == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
next_icd_phys_devs->device_count = count;
} while ((res = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(icd_term->instance, luid, &count,
next_icd_phys_devs->physical_devices)) == VK_INCOMPLETE);
if (res != VK_SUCCESS) {
loader_instance_heap_free(inst, next_icd_phys_devs->physical_devices);
next_icd_phys_devs->physical_devices = NULL;
// Unless OOHM occurs, only return VK_SUCCESS
if (res != VK_ERROR_OUT_OF_HOST_MEMORY) {
res = VK_SUCCESS;
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Failed to convert DXGI adapter into Vulkan physical device");
}
return res;
}
// Because the loader calls EnumerateAdapterPhysicalDevices on all drivers with each DXGI Adapter, if there are multiple drivers
// that share a luid the physical device will get queried multiple times. We can prevent that by not adding them if the
// enumerated physical devices have already been added.
bool already_enumerated = false;
for (uint32_t j = 0; j < *icd_phys_devs_array_count; j++) {
if (count == icd_phys_devs_array[j].device_count) {
bool matches = true;
for (uint32_t k = 0; k < icd_phys_devs_array[j].device_count; k++) {
if (icd_phys_devs_array[j].physical_devices[k] != next_icd_phys_devs->physical_devices[k]) {
matches = false;
break;
}
}
if (matches) {
already_enumerated = true;
}
}
}
if (!already_enumerated) {
next_icd_phys_devs->device_count = count;
next_icd_phys_devs->icd_index = icd_idx;
next_icd_phys_devs->icd_term = icd_term;
next_icd_phys_devs->windows_adapter_luid = luid;
(*icd_phys_devs_array_count)++;
}
return VK_SUCCESS;
}
// Whenever there are multiple drivers for the same hardware and one of the drivers is an implementation layered on top of another
// API (such as the Dozen driver which converts vulkan to Dx12), we want to make sure the layered driver appears after the 'native'
// driver. This function iterates over all physical devices and make sure any with matching LUID's are sorted such that drivers with
// a underlyingAPI of VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT are ordered after drivers without it.
void sort_physical_devices_with_same_luid(struct loader_instance *inst, uint32_t icd_phys_devs_array_count,
struct loader_icd_physical_devices *icd_phys_devs_array) {
bool app_is_vulkan_1_1 = loader_check_version_meets_required(LOADER_VERSION_1_1_0, inst->app_api_version);
for (uint32_t i = 0; icd_phys_devs_array_count > 1 && i < icd_phys_devs_array_count - 1; i++) {
for (uint32_t j = i + 1; j < icd_phys_devs_array_count; j++) {
// Only want to reorder physical devices if their ICD's LUID's match
if ((icd_phys_devs_array[i].windows_adapter_luid.HighPart != icd_phys_devs_array[j].windows_adapter_luid.HighPart) ||
(icd_phys_devs_array[i].windows_adapter_luid.LowPart != icd_phys_devs_array[j].windows_adapter_luid.LowPart)) {
continue;
}
VkLayeredDriverUnderlyingApiMSFT underlyingAPI = VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT;
VkPhysicalDeviceLayeredDriverPropertiesMSFT layered_driver_properties_msft = {0};
layered_driver_properties_msft.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_LAYERED_DRIVER_PROPERTIES_MSFT;
VkPhysicalDeviceProperties2 props2 = {0};
props2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
props2.pNext = (void *)&layered_driver_properties_msft;
// Because there may be multiple physical devices associated with each ICD, we need to check each physical device
// whether it is layered
for (uint32_t k = 0; k < icd_phys_devs_array[i].device_count; k++) {
VkPhysicalDeviceProperties dev_props = {0};
icd_phys_devs_array[i].icd_term->dispatch.GetPhysicalDeviceProperties(icd_phys_devs_array[i].physical_devices[k],
&dev_props);
bool device_is_1_1_capable =
loader_check_version_meets_required(LOADER_VERSION_1_1_0, loader_make_version(dev_props.apiVersion));
PFN_vkGetPhysicalDeviceProperties2 GetPhysDevProps2 = NULL;
if (app_is_vulkan_1_1 && device_is_1_1_capable) {
GetPhysDevProps2 = icd_phys_devs_array[i].icd_term->dispatch.GetPhysicalDeviceProperties2;
} else {
GetPhysDevProps2 = (PFN_vkGetPhysicalDeviceProperties2)icd_phys_devs_array[i]
.icd_term->dispatch.GetPhysicalDeviceProperties2KHR;
}
if (GetPhysDevProps2) {
GetPhysDevProps2(icd_phys_devs_array[i].physical_devices[k], &props2);
if (layered_driver_properties_msft.underlyingAPI != VK_LAYERED_DRIVER_UNDERLYING_API_NONE_MSFT) {
underlyingAPI = layered_driver_properties_msft.underlyingAPI;
break;
}
}
}
if (underlyingAPI == VK_LAYERED_DRIVER_UNDERLYING_API_D3D12_MSFT) {
struct loader_icd_physical_devices swap_icd = icd_phys_devs_array[i];
icd_phys_devs_array[i] = icd_phys_devs_array[j];
icd_phys_devs_array[j] = swap_icd;
}
}
}
}
// This function allocates icd_phys_devs_array which must be freed by the caller if not null
VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint32_t *icd_phys_devs_array_count,
struct loader_icd_physical_devices **icd_phys_devs_array) {
VkResult res = VK_SUCCESS;
uint32_t sorted_alloc = 0;
uint32_t icd_phys_devs_array_size = 0;
struct loader_icd_term *icd_term = NULL;
IDXGIFactory6 *dxgi_factory = NULL;
HRESULT hres = fpCreateDXGIFactory1(&IID_IDXGIFactory6, (void **)&dxgi_factory);
@ -796,10 +935,10 @@ VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Failed to create DXGI factory 6. Physical devices will not be sorted");
goto out;
}
sorted_alloc = 16;
*sorted_devices = loader_instance_heap_calloc(inst, sorted_alloc * sizeof(struct loader_phys_dev_per_icd),
icd_phys_devs_array_size = 16;
*icd_phys_devs_array = loader_instance_heap_calloc(inst, icd_phys_devs_array_size * sizeof(struct loader_icd_physical_devices),
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (*sorted_devices == NULL) {
if (*icd_phys_devs_array == NULL) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
@ -823,20 +962,19 @@ VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint
continue;
}
if (sorted_alloc <= i) {
uint32_t old_size = sorted_alloc * sizeof(struct loader_phys_dev_per_icd);
*sorted_devices =
loader_instance_heap_realloc(inst, *sorted_devices, old_size, 2 * old_size, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (*sorted_devices == NULL) {
if (icd_phys_devs_array_size <= i) {
uint32_t old_size = icd_phys_devs_array_size * sizeof(struct loader_icd_physical_devices);
*icd_phys_devs_array = loader_instance_heap_realloc(inst, *icd_phys_devs_array, old_size, 2 * old_size,
VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (*icd_phys_devs_array == NULL) {
adapter->lpVtbl->Release(adapter);
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
sorted_alloc *= 2;
icd_phys_devs_array_size *= 2;
}
struct loader_phys_dev_per_icd *sorted_array = *sorted_devices;
sorted_array[*sorted_devices_count].device_count = 0;
sorted_array[*sorted_devices_count].physical_devices = NULL;
(*icd_phys_devs_array)[*icd_phys_devs_array_count].device_count = 0;
(*icd_phys_devs_array)[*icd_phys_devs_array_count].physical_devices = NULL;
icd_term = inst->icd_terms;
for (uint32_t icd_idx = 0; NULL != icd_term; icd_term = icd_term->next, icd_idx++) {
@ -845,52 +983,12 @@ VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint
continue;
}
uint32_t count = 0;
VkResult vkres =
icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(icd_term->instance, description.AdapterLuid, &count, NULL);
if (vkres == VK_ERROR_INCOMPATIBLE_DRIVER) {
continue; // This driver doesn't support the adapter
} else if (vkres == VK_ERROR_OUT_OF_HOST_MEMORY) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
res = enumerate_adapter_physical_devices(inst, icd_term, icd_idx, description.AdapterLuid, icd_phys_devs_array_count,
*icd_phys_devs_array);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) {
adapter->lpVtbl->Release(adapter);
goto out;
} else if (vkres != VK_SUCCESS) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"Failed to convert DXGI adapter into Vulkan physical device with unexpected error code");
continue;
}
// Get the actual physical devices
if (0 != count) {
do {
sorted_array[*sorted_devices_count].physical_devices =
loader_instance_heap_realloc(inst, sorted_array[*sorted_devices_count].physical_devices,
sorted_array[*sorted_devices_count].device_count * sizeof(VkPhysicalDevice),
count * sizeof(VkPhysicalDevice), VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (sorted_array[*sorted_devices_count].physical_devices == NULL) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
break;
}
sorted_array[*sorted_devices_count].device_count = count;
} while ((vkres = icd_term->scanned_icd->EnumerateAdapterPhysicalDevices(
icd_term->instance, description.AdapterLuid, &count,
sorted_array[*sorted_devices_count].physical_devices)) == VK_INCOMPLETE);
}
if (vkres != VK_SUCCESS) {
loader_instance_heap_free(inst, sorted_array[*sorted_devices_count].physical_devices);
sorted_array[*sorted_devices_count].physical_devices = NULL;
if (vkres == VK_ERROR_OUT_OF_HOST_MEMORY) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
} else {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0, "Failed to convert DXGI adapter into Vulkan physical device");
continue;
}
}
sorted_array[*sorted_devices_count].device_count = count;
sorted_array[*sorted_devices_count].icd_index = icd_idx;
sorted_array[*sorted_devices_count].icd_term = icd_term;
(*sorted_devices_count)++;
}
adapter->lpVtbl->Release(adapter);
@ -898,13 +996,13 @@ VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint
dxgi_factory->lpVtbl->Release(dxgi_factory);
sort_physical_devices_with_same_luid(inst, *icd_phys_devs_array_count, *icd_phys_devs_array);
out:
if (*sorted_devices_count == 0 && *sorted_devices != NULL) {
loader_instance_heap_free(inst, *sorted_devices);
*sorted_devices = NULL;
if (*icd_phys_devs_array_count == 0 && *icd_phys_devs_array != NULL) {
loader_instance_heap_free(inst, *icd_phys_devs_array);
*icd_phys_devs_array = NULL;
}
*sorted_devices_count = *sorted_devices_count;
*sorted_devices = *sorted_devices;
return res;
}
@ -923,7 +1021,7 @@ VkLoaderFeatureFlags windows_initialize_dxgi(void) {
// Multiple groups could have devices out of the same sorted list, however, a single group's devices must all come
// from the same sorted list.
void windows_sort_devices_in_group(struct loader_instance *inst, struct VkPhysicalDeviceGroupProperties *group_props,
struct loader_phys_dev_per_icd *icd_sorted_list) {
struct loader_icd_physical_devices *icd_sorted_list) {
uint32_t cur_index = 0;
for (uint32_t dev = 0; dev < icd_sorted_list->device_count; ++dev) {
for (uint32_t grp_dev = cur_index; grp_dev < group_props->physicalDeviceCount; ++grp_dev) {
@ -948,7 +1046,7 @@ void windows_sort_devices_in_group(struct loader_instance *inst, struct VkPhysic
VkResult windows_sort_physical_device_groups(struct loader_instance *inst, const uint32_t group_count,
struct loader_physical_device_group_term *sorted_group_term,
const uint32_t sorted_device_count,
struct loader_phys_dev_per_icd *sorted_phys_dev_array) {
struct loader_icd_physical_devices *sorted_phys_dev_array) {
if (0 == group_count || NULL == sorted_group_term) {
loader_log(inst, VULKAN_LOADER_WARN_BIT, 0,
"windows_sort_physical_device_groups: Called with invalid information (Group count %d, Sorted Info %p)",
@ -993,13 +1091,13 @@ char *windows_get_app_package_manifest_path(const struct loader_instance *inst)
// These functions are only available on Windows 8 and above, load them dynamically for compatibility with Windows 7
typedef LONG(WINAPI * PFN_GetPackagesByPackageFamily)(PCWSTR, UINT32 *, PWSTR *, UINT32 *, WCHAR *);
PFN_GetPackagesByPackageFamily fpGetPackagesByPackageFamily =
(PFN_GetPackagesByPackageFamily)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetPackagesByPackageFamily");
(PFN_GetPackagesByPackageFamily)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetPackagesByPackageFamily");
if (!fpGetPackagesByPackageFamily) {
return NULL;
}
typedef LONG(WINAPI * PFN_GetPackagePathByFullName)(PCWSTR, UINT32 *, PWSTR);
PFN_GetPackagePathByFullName fpGetPackagePathByFullName =
(PFN_GetPackagePathByFullName)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetPackagePathByFullName");
(PFN_GetPackagePathByFullName)(void *)GetProcAddress(GetModuleHandle(TEXT("kernel32.dll")), "GetPackagePathByFullName");
if (!fpGetPackagePathByFullName) {
return NULL;
}
@ -1013,7 +1111,7 @@ char *windows_get_app_package_manifest_path(const struct loader_instance *inst)
if (ERROR_INSUFFICIENT_BUFFER != fpGetPackagesByPackageFamily(familyName, &numPackages, NULL, &bufferLength, NULL) ||
numPackages == 0 || bufferLength == 0) {
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0,
"windows_get_app_package_manifest_path: Failed to find mapping layers packages by family name\n");
"windows_get_app_package_manifest_path: Failed to find mapping layers packages by family name");
return NULL;
}
@ -1022,13 +1120,13 @@ char *windows_get_app_package_manifest_path(const struct loader_instance *inst)
PWSTR *packages = loader_instance_heap_alloc(inst, sizeof(PWSTR) * numPackages, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (!buffer || !packages) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"windows_get_app_package_manifest_path: Failed to allocate memory for package names\n");
"windows_get_app_package_manifest_path: Failed to allocate memory for package names");
goto cleanup;
}
if (ERROR_SUCCESS != fpGetPackagesByPackageFamily(familyName, &numPackages, packages, &bufferLength, buffer)) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"windows_get_app_package_manifest_path: Failed to mapping layers package full names\n");
"windows_get_app_package_manifest_path: Failed to mapping layers package full names");
goto cleanup;
}
@ -1038,20 +1136,20 @@ char *windows_get_app_package_manifest_path(const struct loader_instance *inst)
if (ERROR_INSUFFICIENT_BUFFER != fpGetPackagePathByFullName(packages[0], &pathLength, NULL) || pathLength > MAX_PATH ||
ERROR_SUCCESS != fpGetPackagePathByFullName(packages[0], &pathLength, path)) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"windows_get_app_package_manifest_path: Failed to get mapping layers package path\n");
"windows_get_app_package_manifest_path: Failed to get mapping layers package path");
goto cleanup;
}
int narrowPathLength = WideCharToMultiByte(CP_ACP, 0, path, -1, NULL, 0, NULL, NULL);
if (narrowPathLength == 0) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0,
"windows_get_app_package_manifest_path: Failed to convert path from wide to narrow\n");
"windows_get_app_package_manifest_path: Failed to convert path from wide to narrow");
goto cleanup;
}
ret = loader_instance_heap_alloc(inst, narrowPathLength, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (!ret) {
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "windows_get_app_package_manifest_path: Failed to allocate path\n");
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "windows_get_app_package_manifest_path: Failed to allocate path");
goto cleanup;
}
@ -1063,4 +1161,99 @@ cleanup:
loader_instance_heap_free(inst, packages);
return ret;
}
VkResult get_settings_path_if_exists_in_registry_key(const struct loader_instance *inst, char **out_path, HKEY key) {
VkResult result = VK_ERROR_INITIALIZATION_FAILED;
char name[MAX_STRING_SIZE] = {0};
DWORD name_size = sizeof(name);
*out_path = NULL;
LONG rtn_value = ERROR_SUCCESS;
for (DWORD idx = 0; rtn_value == ERROR_SUCCESS; idx++) {
DWORD value = 0;
DWORD value_size = sizeof(value);
rtn_value = RegEnumValue(key, idx, name, &name_size, NULL, NULL, (LPBYTE)&value, &value_size);
if (ERROR_SUCCESS != rtn_value) {
break;
}
uint32_t start_of_path_filename = 0;
for (uint32_t last_char = name_size; last_char > 0; last_char--) {
if (name[last_char] == '\\') {
start_of_path_filename = last_char + 1;
break;
}
}
// Make sure the path exists first
if (*out_path && !loader_platform_file_exists(name)) {
return VK_ERROR_INITIALIZATION_FAILED;
}
if (strcmp(VK_LOADER_SETTINGS_FILENAME, &(name[start_of_path_filename])) == 0) {
*out_path = loader_instance_heap_calloc(inst, name_size + 1, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (*out_path == NULL) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
loader_strncpy(*out_path, name_size + 1, name, name_size);
(*out_path)[name_size] = '\0';
result = VK_SUCCESS;
break;
}
}
return result;
}
VkResult windows_get_loader_settings_file_path(const struct loader_instance *inst, char **out_path) {
VkResult result = VK_SUCCESS;
DWORD access_flags = KEY_QUERY_VALUE;
HKEY key = NULL;
*out_path = NULL;
// if we are running with admin privileges, only check HKEY_LOCAL_MACHINE.
// Otherwise check HKEY_CURRENT_USER, and if nothing is there, look in HKEY_LOCAL_MACHINE
if (is_high_integrity()) {
LONG rtn_value = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VK_SETTINGS_INFO_REGISTRY_LOC, 0, access_flags, &key);
if (ERROR_SUCCESS != rtn_value) {
result = VK_ERROR_FEATURE_NOT_PRESENT;
goto out;
}
result = get_settings_path_if_exists_in_registry_key(inst, out_path, key);
} else {
LONG rtn_value = RegOpenKeyEx(HKEY_CURRENT_USER, VK_SETTINGS_INFO_REGISTRY_LOC, 0, access_flags, &key);
if (ERROR_SUCCESS == rtn_value) {
result = get_settings_path_if_exists_in_registry_key(inst, out_path, key);
RegCloseKey(key);
// Either we got OOM and *must* exit or we successfully found the settings file and can exit
if (result == VK_ERROR_OUT_OF_HOST_MEMORY || result == VK_SUCCESS) {
goto out;
}
}
rtn_value = RegOpenKeyEx(HKEY_LOCAL_MACHINE, VK_SETTINGS_INFO_REGISTRY_LOC, 0, access_flags, &key);
if (ERROR_SUCCESS != rtn_value) {
result = VK_ERROR_FEATURE_NOT_PRESENT;
goto out;
}
result = get_settings_path_if_exists_in_registry_key(inst, out_path, key);
if (result == VK_ERROR_OUT_OF_HOST_MEMORY) {
goto out;
}
}
out:
if (NULL != key) {
RegCloseKey(key);
}
return result;
}
#endif // _WIN32

View File

@ -97,17 +97,17 @@ VkResult windows_read_manifest_from_d3d_adapters(const struct loader_instance *i
// Look for data files in the registry.
VkResult windows_read_data_files_in_registry(const struct loader_instance *inst, enum loader_data_files_type data_file_type,
bool warn_if_not_present, char *registry_location,
struct loader_data_files *out_files);
struct loader_string_list *out_files);
// This function allocates an array in sorted_devices which must be freed by the caller if not null
VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint32_t *sorted_devices_count,
struct loader_phys_dev_per_icd **sorted_devices);
VkResult windows_read_sorted_physical_devices(struct loader_instance *inst, uint32_t *icd_phys_devs_array_count,
struct loader_icd_physical_devices **icd_phys_devs_array);
// This function sorts an array in physical device groups based on the sorted physical device information
VkResult windows_sort_physical_device_groups(struct loader_instance *inst, const uint32_t group_count,
struct loader_physical_device_group_term *sorted_group_term,
const uint32_t sorted_device_count,
struct loader_phys_dev_per_icd *sorted_phys_dev_array);
struct loader_icd_physical_devices *sorted_phys_dev_array);
// Creates a DXGI factory
// Returns VkLoaderFeatureFlags containing VK_LOADER_FEATURE_PHYSICAL_DEVICE_SORTING if successful, otherwise 0
@ -116,4 +116,10 @@ VkLoaderFeatureFlags windows_initialize_dxgi(void);
// Retrieve a path to an installed app package that contains Vulkan manifests.
// When done using the returned string, the caller should free the pointer.
char *windows_get_app_package_manifest_path(const struct loader_instance *inst);
// Gets the path to the loader settings file, if it exists. If it doesn't exists, writes NULL to out_path.
// The path is located through the registry as an entry in HKEY_CURRENT_USER/SOFTWARE/Khronos/Vulkan/LoaderSettings
// and if nothing is there, will try to look in HKEY_LOCAL_MACHINE/SOFTWARE/Khronos/Vulkan/LoaderSettings.
// If running with elevated privileges, this function only looks in HKEY_LOCAL_MACHINE.
VkResult windows_get_loader_settings_file_path(const struct loader_instance *inst, char **out_path);
#endif // WIN32

View File

@ -32,14 +32,17 @@
#include <stdarg.h>
#include "debug_utils.h"
#include "get_environment.h"
#include "loader_common.h"
#include "loader_environment.h"
#include "settings.h"
#include "vk_loader_platform.h"
#ifdef VK_USE_PLATFORM_OHOS
#include "loader_hilog.h"
#endif
uint32_t g_loader_debug = ~0u;
void loader_debug_init(void) {
void loader_init_global_debug_level(void) {
char *env, *orig;
if (g_loader_debug > 0) return;
@ -86,18 +89,15 @@ void loader_debug_init(void) {
loader_free_getenv(orig, NULL);
}
uint32_t loader_get_debug_level(void) { return g_loader_debug; }
void loader_set_global_debug_level(uint32_t new_loader_debug) { g_loader_debug = new_loader_debug; }
void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...) {
char msg[512];
char cmd_line_msg[512];
size_t cmd_line_size = sizeof(cmd_line_msg);
size_t num_used = 0;
va_list ap;
int ret;
(void)msg_code;
char msg[512] = {0};
va_list ap;
va_start(ap, format);
ret = vsnprintf(msg, sizeof(msg), format, ap);
int ret = vsnprintf(msg, sizeof(msg), format, ap);
if ((ret >= (int)sizeof(msg)) || ret < 0) {
msg[sizeof(msg) - 1] = '\0';
}
@ -105,9 +105,9 @@ void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t ms
if (inst) {
VkDebugUtilsMessageSeverityFlagBitsEXT severity = 0;
VkDebugUtilsMessageTypeFlagsEXT type;
VkDebugUtilsMessengerCallbackDataEXT callback_data;
VkDebugUtilsObjectNameInfoEXT object_name;
VkDebugUtilsMessageTypeFlagsEXT type = 0;
VkDebugUtilsMessengerCallbackDataEXT callback_data = {0};
VkDebugUtilsObjectNameInfoEXT object_name = {0};
if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
severity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
@ -133,106 +133,107 @@ void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t ms
}
callback_data.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CALLBACK_DATA_EXT;
callback_data.pNext = NULL;
callback_data.flags = 0;
callback_data.pMessageIdName = "Loader Message";
callback_data.messageIdNumber = 0;
callback_data.pMessage = msg;
callback_data.queueLabelCount = 0;
callback_data.pQueueLabels = NULL;
callback_data.cmdBufLabelCount = 0;
callback_data.pCmdBufLabels = NULL;
callback_data.objectCount = 1;
callback_data.pObjects = &object_name;
object_name.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
object_name.pNext = NULL;
object_name.objectType = VK_OBJECT_TYPE_INSTANCE;
object_name.objectHandle = (uint64_t)(uintptr_t)inst;
object_name.pObjectName = NULL;
util_SubmitDebugUtilsMessageEXT(inst, severity, type, &callback_data);
}
uint32_t filtered_msg_type = (msg_type & g_loader_debug);
if (0 == filtered_msg_type) {
// Always log to stderr if this is a fatal error
if (0 == (msg_type & VULKAN_LOADER_FATAL_ERROR_BIT)) {
// Exit early if the current instance settings do not ask for logging to stderr
if (inst && inst->settings.settings_active && 0 == (msg_type & inst->settings.debug_level)) {
return;
// Check the global settings and if that doesn't say to skip, check the environment variable
} else if (0 == (msg_type & g_loader_debug)) {
return;
}
}
// Only need enough space to create the filter description header for log messages
// Also use the same header for all output
char cmd_line_msg[64];
size_t cmd_line_size = sizeof(cmd_line_msg);
size_t num_used = 0;
cmd_line_msg[0] = '\0';
cmd_line_size -= 1;
num_used = 1;
// Helper macro which strncat's the given string literal, then updates num_used & cmd_line_end
// Assumes that we haven't used the entire buffer - must manually check this when adding new filter types
// We concat at the end of cmd_line_msg, so that strncat isn't a victim of Schlemiel the Painter
// We write to the end - 1 of cmd_line_msg, as the end is actually a null terminator
#define STRNCAT_TO_BUFFER(string_literal_to_cat) \
loader_strncat(cmd_line_msg + num_used, cmd_line_size - num_used, string_literal_to_cat, sizeof(string_literal_to_cat)); \
num_used += sizeof(string_literal_to_cat) - 1; // subtract one to remove the null terminator in the string literal
if ((msg_type & VULKAN_LOADER_ERROR_BIT) != 0) {
strncat(cmd_line_msg, "ERROR", cmd_line_size - num_used);
num_used += 5;
STRNCAT_TO_BUFFER("ERROR");
} else if ((msg_type & VULKAN_LOADER_WARN_BIT) != 0) {
strncat(cmd_line_msg, "WARNING", cmd_line_size - num_used);
num_used += 7;
STRNCAT_TO_BUFFER("WARNING");
} else if ((msg_type & VULKAN_LOADER_INFO_BIT) != 0) {
strncat(cmd_line_msg, "INFO", cmd_line_size - num_used);
num_used += 4;
STRNCAT_TO_BUFFER("INFO");
} else if ((msg_type & VULKAN_LOADER_DEBUG_BIT) != 0) {
strncat(cmd_line_msg, "DEBUG", cmd_line_size - num_used);
num_used += 5;
}
// For the remaining messages, we only want to add any tags that are
// explicitly enabled by the tools.
if ((filtered_msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
if (num_used > 1) {
strncat(cmd_line_msg, " | ", cmd_line_size - num_used);
num_used += 3;
}
strncat(cmd_line_msg, "PERF", cmd_line_size - num_used);
num_used += 4;
}
if ((filtered_msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
if (num_used > 1) {
strncat(cmd_line_msg, " | ", cmd_line_size - num_used);
num_used += 3;
}
strncat(cmd_line_msg, "DRIVER", cmd_line_size - num_used);
num_used += 6;
}
if ((filtered_msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
if (num_used > 1) {
strncat(cmd_line_msg, " | ", cmd_line_size - num_used);
num_used += 3;
}
strncat(cmd_line_msg, "LAYER", cmd_line_size - num_used);
num_used += 5;
}
// Add any preceeding spaces so we can have clean output
if (num_used > 1) {
strncat(cmd_line_msg, ": ", cmd_line_size - num_used);
num_used += 2;
}
while (num_used < 19) {
strncat(cmd_line_msg, " ", cmd_line_size - num_used);
num_used++;
STRNCAT_TO_BUFFER("DEBUG");
}
size_t available_space = cmd_line_size - num_used;
if (available_space > 0) {
// If the message is too long, trim it down
if (strlen(msg) > available_space) {
msg[available_space - 1] = '\0';
if ((msg_type & VULKAN_LOADER_PERF_BIT) != 0) {
if (num_used > 1) {
STRNCAT_TO_BUFFER(" | ");
}
STRNCAT_TO_BUFFER("PERF");
}
if ((msg_type & VULKAN_LOADER_DRIVER_BIT) != 0) {
if (num_used > 1) {
STRNCAT_TO_BUFFER(" | ");
}
STRNCAT_TO_BUFFER("DRIVER");
}
if ((msg_type & VULKAN_LOADER_LAYER_BIT) != 0) {
if (num_used > 1) {
STRNCAT_TO_BUFFER(" | ");
}
STRNCAT_TO_BUFFER("LAYER");
}
strncat(cmd_line_msg, msg, cmd_line_size);
// Add a ": " to separate the filters from the message
STRNCAT_TO_BUFFER(": ");
#undef STRNCAT_TO_BUFFER
// Justifies the output to at least 19 spaces
if (num_used < 19) {
const char *space_buffer = " ";
// Only write (19 - num_used) spaces
loader_strncat(cmd_line_msg + num_used, cmd_line_size - num_used, space_buffer, 19 - num_used);
num_used += sizeof(space_buffer) - 1 - num_used;
}
// Assert that we didn't write more than what is available in cmd_line_msg
assert(cmd_line_size > num_used);
#if !defined (__OHOS__)
fputs(cmd_line_msg, stderr);
fputs(msg, stderr);
fputc('\n', stderr);
#endif
#if defined(WIN32)
OutputDebugString(cmd_line_msg);
OutputDebugString(msg);
OutputDebugString("\n");
#endif
#if defined(VK_USE_PLATFORM_OHOS)
OpenHarmonyLog(msg_type, cmd_line_msg);
#if defined(__OHOS__)
char result[512 + 64];
strcpy(result, cmd_line_msg);
strcat(result, msg);
OpenHarmonyLog(msg_type, result);
#endif
fputs(cmd_line_msg, stderr);
fputc('\n', stderr);
} else {
// Shouldn't get here, but check to make sure if we've already overrun
// the string boundary
assert(false);
}
}
void loader_log_asm_function_not_supported(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code,
const char *func_name) {
loader_log(inst, msg_type, msg_code, "Function %s not supported for this physical device", func_name);
}

View File

@ -26,7 +26,14 @@
*
*/
#include "loader_common.h"
#pragma once
#include <stdint.h>
#include <stdbool.h>
#include "vulkan/vulkan_core.h"
struct loader_instance;
enum vulkan_loader_debug_flags {
VULKAN_LOADER_INFO_BIT = 0x01,
@ -37,15 +44,31 @@ enum vulkan_loader_debug_flags {
VULKAN_LOADER_LAYER_BIT = 0x20,
VULKAN_LOADER_DRIVER_BIT = 0x40,
VULKAN_LOADER_VALIDATION_BIT = 0x80,
VULKAN_LOADER_FATAL_ERROR_BIT = 0x100, // only forces the output to be printed to stderr, has no other effect
};
// Checks for the environment variable VK_LOADER_DEBUG and sets up the current debug level accordingly
// This should be called before any Vulkan API calls, eg in the initialization of the .dll or .so
void loader_debug_init(void);
void loader_init_global_debug_level(void);
// Returns a bitmask that indicates the current flags that should be output
uint32_t loader_get_debug_level(void);
// Sets the global debug level - used by global settings files
void loader_set_global_debug_level(uint32_t new_loader_debug);
// The asm declaration prevents name mangling which is necessary for macOS
#if defined(MODIFY_UNKNOWN_FUNCTION_DECLS)
#define ASM_NAME(name) __asm(name)
#else
#define ASM_NAME(name)
#endif
// Logs a message to stderr
// May output to DebugUtils if the instance isn't null and the extension is enabled.
void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...);
void loader_log(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code, const char *format, ...)
ASM_NAME("loader_log");
// Used for the assembly code to emit an specific error message
// This is a work around for linux 32 bit error handling not passing relocatable strings correctly
void loader_log_asm_function_not_supported(const struct loader_instance *inst, VkFlags msg_type, int32_t msg_code,
const char *func_name) ASM_NAME("loader_log_asm_function_not_supported");
#undef ASM_NAME

File diff suppressed because it is too large Load Diff

807
loader/settings.c Normal file
View File

@ -0,0 +1,807 @@
/*
*
* Copyright (c) 2023 The Khronos Group Inc.
* 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.
*
*
* Author: Charles Giessen <charles@lunarg.com>
*
*/
#include "settings.h"
#include "allocation.h"
#include "cJSON.h"
#include "loader.h"
#include "loader_environment.h"
#include "loader_windows.h"
#include "log.h"
#include "stack_allocation.h"
#include "vk_loader_platform.h"
loader_platform_thread_mutex global_loader_settings_lock;
loader_settings global_loader_settings;
void free_layer_configuration(const struct loader_instance* inst, loader_settings_layer_configuration* layer_configuration) {
loader_instance_heap_free(inst, layer_configuration->name);
loader_instance_heap_free(inst, layer_configuration->path);
memset(layer_configuration, 0, sizeof(loader_settings_layer_configuration));
}
void free_loader_settings(const struct loader_instance* inst, loader_settings* settings) {
if (NULL != settings->layer_configurations) {
for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
free_layer_configuration(inst, &settings->layer_configurations[i]);
}
}
loader_instance_heap_free(inst, settings->layer_configurations);
loader_instance_heap_free(inst, settings->settings_file_path);
memset(settings, 0, sizeof(loader_settings));
}
loader_settings_layer_control parse_control_string(char* control_string) {
loader_settings_layer_control layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
if (strcmp(control_string, "auto") == 0)
layer_control = LOADER_SETTINGS_LAYER_CONTROL_DEFAULT;
else if (strcmp(control_string, "on") == 0)
layer_control = LOADER_SETTINGS_LAYER_CONTROL_ON;
else if (strcmp(control_string, "off") == 0)
layer_control = LOADER_SETTINGS_LAYER_CONTROL_OFF;
else if (strcmp(control_string, "unordered_layer_location") == 0)
layer_control = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
return layer_control;
}
const char* loader_settings_layer_control_to_string(loader_settings_layer_control control) {
switch (control) {
case (LOADER_SETTINGS_LAYER_CONTROL_DEFAULT):
return "auto";
case (LOADER_SETTINGS_LAYER_CONTROL_ON):
return "on";
case (LOADER_SETTINGS_LAYER_CONTROL_OFF):
return "off";
case (LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION):
return "unordered_layer_location";
default:
return "UNKNOWN_LAYER_CONTROl";
}
}
uint32_t parse_log_filters_from_strings(struct loader_string_list* log_filters) {
uint32_t filters = 0;
for (uint32_t i = 0; i < log_filters->count; i++) {
if (strcmp(log_filters->list[i], "all") == 0)
filters |= VULKAN_LOADER_INFO_BIT | VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_PERF_BIT | VULKAN_LOADER_ERROR_BIT |
VULKAN_LOADER_DEBUG_BIT | VULKAN_LOADER_LAYER_BIT | VULKAN_LOADER_DRIVER_BIT | VULKAN_LOADER_VALIDATION_BIT;
else if (strcmp(log_filters->list[i], "info") == 0)
filters |= VULKAN_LOADER_INFO_BIT;
else if (strcmp(log_filters->list[i], "warn") == 0)
filters |= VULKAN_LOADER_WARN_BIT;
else if (strcmp(log_filters->list[i], "perf") == 0)
filters |= VULKAN_LOADER_PERF_BIT;
else if (strcmp(log_filters->list[i], "error") == 0)
filters |= VULKAN_LOADER_ERROR_BIT;
else if (strcmp(log_filters->list[i], "debug") == 0)
filters |= VULKAN_LOADER_DEBUG_BIT;
else if (strcmp(log_filters->list[i], "layer") == 0)
filters |= VULKAN_LOADER_LAYER_BIT;
else if (strcmp(log_filters->list[i], "driver") == 0)
filters |= VULKAN_LOADER_DRIVER_BIT;
else if (strcmp(log_filters->list[i], "validation") == 0)
filters |= VULKAN_LOADER_VALIDATION_BIT;
}
return filters;
}
bool parse_json_enable_disable_option(const struct loader_instance* inst, cJSON* object, const char* key) {
char* str = NULL;
VkResult res = loader_parse_json_string(object, key, &str);
if (res != VK_SUCCESS || NULL == str) {
return false;
}
bool enable = false;
if (strcmp(str, "enabled") == 0) {
enable = true;
}
loader_instance_heap_free(inst, str);
return enable;
}
VkResult parse_layer_configuration(const struct loader_instance* inst, cJSON* layer_configuration_json,
loader_settings_layer_configuration* layer_configuration) {
char* control_string = NULL;
VkResult res = loader_parse_json_string(layer_configuration_json, "control", &control_string);
if (res != VK_SUCCESS) {
goto out;
}
layer_configuration->control = parse_control_string(control_string);
loader_instance_heap_free(inst, control_string);
// If that is the only value - do no further parsing
if (layer_configuration->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
goto out;
}
res = loader_parse_json_string(layer_configuration_json, "name", &(layer_configuration->name));
if (res != VK_SUCCESS) {
goto out;
}
res = loader_parse_json_string(layer_configuration_json, "path", &(layer_configuration->path));
if (res != VK_SUCCESS) {
goto out;
}
cJSON* treat_as_implicit_manifest = loader_cJSON_GetObjectItem(layer_configuration_json, "treat_as_implicit_manifest");
if (treat_as_implicit_manifest && treat_as_implicit_manifest->type == cJSON_True) {
layer_configuration->treat_as_implicit_manifest = true;
}
out:
if (VK_SUCCESS != res) {
free_layer_configuration(inst, layer_configuration);
}
return res;
}
VkResult parse_layer_configurations(const struct loader_instance* inst, cJSON* settings_object, loader_settings* loader_settings) {
VkResult res = VK_SUCCESS;
cJSON* layer_configurations = loader_cJSON_GetObjectItem(settings_object, "layers");
if (NULL == layer_configurations) {
return VK_ERROR_INITIALIZATION_FAILED;
}
uint32_t layer_configurations_count = loader_cJSON_GetArraySize(layer_configurations);
if (layer_configurations_count == 0) {
return VK_SUCCESS;
}
loader_settings->layer_configuration_count = layer_configurations_count;
loader_settings->layer_configurations = loader_instance_heap_calloc(
inst, sizeof(loader_settings_layer_configuration) * layer_configurations_count, VK_SYSTEM_ALLOCATION_SCOPE_INSTANCE);
if (NULL == loader_settings->layer_configurations) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
for (uint32_t i = 0; i < layer_configurations_count; i++) {
cJSON* layer = loader_cJSON_GetArrayItem(layer_configurations, i);
if (NULL == layer) {
res = VK_ERROR_INITIALIZATION_FAILED;
goto out;
}
res = parse_layer_configuration(inst, layer, &(loader_settings->layer_configurations[i]));
if (VK_SUCCESS != res) {
goto out;
}
}
out:
if (res != VK_SUCCESS) {
if (loader_settings->layer_configurations) {
for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
free_layer_configuration(inst, &(loader_settings->layer_configurations[i]));
}
loader_settings->layer_configuration_count = 0;
loader_instance_heap_free(inst, loader_settings->layer_configurations);
loader_settings->layer_configurations = NULL;
}
}
return res;
}
VkResult check_if_settings_path_exists(const struct loader_instance* inst, char* base, char* suffix, char** settings_file_path) {
if (NULL == base || NULL == suffix) {
return VK_ERROR_INITIALIZATION_FAILED;
}
size_t base_len = strlen(base);
size_t suffix_len = strlen(suffix);
size_t path_len = base_len + suffix_len + 1;
*settings_file_path = loader_instance_heap_calloc(inst, path_len, VK_SYSTEM_ALLOCATION_SCOPE_COMMAND);
if (NULL == *settings_file_path) {
return VK_ERROR_OUT_OF_HOST_MEMORY;
}
loader_strncpy(*settings_file_path, path_len, base, base_len);
loader_strncat(*settings_file_path, path_len, suffix, suffix_len);
if (!loader_platform_file_exists(*settings_file_path)) {
loader_instance_heap_free(inst, *settings_file_path);
*settings_file_path = NULL;
return VK_ERROR_INITIALIZATION_FAILED;
}
return VK_SUCCESS;
}
VkResult get_unix_settings_path(const struct loader_instance* inst, char** settings_file_path) {
VkResult res =
check_if_settings_path_exists(inst, loader_secure_getenv("HOME", inst),
"/.local/share/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
if (res == VK_SUCCESS) {
return res;
}
// If HOME isn't set, fallback to XDG_DATA_HOME
res = check_if_settings_path_exists(inst, loader_secure_getenv("XDG_DATA_HOME", inst),
"/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME, settings_file_path);
if (res == VK_SUCCESS) {
return res;
}
// if XDG_DATA_HOME isn't set, fallback to /etc.
// note that the settings_fil_path_suffix stays the same since its the same layout as for XDG_DATA_HOME
return check_if_settings_path_exists(inst, "/etc", "/vulkan/loader_settings.d/" VK_LOADER_SETTINGS_FILENAME,
settings_file_path);
}
bool check_if_settings_are_equal(loader_settings* a, loader_settings* b) {
// If either pointer is null, return true
if (NULL == a || NULL == b) return false;
bool are_equal = true;
are_equal &= a->settings_active == b->settings_active;
are_equal &= a->has_unordered_layer_location == b->has_unordered_layer_location;
are_equal &= a->debug_level == b->debug_level;
are_equal &= a->layer_configuration_count == b->layer_configuration_count;
if (!are_equal) return false;
for (uint32_t i = 0; i < a->layer_configuration_count && i < b->layer_configuration_count; i++) {
if (a->layer_configurations[i].name && b->layer_configurations[i].name) {
are_equal &= 0 == strcmp(a->layer_configurations[i].name, b->layer_configurations[i].name);
} else {
are_equal = false;
}
if (a->layer_configurations[i].path && b->layer_configurations[i].path) {
are_equal &= 0 == strcmp(a->layer_configurations[i].path, b->layer_configurations[i].path);
} else {
are_equal = false;
}
are_equal &= a->layer_configurations[i].control == b->layer_configurations[i].control;
}
return are_equal;
}
void log_settings(const struct loader_instance* inst, loader_settings* settings) {
if (settings == NULL) {
return;
}
loader_log(inst, VULKAN_LOADER_INFO_BIT, 0, "Using layer configurations found in loader settings from %s",
settings->settings_file_path);
loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Layer Configurations count = %d", settings->layer_configuration_count);
for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---- Layer Configuration [%d] ----", i);
if (settings->layer_configurations[i].control != LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Name: %s", settings->layer_configurations[i].name);
loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Path: %s", settings->layer_configurations[i].path);
}
loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "Control: %s",
loader_settings_layer_control_to_string(settings->layer_configurations[i].control));
}
loader_log(inst, VULKAN_LOADER_DEBUG_BIT, 0, "---------------------------------");
}
// Loads the vk_loader_settings.json file
// Returns VK_SUCCESS if it was found & was successfully parsed. Otherwise, it returns VK_ERROR_INITIALIZATION_FAILED if it
// wasn't found or failed to parse, and returns VK_ERROR_OUT_OF_HOST_MEMORY if it was unable to allocate enough memory.
VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings) {
VkResult res = VK_SUCCESS;
cJSON* json = NULL;
char* file_format_version_string = NULL;
char* settings_file_path = NULL;
#if defined(WIN32)
res = windows_get_loader_settings_file_path(inst, &settings_file_path);
if (res != VK_SUCCESS) {
goto out;
}
#elif COMMON_UNIX_PLATFORMS
res = get_unix_settings_path(inst, &settings_file_path);
if (res != VK_SUCCESS) {
goto out;
}
#else
#warning "Unsupported platform - must specify platform specific location for vk_loader_settings.json"
#endif
res = loader_get_json(inst, settings_file_path, &json);
// Make sure sure the top level json value is an object
if (res != VK_SUCCESS || NULL == json || json->type != 6) {
goto out;
}
res = loader_parse_json_string(json, "file_format_version", &file_format_version_string);
if (res != VK_SUCCESS) {
goto out;
}
uint32_t settings_array_count = 0;
bool has_multi_setting_file = false;
cJSON* settings_array = loader_cJSON_GetObjectItem(json, "settings_array");
cJSON* single_settings_object = loader_cJSON_GetObjectItem(json, "settings");
if (NULL != settings_array) {
has_multi_setting_file = true;
settings_array_count = loader_cJSON_GetArraySize(settings_array);
} else if (NULL != single_settings_object) {
settings_array_count = 1;
}
// Corresponds to the settings object that has no app keys
int global_settings_index = -1;
// Corresponds to the settings object which has a matching app key
int index_to_use = -1;
char current_process_path[1024];
bool valid_exe_path = NULL != loader_platform_executable_path(current_process_path, 1024);
for (int i = 0; i < (int)settings_array_count; i++) {
if (has_multi_setting_file) {
single_settings_object = loader_cJSON_GetArrayItem(settings_array, i);
}
cJSON* app_keys = loader_cJSON_GetObjectItem(single_settings_object, "app_keys");
if (NULL == app_keys) {
if (global_settings_index == -1) {
global_settings_index = i; // use the first 'global' settings that has no app keys as the global one
}
continue;
} else if (valid_exe_path) {
int app_key_count = loader_cJSON_GetArraySize(app_keys);
if (app_key_count == 0) {
continue; // empty array
}
for (int j = 0; j < app_key_count; j++) {
cJSON* app_key_json = loader_cJSON_GetArrayItem(app_keys, j);
if (NULL == app_key_json) {
continue;
}
char* app_key = loader_cJSON_Print(app_key_json);
if (NULL == app_key) {
continue;
}
if (strcmp(current_process_path, app_key) == 0) {
index_to_use = i;
}
loader_instance_heap_free(inst, app_key);
if (index_to_use == i) {
break; // break only after freeing the app key
}
}
}
}
// No app specific settings match - either use global settings or exit
if (index_to_use == -1) {
if (global_settings_index == -1) {
goto out; // No global settings were found - exit
} else {
index_to_use = global_settings_index; // Global settings are present - use it
}
}
// Now get the actual settings object to use - already have it if there is only one settings object
// If there are multiple settings, just need to set single_settings_object to the desired settings object
if (has_multi_setting_file) {
single_settings_object = loader_cJSON_GetArrayItem(settings_array, index_to_use);
if (NULL == single_settings_object) {
res = VK_ERROR_INITIALIZATION_FAILED;
goto out;
}
}
// optional
cJSON* stderr_filter = loader_cJSON_GetObjectItem(single_settings_object, "stderr_log");
if (NULL != stderr_filter) {
struct loader_string_list stderr_log = {0};
res = loader_parse_json_array_of_strings(inst, single_settings_object, "stderr_log", &stderr_log);
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
goto out;
}
loader_settings->debug_level = parse_log_filters_from_strings(&stderr_log);
free_string_list(inst, &stderr_log);
}
// optional
cJSON* logs_to_use = loader_cJSON_GetObjectItem(single_settings_object, "log_locations");
if (NULL != logs_to_use) {
int log_count = loader_cJSON_GetArraySize(logs_to_use);
for (int i = 0; i < log_count; i++) {
cJSON* log_element = loader_cJSON_GetArrayItem(logs_to_use, i);
// bool is_valid = true;
if (NULL != log_element) {
struct loader_string_list log_destinations = {0};
res = loader_parse_json_array_of_strings(inst, log_element, "destinations", &log_destinations);
if (res != VK_SUCCESS) {
// is_valid = false;
}
free_string_list(inst, &log_destinations);
struct loader_string_list log_filters = {0};
res = loader_parse_json_array_of_strings(inst, log_element, "filters", &log_filters);
if (res != VK_SUCCESS) {
// is_valid = false;
}
free_string_list(inst, &log_filters);
}
}
}
res = parse_layer_configurations(inst, single_settings_object, loader_settings);
if (res != VK_SUCCESS) {
goto out;
}
// Determine if there exists a layer configuration indicating where to put layers not contained in the settings file
// LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION
for (uint32_t i = 0; i < loader_settings->layer_configuration_count; i++) {
if (loader_settings->layer_configurations[i].control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
loader_settings->has_unordered_layer_location = true;
break;
}
}
loader_settings->settings_file_path = settings_file_path;
settings_file_path = NULL;
loader_settings->settings_active = true;
out:
if (NULL != json) {
loader_cJSON_Delete(json);
}
loader_instance_heap_free(inst, settings_file_path);
loader_instance_heap_free(inst, file_format_version_string);
return res;
}
VkResult update_global_loader_settings(void) {
loader_settings settings = {0};
VkResult res = get_loader_settings(NULL, &settings);
loader_platform_thread_lock_mutex(&global_loader_settings_lock);
free_loader_settings(NULL, &global_loader_settings);
if (res == VK_SUCCESS) {
if (!check_if_settings_are_equal(&settings, &global_loader_settings)) {
log_settings(NULL, &settings);
}
memcpy(&global_loader_settings, &settings, sizeof(loader_settings));
if (global_loader_settings.settings_active) {
loader_set_global_debug_level(global_loader_settings.debug_level);
}
}
loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
return res;
}
void init_global_loader_settings(void) {
loader_platform_thread_create_mutex(&global_loader_settings_lock);
// Free out the global settings in case the process was loaded & unloaded
free_loader_settings(NULL, &global_loader_settings);
}
void teardown_global_loader_settings(void) {
free_loader_settings(NULL, &global_loader_settings);
loader_platform_thread_delete_mutex(&global_loader_settings_lock);
}
bool should_skip_logging_global_messages(VkFlags msg_type) {
loader_platform_thread_lock_mutex(&global_loader_settings_lock);
bool should_skip = global_loader_settings.settings_active && 0 != (msg_type & global_loader_settings.debug_level);
loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
return should_skip;
}
// Use this function to get the correct settings to use based on the context
// If inst is NULL - use the global settings and lock the mutex
// Else return the settings local to the instance - but do nto lock the mutex
const loader_settings* get_current_settings_and_lock(const struct loader_instance* inst) {
if (inst) {
return &inst->settings;
}
loader_platform_thread_lock_mutex(&global_loader_settings_lock);
return &global_loader_settings;
}
// Release the global settings lock if we are using the global settings - aka if inst is NULL
void release_current_settings_lock(const struct loader_instance* inst) {
if (inst == NULL) {
loader_platform_thread_unlock_mutex(&global_loader_settings_lock);
}
}
VkResult get_settings_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
bool* should_search_for_other_layers) {
VkResult res = VK_SUCCESS;
*should_search_for_other_layers = true; // default to true
const loader_settings* settings = get_current_settings_and_lock(inst);
if (NULL == settings || !settings->settings_active) {
goto out;
}
// Assume the list doesn't contain LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION at first
*should_search_for_other_layers = false;
for (uint32_t i = 0; i < settings->layer_configuration_count; i++) {
loader_settings_layer_configuration* layer_config = &settings->layer_configurations[i];
// If we encountered a layer that should be forced off, we add it to the settings_layers list but only
// with the data required to compare it with layers not in the settings file (aka name and manifest path)
if (layer_config->control == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
struct loader_layer_properties props = {0};
props.settings_control_value = LOADER_SETTINGS_LAYER_CONTROL_OFF;
loader_strncpy(props.info.layerName, VK_MAX_EXTENSION_NAME_SIZE, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE);
props.info.layerName[VK_MAX_EXTENSION_NAME_SIZE - 1] = '\0';
res = loader_copy_to_new_str(inst, layer_config->path, &props.manifest_file_name);
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
goto out;
}
res = loader_append_layer_property(inst, settings_layers, &props);
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
loader_free_layer_properties(inst, &props);
goto out;
}
continue;
}
// The special layer location that indicates where unordered layers should go only should have the
// settings_control_value set - everything else should be NULL
if (layer_config->control == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
struct loader_layer_properties props = {0};
props.settings_control_value = LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION;
res = loader_append_layer_property(inst, settings_layers, &props);
if (VK_ERROR_OUT_OF_HOST_MEMORY == res) {
loader_free_layer_properties(inst, &props);
goto out;
}
*should_search_for_other_layers = true;
continue;
}
if (layer_config->path == NULL) {
continue;
}
cJSON* json = NULL;
VkResult local_res = loader_get_json(inst, layer_config->path, &json);
if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
} else if (VK_SUCCESS != local_res || NULL == json) {
continue;
}
local_res =
loader_add_layer_properties(inst, settings_layers, json, layer_config->treat_as_implicit_manifest, layer_config->path);
loader_cJSON_Delete(json);
// If the error is anything other than out of memory we still want to try to load the other layers
if (VK_ERROR_OUT_OF_HOST_MEMORY == local_res) {
res = VK_ERROR_OUT_OF_HOST_MEMORY;
goto out;
}
struct loader_layer_properties* newly_added_layer = &settings_layers->list[settings_layers->count - 1];
newly_added_layer->settings_control_value = layer_config->control;
// If the manifest file found has a name that differs from the one in the settings, remove this layer from consideration
bool should_remove = false;
if (strncmp(newly_added_layer->info.layerName, layer_config->name, VK_MAX_EXTENSION_NAME_SIZE) != 0) {
should_remove = true;
loader_remove_layer_in_list(inst, settings_layers, settings_layers->count - 1);
}
// Make sure the layer isn't already in the list
for (uint32_t j = 0; settings_layers->count > 0 && j < settings_layers->count - 1; j++) {
if (0 ==
strncmp(settings_layers->list[j].info.layerName, newly_added_layer->info.layerName, VK_MAX_EXTENSION_NAME_SIZE)) {
if (0 == (newly_added_layer->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
strcmp(settings_layers->list[j].lib_name, newly_added_layer->lib_name) == 0) {
should_remove = true;
break;
}
}
}
if (should_remove) {
loader_remove_layer_in_list(inst, settings_layers, settings_layers->count - 1);
}
}
out:
release_current_settings_lock(inst);
return res;
}
// Check if layers has an element with the same name.
// If layer_property is a regular layer, check if the lib_path is the same.
// If layer_property is a meta layer, just use the layerName
bool check_if_layer_is_in_list(struct loader_layer_list* layer_list, struct loader_layer_properties* layer_property) {
// If the layer is a meta layer, just check against the name
for (uint32_t i = 0; i < layer_list->count; i++) {
if (0 == strncmp(layer_list->list[i].info.layerName, layer_property->info.layerName, VK_MAX_EXTENSION_NAME_SIZE)) {
if (0 == (layer_property->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) &&
strcmp(layer_list->list[i].lib_name, layer_property->lib_name) == 0) {
return true;
}
}
}
return false;
}
VkResult combine_settings_layers_with_regular_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
struct loader_layer_list* regular_layers,
struct loader_layer_list* output_layers) {
VkResult res = VK_SUCCESS;
bool has_unordered_layer_location = false;
uint32_t unordered_layer_location_index = 0;
// Location to put layers that aren't known to the settings file
// Find it here so we dont have to pass in a loader_settings struct
for (uint32_t i = 0; i < settings_layers->count; i++) {
if (settings_layers->list[i].settings_control_value == LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION) {
has_unordered_layer_location = true;
unordered_layer_location_index = i;
break;
}
}
if (settings_layers->count == 0 && regular_layers->count == 0) {
// No layers to combine
goto out;
} else if (settings_layers->count == 0) {
// No settings layers - just copy regular to output_layers - memset regular layers to prevent double frees
*output_layers = *regular_layers;
memset(regular_layers, 0, sizeof(struct loader_layer_list));
goto out;
} else if (regular_layers->count == 0 || !has_unordered_layer_location) {
// No regular layers or has_unordered_layer_location is false - just copy settings to output_layers -
// memset settings layers to prevent double frees
*output_layers = *settings_layers;
memset(settings_layers, 0, sizeof(struct loader_layer_list));
goto out;
}
res = loader_init_generic_list(inst, (struct loader_generic_list*)output_layers,
(settings_layers->count + regular_layers->count) * sizeof(struct loader_layer_properties));
if (VK_SUCCESS != res) {
goto out;
}
// Insert the settings layers into output_layers up to unordered_layer_index
for (uint32_t i = 0; i < unordered_layer_location_index; i++) {
if (!check_if_layer_is_in_list(output_layers, &settings_layers->list[i])) {
res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
if (VK_SUCCESS != res) {
goto out;
}
}
}
for (uint32_t i = 0; i < regular_layers->count; i++) {
// Check if its already been put in the output_layers list as well as the remaining settings_layers
bool regular_layer_is_ordered = check_if_layer_is_in_list(output_layers, &regular_layers->list[i]) ||
check_if_layer_is_in_list(settings_layers, &regular_layers->list[i]);
// If it isn't found, add it
if (!regular_layer_is_ordered) {
res = loader_append_layer_property(inst, output_layers, &regular_layers->list[i]);
if (VK_SUCCESS != res) {
goto out;
}
} else {
// layer is already ordered and can be safely freed
loader_free_layer_properties(inst, &regular_layers->list[i]);
}
}
// Insert the rest of the settings layers into combined_layers from unordered_layer_index to the end
// start at one after the unordered_layer_index
for (uint32_t i = unordered_layer_location_index + 1; i < settings_layers->count; i++) {
res = loader_append_layer_property(inst, output_layers, &settings_layers->list[i]);
if (VK_SUCCESS != res) {
goto out;
}
}
out:
if (res != VK_SUCCESS) {
loader_delete_layer_list_and_properties(inst, output_layers);
}
return res;
}
VkResult enable_correct_layers_from_settings(const struct loader_instance* inst, const struct loader_envvar_all_filters* filters,
uint32_t app_enabled_name_count, const char* const* app_enabled_names,
const struct loader_layer_list* instance_layers,
struct loader_pointer_layer_list* target_layer_list,
struct loader_pointer_layer_list* activated_layer_list) {
VkResult res = VK_SUCCESS;
char* vk_instance_layers_env = loader_getenv(ENABLED_LAYERS_ENV, inst);
size_t vk_instance_layers_env_len = 0;
char* vk_instance_layers_env_copy = NULL;
if (vk_instance_layers_env != NULL) {
vk_instance_layers_env_len = strlen(vk_instance_layers_env) + 1;
vk_instance_layers_env_copy = loader_stack_alloc(vk_instance_layers_env_len);
loader_log(inst, VULKAN_LOADER_WARN_BIT | VULKAN_LOADER_LAYER_BIT, 0, "env var \'%s\' defined and adding layers: %s",
ENABLED_LAYERS_ENV, vk_instance_layers_env);
}
for (uint32_t i = 0; i < instance_layers->count; i++) {
bool enable_layer = false;
struct loader_layer_properties* props = &instance_layers->list[i];
// Do not enable the layer if the settings have it set as off
if (props->settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_OFF) {
continue;
}
// Force enable it based on settings
if (props->settings_control_value == LOADER_SETTINGS_LAYER_CONTROL_ON) {
enable_layer = true;
}
// Check if disable filter needs to skip the layer
if ((filters->disable_filter.disable_all || filters->disable_filter.disable_all_implicit ||
check_name_matches_filter_environment_var(props->info.layerName, &filters->disable_filter.additional_filters)) &&
!check_name_matches_filter_environment_var(props->info.layerName, &filters->allow_filter)) {
continue;
}
// Check the enable filter
if (!enable_layer && check_name_matches_filter_environment_var(props->info.layerName, &filters->enable_filter)) {
enable_layer = true;
}
// First look for the old-fashion layers forced on with VK_INSTANCE_LAYERS
if (!enable_layer && vk_instance_layers_env && vk_instance_layers_env_copy && vk_instance_layers_env_len > 0) {
// Copy the env-var on each iteration, so that loader_get_next_path can correctly find the separators
// This solution only needs one stack allocation ahead of time rather than an allocation per layer in the env-var
loader_strncpy(vk_instance_layers_env_copy, vk_instance_layers_env_len, vk_instance_layers_env,
vk_instance_layers_env_len);
while (vk_instance_layers_env_copy && *vk_instance_layers_env_copy) {
char* next = loader_get_next_path(vk_instance_layers_env_copy);
if (0 == strcmp(vk_instance_layers_env_copy, props->info.layerName)) {
enable_layer = true;
break;
}
vk_instance_layers_env_copy = next;
}
}
// Check if it should be enabled by the application
if (!enable_layer) {
for (uint32_t j = 0; j < app_enabled_name_count; j++) {
if (strcmp(props->info.layerName, app_enabled_names[j]) == 0) {
enable_layer = true;
break;
}
}
}
// Check if its an implicit layers and thus enabled by default
if (!enable_layer && (0 == (props->type_flags & VK_LAYER_TYPE_FLAG_EXPLICIT_LAYER)) &&
loader_implicit_layer_is_enabled(inst, filters, props)) {
enable_layer = true;
}
if (enable_layer) {
// Check if the layer is a meta layer reuse the existing function to add the meta layer
if (props->type_flags & VK_LAYER_TYPE_FLAG_META_LAYER) {
res = loader_add_meta_layer(inst, filters, props, target_layer_list, activated_layer_list, instance_layers, NULL);
if (res == VK_ERROR_OUT_OF_HOST_MEMORY) goto out;
} else {
res = loader_add_layer_properties_to_list(inst, target_layer_list, props);
if (res != VK_SUCCESS) {
goto out;
}
res = loader_add_layer_properties_to_list(inst, activated_layer_list, props);
if (res != VK_SUCCESS) {
goto out;
}
}
}
}
out:
return res;
}

114
loader/settings.h Normal file
View File

@ -0,0 +1,114 @@
/*
*
* Copyright (c) 2023 The Khronos Group Inc.
* 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.
*
*
* Author: Charles Giessen <charles@lunarg.com>
*
*/
#pragma once
#include <stdio.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdint.h>
#include "vulkan/vulkan_core.h"
#include "log.h"
struct loader_instance;
struct loader_layer_list;
struct loader_pointer_layer_list;
struct loader_envvar_all_filters;
typedef struct log_configuration log_configuration;
typedef enum loader_settings_layer_control {
LOADER_SETTINGS_LAYER_CONTROL_DEFAULT, // layer is not enabled by settings file but can be enabled through other means
LOADER_SETTINGS_LAYER_CONTROL_ON, // layer is enabled by settings file
LOADER_SETTINGS_LAYER_CONTROL_OFF, // layer is prevented from being enabled
LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION // special control indicating unspecified layers should go here. If this is not
// in the settings file, then the loader assume no other layers should be
// searched & loaded.
} loader_settings_layer_control;
// If a loader_settings_layer_configuration has a name of loader_settings_unknown_layers_location, then it specifies that the
// layer configuration it was found in shall be the location all layers not listed in the settings file that are enabled.
#define LOADER_SETTINGS_UNKNOWN_LAYERS_LOCATION "loader_settings_unknown_layers_location"
#define LOADER_SETTINGS_MAX_NAME_SIZE 256U;
typedef struct loader_settings_layer_configuration {
char* name;
char* path;
loader_settings_layer_control control;
bool treat_as_implicit_manifest; // whether or not the layer should be parsed as if it is implicit
} loader_settings_layer_configuration;
typedef struct loader_settings {
bool settings_active;
bool has_unordered_layer_location;
enum vulkan_loader_debug_flags debug_level;
uint32_t layer_configuration_count;
loader_settings_layer_configuration* layer_configurations;
char* settings_file_path;
} loader_settings;
// Call this function to get the current settings that the loader should use.
// It will open up the current loader settings file and return a loader_settings in out_loader_settings if it.
// It should be called on every call to the global functions excluding vkGetInstanceProcAddr
// Caller is responsible for cleaning up by calling free_loader_settings()
VkResult get_loader_settings(const struct loader_instance* inst, loader_settings* out_loader_settings);
void free_loader_settings(const struct loader_instance* inst, loader_settings* loader_settings);
// Log the settings to the console
void log_settings(const struct loader_instance* inst, loader_settings* settings);
// Every global function needs to call this at startup to insure that
VkResult update_global_loader_settings(void);
// Needs to be called during startup -
void init_global_loader_settings(void);
void teardown_global_loader_settings(void);
// Check the global settings and return true if msg_type does not correspond to the active global loader settings
bool should_skip_logging_global_messages(VkFlags msg_type);
// Query the current settings (either global or per-instance) and return the list of layers contained within.
// should_search_for_other_layers tells the caller if the settings file should be used exclusively for layer searching or not
VkResult get_settings_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
bool* should_search_for_other_layers);
// Take the provided list of settings_layers and add in the layers from regular search paths
// Only adds layers that aren't already present in the settings_layers and in the location of the
// layer configuration with LOADER_SETTINGS_LAYER_UNORDERED_LAYER_LOCATION set
VkResult combine_settings_layers_with_regular_layers(const struct loader_instance* inst, struct loader_layer_list* settings_layers,
struct loader_layer_list* regular_layers,
struct loader_layer_list* output_layers);
// Fill out activated_layer_list with the layers that should be activated, based on environment variables, VkInstanceCreateInfo, and
// the settings
VkResult enable_correct_layers_from_settings(const struct loader_instance* inst, const struct loader_envvar_all_filters* filters,
uint32_t app_enabled_name_count, const char* const* app_enabled_names,
const struct loader_layer_list* instance_layers,
struct loader_pointer_layer_list* target_layer_list,
struct loader_pointer_layer_list* activated_layer_list);

View File

@ -36,8 +36,10 @@
#include <stdlib.h>
#endif
#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#if COMMON_UNIX_PLATFORMS
#define loader_stack_alloc(size) alloca(size)
#elif defined(_WIN32)
#define loader_stack_alloc(size) _alloca(size)
#else
#warning "alloca not available on this platform!"
#endif // defined(_WIN32)

View File

@ -4,6 +4,8 @@
* Copyright (c) 2014-2021 Valve Corporation
* Copyright (c) 2014-2021 LunarG, Inc.
* Copyright (C) 2015 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.
@ -113,6 +115,8 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceSparseImageFormatProperti
VKAPI_ATTR VkResult VKAPI_CALL terminator_EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount,
VkLayerProperties *pProperties) {
(void)pPropertyCount;
(void)pProperties;
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
loader_log(icd_term->this_instance, VULKAN_LOADER_ERROR_BIT, 0,
@ -280,8 +284,8 @@ VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceFormatProperties2(VkPhysi
}
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties2(
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2KHR *pImageFormatInfo,
VkImageFormatProperties2KHR *pImageFormatProperties) {
VkPhysicalDevice physicalDevice, const VkPhysicalDeviceImageFormatInfo2 *pImageFormatInfo,
VkImageFormatProperties2 *pImageFormatProperties) {
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
const struct loader_instance *inst = icd_term->this_instance;
@ -321,7 +325,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceImageFormatProperties
VKAPI_ATTR void VKAPI_CALL terminator_GetPhysicalDeviceQueueFamilyProperties2(VkPhysicalDevice physicalDevice,
uint32_t *pQueueFamilyPropertyCount,
VkQueueFamilyProperties2KHR *pQueueFamilyProperties) {
VkQueueFamilyProperties2 *pQueueFamilyProperties) {
struct loader_physical_device_term *phys_dev_term = (struct loader_physical_device_term *)physicalDevice;
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term;
const struct loader_instance *inst = icd_term->this_instance;

File diff suppressed because it is too large Load Diff

View File

@ -48,7 +48,7 @@
struct loader_icd_term *icd_term = phys_dev_term->this_icd_term; \
struct loader_instance *inst = (struct loader_instance *)icd_term->this_instance; \
if (NULL == icd_term->phys_dev_ext[num]) { \
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "Extension %s not supported for this physical device", \
loader_log(inst, VULKAN_LOADER_ERROR_BIT, 0, "Function %s not supported for this physical device", \
inst->phys_dev_ext_disp_functions[num]); \
} \
icd_term->phys_dev_ext[num](phys_dev_term->phys_dev); \

View File

@ -27,6 +27,11 @@
.macro PhysDevExtTramp num
.global vkPhysDevExtTramp\num
#if defined(__ELF__)
.hidden vkPhysDevExtTramp\num
#endif
.balign 4
vkPhysDevExtTramp\num:
ldr x9, [x0] // Load the loader_instance_dispatch_table* into x9
ldr x0, [x0, PHYS_DEV_OFFSET_PHYS_DEV_TRAMP] // Load the unwrapped VkPhysicalDevice into x0
@ -37,6 +42,10 @@ vkPhysDevExtTramp\num:
.macro PhysDevExtTermin num
.global vkPhysDevExtTermin\num
#if defined(__ELF__)
.hidden vkPhysDevExtTermin\num
#endif
.balign 4
vkPhysDevExtTermin\num:
ldr x9, [x0, ICD_TERM_OFFSET_PHYS_DEV_TERM] // Load the loader_icd_term* in x9
mov x11, (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num)) // Put the offset into the dispatch table in x11
@ -50,16 +59,18 @@ terminError\num:
mov x0, x11 // Vulkan instance pointer (first arg)
mov x1, VULKAN_LOADER_ERROR_BIT // The error logging bit (second arg)
mov x2, #0 // Zero (third arg)
adrp x9, termin_error_string
add x3, x9, #:lo12:termin_error_string // The error string (fourth arg)
ldr x4, [x11, x10] // The function name (fifth arg)
bl loader_log // Log the error message before we crash
ldr x3, [x11, x10] // The function name (fourth arg)
bl loader_log_asm_function_not_supported // Log the error message before we crash
mov x0, #0
br x0 // Crash intentionally by jumping to address zero
.endm
.macro DevExtTramp num
.global vkdev_ext\num
#if defined(__ELF__)
.hidden vkdev_ext\num
#endif
.balign 4
vkdev_ext\num:
ldr x9, [x0] // Load the loader_instance_dispatch_table* into x9
mov x10, (EXT_OFFSET_DEVICE_DISPATCH + (PTR_SIZE * \num)) // Offset of the desired function in the dispatch table
@ -76,7 +87,7 @@ vkdev_ext\num:
.data
termin_error_string:
.string "Extension %s not supported for this physical device"
.string "Function %s not supported for this physical device"
.text

View File

@ -1,7 +1,7 @@
#
# Copyright (c) 2017-2021 The Khronos Group Inc.
# Copyright (c) 2017-2021 Valve Corporation
# Copyright (c) 2017-2021 LunarG, Inc.
# Copyright (c) 2017-2023 The Khronos Group Inc.
# Copyright (c) 2017-2023 Valve Corporation
# Copyright (c) 2017-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.
@ -24,7 +24,9 @@
# VkPhysicalDevice or a dispatchable object it can unwrap the object, possibly overwriting the wrapped physical device, and then
# jump to the next function in the call chain
#ifdef HAVE_CET_H
# The .hidden directive is only supported in ELF executables so in APPLE builds, the directive is removed
#if defined(HAVE_CET_H)
#include <cet.h>
#else
#define _CET_ENDBR
@ -37,6 +39,9 @@
.macro PhysDevExtTramp num
.global vkPhysDevExtTramp\num
#if defined(__ELF__)
.hidden vkPhysDevExtTramp\num
#endif
vkPhysDevExtTramp\num:
_CET_ENDBR
mov rax, [rdi]
@ -46,6 +51,9 @@ vkPhysDevExtTramp\num:
.macro PhysDevExtTermin num
.global vkPhysDevExtTermin\num
#if defined(__ELF__)
.hidden vkPhysDevExtTermin\num
#endif
vkPhysDevExtTermin\num:
_CET_ENDBR
mov rax, [rdi + ICD_TERM_OFFSET_PHYS_DEV_TERM] # Store the loader_icd_term* in rax
@ -68,6 +76,9 @@ terminError\num:
.macro DevExtTramp num
.global vkdev_ext\num
#if defined(__ELF__)
.hidden vkdev_ext\num
#endif
vkdev_ext\num:
_CET_ENDBR
mov rax, [rdi] # Dereference the handle to get the dispatch table
@ -78,6 +89,9 @@ vkdev_ext\num:
.macro PhysDevExtTramp num
.global vkPhysDevExtTramp\num
#if defined(__ELF__)
.hidden vkPhysDevExtTramp\num
#endif
vkPhysDevExtTramp\num:
_CET_ENDBR
mov eax, [esp + 4] # Load the wrapped VkPhysicalDevice into eax
@ -89,6 +103,9 @@ vkPhysDevExtTramp\num:
.macro PhysDevExtTermin num
.global vkPhysDevExtTermin\num
#if defined(__ELF__)
.hidden vkPhysDevExtTermin\num
#endif
vkPhysDevExtTermin\num:
_CET_ENDBR
mov ecx, [esp + 4] # Move the wrapped VkPhysicalDevice into ecx
@ -100,12 +117,11 @@ vkPhysDevExtTermin\num:
jmp [eax + (DISPATCH_OFFSET_ICD_TERM + (PTR_SIZE * \num))] # Jump to the next function in the chain
terminError\num:
mov eax, dword ptr [eax + INSTANCE_OFFSET_ICD_TERM] # Load the loader_instance into eax
push dword ptr [eax + (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * \num))] # Push the func name (fifth arg)
push offset termin_error_string@GOT # Push the error string (fourth arg)
push dword ptr [eax + (FUNCTION_OFFSET_INSTANCE + (CHAR_PTR_SIZE * \num))] # Push the func name (fourth arg)
push 0 # Push zero (third arg)
push VULKAN_LOADER_ERROR_BIT # Push the error logging bit (second arg)
push eax # Push the loader_instance (first arg)
call loader_log # Log the error message before we crash
call loader_log_asm_function_not_supported # Log the error message before we crash
add esp, 20 # Clean up the args
mov eax, 0
jmp eax # Crash intentionally by jumping to address zero
@ -113,6 +129,9 @@ terminError\num:
.macro DevExtTramp num
.global vkdev_ext\num
#if defined(__ELF__)
.hidden vkdev_ext\num
#endif
vkdev_ext\num:
_CET_ENDBR
mov eax, dword ptr [esp + 4] # Dereference the handle to get the dispatch table
@ -129,7 +148,7 @@ vkdev_ext\num:
.data
termin_error_string:
.string "Extension %s not supported for this physical device"
.string "Function %s not supported for this physical device"
.text

View File

@ -119,7 +119,7 @@ endm
ENDIF
.const
termin_error_string db 'Extension %s not supported for this physical device', 0
termin_error_string db 'Function %s not supported for this physical device', 0
.code

View File

@ -85,17 +85,16 @@ bool loader_check_icds_for_dev_ext_address(struct loader_instance *inst, const c
// Look in the layers list of device extensions, which contain names of entry points. If funcName is present, return true
// If not, call down the first layer's vkGetInstanceProcAddr to determine if any layers support the function
bool loader_check_layer_list_for_dev_ext_address(struct loader_instance *inst, const char *funcName) {
struct loader_layer_properties *layer_prop_list = inst->expanded_activated_layer_list.list;
// Iterate over the layers.
for (uint32_t layer = 0; layer < inst->expanded_activated_layer_list.count; ++layer) {
// Iterate over the extensions.
const struct loader_device_extension_list *const extensions = &(layer_prop_list[layer].device_extension_list);
const struct loader_device_extension_list *const extensions =
&(inst->expanded_activated_layer_list.list[layer]->device_extension_list);
for (uint32_t extension = 0; extension < extensions->count; ++extension) {
// Iterate over the entry points.
const struct loader_dev_ext_props *const property = &(extensions->list[extension]);
for (uint32_t entry = 0; entry < property->entrypoint_count; ++entry) {
if (strcmp(property->entrypoints[entry], funcName) == 0) {
for (uint32_t entry = 0; entry < property->entrypoints.count; ++entry) {
if (strcmp(property->entrypoints.list[entry], funcName) == 0) {
return true;
}
}
@ -104,7 +103,7 @@ bool loader_check_layer_list_for_dev_ext_address(struct loader_instance *inst, c
// If the function pointer doesn't appear in the layer manifest for intercepted device functions, look down the
// vkGetInstanceProcAddr chain
if (inst->expanded_activated_layer_list.count > 0) {
const struct loader_layer_functions *const functions = &(layer_prop_list[0].functions);
const struct loader_layer_functions *const functions = &(inst->expanded_activated_layer_list.list[0]->functions);
if (NULL != functions->get_instance_proc_addr) {
return NULL != functions->get_instance_proc_addr((VkInstance)inst->instance, funcName);
}
@ -165,7 +164,7 @@ void *loader_dev_ext_gpa_impl(struct loader_instance *inst, const char *funcName
// failed to allocate memory, return NULL
return NULL;
}
strncpy(inst->dev_ext_disp_functions[inst->dev_ext_disp_function_count], funcName, funcName_len);
loader_strncpy(inst->dev_ext_disp_functions[inst->dev_ext_disp_function_count], funcName_len, funcName, funcName_len);
// init any dev dispatch table entries as needed
loader_init_dispatch_dev_ext_entry(inst, NULL, inst->dev_ext_disp_function_count, funcName);
void *out_function = loader_get_dev_ext_trampoline(inst->dev_ext_disp_function_count);
@ -188,6 +187,7 @@ bool loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst, co
icd_term = inst->icd_terms;
while (NULL != icd_term) {
if (icd_term->scanned_icd->interface_version >= MIN_PHYS_DEV_EXTENSION_ICD_INTERFACE_VERSION &&
icd_term->scanned_icd->GetPhysicalDeviceProcAddr &&
icd_term->scanned_icd->GetPhysicalDeviceProcAddr(icd_term->instance, funcName))
// this icd supports funcName
return true;
@ -198,13 +198,13 @@ bool loader_check_icds_for_phys_dev_ext_address(struct loader_instance *inst, co
}
bool loader_check_layer_list_for_phys_dev_ext_address(struct loader_instance *inst, const char *funcName) {
struct loader_layer_properties *layer_prop_list = inst->expanded_activated_layer_list.list;
for (uint32_t layer = 0; layer < inst->expanded_activated_layer_list.count; layer++) {
struct loader_layer_properties *layer_prop_list = inst->expanded_activated_layer_list.list[layer];
// Find the first layer in the call chain which supports vk_layerGetPhysicalDeviceProcAddr
// and call that, returning whether it found a valid pointer for this function name.
// We return if the topmost layer supports GPDPA since the layer should call down the chain for us.
if (layer_prop_list[layer].interface_version > 1) {
const struct loader_layer_functions *const functions = &(layer_prop_list[layer].functions);
if (layer_prop_list->interface_version > 1) {
const struct loader_layer_functions *const functions = &(layer_prop_list->functions);
if (NULL != functions->get_physical_device_proc_addr) {
return NULL != functions->get_physical_device_proc_addr((VkInstance)inst->instance, funcName);
}
@ -276,12 +276,12 @@ void *loader_phys_dev_ext_gpa_impl(struct loader_instance *inst, const char *fun
// failed to allocate memory, return NULL
return NULL;
}
strncpy(inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count], funcName, funcName_len);
loader_strncpy(inst->phys_dev_ext_disp_functions[inst->phys_dev_ext_disp_function_count], funcName_len, funcName,
funcName_len);
new_function_index = inst->phys_dev_ext_disp_function_count;
// increment the count so that the subsequent logic includes the newly added entry point when searching for functions
inst->phys_dev_ext_disp_function_count++;
has_found = true;
}
// Setup the ICD function pointers
@ -310,7 +310,7 @@ void *loader_phys_dev_ext_gpa_impl(struct loader_instance *inst, const char *fun
// point. Only set the instance dispatch table to it if it isn't NULL.
if (is_tramp) {
for (uint32_t i = 0; i < inst->expanded_activated_layer_list.count; i++) {
struct loader_layer_properties *layer_prop = &inst->expanded_activated_layer_list.list[i];
struct loader_layer_properties *layer_prop = inst->expanded_activated_layer_list.list[i];
if (layer_prop->interface_version > 1 && NULL != layer_prop->functions.get_physical_device_proc_addr) {
void *layer_ret_function =
(PFN_PhysDevExt)layer_prop->functions.get_physical_device_proc_addr(inst->instance, funcName);

View File

@ -3,6 +3,8 @@
* Copyright (c) 2015-2022 The Khronos Group Inc.
* Copyright (c) 2015-2022 Valve Corporation
* Copyright (c) 2015-2022 LunarG, 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.
@ -29,21 +31,26 @@
#include <sys/select.h>
#endif
#if defined(_WIN32)
// WinSock2.h must be included *BEFORE* windows.h
#include <winsock2.h>
#endif // _WIN32
#include <assert.h>
#include <string.h>
#include <float.h>
#include <stdbool.h>
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#if defined(__Fuchsia__)
#include "dlopen_fuchsia.h"
#endif // defined(__Fuchsia__)
#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
// Set of platforms with a common set of functionality which is queried throughout the program
#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNX__) || defined(__FreeBSD__) || \
defined(__OpenBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || defined(__GNU__)
#define COMMON_UNIX_PLATFORMS 1
#else
#define COMMON_UNIX_PLATFORMS 0
#endif
#if COMMON_UNIX_PLATFORMS
#include <unistd.h>
// Note: The following file is for dynamic loading:
#include <dlfcn.h>
@ -51,14 +58,13 @@
#include <stdlib.h>
#include <libgen.h>
#elif defined(_WIN32) // defined(__linux__)
/* Windows-specific common code: */
#elif defined(_WIN32)
// WinBase.h defines CreateSemaphore and synchapi.h defines CreateEvent
// undefine them to avoid conflicts with VkLayerDispatchTable struct members.
#ifdef CreateSemaphore
#if defined(CreateSemaphore)
#undef CreateSemaphore
#endif
#ifdef CreateEvent
#if defined(CreateEvent)
#undef CreateEvent
#endif
#include <stdio.h>
@ -69,7 +75,13 @@
#include "stack_allocation.h"
#if defined(__GNUC__) && __GNUC__ >= 4
#if defined(APPLE_STATIC_LOADER) && !defined(__APPLE__)
#error "APPLE_STATIC_LOADER can only be defined on Apple platforms!"
#endif
#if defined(APPLE_STATIC_LOADER)
#define LOADER_EXPORT
#elif defined(__GNUC__) && __GNUC__ >= 4
#define LOADER_EXPORT __attribute__((visibility("default")))
#elif defined(__SUNPRO_C) && (__SUNPRO_C >= 0x590)
#define LOADER_EXPORT __attribute__((visibility("default")))
@ -81,24 +93,39 @@
// This is defined in vk_layer.h, but if there's problems we need to create the define
// here.
#ifndef MAX_NUM_UNKNOWN_EXTS
#if !defined(MAX_NUM_UNKNOWN_EXTS)
#define MAX_NUM_UNKNOWN_EXTS 250
#endif
// Environment Variable information
#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES" // Deprecated
#define VK_ICD_FILENAMES_ENV_VAR "VK_ICD_FILENAMES" // Deprecated in v1.3.207 loader
#define VK_DRIVER_FILES_ENV_VAR "VK_DRIVER_FILES"
#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
#define VK_LAYER_PATH_ENV_VAR "VK_LAYER_PATH"
// Support added in v1.3.207 loader
#define VK_ADDITIONAL_DRIVER_FILES_ENV_VAR "VK_ADD_DRIVER_FILES"
#define VK_ADDITIONAL_LAYER_PATH_ENV_VAR "VK_ADD_LAYER_PATH"
// Support added in v1.3.234 loader
#define VK_LAYERS_ENABLE_ENV_VAR "VK_LOADER_LAYERS_ENABLE"
#define VK_LAYERS_DISABLE_ENV_VAR "VK_LOADER_LAYERS_DISABLE"
#define VK_LAYERS_ALLOW_ENV_VAR "VK_LOADER_LAYERS_ALLOW"
#define VK_DRIVERS_SELECT_ENV_VAR "VK_LOADER_DRIVERS_SELECT"
#define VK_DRIVERS_DISABLE_ENV_VAR "VK_LOADER_DRIVERS_DISABLE"
#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_1 "~all~"
#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_2 "*"
#define VK_LOADER_DISABLE_ALL_LAYERS_VAR_3 "**"
#define VK_LOADER_DISABLE_IMPLICIT_LAYERS_VAR "~implicit~"
#define VK_LOADER_DISABLE_EXPLICIT_LAYERS_VAR "~explicit~"
// Override layer information
#define VK_OVERRIDE_LAYER_NAME "VK_LAYER_LUNARG_override"
// Loader Settings filename
#define VK_LOADER_SETTINGS_FILENAME "vk_loader_settings.json"
#define LAYERS_PATH_ENV "VK_LAYER_PATH"
#define ENABLED_LAYERS_ENV "VK_INSTANCE_LAYERS"
#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#if COMMON_UNIX_PLATFORMS
/* Linux-specific common code: */
// VK Library Filenames, Paths, etc.:
@ -119,11 +146,11 @@
#define VK_ILAYERS_INFO_RELATIVE_DIR VULKAN_DIR VULKAN_ILAYERCONF_DIR
#define VK_DRIVERS_INFO_REGISTRY_LOC ""
#define VK_SETTINGS_INFO_REGISTRY_LOC ""
#define VK_ELAYERS_INFO_REGISTRY_LOC ""
#define VK_ILAYERS_INFO_REGISTRY_LOC ""
#define VK_SETTINGS_INFO_REGISTRY_LOC ""
#if defined(__QNXNTO__)
#if defined(__QNX__)
#define SYSCONFDIR "/etc"
#endif
@ -144,8 +171,8 @@ typedef pthread_mutex_t loader_platform_thread_mutex;
typedef pthread_cond_t loader_platform_thread_cond;
#elif defined(_WIN32) // defined(__linux__)
#elif defined(_WIN32)
/* Windows-specific common code: */
// VK Library Filenames, Paths, etc.:
#define PATH_SEPARATOR ';'
#define DIRECTORY_SYMBOL '\\'
@ -159,15 +186,13 @@ typedef pthread_cond_t loader_platform_thread_cond;
#define VK_ELAYERS_INFO_RELATIVE_DIR ""
#define VK_ILAYERS_INFO_RELATIVE_DIR ""
#ifdef _WIN64
#define HKR_VK_DRIVER_NAME API_NAME "DriverName"
#else
#define HKR_VK_DRIVER_NAME API_NAME "DriverNameWow"
#endif
#define VK_DRIVERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\Drivers"
#define VK_SETTINGS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\Settings"
#define VK_ELAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\ExplicitLayers"
#define VK_ILAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\" API_NAME "\\ImplicitLayers"
#define VK_VARIANT_REG_STR ""
#define VK_VARIANT_REG_STR_W L""
#define VK_DRIVERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\Drivers"
#define VK_ELAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\ExplicitLayers"
#define VK_ILAYERS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\ImplicitLayers"
#define VK_SETTINGS_INFO_REGISTRY_LOC "SOFTWARE\\Khronos\\Vulkan" VK_VARIANT_REG_STR "\\LoaderSettings"
#define PRINTF_SIZE_T_SPECIFIER "%Iu"
@ -185,16 +210,19 @@ typedef CRITICAL_SECTION loader_platform_thread_mutex;
typedef CONDITION_VARIABLE loader_platform_thread_cond;
#else // defined(_WIN32)
#else
#error The "vk_loader_platform.h" file must be modified for this OS.
#warning The "vk_loader_platform.h" file must be modified for this OS.
// NOTE: In order to support another OS, an #elif needs to be added (above the
// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the
// contents of this file must be created, or extend one of the existing OS specific
// sections with the necessary changes.
#endif // defined(_WIN32)
#endif
// controls whether loader_platform_close_library() closes the libraries or not - controlled by an environment variables
extern bool loader_disable_dynamic_library_unloading;
// Returns true if the DIRECTORY_SYMBOL is contained within path
static inline bool loader_platform_is_path(const char *path) { return strchr(path, DIRECTORY_SYMBOL) != NULL; }
@ -203,7 +231,7 @@ static inline bool loader_platform_is_path(const char *path) { return strchr(pat
// resources allocated by anything allocated by once init. This isn't a problem for static libraries, but it is for dynamic
// ones. When building a DLL, we use DllMain() instead to allow properly cleaning up resources.
#if defined(__APPLE__) && defined(BUILD_STATIC_LOADER)
#if defined(APPLE_STATIC_LOADER)
static inline void loader_platform_thread_once_fn(pthread_once_t *ctl, void (*func)(void)) {
assert(func != NULL);
assert(ctl != NULL);
@ -219,7 +247,7 @@ static inline void loader_platform_thread_once_fn(pthread_once_t *ctl, void (*fu
#endif
#if defined(__linux__) || defined(__APPLE__) || defined(__Fuchsia__) || defined(__QNXNTO__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#if COMMON_UNIX_PLATFORMS
// File IO
static inline bool loader_platform_file_exists(const char *path) {
@ -242,7 +270,7 @@ static inline char *loader_platform_dirname(char *path) { return dirname(path);
// loader_platform_executable_path finds application path + name.
// Path cannot be longer than 1024, returns NULL if it is greater than that.
#if defined(__linux__)
#if defined(__linux__) || defined(__GNU__)
static inline char *loader_platform_executable_path(char *buffer, size_t size) {
ssize_t count = readlink("/proc/self/exe", buffer, size);
if (count == -1) return NULL;
@ -250,15 +278,32 @@ static inline char *loader_platform_executable_path(char *buffer, size_t size) {
buffer[count] = '\0';
return buffer;
}
#elif defined(__APPLE__) // defined(__linux__)
#elif defined(__APPLE__)
#include <TargetConditionals.h>
// TARGET_OS_IPHONE isn't just iOS it's also iOS/tvOS/watchOS. See TargetConditionals.h documentation.
#if TARGET_OS_IPHONE
static inline char *loader_platform_executable_path(char *buffer, size_t size) {
(void)size;
buffer[0] = '\0';
return buffer;
}
#endif
#if TARGET_OS_OSX
#include <libproc.h>
static inline char *loader_platform_executable_path(char *buffer, size_t size) {
// proc_pidpath takes a uint32_t for the buffer size
if (size > UINT32_MAX) {
return NULL;
}
pid_t pid = getpid();
int ret = proc_pidpath(pid, buffer, size);
if (ret <= 0) return NULL;
int ret = proc_pidpath(pid, buffer, (uint32_t)size);
if (ret <= 0) {
return NULL;
}
buffer[ret] = '\0';
return buffer;
}
#endif
#elif defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__)
#include <sys/sysctl.h>
static inline char *loader_platform_executable_path(char *buffer, size_t size) {
@ -282,7 +327,7 @@ static inline char *loader_platform_executable_path(char *buffer, size_t size) {
}
#elif defined(__Fuchsia__) || defined(__OpenBSD__)
static inline char *loader_platform_executable_path(char *buffer, size_t size) { return NULL; }
#elif defined(__QNXNTO__)
#elif defined(__QNX__)
#define SYSCONFDIR "/etc"
@ -306,15 +351,15 @@ static inline char *loader_platform_executable_path(char *buffer, size_t size) {
return buffer;
}
#endif // defined (__QNXNTO__)
#endif // defined (__QNX__)
// Compatability with compilers that don't support __has_feature
#ifndef __has_feature
// Compatibility with compilers that don't support __has_feature
#if !defined(__has_feature)
#define __has_feature(x) 0
#endif
#if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__)
#define LOADER_ADDRESS_SANITIZER // TODO: Add proper build flag for ASAN support
#define LOADER_ADDRESS_SANITIZER_ACTIVE // TODO: Add proper build flag for ASAN support
#endif
// When loading the library, we use RTLD_LAZY so that not all symbols have to be
@ -337,23 +382,29 @@ static inline loader_platform_dl_handle loader_platform_open_library(const char
#endif
static inline const char *loader_platform_open_library_error(const char *libPath) {
#ifdef __Fuchsia__
(void)libPath;
#if defined(__Fuchsia__)
return dlerror_fuchsia();
#else
return dlerror();
#endif
}
static inline void loader_platform_close_library(loader_platform_dl_handle library) {
#if !defined (__OHOS__)
if (!loader_disable_dynamic_library_unloading) {
dlclose(library);
#endif
} else {
(void)library;
}
}
static inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
assert(library);
assert(name);
return dlsym(library, name);
}
static inline const char *loader_platform_get_proc_address_error(const char *name) { return dlerror(); }
static inline const char *loader_platform_get_proc_address_error(const char *name) {
(void)name;
return dlerror();
}
// Thread mutex:
static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_init(pMutex, NULL); }
@ -361,19 +412,31 @@ static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mute
static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_unlock(pMutex); }
static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { pthread_mutex_destroy(pMutex); }
#elif defined(_WIN32) // defined(__linux__)
static inline void *thread_safe_strtok(char *str, const char *delim, char **saveptr) { return strtok_r(str, delim, saveptr); }
static inline FILE *loader_fopen(const char *fileName, const char *mode) { return fopen(fileName, mode); }
static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
(void)dest_sz;
return strncat(dest, src, count);
}
static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
(void)dest_sz;
return strncpy(dest, src, count);
}
#elif defined(_WIN32)
// Get the key for the plug n play driver registry
// The string returned by this function should NOT be freed
static inline const char *LoaderPnpDriverRegistry() {
BOOL is_wow;
IsWow64Process(GetCurrentProcess(), &is_wow);
return is_wow ? "VulkanDriverNameWow" : "VulkanDriverName";
return is_wow ? "Vulkan" VK_VARIANT_REG_STR "DriverNameWow" : "Vulkan" VK_VARIANT_REG_STR "DriverName";
}
static inline const wchar_t *LoaderPnpDriverRegistryWide() {
BOOL is_wow;
IsWow64Process(GetCurrentProcess(), &is_wow);
return is_wow ? L"VulkanDriverNameWow" : L"VulkanDriverName";
return is_wow ? L"Vulkan" VK_VARIANT_REG_STR_W L"DriverNameWow" : L"Vulkan" VK_VARIANT_REG_STR_W L"DriverName";
}
// Get the key for the plug 'n play explicit layer registry
@ -381,12 +444,12 @@ static inline const wchar_t *LoaderPnpDriverRegistryWide() {
static inline const char *LoaderPnpELayerRegistry() {
BOOL is_wow;
IsWow64Process(GetCurrentProcess(), &is_wow);
return is_wow ? "VulkanExplicitLayersWow" : "VulkanExplicitLayers";
return is_wow ? "Vulkan" VK_VARIANT_REG_STR "ExplicitLayersWow" : "Vulkan" VK_VARIANT_REG_STR "ExplicitLayers";
}
static inline const wchar_t *LoaderPnpELayerRegistryWide() {
BOOL is_wow;
IsWow64Process(GetCurrentProcess(), &is_wow);
return is_wow ? L"VulkanExplicitLayersWow" : L"VulkanExplicitLayers";
return is_wow ? L"Vulkan" VK_VARIANT_REG_STR_W L"ExplicitLayersWow" : L"Vulkan" VK_VARIANT_REG_STR_W L"ExplicitLayers";
}
// Get the key for the plug 'n play implicit layer registry
@ -394,16 +457,16 @@ static inline const wchar_t *LoaderPnpELayerRegistryWide() {
static inline const char *LoaderPnpILayerRegistry() {
BOOL is_wow;
IsWow64Process(GetCurrentProcess(), &is_wow);
return is_wow ? "VulkanImplicitLayersWow" : "VulkanImplicitLayers";
return is_wow ? "Vulkan" VK_VARIANT_REG_STR "ImplicitLayersWow" : "Vulkan" VK_VARIANT_REG_STR "ImplicitLayers";
}
static inline const wchar_t *LoaderPnpILayerRegistryWide() {
BOOL is_wow;
IsWow64Process(GetCurrentProcess(), &is_wow);
return is_wow ? L"VulkanImplicitLayersWow" : L"VulkanImplicitLayers";
return is_wow ? L"Vulkan" VK_VARIANT_REG_STR_W L"ImplicitLayersWow" : L"Vulkan" VK_VARIANT_REG_STR_W L"ImplicitLayers";
}
// File IO
static bool loader_platform_file_exists(const char *path) {
static inline bool loader_platform_file_exists(const char *path) {
int path_utf16_size = MultiByteToWideChar(CP_UTF8, 0, path, -1, NULL, 0);
if (path_utf16_size <= 0) {
return false;
@ -420,7 +483,7 @@ static bool loader_platform_file_exists(const char *path) {
// Returns true if the given string appears to be a relative or absolute
// path, as opposed to a bare filename.
static bool loader_platform_is_path_absolute(const char *path) {
static inline bool loader_platform_is_path_absolute(const char *path) {
if (!path || !*path) {
return false;
}
@ -469,7 +532,7 @@ static inline char *loader_platform_executable_path(char *buffer, size_t size) {
}
// Dynamic Loading:
static loader_platform_dl_handle loader_platform_open_library(const char *lib_path) {
static inline loader_platform_dl_handle loader_platform_open_library(const char *lib_path) {
int lib_path_utf16_size = MultiByteToWideChar(CP_UTF8, 0, lib_path, -1, NULL, 0);
if (lib_path_utf16_size <= 0) {
return NULL;
@ -486,32 +549,61 @@ static loader_platform_dl_handle loader_platform_open_library(const char *lib_pa
}
return lib_handle;
}
static const char *loader_platform_open_library_error(const char *libPath) {
static inline const char *loader_platform_open_library_error(const char *libPath) {
static char errorMsg[512];
(void)snprintf(errorMsg, 511, "Failed to open dynamic library \"%s\" with error %lu", libPath, GetLastError());
return errorMsg;
}
static void loader_platform_close_library(loader_platform_dl_handle library) { FreeLibrary(library); }
static void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
static inline void loader_platform_close_library(loader_platform_dl_handle library) {
if (!loader_disable_dynamic_library_unloading) {
FreeLibrary(library);
} else {
(void)library;
}
}
static inline void *loader_platform_get_proc_address(loader_platform_dl_handle library, const char *name) {
assert(library);
assert(name);
return (void *)GetProcAddress(library, name);
}
static const char *loader_platform_get_proc_address_error(const char *name) {
static inline const char *loader_platform_get_proc_address_error(const char *name) {
static char errorMsg[120];
(void)snprintf(errorMsg, 119, "Failed to find function \"%s\" in dynamic library", name);
return errorMsg;
}
// Thread mutex:
static void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { InitializeCriticalSection(pMutex); }
static void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { EnterCriticalSection(pMutex); }
static void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { LeaveCriticalSection(pMutex); }
static void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { DeleteCriticalSection(pMutex); }
static inline void loader_platform_thread_create_mutex(loader_platform_thread_mutex *pMutex) { InitializeCriticalSection(pMutex); }
static inline void loader_platform_thread_lock_mutex(loader_platform_thread_mutex *pMutex) { EnterCriticalSection(pMutex); }
static inline void loader_platform_thread_unlock_mutex(loader_platform_thread_mutex *pMutex) { LeaveCriticalSection(pMutex); }
static inline void loader_platform_thread_delete_mutex(loader_platform_thread_mutex *pMutex) { DeleteCriticalSection(pMutex); }
static inline void *thread_safe_strtok(char *str, const char *delimiters, char **context) {
return strtok_s(str, delimiters, context);
}
static inline FILE *loader_fopen(const char *fileName, const char *mode) {
FILE *file = NULL;
errno_t err = fopen_s(&file, fileName, mode);
if (err != 0) return NULL;
return file;
}
static inline char *loader_strncat(char *dest, size_t dest_sz, const char *src, size_t count) {
errno_t err = strncat_s(dest, dest_sz, src, count);
if (err != 0) return NULL;
return dest;
}
static inline char *loader_strncpy(char *dest, size_t dest_sz, const char *src, size_t count) {
errno_t err = strncpy_s(dest, dest_sz, src, count);
if (err != 0) return NULL;
return dest;
}
#else // defined(_WIN32)
#error The "vk_loader_platform.h" file must be modified for this OS.
#warning The "vk_loader_platform.h" file must be modified for this OS.
// NOTE: In order to support another OS, an #elif needs to be added (above the
// "#else // defined(_WIN32)") for that OS, and OS-specific versions of the

View File

@ -1,12 +1,10 @@
prefix=@CMAKE_INSTALL_PREFIX@
exec_prefix=${prefix}
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR@
libdir=${exec_prefix}/@CMAKE_INSTALL_LIBDIR_PC@
includedir=${prefix}/@CMAKE_INSTALL_INCLUDEDIR_PC@
Name: @CMAKE_PROJECT_NAME@
Name: Vulkan-Loader
Description: Vulkan Loader
Version: @VK_API_VERSION@
Version: @VULKAN_LOADER_VERSION@
Libs: -L${libdir} -lvulkan@VULKAN_LIB_SUFFIX@
Libs.private: @PRIVATE_LIBS@
Cflags: -I${includedir}

File diff suppressed because it is too large Load Diff

View File

@ -26,37 +26,37 @@
typedef struct {
union {
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
VkIcdSurfaceWayland wayland_surf;
#endif // VK_USE_PLATFORM_WAYLAND_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VkIcdSurfaceWin32 win_surf;
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
VkIcdSurfaceXcb xcb_surf;
#endif // VK_USE_PLATFORM_XCB_KHR
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
VkIcdSurfaceXlib xlib_surf;
#endif // VK_USE_PLATFORM_XLIB_KHR
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
VkIcdSurfaceDirectFB directfb_surf;
#endif // VK_USE_PLATFORM_DIRECTFB_EXT
#ifdef VK_USE_PLATFORM_MACOS_MVK
#if defined(VK_USE_PLATFORM_MACOS_MVK)
VkIcdSurfaceMacOS macos_surf;
#endif // VK_USE_PLATFORM_MACOS_MVK
#ifdef VK_USE_PLATFORM_GGP
#if defined(VK_USE_PLATFORM_GGP)
VkIcdSurfaceGgp ggp_surf;
#endif // VK_USE_PLATFORM_GGP
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
VkIcdSurfaceImagePipe imagepipe_surf;
#endif // VK_USE_PLATFORM_FUCHSIA
#ifdef VK_USE_PLATFORM_METAL_EXT
#if defined(VK_USE_PLATFORM_METAL_EXT)
VkIcdSurfaceMetal metal_surf;
#endif // VK_USE_PLATFORM_METAL_EXT
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
VkIcdSurfaceScreen screen_surf;
#endif // VK_USE_PLATFORM_SCREEN_QNX
#ifdef VK_USE_PLATFORM_VI_NN
#if defined(VK_USE_PLATFORM_VI_NN)
VkIcdSurfaceVi vi_surf;
#endif // VK_USE_PLATFORM_VI_NN
VkIcdSurfaceDisplay display_surf;
@ -103,13 +103,13 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetPhysicalDeviceSurfacePresentModesKH
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDeviceGroupSurfacePresentModesKHR(VkDevice device, VkSurfaceKHR surface,
VkDeviceGroupPresentModeFlagsKHR *pModes);
#ifdef VK_USE_PLATFORM_WIN32_KHR
#if defined(VK_USE_PLATFORM_WIN32_KHR)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWin32SurfaceKHR(VkInstance instance, const VkWin32SurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWin32PresentationSupportKHR(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex);
#endif
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
#if defined(VK_USE_PLATFORM_WAYLAND_KHR)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(VkInstance instance,
const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
@ -117,7 +117,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceWaylandPresentationSu
uint32_t queueFamilyIndex,
struct wl_display *display);
#endif
#ifdef VK_USE_PLATFORM_XCB_KHR
#if defined(VK_USE_PLATFORM_XCB_KHR)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXcbSurfaceKHR(VkInstance instance, const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
@ -126,14 +126,14 @@ VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXcbPresentationSuppor
xcb_connection_t *connection,
xcb_visualid_t visual_id);
#endif
#ifdef VK_USE_PLATFORM_XLIB_KHR
#if defined(VK_USE_PLATFORM_XLIB_KHR)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateXlibSurfaceKHR(VkInstance instance, const VkXlibSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceXlibPresentationSupportKHR(VkPhysicalDevice physicalDevice,
uint32_t queueFamilyIndex, Display *dpy,
VisualID visualID);
#endif
#ifdef VK_USE_PLATFORM_DIRECTFB_EXT
#if defined(VK_USE_PLATFORM_DIRECTFB_EXT)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDirectFBSurfaceEXT(VkInstance instance,
const VkDirectFBSurfaceCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
@ -141,15 +141,15 @@ VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceDirectFBPresentationS
uint32_t queueFamilyIndex,
IDirectFB *dfb);
#endif
#ifdef VK_USE_PLATFORM_MACOS_MVK
#if defined(VK_USE_PLATFORM_MACOS_MVK)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMacOSSurfaceMVK(VkInstance instance, const VkMacOSSurfaceCreateInfoMVK *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
#endif
#ifdef VK_USE_PLATFORM_IOS_MVK
#if defined(VK_USE_PLATFORM_IOS_MVK)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateIOSSurfaceMVK(VkInstance instance, const VkIOSSurfaceCreateInfoMVK *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
#endif
#ifdef VK_USE_PLATFORM_GGP
#if defined(VK_USE_PLATFORM_GGP)
VKAPI_ATTR VkResult VKAPI_CALL
terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamDescriptorSurfaceCreateInfoGGP *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
@ -158,7 +158,7 @@ terminator_CreateStreamDescriptorSurfaceGGP(VkInstance instance, const VkStreamD
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateMetalSurfaceEXT(VkInstance instance, const VkMetalSurfaceCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
#endif
#ifdef VK_USE_PLATFORM_SCREEN_QNX
#if defined(VK_USE_PLATFORM_SCREEN_QNX)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateScreenSurfaceQNX(VkInstance instance,
const VkScreenSurfaceCreateInfoQNX *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
@ -166,7 +166,7 @@ VKAPI_ATTR VkBool32 VKAPI_CALL terminator_GetPhysicalDeviceScreenPresentationSup
uint32_t queueFamilyIndex,
struct _screen_window *window);
#endif // VK_USE_PLATFORM_SCREEN_QNX
#ifdef VK_USE_PLATFORM_VI_NN
#if defined(VK_USE_PLATFORM_VI_NN)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateViSurfaceNN(VkInstance instance, const VkViSurfaceCreateInfoNN *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
#endif // VK_USE_PLATFORM_VI_NN
@ -216,20 +216,20 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayModeProperties2KHR(VkPhysica
VKAPI_ATTR VkResult VKAPI_CALL terminator_GetDisplayPlaneCapabilities2KHR(VkPhysicalDevice physicalDevice,
const VkDisplayPlaneInfo2KHR *pDisplayPlaneInfo,
VkDisplayPlaneCapabilities2KHR *pCapabilities);
#ifdef VK_USE_PLATFORM_FUCHSIA
#if defined(VK_USE_PLATFORM_FUCHSIA)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateImagePipeSurfaceFUCHSIA(VkInstance instance,
const VkImagePipeSurfaceCreateInfoFUCHSIA *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkSurfaceKHR *pSurface);
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
#if defined(VK_USE_PLATFORM_ANDROID_KHR)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateAndroidSurfaceKHR(VkInstance instance,
const VkAndroidSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface);
#endif
#ifdef VK_USE_PLATFORM_OHOS
#if defined(VK_USE_PLATFORM_OHOS)
VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateSurfaceOHOS(VkInstance instance,
const VkSurfaceCreateInfoOHOS* pCreateInfo,
const VkAllocationCallbacks* pAllocator, VkSurfaceKHR* pSurface);

146
scripts/CMakeLists.txt Normal file
View File

@ -0,0 +1,146 @@
# ~~~
# 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 ("${CMAKE_OSX_ARCHITECTURES}" MATCHES ";")
list(APPEND update_dep_command "--osx-archs")
string(REPLACE ";" ":" osx_archs "${CMAKE_OSX_ARCHITECTURES}")
list(APPEND update_dep_command "${osx_archs}")
set(APPLE_UNIVERSAL_BINARY ON)
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)
if (APPLE_UNIVERSAL_BINARY)
set(UPDATE_DEPS_DIR_SUFFIX "${CMAKE_SYSTEM_NAME}/${UPDATE_DEPS_DIR_SUFFIX}/universal")
else()
set(UPDATE_DEPS_DIR_SUFFIX "${CMAKE_SYSTEM_NAME}/${UPDATE_DEPS_DIR_SUFFIX}/${CMAKE_SYSTEM_PROCESSOR}")
endif()
else()
if (APPLE_UNIVERSAL_BINARY)
set(UPDATE_DEPS_DIR_SUFFIX "${UPDATE_DEPS_DIR_SUFFIX}/universal")
else()
math(EXPR bitness "8 * ${CMAKE_SIZEOF_VOID_P}")
set(UPDATE_DEPS_DIR_SUFFIX "${UPDATE_DEPS_DIR_SUFFIX}/${bitness}")
endif()
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_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})
set(CMAKE_REQUIRE_FIND_PACKAGE_VulkanHeaders TRUE PARENT_SCOPE)
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()

View File

@ -1,41 +0,0 @@
#!/bin/bash
# Copyright (c) 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.
#
# Script to determine if source code in Pull Request is properly formatted.
# Exits with non 0 exit code if formatting is needed.
#
# This script assumes to be invoked at the project root directory.
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
FILES_TO_CHECK=$(git diff --name-only master | grep -v -E "^include/vulkan" | grep -E ".*\.(cpp|cc|c\+\+|cxx|c|h|hpp)$")
if [ -z "${FILES_TO_CHECK}" ]; then
echo -e "${GREEN}No source code to check for formatting.${NC}"
exit 0
fi
FORMAT_DIFF=$(git diff -U0 master -- ${FILES_TO_CHECK} | python ./scripts/clang-format-diff.py -p1 -style=file)
if [ -z "${FORMAT_DIFF}" ]; then
echo -e "${GREEN}All source code in PR properly formatted.${NC}"
exit 0
else
echo -e "${RED}Found formatting errors!${NC}"
echo "${FORMAT_DIFF}"
exit 1
fi

View File

@ -1,102 +0,0 @@
#!/bin/bash
# Copyright (c) 2018 Valve Corporation
# Copyright (c) 2018 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.
#
# Checks commit messages against project standards in CONTRIBUTING.md document
# Script to determine if commit messages in Pull Request are properly formatted.
# Exits with non 0 exit code if reformatting is needed.
# Disable subshells
shopt -s lastpipe
RED='\033[0;31m'
GREEN='\033[0;32m'
NC='\033[0m' # No Color
# TRAVIS_COMMIT_RANGE contains range of commits for this PR
# Get user-supplied commit message text for applicable commits and insert
# a unique separator string identifier. The git command returns ONLY the
# subject line and body for each of the commits.
COMMIT_TEXT=$(git log ${TRAVIS_COMMIT_RANGE} --pretty=format:"XXXNEWLINEXXX"%n%B)
# Bail if there are none
if [ -z "${COMMIT_TEXT}" ]; then
echo -e "${GREEN}No commit messgages to check for formatting.${NC}"
exit 0
elif ! echo $TRAVIS_COMMIT_RANGE | grep -q "\.\.\."; then
echo -e "${GREEN}No commit messgages to check for formatting.${NC}"
exit 0
fi
# Process commit messages
success=1
current_line=0
prevline=""
# Process each line of the commit message output, resetting counter on separator
printf %s "$COMMIT_TEXT" | while IFS='' read -r line; do
# echo "Count = $current_line <Line> = $line"
current_line=$((current_line+1))
if [ "$line" = "XXXNEWLINEXXX" ]; then
current_line=0
fi
chars=${#line}
if [ $current_line -eq 1 ]; then
# Subject line should be 50 chars or less (but give some slack here)
if [ $chars -gt 54 ]; then
echo "The following subject line exceeds 50 characters in length."
echo " '$line'"
success=0
fi
i=$(($chars-1))
last_char=${line:$i:1}
# Output error if last char of subject line is not alpha-numeric
if [[ ! $last_char =~ [0-9a-zA-Z] ]]; then
echo "For the following commit, the last character of the subject line must not be non-alphanumeric."
echo " '$line'"
success=0
fi
# Checking if subject line doesn't start with 'module: '
prefix=$(echo $line | cut -f1 -d " ")
if [ "${prefix: -1}" != ":" ]; then
echo "The following subject line must start with a single word specifying the functional area of the change, followed by a colon and space. I.e., 'layers: Subject line here'"
echo " '$line'"
success=0
fi
elif [ $current_line -eq 2 ]; then
# Commit message must have a blank line between subject and body
if [ $chars -ne 0 ]; then
echo "The following subject line must be followed by a blank line."
echo " '$prevline'"
success=0
fi
else
# Lines in a commit message body must be less than 72 characters in length (but give some slack)
if [ $chars -gt 76 ]; then
echo "The following commit message body line exceeds the 72 character limit."
echo "'$line\'"
success=0
fi
fi
prevline=$line
done
if [ $success -eq 1 ]; then
echo -e "${GREEN}All commit messages in pull request are properly formatted.${NC}"
exit 0
else
exit 1
fi

View File

@ -103,7 +103,7 @@ class DispatchTableHelperOutputGenerator(OutputGenerator):
write(s, file=self.outFile)
# File Comment
file_comment = '// *** THIS FILE IS GENERATED - DO NOT EDIT ***\n'
file_comment += '// See dispatch_helper_generator.py for modifications\n'
file_comment += '// See dispatch_table_helper_generator.py for modifications\n'
write(file_comment, file=self.outFile)
# Copyright Notice
copyright = '/*\n'
@ -132,7 +132,7 @@ class DispatchTableHelperOutputGenerator(OutputGenerator):
preamble += '#include <vulkan/vulkan.h>\n'
preamble += '#include <vulkan/vk_layer.h>\n'
preamble += '#include <string.h>\n'
preamble += '#include "vk_layer_dispatch_table.h"\n'
preamble += '#include "loader/generated/vk_layer_dispatch_table.h"\n'
write(copyright, file=self.outFile)
write(preamble, file=self.outFile)
@ -183,27 +183,6 @@ class DispatchTableHelperOutputGenerator(OutputGenerator):
return
if handle_type != 'VkInstance' and handle_type != 'VkPhysicalDevice' and name != 'vkGetInstanceProcAddr':
self.device_dispatch_list.append((name, self.featureExtraProtect))
if "VK_VERSION" not in self.featureName and self.extension_type == 'device':
self.device_extension_list.append(name)
# Build up stub function
decl = self.makeCDecls(cmdinfo.elem)[1]
return_type = cmdinfo.elem.find('proto/type').text
return_statement = "" # default type is void, so no return type
try:
return_statement = 'return ' + return_type_table[return_type] + ';'
except KeyError:
if return_type != "void":
raise AssertionError("return_type_table does not contain all possible types. Add an entry for `" + return_type + "`.")
decl = decl.split('*PFN_vk')[1]
decl = decl.replace(')(', '(')
decl = 'static VKAPI_ATTR ' + return_type + ' VKAPI_CALL Stub' + decl
func_body = ' { ' + return_statement + ' }'
decl = decl.replace (';', func_body)
if self.featureExtraProtect is not None:
self.dev_ext_stub_list.append('#ifdef %s' % self.featureExtraProtect)
self.dev_ext_stub_list.append(decl)
if self.featureExtraProtect is not None:
self.dev_ext_stub_list.append('#endif // %s' % self.featureExtraProtect)
else:
self.instance_dispatch_list.append((name, self.featureExtraProtect))
return
@ -240,7 +219,7 @@ class DispatchTableHelperOutputGenerator(OutputGenerator):
base_name = item[0][2:]
if item[1] is not None:
table += '#ifdef %s\n' % item[1]
table += '#if defined(%s)\n' % item[1]
# If we're looking for the proc we are passing in, just point the table to it. This fixes the issue where
# a layer overrides the function name for the loader.
@ -250,9 +229,6 @@ class DispatchTableHelperOutputGenerator(OutputGenerator):
table += ' table->GetInstanceProcAddr = gpa;\n'
else:
table += ' table->%s = (PFN_%s) gpa(%s, "%s");\n' % (base_name, item[0], table_type, item[0])
if item[0] in self.device_extension_list:
stub_check = ' if (table->%s == nullptr) { table->%s = (PFN_%s)Stub%s; }\n' % (base_name, base_name, item[0], base_name)
table += stub_check
if item[1] is not None:
table += '#endif // %s\n' % item[1]

View File

@ -3,6 +3,8 @@
# 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.
@ -26,13 +28,17 @@ import shutil
import subprocess
import sys
import tempfile
# files to exclude from --verify check
verify_exclude = ['.clang-format']
import datetime
import re
def main(argv):
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'],
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('-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')
@ -41,19 +47,17 @@ def main(argv):
gen_cmds = [[common_codegen.repo_relative('scripts/loader_genvk.py'),
'-registry', os.path.abspath(os.path.join(args.registry, 'vk.xml')),
'-quiet',
filename] for filename in ['vk_dispatch_table_helper.h',
'vk_layer_dispatch_table.h',
filename] for filename in ['vk_layer_dispatch_table.h',
'vk_loader_extensions.h',
'vk_loader_extensions.c',
'vk_object_types.h',
'loader_generated_header_version.cmake']]
'vk_object_types.h']]
repo_dir = common_codegen.repo_relative('loader/generated')
# 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='VulkanLoader_generated_source_')
temp_obj = tempfile.TemporaryDirectory(prefix='loader_codegen_')
temp_dir = temp_obj.name
gen_dir = temp_dir
else:
@ -78,7 +82,7 @@ def main(argv):
temp_files = set(os.listdir(temp_dir))
repo_files = set(os.listdir(repo_dir))
files_match = True
for filename in sorted((temp_files | repo_files) - set(verify_exclude)):
for filename in sorted((temp_files | repo_files)):
if filename not in repo_files:
print('ERROR: Missing repo file', filename)
files_match = False
@ -107,6 +111,26 @@ def main(argv):
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:
# Update the CMake project version
with open(common_codegen.repo_relative('CMakeLists.txt'), "r+") as f:
data = f.read()
f.seek(0)
f.write(re.sub("project.*VERSION.*", f"project(VULKAN_LOADER VERSION {args.generated_version} LANGUAGES C)", data))
f.truncate()
with open(common_codegen.repo_relative('loader/loader.rc.in'), "r") as rc_file:
rc_file_contents = rc_file.read()
rc_ver = ', '.join(args.generated_version.split('.') + ['0'])
rc_file_contents = rc_file_contents.replace('${LOADER_VER_FILE_VERSION}', f'{rc_ver}')
rc_file_contents = rc_file_contents.replace('${LOADER_VER_FILE_DESCRIPTION_STR}', f'"{args.generated_version}.Dev Build"')
rc_file_contents = rc_file_contents.replace('${LOADER_VER_FILE_VERSION_STR}', f'"Vulkan Loader - Dev Build"')
rc_file_contents = rc_file_contents.replace('${LOADER_CUR_COPYRIGHT_YEAR}', f'{datetime.date.today().year}')
with open(common_codegen.repo_relative('loader/loader.rc'), "w") as rc_file_out:
rc_file_out.write(rc_file_contents)
rc_file_out.close()
return 0
if __name__ == '__main__':

68
scripts/gn/DEPS Normal file
View File

@ -0,0 +1,68 @@
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',
]

56
scripts/gn/gn.py Normal file
View File

@ -0,0 +1,56 @@
#!/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()

Some files were not shown because too many files have changed in this diff Show More