aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGreg Fischer <greg@lunarg.com>2016-06-17 12:21:47 -0600
committerGreg Fischer <greg@lunarg.com>2016-06-17 12:21:47 -0600
commit98e416e97e3d060f474ea017722aa81a18ef1413 (patch)
treef678a48d309cb884d566417be4b6f60ebf37ec5f
parentae957adfb5feb5c5e67174998d9087e030bb479b (diff)
parent9063e2ab9c0c32e25aab2c46af38302a4ac2c98e (diff)
downloadusermoji-98e416e97e3d060f474ea017722aa81a18ef1413.tar.xz
Merge branch 'master' of github.com:KhronosGroup/Vulkan-LoaderAndValidationLayers
-rw-r--r--.gitignore5
-rw-r--r--BUILD.md37
-rw-r--r--[-rwxr-xr-x]CMakeLists.txt8
-rw-r--r--[-rwxr-xr-x]README.md102
-rwxr-xr-xbuild-android/update_external_sources_android.sh2
-rw-r--r--demos/CMakeLists.txt8
-rw-r--r--demos/cube.c150
-rw-r--r--demos/smoke/CMakeLists.txt2
-rw-r--r--demos/tri.c105
-rw-r--r--demos/vulkaninfo.c682
-rwxr-xr-x[-rw-r--r--]determine_vs_version.py0
-rwxr-xr-x[-rw-r--r--]generator.py158
-rwxr-xr-xgenvk.py2
-rw-r--r--glslang_revision2
-rw-r--r--include/vulkan/vk_icd.h18
-rw-r--r--include/vulkan/vk_layer.h17
-rw-r--r--include/vulkan/vulkan.h26
-rw-r--r--layers/CMakeLists.txt29
-rw-r--r--layers/README.md74
-rw-r--r--layers/VkLayer_utils.def47
-rw-r--r--layers/core_validation.cpp2078
-rw-r--r--layers/core_validation.h345
-rw-r--r--layers/core_validation_error_enums.h19
-rw-r--r--layers/core_validation_types.h364
-rw-r--r--layers/descriptor_sets.cpp1079
-rw-r--r--layers/descriptor_sets.h152
-rw-r--r--layers/device_limits.cpp124
-rw-r--r--layers/device_limits.h22
-rw-r--r--layers/image.cpp297
-rw-r--r--layers/image.h20
-rw-r--r--layers/linux/VkLayer_core_validation.json4
-rw-r--r--layers/linux/VkLayer_device_limits.json4
-rw-r--r--layers/linux/VkLayer_image.json4
-rw-r--r--layers/linux/VkLayer_object_tracker.json4
-rw-r--r--layers/linux/VkLayer_parameter_validation.json4
-rw-r--r--layers/linux/VkLayer_swapchain.json4
-rw-r--r--layers/linux/VkLayer_threading.json4
-rw-r--r--layers/linux/VkLayer_unique_objects.json4
-rw-r--r--layers/object_tracker.h42
-rw-r--r--layers/parameter_validation.cpp1917
-rw-r--r--layers/parameter_validation_utils.h4
-rw-r--r--layers/swapchain.cpp72
-rw-r--r--layers/swapchain.h43
-rw-r--r--layers/threading.cpp198
-rw-r--r--layers/threading.h6
-rw-r--r--layers/unique_objects.h11
-rw-r--r--layers/vk_layer_config.cpp179
-rw-r--r--layers/vk_layer_config.h39
-rw-r--r--layers/vk_layer_logging.h227
-rw-r--r--layers/vk_layer_settings.txt9
-rw-r--r--layers/vk_layer_utils.cpp33
-rw-r--r--layers/vk_validation_layer_details.md108
-rw-r--r--layers/windows/VkLayer_core_validation.json4
-rw-r--r--layers/windows/VkLayer_device_limits.json4
-rw-r--r--layers/windows/VkLayer_image.json4
-rw-r--r--layers/windows/VkLayer_object_tracker.json4
-rw-r--r--layers/windows/VkLayer_parameter_validation.json4
-rw-r--r--layers/windows/VkLayer_swapchain.json4
-rw-r--r--layers/windows/VkLayer_threading.json4
-rw-r--r--layers/windows/VkLayer_unique_objects.json4
-rw-r--r--loader/CMakeLists.txt11
-rw-r--r--loader/LoaderAndLayerInterface.md588
-rw-r--r--loader/cJSON.c11
-rw-r--r--loader/loader.c607
-rw-r--r--loader/loader.h3
-rw-r--r--loader/vk_loader_layer.h32
-rw-r--r--loader/wsi.c19
-rw-r--r--spirv-tools_revision2
-rw-r--r--[-rwxr-xr-x]update_external_sources.bat0
-rwxr-xr-xvk-layer-generate.py445
-rwxr-xr-xvk-layer-introspect399
-rw-r--r--vk.xml54
-rwxr-xr-xvk_helper.py40
-rw-r--r--[-rwxr-xr-x]vulkan.py0
-rw-r--r--windowsRuntimeInstaller/ConfigLayersAndVulkanDLL.ps1533
-rw-r--r--windowsRuntimeInstaller/InstallerRT.nsi237
-rw-r--r--windowsRuntimeInstaller/vcredist_x64.exebin7194312 -> 0 bytes
-rw-r--r--windowsRuntimeInstaller/vcredist_x86.exebin6503984 -> 0 bytes
78 files changed, 7113 insertions, 4794 deletions
diff --git a/.gitignore b/.gitignore
index 3c8b7652..2ff8e41a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -31,3 +31,8 @@ build
build32
dbuild
external
+*.config
+*.creator
+*.creator.user
+*.files
+*.includes
diff --git a/BUILD.md b/BUILD.md
index ad05e863..c5b8f488 100644
--- a/BUILD.md
+++ b/BUILD.md
@@ -19,7 +19,7 @@ Please see the [CONTRIBUTING](CONTRIBUTING.md) file in this respository for more
To create your local git repository:
```
-git clone https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers
+git clone https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers
```
## Linux Build
@@ -30,12 +30,12 @@ The build generates the loader, layers, and tests.
This repo has been built and tested on Ubuntu 14.04.3 LTS, 14.10, 15.04, 15.10, and 16.04 LTS.
It should be straightforward to use it on other Linux distros.
-These packages are needed to build this repository:
+These packages are needed to build this repository:
```
sudo apt-get install git cmake build-essential bison libx11-dev libxcb1-dev
```
-Example debug build (Note that the update\_external\_sources script used below builds external tools into predefined locations. See **LVL's Dependencies** for more information and other options):
+Example debug build (Note that the update\_external\_sources script used below builds external tools into predefined locations. See **Loader and Validation Layer Dependencies** for more information and other options):
```
cd Vulkan-LoaderAndValidationLayers # cd to the root of the cloned git repository
./update_external_sources.sh
@@ -52,9 +52,6 @@ If you want to use the loader and layers that you have just built:
export LD_LIBRARY_PATH=<path to your repository root>/dbuild/loader
export VK_LAYER_PATH=<path to your repository root>/dbuild/layers
```
-Note that if you have installed the [LunarG Vulkan SDK](https://vulkan.lunarg.com),
-you will also have the SDK version of the loader and layers installed in your default system libraries.
-
You can run the `vulkaninfo` application to see which driver, loader and layers are being used.
The `LoaderAndLayerInterface` document in the `loader` folder in this repository is a specification that
@@ -63,7 +60,7 @@ packaged, and how developers can point to ICDs and layers within their builds.
## Validation Test
-The test executables can be found in the dbuild/tests directory.
+The test executables can be found in the dbuild/tests directory.
Some of the tests that are available:
- vk\_layer\_validation\_tests: Test Vulkan layers.
@@ -98,7 +95,7 @@ Windows 7+ with additional required software packages:
- glslang is required for demos and tests.
- [You can download and configure it (in a peer directory) here](https://github.com/KhronosGroup/glslang/blob/master/README.md)
- A windows batch file has been included that will pull and build the correct version. Run it from Developer Command Prompt for VS2013 like so:
- - update\_external\_sources.bat --build-glslang (Note: see **LVL's Dependencies** below for other options)
+ - update\_external\_sources.bat --build-glslang (Note: see **Loader and Validation Layer Dependencies** below for other options)
## Windows Build - MSVC
@@ -106,16 +103,16 @@ Before building on Windows, you may want to modify the customize section in load
set the version numbers and build description for your build. Doing so will set the information displayed
for the Properites->Details tab of the loader vulkan-1.dll file that is built.
-Build all Windows targets after installing required software and cloning the LVL repo as described above by completing the following steps in a "Developer Command Prompt for VS2013" window (Note that the update\_external\_sources script used below builds external tools into predefined locations. See **LVL's Dependencies** for more information and other options):
+Build all Windows targets after installing required software and cloning the Loader and Validation Layer repo as described above by completing the following steps in a "Developer Command Prompt for VS2013" window (Note that the update\_external\_sources script used below builds external tools into predefined locations. See **Loader and Validation Layer Dependencies** for more information and other options):
```
cd Vulkan-LoaderAndValidationLayers # cd to the root of the cloned git repository
update_external_sources.bat --all
-build_windows_targets.bat
+build_windows_targets.bat
```
At this point, you can use Windows Explorer to launch Visual Studio by double-clicking on the "VULKAN.sln" file in the \build folder. Once Visual Studio comes up, you can select "Debug" or "Release" from a drop-down list. You can start a build with either the menu (Build->Build Solution), or a keyboard shortcut (Ctrl+Shift+B). As part of the build process, Python scripts will create additional Visual Studio files and projects, along with additional source files. All of these auto-generated files are under the "build" folder.
-Vulkan programs must be able to find and use the vulkan-1.dll library. Make sure it is either installed in the C:\Windows\System32 folder, or the PATH environment variable includes the folder that it is located in.
+Vulkan programs must be able to find and use the vulkan-1.dll library. Make sure it is either installed in the system library directory (typically C:\Windows\System32), or the PATH environment variable includes the folder that it is located in. Similarly, Vulkan layers require access to the VkLayer-utils.dll shared layer utility library. This file must be copied to the system library directory or into the directory containing the program executable.
To run Vulkan programs you must tell the icd loader where to find the libraries.
This is described in a `LoaderAndLayerInterface` document in the `loader` folder in this repository.
@@ -155,13 +152,11 @@ Tested on OSX version 10.11.4
```
- Ensure Homebrew is at the beginning of your PATH:
```
-export PATH=$HOME/homebrew/bin:$PATH
+export PATH=/usr/local/bin:$PATH
```
- Add packages with the following (may need refinement)
```
-brew install cmake
-brew install python
-brew install python3
+brew install cmake python python3 git
```
### Build steps for Android
Use the following to ensure the Android build works.
@@ -171,7 +166,7 @@ Follow the setup steps for Linux or OSX above, then from your terminal:
cd build-android
./update_external_sources_android.sh
./android-generate.sh
-ndk-build
+ndk-build -j $(sysctl -n hw.ncpu)
```
#### Windows
Follow the setup steps for Windows above, then from Developer Command Prompt for VS2013:
@@ -185,13 +180,13 @@ ndk-build
## Ninja Builds - All Platforms
The [Qt Creator IDE](https://qt.io/download-open-source/#section-2) can open a root CMakeList.txt as a project directly, and it provides tools within Creator to configure and generate Vulkan SDK build files for one to many targets concurrently, resolving configuration issues as needed. Alternatively, when invoking CMake use the -G Codeblocks Ninja option to generate Ninja build files to be used as project files for QtCreator
-- Follow the steps defined elsewhere for the OS using the update\_external\_sources script or as shown in **LVL's Dependencies** below
+- Follow the steps defined elsewhere for the OS using the update\_external\_sources script or as shown in **Loader and Validation Layer Dependencies** below
- Open, configure, and build the gslang and spirv-tools CMakeList.txt files
- Then do the same with the Vulkan-LoaderAndValidationLayers CMakeList.txt file.
- In order to debug with QtCreator, a [Microsoft WDK: eg WDK 10](http://go.microsoft.com/fwlink/p/?LinkId=526733) is required. Note that installing the WDK breaks the MSVC vcvarsall.bat build scripts provided by MSVC, requiring that the LIB, INCLUDE, and PATH env variables be set to the WDK paths by some other means
-## LVL's Dependencies
-gslang and SPIRV-Tools repos are required to build and run LVL components. They are not git sub-modules of Vulkan-LoaderAndValidationLayers but Vulkan-LoaderAndValidationLayers is linked to specific revisions of gslang and spirv-tools. These can be automatically cloned and built to predefined locations with the update\_external\_sources scripts. If a custom configuration is required, do the following steps:
+## Loader and Validation Layer Dependencies
+gslang and SPIRV-Tools repos are required to build and run Loader and Validation Layer components. They are not git sub-modules of Vulkan-LoaderAndValidationLayers but Vulkan-LoaderAndValidationLayers is linked to specific revisions of gslang and spirv-tools. These can be automatically cloned and built to predefined locations with the update\_external\_sources scripts. If a custom configuration is required, do the following steps:
1) clone the repos:
@@ -224,7 +219,7 @@ _on windows_
Especially valuable are the BASH shell and git packages.
- If you don't want to use Cygwin, there are other shells and environments that can be used.
You can also use a Git package that doesn't come from Cygwin.
-
-- [Ninja on all platforms](https://github.com/ninja-build/ninja/releases). [The Ninja-build project](ninja-build.org). [Ninja Users Manual](ninja-build.org/manual.html)
+
+- [Ninja on all platforms](https://github.com/ninja-build/ninja/releases). [The Ninja-build project](ninja-build.org). [Ninja Users Manual](ninja-build.org/manual.html)
- [QtCreator as IDE for CMake builds on all platforms](https://qt.io/download-open-source/#section-2)
diff --git a/CMakeLists.txt b/CMakeLists.txt
index e7e25b33..e5f32383 100755..100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -112,7 +112,7 @@ option(CUSTOM_SPIRV_TOOLS_BIN_ROOT "Use the user defined SPIRV_TOOLS_BINARY_ROOT
#Choose natural default paths for glslang and SPIRV-Tools binaries to support custom definition by the user on the CMake command line or in the GUI
set(GLSLANG_BINARY_ROOT "${CMAKE_BINARY_DIR}/../glslang" CACHE STRING "User defined path to the glslang binaries for this project")
-set(SPRIV_TOOLS_BINARY_ROOT "${CMAKE_BINARY_DIR}/../SPIRV-Tools" CACHE STRING "User defined path to the SPIRV-Tools binaries for this project")
+set(SPIRV_TOOLS_BINARY_ROOT "${CMAKE_BINARY_DIR}/../SPIRV-Tools" CACHE STRING "User defined path to the SPIRV-Tools binaries for this project")
# Define a variable for a default root location to the gslang, SPIRV-Tools and other external sources and cache it to allow the user to customize it as needed
set(EXTERNAL_SOURCE_ROOT "${CMAKE_SOURCE_DIR}/external" CACHE STRING "Root path to external sources such as glslang and SPIRV-Tools")
@@ -147,8 +147,8 @@ if (WIN32)
"${GSLANG_FINAL_BINARY_PATH}/SPIRV/${DEBUG_DECORATION}")
if(CUSTOM_SPIRV_TOOLS_BIN_ROOT)
- set (SPIRV_TOOLS_SEARCH_PATH "${SPRIV_TOOLS_BINARY_ROOT}/${BUILDTGT_DIR}/source/${RELEASE_DECORATION}")
- set (SPIRV_TOOLS_DEBUG_SEARCH_PATH "${SPRIV_TOOLS_BINARY_ROOT}/${BUILDTGT_DIR}/source/${DEBUG_DECORATION}")
+ set (SPIRV_TOOLS_SEARCH_PATH "${SPIRV_TOOLS_BINARY_ROOT}/${BUILDTGT_DIR}/source/${RELEASE_DECORATION}")
+ set (SPIRV_TOOLS_DEBUG_SEARCH_PATH "${SPIRV_TOOLS_BINARY_ROOT}/${BUILDTGT_DIR}/source/${DEBUG_DECORATION}")
else()
set (SPIRV_TOOLS_SEARCH_PATH "${EXTERNAL_SOURCE_ROOT}/spirv-tools/${BUILDTGT_DIR}/source/${RELEASE_DECORATION}")
set (SPIRV_TOOLS_DEBUG_SEARCH_PATH "${EXTERNAL_SOURCE_ROOT}/spirv-tools/${BUILDTGT_DIR}/source/${DEBUG_DECORATION}")
@@ -168,7 +168,7 @@ else()
endif()
if(CUSTOM_SPIRV_TOOLS_BIN_ROOT)
- set (SPIRV_TOOLS_SEARCH_PATH "${SPRIV_TOOLS_BINARY_ROOT}/source" )
+ set (SPIRV_TOOLS_SEARCH_PATH "${SPIRV_TOOLS_BINARY_ROOT}/source" )
else()
set (SPIRV_TOOLS_SEARCH_PATH "${EXTERNAL_SOURCE_ROOT}/spirv-tools/${BUILDTGT_DIR}/source" "${CMAKE_SOURCE_DIR}/../x86_64/lib/spirv-tools" )
endif()
diff --git a/README.md b/README.md
index 4b7fde49..f79d941b 100755..100644
--- a/README.md
+++ b/README.md
@@ -1,49 +1,53 @@
-# Vulkan Ecosystem Components
-
-This project provides Khronos official ICD loader and validation layers for Vulkan developers on Windows and Linux.
-
-## Introduction
-
-Vulkan is an Explicit API, enabling direct control over how GPUs actually work. No (or very little) validation
-or error checking is done inside a Vulkan driver. Applications have full control and responsibility. Any errors in
-how Vulkan is used often result in a crash. This project provides standard validation layers that can be enabled to ease development by
-helping developers verify their applications correctly use the Vulkan API.
-
-Vulkan supports multiple GPUs and multiple global contexts (VkInstance). The ICD loader is necessary to support multiple GPUs and the VkInstance level Vulkan commands. Additionally, the loader manages inserting Vulkan layer libraries,
-including validation layers between the application and the ICD.
-
-The following components are available in this repository:
-- Vulkan header files
-- [*ICD Loader*](loader/)
-- [*Validation Layers*](layers/)
-- Demos and tests for the loader and validation layers
-
-## Contributing
-
-If you intend to contribute, the preferred work flow is for you to develop your contribution
-in a fork of this repo in your GitHub account and then submit a pull request.
-Please see the [CONTRIBUTING](CONTRIBUTING.md) file in this respository for more details
-
-## How to Build and Run
-
-[BUILD.md](BUILD.md)
-includes directions for building all the components, running the validation tests and running the demo applications.
-
-Information on how to enable the various Validation layers is in
-[layers/README.md](layers/README.md).
-
-Architecture and interface information for the loader is in
-[loader/LoaderAndLayerInterface.md](loader/LoaderAndLayerInterface.md).
-
-## License
-This work is released as open source under a Apache-style license from Khronos including a Khronos copyright.
-
-See COPYRIGHT.txt for a full list of licenses used in this repository.
-
-## Acknowledgements
-While this project has been developed primarily by LunarG, Inc; there are many other
-companies and individuals making this possible: Valve Corporation, funding
-project development; Google providing significant contributions to the validation layers;
-Khronos providing oversight and hosting of the project.
-
-
+NOTE: Recent changes have been made regarding the loading of the shared layer utilities library on Windows.
+ Please see [BUILD.md](BUILD.md) for details.
+
+# Vulkan Ecosystem Components
+
+This project provides Khronos official ICD loader and validation layers for Vulkan developers on Windows and Linux.
+
+## Introduction
+
+Vulkan is an Explicit API, enabling direct control over how GPUs actually work. No (or very little) validation
+or error checking is done inside a Vulkan driver. Applications have full control and responsibility. Any errors in
+how Vulkan is used often result in a crash. This project provides standard validation layers that can be enabled
+to ease development by helping developers verify their applications correctly use the Vulkan API.
+
+Vulkan supports multiple GPUs and multiple global contexts (VkInstance). The ICD loader is necessary to
+support multiple GPUs and the VkInstance level Vulkan commands. Additionally, the loader manages inserting
+Vulkan layer libraries, including validation layers between the application and the ICD.
+
+The following components are available in this repository:
+- Vulkan header files
+- [*ICD Loader*](loader/)
+- [*Validation Layers*](layers/)
+- Demos and tests for the loader and validation layers
+
+## Contributing
+
+If you intend to contribute, the preferred work flow is for you to develop your contribution
+in a fork of this repo in your GitHub account and then submit a pull request.
+Please see the [CONTRIBUTING](CONTRIBUTING.md) file in this respository for more details
+
+## How to Build and Run
+
+[BUILD.md](BUILD.md)
+includes directions for building all the components, running the validation tests and running the demo applications.
+
+Information on how to enable the various Validation layers is in
+[layers/README.md](layers/README.md).
+
+Architecture and interface information for the loader is in
+[loader/LoaderAndLayerInterface.md](loader/LoaderAndLayerInterface.md).
+
+## License
+This work is released as open source under a Apache-style license from Khronos including a Khronos copyright.
+
+See COPYRIGHT.txt for a full list of licenses used in this repository.
+
+## Acknowledgements
+While this project has been developed primarily by LunarG, Inc; there are many other
+companies and individuals making this possible: Valve Corporation, funding
+project development; Google providing significant contributions to the validation layers;
+Khronos providing oversight and hosting of the project.
+
+
diff --git a/build-android/update_external_sources_android.sh b/build-android/update_external_sources_android.sh
index e728d893..4ceaeeb9 100755
--- a/build-android/update_external_sources_android.sh
+++ b/build-android/update_external_sources_android.sh
@@ -66,7 +66,7 @@ function create_shaderc () {
rm -rf $BASEDIR/shaderc
echo "Creating local shaderc repository ($BASEDIR/shaderc)."
cd $BASEDIR
- git clone git@github.com:google/shaderc.git
+ git clone https://github.com/google/shaderc.git
cd shaderc
git checkout $SHADERC_REVISION
}
diff --git a/demos/CMakeLists.txt b/demos/CMakeLists.txt
index c9aea49f..652efb75 100644
--- a/demos/CMakeLists.txt
+++ b/demos/CMakeLists.txt
@@ -28,6 +28,14 @@ if(WIN32)
set (BUILDTGT_DIR build32)
endif()
+ # 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()
+
add_custom_command(OUTPUT ${CMAKE_BINARY_DIR}/demos/tri-vert.spv
COMMAND ${GLSLANG_VALIDATOR} -s -V ${PROJECT_SOURCE_DIR}/demos/tri.vert
COMMAND move vert.spv ${CMAKE_BINARY_DIR}/demos/tri-vert.spv
diff --git a/demos/cube.c b/demos/cube.c
index bc391414..d5269bc8 100644
--- a/demos/cube.c
+++ b/demos/cube.c
@@ -61,7 +61,8 @@
#ifdef _WIN32
#define ERR_EXIT(err_msg, err_class) \
do { \
- MessageBox(NULL, err_msg, err_class, MB_OK); \
+ if (!demo->suppress_popups) \
+ MessageBox(NULL, err_msg, err_class, MB_OK); \
exit(1); \
} while (0)
@@ -266,51 +267,6 @@ void dumpVec4(const char *note, vec4 vector) {
}
VKAPI_ATTR VkBool32 VKAPI_CALL
-dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject, size_t location, int32_t msgCode,
- const char *pLayerPrefix, const char *pMsg, void *pUserData) {
- char *message = (char *)malloc(strlen(pMsg) + 100);
-
- assert(message);
-
- if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
- sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
- pMsg);
- validation_error = 1;
- } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
- // We know that we're submitting queues without fences, ignore this
- // warning
- if (strstr(pMsg,
- "vkQueueSubmit parameter, VkFence fence, is null pointer")) {
- return false;
- }
- sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
- pMsg);
- validation_error = 1;
- } else {
- validation_error = 1;
- return false;
- }
-
-#ifdef _WIN32
- MessageBox(NULL, message, "Alert", MB_OK);
-#else
- printf("%s\n", message);
- fflush(stdout);
-#endif
- free(message);
-
- /*
- * false indicates that layer should not bail-out of an
- * API call that had validation failures. This may mean that the
- * app dies inside the driver due to invalid parameter(s).
- * That's what would happen without validation layers, so we'll
- * keep that behavior here.
- */
- return false;
-}
-
-VKAPI_ATTR VkBool32 VKAPI_CALL
BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
uint64_t srcObject, size_t location, int32_t msgCode,
const char *pLayerPrefix, const char *pMsg,
@@ -324,7 +280,7 @@ BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
return false;
}
-typedef struct _SwapchainBuffers {
+typedef struct {
VkImage image;
VkCommandBuffer cmd;
VkImageView view;
@@ -436,6 +392,7 @@ struct demo {
int32_t frameCount;
bool validate;
bool use_break;
+ bool suppress_popups;
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback;
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback;
VkDebugReportCallbackEXT msg_callback;
@@ -445,6 +402,53 @@ struct demo {
uint32_t queue_count;
};
+VKAPI_ATTR VkBool32 VKAPI_CALL
+dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
+ uint64_t srcObject, size_t location, int32_t msgCode,
+ const char *pLayerPrefix, const char *pMsg, void *pUserData) {
+ char *message = (char *)malloc(strlen(pMsg) + 100);
+
+ assert(message);
+
+ if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
+ pMsg);
+ validation_error = 1;
+ } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ // We know that we're submitting queues without fences, ignore this
+ // warning
+ if (strstr(pMsg,
+ "vkQueueSubmit parameter, VkFence fence, is null pointer")) {
+ return false;
+ }
+ sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
+ pMsg);
+ validation_error = 1;
+ } else {
+ validation_error = 1;
+ return false;
+ }
+
+#ifdef _WIN32
+ struct demo *demo = (struct demo*) pUserData;
+ if (!demo->suppress_popups)
+ MessageBox(NULL, message, "Alert", MB_OK);
+#else
+ printf("%s\n", message);
+ fflush(stdout);
+#endif
+ free(message);
+
+ /*
+ * false indicates that layer should not bail-out of an
+ * API call that had validation failures. This may mean that the
+ * app dies inside the driver due to invalid parameter(s).
+ * That's what would happen without validation layers, so we'll
+ * keep that behavior here.
+ */
+ return false;
+}
+
// Forward declaration:
static void demo_resize(struct demo *demo);
@@ -1023,17 +1027,17 @@ bool loadTexture(const char *filename, uint8_t *rgba_data,
#ifdef __ANDROID__
#include <lunarg.ppm.h>
char *cPtr;
- cPtr = (char*)___lunarg_ppm;
- if ((unsigned char*)cPtr >= (___lunarg_ppm + ___lunarg_ppm_len) || strncmp(cPtr, "P6\n", 3)) {
+ cPtr = (char*)lunarg_ppm;
+ if ((unsigned char*)cPtr >= (lunarg_ppm + lunarg_ppm_len) || strncmp(cPtr, "P6\n", 3)) {
return false;
}
while(strncmp(cPtr++, "\n", 1));
- sscanf(cPtr, "%u %u", height, width);
+ sscanf(cPtr, "%u %u", width, height);
if (rgba_data == NULL) {
return true;
}
while(strncmp(cPtr++, "\n", 1));
- if ((unsigned char*)cPtr >= (___lunarg_ppm + ___lunarg_ppm_len) || strncmp(cPtr, "255\n", 4)) {
+ if ((unsigned char*)cPtr >= (lunarg_ppm + lunarg_ppm_len) || strncmp(cPtr, "255\n", 4)) {
return false;
}
while(strncmp(cPtr++, "\n", 1));
@@ -1071,7 +1075,7 @@ bool loadTexture(const char *filename, uint8_t *rgba_data,
}
} while (!strncmp(header, "#", 1));
- sscanf(header, "%u %u", height, width);
+ sscanf(header, "%u %u", width, height);
if (rgba_data == NULL) {
fclose(fPtr);
return true;
@@ -1917,7 +1921,7 @@ static void demo_cleanup(struct demo *demo) {
}
free(demo->atom_wm_delete_window);
#elif defined(VK_USE_PLATFORM_XCB_KHR)
- xcb_destroy_window(demo->connection, demo->window);
+ xcb_destroy_window(demo->connection, demo->xcb_window);
xcb_disconnect(demo->connection);
free(demo->atom_wm_delete_window);
#endif
@@ -2073,7 +2077,7 @@ static void demo_create_xlib_window(struct demo *demo) {
demo->display = XOpenDisplay(NULL);
long visualMask = VisualScreenMask;
int numberOfVisuals;
- XVisualInfo vInfoTemplate;
+ XVisualInfo vInfoTemplate={};
vInfoTemplate.screen = DefaultScreen(demo->display);
XVisualInfo *visualInfo = XGetVisualInfo(demo->display, visualMask,
&vInfoTemplate, &numberOfVisuals);
@@ -2082,7 +2086,7 @@ static void demo_create_xlib_window(struct demo *demo) {
demo->display, RootWindow(demo->display, vInfoTemplate.screen),
visualInfo->visual, AllocNone);
- XSetWindowAttributes windowAttributes;
+ XSetWindowAttributes windowAttributes={};
windowAttributes.colormap = colormap;
windowAttributes.background_pixel = 0xFFFFFFFF;
windowAttributes.border_pixel = 0;
@@ -2396,7 +2400,7 @@ static void demo_init_vk(struct demo *demo) {
/* Look for instance extensions */
VkBool32 surfaceExtFound = 0;
VkBool32 platformSurfaceExtFound = 0;
-#if defined(VK_USE_PLATFORM_XLIB_KHR) | defined(VK_USE_PLATFORM_XCB_KHR)
+#if defined(VK_USE_PLATFORM_XLIB_KHR)
VkBool32 xlibSurfaceExtFound = 0;
#endif
memset(demo->extension_names, 0, sizeof(demo->extension_names));
@@ -2425,7 +2429,8 @@ static void demo_init_vk(struct demo *demo) {
demo->extension_names[demo->enabled_extension_count++] =
VK_KHR_WIN32_SURFACE_EXTENSION_NAME;
}
-#elif defined(VK_USE_PLATFORM_XLIB_KHR) | defined(VK_USE_PLATFORM_XCB_KHR)
+#endif
+#if defined(VK_USE_PLATFORM_XLIB_KHR)
if (!strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME,
instance_extensions[i].extensionName)) {
platformSurfaceExtFound = 1;
@@ -2433,14 +2438,16 @@ static void demo_init_vk(struct demo *demo) {
demo->extension_names[demo->enabled_extension_count++] =
VK_KHR_XLIB_SURFACE_EXTENSION_NAME;
}
-
+#endif
+#if defined(VK_USE_PLATFORM_XCB_KHR)
if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME,
instance_extensions[i].extensionName)) {
platformSurfaceExtFound = 1;
demo->extension_names[demo->enabled_extension_count++] =
VK_KHR_XCB_SURFACE_EXTENSION_NAME;
}
-#elif defined(VK_USE_PLATFORM_ANDROID_KHR)
+#endif
+#if defined(VK_USE_PLATFORM_ANDROID_KHR)
if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME,
instance_extensions[i].extensionName)) {
platformSurfaceExtFound = 1;
@@ -2537,7 +2544,7 @@ static void demo_init_vk(struct demo *demo) {
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
dbgCreateInfo.pNext = NULL;
dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
- dbgCreateInfo.pUserData = NULL;
+ dbgCreateInfo.pUserData = demo;
dbgCreateInfo.flags =
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
inst_info.pNext = &dbgCreateInfo;
@@ -2686,7 +2693,7 @@ static void demo_init_vk(struct demo *demo) {
dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
dbgCreateInfo.pNext = NULL;
dbgCreateInfo.pfnCallback = callback;
- dbgCreateInfo.pUserData = NULL;
+ dbgCreateInfo.pUserData = demo;
dbgCreateInfo.flags =
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
@@ -2966,9 +2973,13 @@ static void demo_init(struct demo *demo, int argc, char **argv) {
i++;
continue;
}
+ if (strcmp(argv[i], "--suppress_popups") == 0) {
+ demo->suppress_popups = true;
+ continue;
+ }
fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] "
- "[--c <framecount>]\n",
+ "[--c <framecount>] [--suppress_popups]\n",
APP_SHORT_NAME);
fflush(stderr);
exit(1);
@@ -3088,6 +3099,19 @@ static void processCommand(struct android_app* app, int32_t cmd) {
switch(cmd) {
case APP_CMD_INIT_WINDOW: {
if (app->window) {
+ // We're getting a new window. If the app is starting up, we
+ // need to initialize. If the app has already been
+ // initialized, that means that we lost our previous window,
+ // which means that we have a lot of work to do. At a minimum,
+ // we need to destroy the swapchain and surface associated with
+ // the old window, and create a new surface and swapchain.
+ // However, since there are a lot of other objects/state that
+ // is tied to the swapchain, it's easiest to simply cleanup and
+ // start over (i.e. use a brute-force approach of re-starting
+ // the app)
+ if (demo.prepared) {
+ demo_cleanup(&demo);
+ }
demo_init(&demo, 0, NULL);
demo.window = (void*)app->window;
demo_init_vk_swapchain(&demo);
@@ -3117,6 +3141,8 @@ void android_main(struct android_app *app)
return;
#endif
+ demo.prepared = false;
+
app->onAppCmd = processCommand;
app->onInputEvent = processInput;
diff --git a/demos/smoke/CMakeLists.txt b/demos/smoke/CMakeLists.txt
index a1789e92..04aae19b 100644
--- a/demos/smoke/CMakeLists.txt
+++ b/demos/smoke/CMakeLists.txt
@@ -60,7 +60,7 @@ if(WIN32)
list(APPEND sources ShellWin32.cpp ShellWin32.h)
else()
- list(APPEND libraries PRIVATE -ldl)
+ list(APPEND libraries PRIVATE -ldl -lrt)
find_package(XCB REQUIRED)
diff --git a/demos/tri.c b/demos/tri.c
index 1c80a22b..318291bc 100644
--- a/demos/tri.c
+++ b/demos/tri.c
@@ -66,7 +66,8 @@
#ifdef _WIN32
#define ERR_EXIT(err_msg, err_class) \
do { \
- MessageBox(NULL, err_msg, err_class, MB_OK); \
+ if (!demo->suppress_popups) \
+ MessageBox(NULL, err_msg, err_class, MB_OK); \
exit(1); \
} while (0)
#elif defined __ANDROID__
@@ -119,44 +120,6 @@ struct texture_object {
static int validation_error = 0;
VKAPI_ATTR VkBool32 VKAPI_CALL
-dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
- uint64_t srcObject, size_t location, int32_t msgCode,
- const char *pLayerPrefix, const char *pMsg, void *pUserData) {
- char *message = (char *)malloc(strlen(pMsg) + 100);
-
- assert(message);
-
- validation_error = 1;
-
- if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
- sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
- pMsg);
- } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
- sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
- pMsg);
- } else {
- return false;
- }
-
-#ifdef _WIN32
- MessageBox(NULL, message, "Alert", MB_OK);
-#else
- printf("%s\n", message);
- fflush(stdout);
-#endif
- free(message);
-
- /*
- * false indicates that layer should not bail-out of an
- * API call that had validation failures. This may mean that the
- * app dies inside the driver due to invalid parameter(s).
- * That's what would happen without validation layers, so we'll
- * keep that behavior here.
- */
- return false;
-}
-
-VKAPI_ATTR VkBool32 VKAPI_CALL
BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
uint64_t srcObject, size_t location, int32_t msgCode,
const char *pLayerPrefix, const char *pMsg,
@@ -170,7 +133,7 @@ BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
return false;
}
-typedef struct _SwapchainBuffers {
+typedef struct {
VkImage image;
VkCommandBuffer cmd;
VkImageView view;
@@ -193,12 +156,14 @@ struct demo {
VkSurfaceKHR surface;
bool prepared;
bool use_staging_buffer;
+ bool suppress_popups;
VkInstance inst;
VkPhysicalDevice gpu;
VkDevice device;
VkQueue queue;
VkPhysicalDeviceProperties gpu_props;
+ VkPhysicalDeviceFeatures gpu_features;
VkQueueFamilyProperties *queue_props;
uint32_t graphics_queue_node_index;
@@ -284,6 +249,46 @@ struct demo {
uint32_t queue_count;
};
+VKAPI_ATTR VkBool32 VKAPI_CALL
+dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType,
+ uint64_t srcObject, size_t location, int32_t msgCode,
+ const char *pLayerPrefix, const char *pMsg, void *pUserData) {
+ char *message = (char *)malloc(strlen(pMsg) + 100);
+
+ assert(message);
+
+ validation_error = 1;
+
+ if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
+ sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode,
+ pMsg);
+ } else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) {
+ sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode,
+ pMsg);
+ } else {
+ return false;
+ }
+
+#ifdef _WIN32
+ struct demo *demo = (struct demo*) pUserData;
+ if (!demo->suppress_popups)
+ MessageBox(NULL, message, "Alert", MB_OK);
+#else
+ printf("%s\n", message);
+ fflush(stdout);
+#endif
+ free(message);
+
+ /*
+ * false indicates that layer should not bail-out of an
+ * API call that had validation failures. This may mean that the
+ * app dies inside the driver due to invalid parameter(s).
+ * That's what would happen without validation layers, so we'll
+ * keep that behavior here.
+ */
+ return false;
+}
+
// Forward declaration:
static void demo_resize(struct demo *demo);
@@ -2119,7 +2124,7 @@ static void demo_init_vk(struct demo *demo) {
dbgCreateInfo.flags =
VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
dbgCreateInfo.pfnCallback = demo->use_break ? BreakCallback : dbgFunc;
- dbgCreateInfo.pUserData = NULL;
+ dbgCreateInfo.pUserData = demo;
dbgCreateInfo.pNext = NULL;
err = demo->CreateDebugReportCallback(demo->inst, &dbgCreateInfo, NULL,
&demo->msg_callback);
@@ -2161,8 +2166,7 @@ static void demo_init_vk(struct demo *demo) {
demo->queue_props);
assert(demo->queue_count >= 1);
- VkPhysicalDeviceFeatures features;
- vkGetPhysicalDeviceFeatures(demo->gpu, &features);
+ vkGetPhysicalDeviceFeatures(demo->gpu, &demo->gpu_features);
// Graphics queue and MemMgr queue can be separate.
// TODO: Add support for separate queues, including synchronization,
@@ -2180,9 +2184,12 @@ static void demo_init_device(struct demo *demo) {
.queueCount = 1,
.pQueuePriorities = queue_priorities};
- VkPhysicalDeviceFeatures features = {
- .shaderClipDistance = VK_TRUE,
- };
+
+ VkPhysicalDeviceFeatures features;
+ memset(&features, 0, sizeof(features));
+ if (demo->gpu_features.shaderClipDistance) {
+ features.shaderClipDistance = VK_TRUE;
+ }
VkDeviceCreateInfo device = {
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO,
@@ -2373,9 +2380,13 @@ static void demo_init(struct demo *demo, const int argc, const char *argv[])
i++;
continue;
}
+ if (strcmp(argv[i], "--suppress_popups") == 0) {
+ demo->suppress_popups = true;
+ continue;
+ }
fprintf(stderr, "Usage:\n %s [--use_staging] [--validate] [--break] "
- "[--c <framecount>]\n",
+ "[--c <framecount>] [--suppress_popups]\n",
APP_SHORT_NAME);
fflush(stderr);
exit(1);
diff --git a/demos/vulkaninfo.c b/demos/vulkaninfo.c
index 86e860c3..866756a0 100644
--- a/demos/vulkaninfo.c
+++ b/demos/vulkaninfo.c
@@ -18,19 +18,24 @@
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: David Pinedo <david@lunarg.com>
* Author: Mark Lobodzinski <mark@lunarg.com>
+ * Author: Rene Lindsay <rene@lunarg.com>
*/
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
#include <assert.h>
#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
#ifdef _WIN32
#include <fcntl.h>
#include <io.h>
#endif // _WIN32
+#ifdef __linux__
+#include <X11/Xutil.h>
+#endif
+
#include <vulkan/vulkan.h>
#define ERR(err) \
@@ -51,7 +56,7 @@ static int ConsoleIsExclusive(void) {
#define WAIT_FOR_CONSOLE_DESTROY \
do { \
- if (ConsoleIsExclusive()) \
+ if (ConsoleIsExclusive()) \
Sleep(INFINITE); \
} while (0)
#else
@@ -100,7 +105,39 @@ struct app_instance {
uint32_t global_layer_count;
struct layer_extension_list *global_layers;
uint32_t global_extension_count;
- VkExtensionProperties *global_extensions;
+ VkExtensionProperties *global_extensions; // Instance Extensions
+
+ PFN_vkGetPhysicalDeviceSurfaceSupportKHR
+ vkGetPhysicalDeviceSurfaceSupportKHR;
+ PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR
+ vkGetPhysicalDeviceSurfaceCapabilitiesKHR;
+ PFN_vkGetPhysicalDeviceSurfaceFormatsKHR
+ vkGetPhysicalDeviceSurfaceFormatsKHR;
+ PFN_vkGetPhysicalDeviceSurfacePresentModesKHR
+ vkGetPhysicalDeviceSurfacePresentModesKHR;
+
+ VkSurfaceKHR surface;
+ int width, height;
+
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ HINSTANCE hInstance; // Windows Instance
+ HWND hWnd; // window handle
+#endif
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ xcb_connection_t *xcb_connection;
+ xcb_screen_t *xcb_screen;
+ xcb_window_t xcb_window;
+#endif
+
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ Display *xlib_display;
+ Window xlib_window;
+#endif
+
+#ifdef VK_USE_PLATFORM_ANDROID_KHR // TODO
+ ANativeWindow *window;
+#endif
};
struct app_gpu {
@@ -451,7 +488,7 @@ static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) {
uint32_t count = 0;
- /* Scan layers */
+ // Scan layers
VkLayerProperties *device_layer_properties = NULL;
struct layer_extension_list *device_layers = NULL;
@@ -485,7 +522,7 @@ static void app_dev_init(struct app_dev *dev, struct app_gpu *gpu) {
memcpy(&dst_info->layer_properties, src_info,
sizeof(VkLayerProperties));
- /* Save away layer extension info for report */
+ // Save away layer extension info for report
app_get_physical_device_layer_extensions(
gpu, src_info->layerName, &dst_info->extension_count,
&dst_info->extension_properties);
@@ -524,6 +561,7 @@ app_get_global_layer_extensions(char *layer_name, uint32_t *extension_count,
/* repeat get until VK_INCOMPLETE goes away */
do {
+ // gets the extension count if the last parameter is NULL
err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count,
NULL);
assert(!err);
@@ -532,34 +570,17 @@ app_get_global_layer_extensions(char *layer_name, uint32_t *extension_count,
free(ext_ptr);
}
ext_ptr = malloc(ext_count * sizeof(VkExtensionProperties));
+ // gets the extension properties if the last parameter is not NULL
err = vkEnumerateInstanceExtensionProperties(layer_name, &ext_count,
ext_ptr);
} while (err == VK_INCOMPLETE);
assert(!err);
-
*extension_count = ext_count;
*extension_properties = ext_ptr;
}
-static void app_create_instance(struct app_instance *inst) {
- const VkApplicationInfo app_info = {
- .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
- .pNext = NULL,
- .pApplicationName = APP_SHORT_NAME,
- .applicationVersion = 1,
- .pEngineName = APP_SHORT_NAME,
- .engineVersion = 1,
- .apiVersion = VK_API_VERSION_1_0,
- };
- VkInstanceCreateInfo inst_info = {
- .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
- .pNext = NULL,
- .pApplicationInfo = &app_info,
- .enabledLayerCount = 0,
- .ppEnabledLayerNames = NULL,
- .enabledExtensionCount = 0,
- .ppEnabledExtensionNames = NULL,
- };
+/* Gets a list of layer and instance extensions */
+static void app_get_instance_extensions(struct app_instance *inst) {
VkResult U_ASSERT_ONLY err;
uint32_t count = 0;
@@ -599,6 +620,7 @@ static void app_create_instance(struct app_instance *inst) {
sizeof(VkLayerProperties));
/* Save away layer extension info for report */
+ /* Gets layer extensions, if first parameter is not NULL*/
app_get_global_layer_extensions(src_info->layerName,
&dst_info->extension_count,
&dst_info->extension_properties);
@@ -607,9 +629,75 @@ static void app_create_instance(struct app_instance *inst) {
/* Collect global extensions */
inst->global_extension_count = 0;
+ /* Gets instance extensions, if no layer was specified in teh first
+ * paramteter */
app_get_global_layer_extensions(NULL, &inst->global_extension_count,
&inst->global_extensions);
+}
+
+static void app_create_instance(struct app_instance *inst) {
+ app_get_instance_extensions(inst);
+//---Build a list of extensions to load---
+#define MAX_EXTENSIONS 4
+ uint32_t i = 0;
+ uint32_t ext_count = 0;
+ const char *ext_names[MAX_EXTENSIONS]; // array of string pointers to
+ // extension names
+ for (i = 0; (i < inst->global_extension_count); i++) {
+ const char *found_name = inst->global_extensions[i].extensionName;
+ if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, found_name))
+ {ext_names[ext_count++] = VK_KHR_SURFACE_EXTENSION_NAME;}
+ }
+
+ if (ext_count)
+ for (i = 0; ((i < inst->global_extension_count) &&
+ (ext_count < MAX_EXTENSIONS));
+ i++) {
+ const char *found_name = inst->global_extensions[i].extensionName;
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, found_name))
+ {ext_names[ext_count++] = VK_KHR_WIN32_SURFACE_EXTENSION_NAME;}
+#endif
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, found_name))
+ {ext_names[ext_count++] = VK_KHR_XCB_SURFACE_EXTENSION_NAME;}
+#endif
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ if (!strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, found_name))
+ {ext_names[ext_count++] = VK_KHR_XLIB_SURFACE_EXTENSION_NAME;}
+#endif
+#ifdef VK_USE_PLATFORM_ANDROID_KHR
+ if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, found_name))
+ {ext_names[ext_count++] = VK_KHR_ANDROID_SURFACE_EXTENSION_NAME;}
+#endif
+ }
+ // If we don't find the KHR_SURFACE extension and at least one other
+ // device-specific extension,
+ // then give up on reporting presentable surface formats."
+ if (ext_count < 2)
+ ext_count = 0;
+ //----------------------------------------
+
+ const VkApplicationInfo app_info = {
+ .sType = VK_STRUCTURE_TYPE_APPLICATION_INFO,
+ .pNext = NULL,
+ .pApplicationName = APP_SHORT_NAME,
+ .applicationVersion = 1,
+ .pEngineName = APP_SHORT_NAME,
+ .engineVersion = 1,
+ .apiVersion = VK_API_VERSION_1_0,
+ };
+
+ VkInstanceCreateInfo inst_info = {
+ .sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
+ .pNext = NULL,
+ .pApplicationInfo = &app_info,
+ .enabledLayerCount = 0,
+ .ppEnabledLayerNames = NULL,
+ .enabledExtensionCount = ext_count,
+ .ppEnabledExtensionNames = ext_names,
+ };
VkDebugReportCallbackCreateInfoEXT dbg_info;
memset(&dbg_info, 0, sizeof(dbg_info));
@@ -620,6 +708,7 @@ static void app_create_instance(struct app_instance *inst) {
dbg_info.pfnCallback = dbg_callback;
inst_info.pNext = &dbg_info;
+ VkResult U_ASSERT_ONLY err;
err = vkCreateInstance(&inst_info, NULL, &inst->instance);
if (err == VK_ERROR_INCOMPATIBLE_DRIVER) {
printf("Cannot create Vulkan instance.\n");
@@ -627,8 +716,24 @@ static void app_create_instance(struct app_instance *inst) {
} else if (err) {
ERR_EXIT(err);
}
+
+ if (ext_count > 0) {
+//--Load Extensions--
+#define GET_INSTANCE_PROC_ADDR(ENTRYPOINT) \
+ { \
+ inst->ENTRYPOINT = \
+ (void *)vkGetInstanceProcAddr(inst->instance, #ENTRYPOINT); \
+ }
+ GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfaceSupportKHR)
+ GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfaceCapabilitiesKHR)
+ GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfaceFormatsKHR)
+ GET_INSTANCE_PROC_ADDR(vkGetPhysicalDeviceSurfacePresentModesKHR)
+#undef GET_INSTANCE_PROC_ADDR
+ }
}
+//-----------------------------------------------------------
+
static void app_destroy_instance(struct app_instance *inst) {
free(inst->global_extensions);
vkDestroyInstance(inst->instance, NULL);
@@ -691,6 +796,197 @@ static void app_gpu_destroy(struct app_gpu *gpu) {
}
// clang-format off
+
+//-----------------------------------------------------------
+
+//---------------------------Win32---------------------------
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+
+// MS-Windows event handling function:
+LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
+ return (DefWindowProc(hWnd, uMsg, wParam, lParam));
+}
+
+static void app_create_win32_window(struct app_instance *inst) {
+ inst->hInstance = GetModuleHandle(NULL);
+
+ WNDCLASSEX win_class;
+
+ // Initialize the window class structure:
+ win_class.cbSize = sizeof(WNDCLASSEX);
+ win_class.style = CS_HREDRAW | CS_VREDRAW;
+ win_class.lpfnWndProc = WndProc;
+ win_class.cbClsExtra = 0;
+ win_class.cbWndExtra = 0;
+ win_class.hInstance = inst->hInstance;
+ win_class.hIcon = LoadIcon(NULL, IDI_APPLICATION);
+ win_class.hCursor = LoadCursor(NULL, IDC_ARROW);
+ win_class.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
+ win_class.lpszMenuName = NULL;
+ win_class.lpszClassName = APP_SHORT_NAME;
+ win_class.hInstance = inst->hInstance;
+ win_class.hIconSm = LoadIcon(NULL, IDI_WINLOGO);
+ // Register window class:
+ if (!RegisterClassEx(&win_class)) {
+ // It didn't work, so try to give a useful error:
+ printf("Failed to register the window class!\n");
+ fflush(stdout);
+ exit(1);
+ }
+ // Create window with the registered class:
+ RECT wr = { 0, 0, inst->width, inst->height };
+ AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
+ inst->hWnd = CreateWindowEx(0,
+ APP_SHORT_NAME, // class name
+ APP_SHORT_NAME, // app name
+ //WS_VISIBLE | WS_SYSMENU |
+ WS_OVERLAPPEDWINDOW, // window style
+ 100, 100, // x/y coords
+ wr.right - wr.left, // width
+ wr.bottom - wr.top, // height
+ NULL, // handle to parent
+ NULL, // handle to menu
+ inst->hInstance, // hInstance
+ NULL); // no extra parameters
+ if (!inst->hWnd) {
+ // It didn't work, so try to give a useful error:
+ printf("Failed to create a window!\n");
+ fflush(stdout);
+ exit(1);
+ }
+}
+
+static void app_create_win32_surface(struct app_instance *inst, struct app_gpu *gpu) {
+ VkResult U_ASSERT_ONLY err;
+ VkWin32SurfaceCreateInfoKHR createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR;
+ createInfo.pNext = NULL;
+ createInfo.flags = 0;
+ createInfo.hinstance = inst->hInstance;
+ createInfo.hwnd = inst->hWnd;
+ err = vkCreateWin32SurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
+ assert(!err);
+}
+
+static void app_destroy_win32_window(struct app_instance *inst) {
+ DestroyWindow(inst->hWnd);
+}
+#endif //VK_USE_PLATFORM_WIN32_KHR
+//-----------------------------------------------------------
+
+static void app_destroy_surface(struct app_instance *inst) { //same for all platforms
+ vkDestroySurfaceKHR(inst->instance, inst->surface, NULL);
+}
+
+//----------------------------XCB----------------------------
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+static void app_create_xcb_window(struct app_instance *inst) {
+ //--Init Connection--
+ const xcb_setup_t *setup;
+ xcb_screen_iterator_t iter;
+ int scr;
+
+ inst->xcb_connection = xcb_connect(NULL, &scr);
+ if (inst->xcb_connection == NULL) {
+ printf("XCB failed to connect to the X server.\nExiting ...\n");
+ fflush(stdout);
+ exit(1);
+ }
+
+ setup = xcb_get_setup(inst->xcb_connection);
+ iter = xcb_setup_roots_iterator(setup);
+ while (scr-- > 0)
+ xcb_screen_next(&iter);
+
+ inst->xcb_screen = iter.data;
+ //-------------------
+
+ inst->xcb_window = xcb_generate_id(inst->xcb_connection);
+ xcb_create_window(inst->xcb_connection, XCB_COPY_FROM_PARENT, inst->xcb_window,
+ inst->xcb_screen->root, 0, 0, inst->width, inst->height, 0,
+ XCB_WINDOW_CLASS_INPUT_OUTPUT, inst->xcb_screen->root_visual,
+ 0, NULL);
+
+ xcb_intern_atom_cookie_t cookie = xcb_intern_atom(inst->xcb_connection, 1, 12, "WM_PROTOCOLS");
+ xcb_intern_atom_reply_t *reply = xcb_intern_atom_reply(inst->xcb_connection, cookie, 0);
+ free(reply);
+}
+
+static void app_create_xcb_surface(struct app_instance *inst, struct app_gpu *gpu) {
+ VkResult U_ASSERT_ONLY err;
+ VkXcbSurfaceCreateInfoKHR xcb_createInfo;
+ xcb_createInfo.sType = VK_STRUCTURE_TYPE_XCB_SURFACE_CREATE_INFO_KHR;
+ xcb_createInfo.pNext = NULL;
+ xcb_createInfo.flags = 0;
+ xcb_createInfo.connection = inst->xcb_connection;
+ xcb_createInfo.window = inst->xcb_window;
+ err = vkCreateXcbSurfaceKHR(inst->instance, &xcb_createInfo, NULL, &inst->surface);
+ assert(!err);
+}
+
+static void app_destroy_xcb_window(struct app_instance *inst) {
+ xcb_destroy_window(inst->xcb_connection, inst->xcb_window);
+ xcb_disconnect(inst->xcb_connection);
+}
+#endif //VK_USE_PLATFORM_XCB_KHR
+//-----------------------------------------------------------
+
+//----------------------------XLib---------------------------
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+static void app_create_xlib_window(struct app_instance *inst) {
+ inst->xlib_display = XOpenDisplay(NULL);
+ long visualMask = VisualScreenMask;
+ int numberOfVisuals;
+
+ XVisualInfo vInfoTemplate={};
+ vInfoTemplate.screen = DefaultScreen(inst->xlib_display);
+ XVisualInfo *visualInfo = XGetVisualInfo(inst->xlib_display, visualMask,
+ &vInfoTemplate, &numberOfVisuals);
+ inst->xlib_window = XCreateWindow(
+ inst->xlib_display, RootWindow(inst->xlib_display, vInfoTemplate.screen), 0, 0,
+ inst->width, inst->height, 0, visualInfo->depth, InputOutput,
+ visualInfo->visual, 0, NULL);
+
+ XFlush(inst->xlib_display);
+}
+
+static void app_create_xlib_surface(struct app_instance *inst, struct app_gpu *gpu) {
+ VkResult U_ASSERT_ONLY err;
+ VkXlibSurfaceCreateInfoKHR createInfo;
+ createInfo.sType = VK_STRUCTURE_TYPE_XLIB_SURFACE_CREATE_INFO_KHR;
+ createInfo.pNext = NULL;
+ createInfo.flags = 0;
+ createInfo.dpy = inst->xlib_display;
+ createInfo.window = inst->xlib_window;
+ err = vkCreateXlibSurfaceKHR(inst->instance, &createInfo, NULL, &inst->surface);
+ assert(!err);
+}
+
+static void app_destroy_xlib_window(struct app_instance *inst) {
+ XDestroyWindow(inst->xlib_display, inst->xlib_window);
+ XCloseDisplay(inst->xlib_display);
+}
+#endif //VK_USE_PLATFORM_XLIB_KHR
+//-----------------------------------------------------------
+
+static int app_dump_surface_formats(struct app_instance *inst, struct app_gpu *gpu){
+ // Get the list of VkFormat's that are supported:
+ VkResult U_ASSERT_ONLY err;
+ uint32_t formatCount=0;
+ err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &formatCount, NULL);
+ assert(!err);
+ VkSurfaceFormatKHR *surfFormats = (VkSurfaceFormatKHR *)malloc(formatCount * sizeof(VkSurfaceFormatKHR));
+ err = inst->vkGetPhysicalDeviceSurfaceFormatsKHR(gpu->obj, inst->surface, &formatCount, surfFormats);
+ assert(!err);
+ printf("Format count = %d\n",formatCount);
+ uint32_t i;
+ for(i=0;i<formatCount;i++) printf("\t%s\n",vk_format_string(surfFormats[i].format));
+ printf("\n");
+ fflush(stdout);
+ return formatCount;
+}
+
static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt)
{
const VkFormatProperties *props = &dev->format_props[fmt];
@@ -713,20 +1009,21 @@ static void app_dev_dump_format_props(const struct app_dev *dev, VkFormat fmt)
if (features[i].flags == 0) {
printf("\n\t\tNone");
} else {
- printf("%s%s%s%s%s%s%s%s%s%s%s%s%s",
- ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""),
- ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : ""));
+ printf("%s%s%s%s%s%s%s%s%s%s%s%s%s%s",
+ ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT" : ""), //0x0001
+ ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_BIT" : ""), //0x0002
+ ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT" : ""), //0x0004
+ ((features[i].flags & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT" : ""), //0x0008
+ ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT" : ""), //0x0010
+ ((features[i].flags & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT" : ""), //0x0020
+ ((features[i].flags & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) ? "\n\t\tVK_FORMAT_FEATURE_VERTEX_BUFFER_BIT" : ""), //0x0040
+ ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT" : ""), //0x0080
+ ((features[i].flags & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) ? "\n\t\tVK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT" : ""), //0x0100
+ ((features[i].flags & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) ? "\n\t\tVK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT" : ""), //0x0200
+ ((features[i].flags & VK_FORMAT_FEATURE_BLIT_SRC_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_SRC_BIT" : ""), //0x0400
+ ((features[i].flags & VK_FORMAT_FEATURE_BLIT_DST_BIT) ? "\n\t\tVK_FORMAT_FEATURE_BLIT_DST_BIT" : ""), //0x0800
+ ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT" : ""), //0x1000
+ ((features[i].flags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG) ? "\n\t\tVK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_CUBIC_BIT_IMG" : "")); //0x2000
}
}
printf("\n");
@@ -828,108 +1125,109 @@ static void app_dump_limits(const VkPhysicalDeviceLimits *limits)
{
printf("\tVkPhysicalDeviceLimits:\n");
printf("\t-----------------------\n");
-
- printf("\t\tmaxImageDimension1D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension1D );
- printf("\t\tmaxImageDimension2D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension2D );
- printf("\t\tmaxImageDimension3D = 0x%" PRIxLEAST32 "\n", limits->maxImageDimension3D );
- printf("\t\tmaxImageDimensionCube = 0x%" PRIxLEAST32 "\n", limits->maxImageDimensionCube );
- printf("\t\tmaxImageArrayLayers = 0x%" PRIxLEAST32 "\n", limits->maxImageArrayLayers );
+ printf("\t\tmaxImageDimension1D = %u\n", limits->maxImageDimension1D );
+ printf("\t\tmaxImageDimension2D = %u\n", limits->maxImageDimension2D );
+ printf("\t\tmaxImageDimension3D = %u\n", limits->maxImageDimension3D );
+ printf("\t\tmaxImageDimensionCube = %u\n", limits->maxImageDimensionCube );
+ printf("\t\tmaxImageArrayLayers = %u\n", limits->maxImageArrayLayers );
printf("\t\tmaxTexelBufferElements = 0x%" PRIxLEAST32 "\n", limits->maxTexelBufferElements );
printf("\t\tmaxUniformBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxUniformBufferRange );
printf("\t\tmaxStorageBufferRange = 0x%" PRIxLEAST32 "\n", limits->maxStorageBufferRange );
- printf("\t\tmaxPushConstantsSize = 0x%" PRIxLEAST32 "\n", limits->maxPushConstantsSize );
- printf("\t\tmaxMemoryAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxMemoryAllocationCount );
- printf("\t\tmaxSamplerAllocationCount = 0x%" PRIxLEAST32 "\n", limits->maxSamplerAllocationCount );
+ printf("\t\tmaxPushConstantsSize = %u\n", limits->maxPushConstantsSize );
+ printf("\t\tmaxMemoryAllocationCount = %u\n", limits->maxMemoryAllocationCount );
+ printf("\t\tmaxSamplerAllocationCount = %u\n", limits->maxSamplerAllocationCount );
printf("\t\tbufferImageGranularity = 0x%" PRIxLEAST64 "\n", limits->bufferImageGranularity );
printf("\t\tsparseAddressSpaceSize = 0x%" PRIxLEAST64 "\n", limits->sparseAddressSpaceSize );
- printf("\t\tmaxBoundDescriptorSets = 0x%" PRIxLEAST32 "\n", limits->maxBoundDescriptorSets );
- printf("\t\tmaxPerStageDescriptorSamplers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSamplers );
- printf("\t\tmaxPerStageDescriptorUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorUniformBuffers );
- printf("\t\tmaxPerStageDescriptorStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageBuffers );
- printf("\t\tmaxPerStageDescriptorSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorSampledImages );
- printf("\t\tmaxPerStageDescriptorStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorStorageImages );
- printf("\t\tmaxPerStageDescriptorInputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxPerStageDescriptorInputAttachments );
- printf("\t\tmaxPerStageResources = 0x%" PRIxLEAST32 "\n", limits->maxPerStageResources );
- printf("\t\tmaxDescriptorSetSamplers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSamplers );
- printf("\t\tmaxDescriptorSetUniformBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffers );
- printf("\t\tmaxDescriptorSetUniformBuffersDynamic = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetUniformBuffersDynamic );
- printf("\t\tmaxDescriptorSetStorageBuffers = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffers );
- printf("\t\tmaxDescriptorSetStorageBuffersDynamic = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageBuffersDynamic );
- printf("\t\tmaxDescriptorSetSampledImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetSampledImages );
- printf("\t\tmaxDescriptorSetStorageImages = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetStorageImages );
- printf("\t\tmaxDescriptorSetInputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxDescriptorSetInputAttachments );
- printf("\t\tmaxVertexInputAttributes = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributes );
- printf("\t\tmaxVertexInputBindings = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindings );
+ printf("\t\tmaxBoundDescriptorSets = %u\n", limits->maxBoundDescriptorSets );
+ printf("\t\tmaxPerStageDescriptorSamplers = %u\n", limits->maxPerStageDescriptorSamplers );
+ printf("\t\tmaxPerStageDescriptorUniformBuffers = %u\n", limits->maxPerStageDescriptorUniformBuffers );
+ printf("\t\tmaxPerStageDescriptorStorageBuffers = %u\n", limits->maxPerStageDescriptorStorageBuffers );
+ printf("\t\tmaxPerStageDescriptorSampledImages = %u\n", limits->maxPerStageDescriptorSampledImages );
+ printf("\t\tmaxPerStageDescriptorStorageImages = %u\n", limits->maxPerStageDescriptorStorageImages );
+ printf("\t\tmaxPerStageDescriptorInputAttachments = %u\n", limits->maxPerStageDescriptorInputAttachments );
+ printf("\t\tmaxPerStageResources = %u\n", limits->maxPerStageResources );
+ printf("\t\tmaxDescriptorSetSamplers = %u\n", limits->maxDescriptorSetSamplers );
+ printf("\t\tmaxDescriptorSetUniformBuffers = %u\n", limits->maxDescriptorSetUniformBuffers );
+ printf("\t\tmaxDescriptorSetUniformBuffersDynamic = %u\n", limits->maxDescriptorSetUniformBuffersDynamic );
+ printf("\t\tmaxDescriptorSetStorageBuffers = %u\n", limits->maxDescriptorSetStorageBuffers );
+ printf("\t\tmaxDescriptorSetStorageBuffersDynamic = %u\n", limits->maxDescriptorSetStorageBuffersDynamic );
+ printf("\t\tmaxDescriptorSetSampledImages = %u\n", limits->maxDescriptorSetSampledImages );
+ printf("\t\tmaxDescriptorSetStorageImages = %u\n", limits->maxDescriptorSetStorageImages );
+ printf("\t\tmaxDescriptorSetInputAttachments = %u\n", limits->maxDescriptorSetInputAttachments );
+ printf("\t\tmaxVertexInputAttributes = %u\n", limits->maxVertexInputAttributes );
+ printf("\t\tmaxVertexInputBindings = %u\n", limits->maxVertexInputBindings );
printf("\t\tmaxVertexInputAttributeOffset = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputAttributeOffset );
printf("\t\tmaxVertexInputBindingStride = 0x%" PRIxLEAST32 "\n", limits->maxVertexInputBindingStride );
- printf("\t\tmaxVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxVertexOutputComponents );
- printf("\t\tmaxTessellationGenerationLevel = 0x%" PRIxLEAST32 "\n", limits->maxTessellationGenerationLevel );
- printf("\t\tmaxTessellationPatchSize = 0x%" PRIxLEAST32 "\n", limits->maxTessellationPatchSize );
- printf("\t\tmaxTessellationControlPerVertexInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerVertexInputComponents );
- printf("\t\tmaxTessellationControlPerVertexOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerVertexOutputComponents);
- printf("\t\tmaxTessellationControlPerPatchOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlPerPatchOutputComponents );
- printf("\t\tmaxTessellationControlTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationControlTotalOutputComponents );
- printf("\t\tmaxTessellationEvaluationInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationEvaluationInputComponents );
- printf("\t\tmaxTessellationEvaluationOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxTessellationEvaluationOutputComponents );
- printf("\t\tmaxGeometryShaderInvocations = 0x%" PRIxLEAST32 "\n", limits->maxGeometryShaderInvocations );
- printf("\t\tmaxGeometryInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryInputComponents );
- printf("\t\tmaxGeometryOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputComponents );
- printf("\t\tmaxGeometryOutputVertices = 0x%" PRIxLEAST32 "\n", limits->maxGeometryOutputVertices );
- printf("\t\tmaxGeometryTotalOutputComponents = 0x%" PRIxLEAST32 "\n", limits->maxGeometryTotalOutputComponents );
- printf("\t\tmaxFragmentInputComponents = 0x%" PRIxLEAST32 "\n", limits->maxFragmentInputComponents );
- printf("\t\tmaxFragmentOutputAttachments = 0x%" PRIxLEAST32 "\n", limits->maxFragmentOutputAttachments );
- printf("\t\tmaxFragmentDualSrcAttachments = 0x%" PRIxLEAST32 "\n", limits->maxFragmentDualSrcAttachments );
- printf("\t\tmaxFragmentCombinedOutputResources = 0x%" PRIxLEAST32 "\n", limits->maxFragmentCombinedOutputResources );
+ printf("\t\tmaxVertexOutputComponents = %u\n", limits->maxVertexOutputComponents );
+ printf("\t\tmaxTessellationGenerationLevel = %u\n", limits->maxTessellationGenerationLevel );
+ printf("\t\tmaxTessellationPatchSize = %u\n", limits->maxTessellationPatchSize );
+ printf("\t\tmaxTessellationControlPerVertexInputComponents = %u\n", limits->maxTessellationControlPerVertexInputComponents );
+ printf("\t\tmaxTessellationControlPerVertexOutputComponents = %u\n", limits->maxTessellationControlPerVertexOutputComponents);
+ printf("\t\tmaxTessellationControlPerPatchOutputComponents = %u\n", limits->maxTessellationControlPerPatchOutputComponents );
+ printf("\t\tmaxTessellationControlTotalOutputComponents = %u\n", limits->maxTessellationControlTotalOutputComponents );
+ printf("\t\tmaxTessellationEvaluationInputComponents = %u\n", limits->maxTessellationEvaluationInputComponents );
+ printf("\t\tmaxTessellationEvaluationOutputComponents = %u\n", limits->maxTessellationEvaluationOutputComponents );
+ printf("\t\tmaxGeometryShaderInvocations = %u\n", limits->maxGeometryShaderInvocations );
+ printf("\t\tmaxGeometryInputComponents = %u\n", limits->maxGeometryInputComponents );
+ printf("\t\tmaxGeometryOutputComponents = %u\n", limits->maxGeometryOutputComponents );
+ printf("\t\tmaxGeometryOutputVertices = %u\n", limits->maxGeometryOutputVertices );
+ printf("\t\tmaxGeometryTotalOutputComponents = %u\n", limits->maxGeometryTotalOutputComponents );
+ printf("\t\tmaxFragmentInputComponents = %u\n", limits->maxFragmentInputComponents );
+ printf("\t\tmaxFragmentOutputAttachments = %u\n", limits->maxFragmentOutputAttachments );
+ printf("\t\tmaxFragmentDualSrcAttachments = %u\n", limits->maxFragmentDualSrcAttachments );
+ printf("\t\tmaxFragmentCombinedOutputResources = %u\n", limits->maxFragmentCombinedOutputResources );
printf("\t\tmaxComputeSharedMemorySize = 0x%" PRIxLEAST32 "\n", limits->maxComputeSharedMemorySize );
- printf("\t\tmaxComputeWorkGroupCount[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[0] );
- printf("\t\tmaxComputeWorkGroupCount[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[1] );
- printf("\t\tmaxComputeWorkGroupCount[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupCount[2] );
- printf("\t\tmaxComputeWorkGroupInvocations = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupInvocations );
- printf("\t\tmaxComputeWorkGroupSize[0] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[0] );
- printf("\t\tmaxComputeWorkGroupSize[1] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[1] );
- printf("\t\tmaxComputeWorkGroupSize[2] = 0x%" PRIxLEAST32 "\n", limits->maxComputeWorkGroupSize[2] );
- printf("\t\tsubPixelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subPixelPrecisionBits );
- printf("\t\tsubTexelPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->subTexelPrecisionBits );
- printf("\t\tmipmapPrecisionBits = 0x%" PRIxLEAST32 "\n", limits->mipmapPrecisionBits );
- printf("\t\tmaxDrawIndexedIndexValue = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndexedIndexValue );
- printf("\t\tmaxDrawIndirectCount = 0x%" PRIxLEAST32 "\n", limits->maxDrawIndirectCount );
+ printf("\t\tmaxComputeWorkGroupCount[0] = %u\n", limits->maxComputeWorkGroupCount[0] );
+ printf("\t\tmaxComputeWorkGroupCount[1] = %u\n", limits->maxComputeWorkGroupCount[1] );
+ printf("\t\tmaxComputeWorkGroupCount[2] = %u\n", limits->maxComputeWorkGroupCount[2] );
+ printf("\t\tmaxComputeWorkGroupInvocations = %u\n", limits->maxComputeWorkGroupInvocations );
+ printf("\t\tmaxComputeWorkGroupSize[0] = %u\n", limits->maxComputeWorkGroupSize[0] );
+ printf("\t\tmaxComputeWorkGroupSize[1] = %u\n", limits->maxComputeWorkGroupSize[1] );
+ printf("\t\tmaxComputeWorkGroupSize[2] = %u\n", limits->maxComputeWorkGroupSize[2] );
+ printf("\t\tsubPixelPrecisionBits = %u\n", limits->subPixelPrecisionBits );
+ printf("\t\tsubTexelPrecisionBits = %u\n", limits->subTexelPrecisionBits );
+ printf("\t\tmipmapPrecisionBits = %u\n", limits->mipmapPrecisionBits );
+ printf("\t\tmaxDrawIndexedIndexValue = %u\n", limits->maxDrawIndexedIndexValue );
+ printf("\t\tmaxDrawIndirectCount = %u\n", limits->maxDrawIndirectCount );
printf("\t\tmaxSamplerLodBias = %f\n", limits->maxSamplerLodBias );
printf("\t\tmaxSamplerAnisotropy = %f\n", limits->maxSamplerAnisotropy );
- printf("\t\tmaxViewports = 0x%" PRIxLEAST32 "\n", limits->maxViewports );
- printf("\t\tmaxViewportDimensions[0] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[0] );
- printf("\t\tmaxViewportDimensions[1] = 0x%" PRIxLEAST32 "\n", limits->maxViewportDimensions[1] );
- printf("\t\tviewportBoundsRange[0] = %f\n", limits->viewportBoundsRange[0] );
- printf("\t\tviewportBoundsRange[1] = %f\n", limits->viewportBoundsRange[1] );
- printf("\t\tviewportSubPixelBits = 0x%" PRIxLEAST32 "\n", limits->viewportSubPixelBits );
+ printf("\t\tmaxViewports = %u\n", limits->maxViewports );
+ printf("\t\tmaxViewportDimensions[0] = %u\n", limits->maxViewportDimensions[0] );
+ printf("\t\tmaxViewportDimensions[1] = %u\n", limits->maxViewportDimensions[1] );
+ printf("\t\tviewportBoundsRange[0] =%13f\n", limits->viewportBoundsRange[0] );
+ printf("\t\tviewportBoundsRange[1] =%13f\n", limits->viewportBoundsRange[1] );
+ printf("\t\tviewportSubPixelBits = %u\n", limits->viewportSubPixelBits );
printf("\t\tminMemoryMapAlignment = " PRINTF_SIZE_T_SPECIFIER "\n", limits->minMemoryMapAlignment );
printf("\t\tminTexelBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minTexelBufferOffsetAlignment );
printf("\t\tminUniformBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minUniformBufferOffsetAlignment );
printf("\t\tminStorageBufferOffsetAlignment = 0x%" PRIxLEAST64 "\n", limits->minStorageBufferOffsetAlignment );
- printf("\t\tminTexelOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelOffset );
- printf("\t\tmaxTexelOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelOffset );
- printf("\t\tminTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->minTexelGatherOffset );
- printf("\t\tmaxTexelGatherOffset = 0x%" PRIxLEAST32 "\n", limits->maxTexelGatherOffset );
- printf("\t\tminInterpolationOffset = %f\n", limits->minInterpolationOffset );
- printf("\t\tmaxInterpolationOffset = %f\n", limits->maxInterpolationOffset );
- printf("\t\tsubPixelInterpolationOffsetBits = 0x%" PRIxLEAST32 "\n", limits->subPixelInterpolationOffsetBits );
- printf("\t\tmaxFramebufferWidth = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferWidth );
- printf("\t\tmaxFramebufferHeight = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferHeight );
- printf("\t\tmaxFramebufferLayers = 0x%" PRIxLEAST32 "\n", limits->maxFramebufferLayers );
- printf("\t\tframebufferColorSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferColorSampleCounts );
- printf("\t\tframebufferDepthSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferDepthSampleCounts );
- printf("\t\tframebufferStencilSampleCounts = 0x%" PRIxLEAST32 "\n", limits->framebufferStencilSampleCounts );
- printf("\t\tmaxColorAttachments = 0x%" PRIxLEAST32 "\n", limits->maxColorAttachments );
- printf("\t\tsampledImageColorSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageColorSampleCounts );
- printf("\t\tsampledImageDepthSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageDepthSampleCounts );
- printf("\t\tsampledImageStencilSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageStencilSampleCounts );
- printf("\t\tsampledImageIntegerSampleCounts = 0x%" PRIxLEAST32 "\n", limits->sampledImageIntegerSampleCounts );
- printf("\t\tstorageImageSampleCounts = 0x%" PRIxLEAST32 "\n", limits->storageImageSampleCounts );
- printf("\t\tmaxSampleMaskWords = 0x%" PRIxLEAST32 "\n", limits->maxSampleMaskWords );
+ printf("\t\tminTexelOffset =%3d\n", limits->minTexelOffset );
+ printf("\t\tmaxTexelOffset =%3d\n", limits->maxTexelOffset );
+ printf("\t\tminTexelGatherOffset =%3d\n", limits->minTexelGatherOffset );
+ printf("\t\tmaxTexelGatherOffset =%3d\n", limits->maxTexelGatherOffset );
+ printf("\t\tminInterpolationOffset =%9f\n", limits->minInterpolationOffset );
+ printf("\t\tmaxInterpolationOffset =%9f\n", limits->maxInterpolationOffset );
+ printf("\t\tsubPixelInterpolationOffsetBits = %u\n", limits->subPixelInterpolationOffsetBits );
+ printf("\t\tmaxFramebufferWidth = %u\n", limits->maxFramebufferWidth );
+ printf("\t\tmaxFramebufferHeight = %u\n", limits->maxFramebufferHeight );
+ printf("\t\tmaxFramebufferLayers = %u\n", limits->maxFramebufferLayers );
+ printf("\t\tframebufferColorSampleCounts = %u\n", limits->framebufferColorSampleCounts );
+ printf("\t\tframebufferDepthSampleCounts = %u\n", limits->framebufferDepthSampleCounts );
+ printf("\t\tframebufferStencilSampleCounts = %u\n", limits->framebufferStencilSampleCounts );
+ printf("\t\tframebufferNoAttachmentsSampleCounts = %u\n", limits->framebufferNoAttachmentsSampleCounts );
+ printf("\t\tmaxColorAttachments = %u\n", limits->maxColorAttachments );
+ printf("\t\tsampledImageColorSampleCounts = %u\n", limits->sampledImageColorSampleCounts );
+ printf("\t\tsampledImageDepthSampleCounts = %u\n", limits->sampledImageDepthSampleCounts );
+ printf("\t\tsampledImageStencilSampleCounts = %u\n", limits->sampledImageStencilSampleCounts );
+ printf("\t\tsampledImageIntegerSampleCounts = %u\n", limits->sampledImageIntegerSampleCounts );
+ printf("\t\tstorageImageSampleCounts = %u\n", limits->storageImageSampleCounts );
+ printf("\t\tmaxSampleMaskWords = %u\n", limits->maxSampleMaskWords );
printf("\t\ttimestampComputeAndGraphics = %u\n", limits->timestampComputeAndGraphics );
- printf("\t\ttimestampPeriod = 0x%f\n", limits->timestampPeriod );
- printf("\t\tmaxClipDistances = 0x%" PRIxLEAST32 "\n", limits->maxClipDistances );
- printf("\t\tmaxCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCullDistances );
- printf("\t\tmaxCombinedClipAndCullDistances = 0x%" PRIxLEAST32 "\n", limits->maxCombinedClipAndCullDistances );
+ printf("\t\ttimestampPeriod = %f\n", limits->timestampPeriod );
+ printf("\t\tmaxClipDistances = %u\n", limits->maxClipDistances );
+ printf("\t\tmaxCullDistances = %u\n", limits->maxCullDistances );
+ printf("\t\tmaxCombinedClipAndCullDistances = %u\n", limits->maxCombinedClipAndCullDistances );
+ printf("\t\tdiscreteQueuePriorities = %u\n", limits->discreteQueuePriorities );
printf("\t\tpointSizeRange[0] = %f\n", limits->pointSizeRange[0] );
printf("\t\tpointSizeRange[1] = %f\n", limits->pointSizeRange[1] );
printf("\t\tlineWidthRange[0] = %f\n", limits->lineWidthRange[0] );
@@ -946,15 +1244,19 @@ static void app_dump_limits(const VkPhysicalDeviceLimits *limits)
static void app_gpu_dump_props(const struct app_gpu *gpu)
{
const VkPhysicalDeviceProperties *props = &gpu->props;
+ const uint32_t apiVersion=props->apiVersion;
+ const uint32_t major = VK_VERSION_MAJOR(apiVersion);
+ const uint32_t minor = VK_VERSION_MINOR(apiVersion);
+ const uint32_t patch = VK_VERSION_PATCH(apiVersion);
printf("VkPhysicalDeviceProperties:\n");
printf("===========================\n");
- printf("\tapiVersion = %u\n", props->apiVersion);
- printf("\tdriverVersion = %u\n", props->driverVersion);
- printf("\tvendorID = 0x%04x\n", props->vendorID);
- printf("\tdeviceID = 0x%04x\n", props->deviceID);
- printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType));
- printf("\tdeviceName = %s\n", props->deviceName);
+ printf("\tapiVersion = 0x%" PRIxLEAST32 " (%d.%d.%d)\n", apiVersion, major, minor, patch);
+ printf("\tdriverVersion = %u (0x%" PRIxLEAST32 ")\n",props->driverVersion, props->driverVersion);
+ printf("\tvendorID = 0x%04x\n", props->vendorID);
+ printf("\tdeviceID = 0x%04x\n", props->deviceID);
+ printf("\tdeviceType = %s\n", vk_physical_device_type_string(props->deviceType));
+ printf("\tdeviceName = %s\n", props->deviceName);
app_dump_limits(&gpu->props.limits);
app_dump_sparse_props(&gpu->props.sparseProperties);
@@ -989,11 +1291,26 @@ static void app_gpu_dump_queue_props(const struct app_gpu *gpu, uint32_t id) {
const VkQueueFamilyProperties *props = &gpu->queue_props[id];
printf("VkQueueFamilyProperties[%d]:\n", id);
- printf("============================\n");
- printf("\tqueueFlags = %c%c%c\n",
- (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) ? 'G' : '.',
- (props->queueFlags & VK_QUEUE_COMPUTE_BIT) ? 'C' : '.',
- (props->queueFlags & VK_QUEUE_TRANSFER_BIT) ? 'D' : '.');
+ printf("===========================\n");
+ char *sep = ""; // separator character
+ printf("\tqueueFlags = ");
+ if (props->queueFlags & VK_QUEUE_GRAPHICS_BIT) {
+ printf("GRAPHICS");
+ sep = " | ";
+ }
+ if (props->queueFlags & VK_QUEUE_COMPUTE_BIT) {
+ printf("%sCOMPUTE", sep);
+ sep = " | ";
+ }
+ if (props->queueFlags & VK_QUEUE_TRANSFER_BIT) {
+ printf("%sTRANSFER", sep);
+ sep = " | ";
+ }
+ if (props->queueFlags & VK_QUEUE_SPARSE_BINDING_BIT) {
+ printf("%sSPARSE", sep);
+ }
+ printf("\n");
+
printf("\tqueueCount = %u\n", props->queueCount);
printf("\ttimestampValidBits = %u\n", props->timestampValidBits);
printf("\tminImageTransferGranularity = (%d, %d, %d)\n",
@@ -1011,14 +1328,36 @@ static void app_gpu_dump_memory_props(const struct app_gpu *gpu) {
printf("\tmemoryTypeCount = %u\n", props->memoryTypeCount);
for (uint32_t i = 0; i < props->memoryTypeCount; i++) {
printf("\tmemoryTypes[%u] : \n", i);
- printf("\t\tpropertyFlags = %u\n", props->memoryTypes[i].propertyFlags);
printf("\t\theapIndex = %u\n", props->memoryTypes[i].heapIndex);
+ printf("\t\tpropertyFlags = 0x%" PRIxLEAST32 ":\n",
+ props->memoryTypes[i].propertyFlags);
+
+ // Print each named flag, if it is set.
+ VkFlags flags = props->memoryTypes[i].propertyFlags;
+#define PRINT_FLAG(FLAG) \
+ if (flags & FLAG) \
+ printf("\t\t\t" #FLAG "\n");
+ PRINT_FLAG(VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT)
+ PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT)
+ PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_COHERENT_BIT)
+ PRINT_FLAG(VK_MEMORY_PROPERTY_HOST_CACHED_BIT)
+ PRINT_FLAG(VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT)
+#undef PRINT_FLAG
}
+ printf("\n");
printf("\tmemoryHeapCount = %u\n", props->memoryHeapCount);
for (uint32_t i = 0; i < props->memoryHeapCount; i++) {
printf("\tmemoryHeaps[%u] : \n", i);
- printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER "\n",
- (size_t)props->memoryHeaps[i].size);
+ const VkDeviceSize memSize = props->memoryHeaps[i].size;
+ printf("\t\tsize = " PRINTF_SIZE_T_SPECIFIER
+ " (0x%" PRIxLEAST64 ")\n",
+ (size_t)memSize, memSize);
+
+ VkMemoryHeapFlags heapFlags = props->memoryHeaps[i].flags;
+ printf("\t\tflags: \n\t\t\t");
+ printf((heapFlags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT)
+ ? "VK_MEMORY_HEAP_DEVICE_LOCAL_BIT\n"
+ : "None\n");
}
fflush(stdout);
}
@@ -1076,8 +1415,7 @@ static void ConsoleEnlarge() {
// make the console window bigger
CONSOLE_SCREEN_BUFFER_INFO csbi;
COORD bufferSize;
- if (GetConsoleScreenBufferInfo(consoleHandle, &csbi))
- {
+ if (GetConsoleScreenBufferInfo(consoleHandle, &csbi)) {
bufferSize.X = csbi.dwSize.X + 30;
bufferSize.Y = 20000;
SetConsoleScreenBufferSize(consoleHandle, bufferSize);
@@ -1107,9 +1445,10 @@ int main(int argc, char **argv) {
ConsoleEnlarge();
#endif
- major = VK_API_VERSION_1_0 >> 22;
- minor = (VK_API_VERSION_1_0 >> 12) & 0x3ff;
- patch = VK_HEADER_VERSION & 0xfff;
+ major = VK_VERSION_MAJOR(VK_API_VERSION_1_0);
+ minor = VK_VERSION_MINOR(VK_API_VERSION_1_0);
+ patch = VK_VERSION_PATCH(VK_HEADER_VERSION);
+
printf("===========\n");
printf("VULKAN INFO\n");
printf("===========\n\n");
@@ -1161,6 +1500,53 @@ int main(int argc, char **argv) {
printf("\n\n");
}
+ printf("Presentable Surface formats:\n");
+ printf("============================\n");
+ inst.width = 256;
+ inst.height = 256;
+ int formatCount = 0;
+
+//--WIN32--
+#ifdef VK_USE_PLATFORM_WIN32_KHR
+ app_create_win32_window(&inst);
+ for (i = 0; i < gpu_count; i++) {
+ app_create_win32_surface(&inst, &gpus[i]);
+ printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName);
+ printf("Surface type : %s\n", VK_KHR_WIN32_SURFACE_EXTENSION_NAME);
+ formatCount += app_dump_surface_formats(&inst, &gpus[i]);
+ app_destroy_surface(&inst);
+ }
+ app_destroy_win32_window(&inst);
+#endif
+//--XCB--
+#ifdef VK_USE_PLATFORM_XCB_KHR
+ app_create_xcb_window(&inst);
+ for (i = 0; i < gpu_count; i++) {
+ app_create_xcb_surface(&inst, &gpus[i]);
+ printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName);
+ printf("Surface type : %s\n", VK_KHR_XCB_SURFACE_EXTENSION_NAME);
+ formatCount += app_dump_surface_formats(&inst, &gpus[i]);
+ app_destroy_surface(&inst);
+ }
+ app_destroy_xcb_window(&inst);
+#endif
+//--XLIB--
+#ifdef VK_USE_PLATFORM_XLIB_KHR
+ app_create_xlib_window(&inst);
+ for (i = 0; i < gpu_count; i++) {
+ app_create_xlib_surface(&inst, &gpus[i]);
+ printf("GPU id : %u (%s)\n", i, gpus[i].props.deviceName);
+ printf("Surface type : %s\n", VK_KHR_XLIB_SURFACE_EXTENSION_NAME);
+ formatCount += app_dump_surface_formats(&inst, &gpus[i]);
+ app_destroy_surface(&inst);
+ }
+ app_destroy_xlib_window(&inst);
+#endif
+ // TODO: Android / Wayland / MIR
+ if (!formatCount)
+ printf("None found\n");
+ //---------
+
for (i = 0; i < gpu_count; i++)
app_gpu_destroy(&gpus[i]);
diff --git a/determine_vs_version.py b/determine_vs_version.py
index 9dec7223..9dec7223 100644..100755
--- a/determine_vs_version.py
+++ b/determine_vs_version.py
diff --git a/generator.py b/generator.py
index d9301dfa..0b97305e 100644..100755
--- a/generator.py
+++ b/generator.py
@@ -2629,15 +2629,13 @@ class ThreadOutputGenerator(OutputGenerator):
OutputGenerator.beginFile(self, genOpts)
# C-specific
#
- # Multiple inclusion protection & C++ wrappers.
+ # Multiple inclusion protection & C++ namespace.
if (genOpts.protectFile and self.genOpts.filename):
headerSym = '__' + re.sub('\.h', '_h_', os.path.basename(self.genOpts.filename))
write('#ifndef', headerSym, file=self.outFile)
write('#define', headerSym, '1', file=self.outFile)
self.newline()
- write('#ifdef __cplusplus', file=self.outFile)
- write('extern "C" {', file=self.outFile)
- write('#endif', file=self.outFile)
+ write('namespace threading {', file=self.outFile)
self.newline()
#
# User-supplied prefix text, if any (list of strings)
@@ -2646,7 +2644,7 @@ class ThreadOutputGenerator(OutputGenerator):
write(s, file=self.outFile)
def endFile(self):
# C-specific
- # Finish C++ wrapper and multiple inclusion protection
+ # Finish C++ namespace and multiple inclusion protection
self.newline()
# record intercepted procedures
write('// intercepts', file=self.outFile)
@@ -2654,9 +2652,7 @@ class ThreadOutputGenerator(OutputGenerator):
write('\n'.join(self.intercepts), file=self.outFile)
write('};\n', file=self.outFile)
self.newline()
- write('#ifdef __cplusplus', file=self.outFile)
- write('}', file=self.outFile)
- write('#endif', file=self.outFile)
+ write('} // namespace threading', file=self.outFile)
if (self.genOpts.protectFile and self.genOpts.filename):
self.newline()
write('#endif', file=self.outFile)
@@ -2743,6 +2739,14 @@ class ThreadOutputGenerator(OutputGenerator):
#
# Command generation
def genCmd(self, cmdinfo, name):
+ # Commands shadowed by interface functions and are not implemented
+ interface_functions = [
+ 'vkEnumerateInstanceLayerProperties',
+ 'vkEnumerateInstanceExtensionProperties',
+ 'vkEnumerateDeviceLayerProperties',
+ ]
+ if name in interface_functions:
+ return
special_functions = [
'vkGetDeviceProcAddr',
'vkGetInstanceProcAddr',
@@ -2750,15 +2754,17 @@ class ThreadOutputGenerator(OutputGenerator):
'vkDestroyDevice',
'vkCreateInstance',
'vkDestroyInstance',
- 'vkEnumerateInstanceLayerProperties',
- 'vkEnumerateInstanceExtensionProperties',
'vkAllocateCommandBuffers',
'vkFreeCommandBuffers',
'vkCreateDebugReportCallbackEXT',
'vkDestroyDebugReportCallbackEXT',
]
if name in special_functions:
- self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (name,name) ]
+ decls = self.makeCDecls(cmdinfo.elem)
+ self.appendSection('command', '')
+ self.appendSection('command', '// declare only')
+ self.appendSection('command', decls[0])
+ self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (name,name[2:]) ]
return
if "KHR" in name:
self.appendSection('command', '// TODO - not wrapping KHR function ' + name)
@@ -2774,7 +2780,7 @@ class ThreadOutputGenerator(OutputGenerator):
# record that the function will be intercepted
if (self.featureExtraProtect != None):
self.intercepts += [ '#ifdef %s' % self.featureExtraProtect ]
- self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (name,name) ]
+ self.intercepts += [ ' {"%s", reinterpret_cast<PFN_vkVoidFunction>(%s)},' % (name,name[2:]) ]
if (self.featureExtraProtect != None):
self.intercepts += [ '#endif' ]
@@ -2814,6 +2820,10 @@ class ThreadOutputGenerator(OutputGenerator):
if (resulttype != None):
self.appendSection('command', ' return result;')
self.appendSection('command', '}')
+ #
+ # override makeProtoName to drop the "vk" prefix
+ def makeProtoName(self, name, tail):
+ return self.genOpts.apientry + name[2:] + tail
# ParamCheckerOutputGenerator - subclass of OutputGenerator.
# Generates param checker layer code.
@@ -2863,7 +2873,7 @@ class ParamCheckerOutputGenerator(OutputGenerator):
self.structMembers = [] # List of StructMemberData records for all Vulkan structs
self.validatedStructs = dict() # Map of structs type names to generated validation code for that struct type
self.enumRanges = dict() # Map of enum name to BEGIN/END range values
- self.flags = dict() # Map of flags typenames to a Boolean value indicating that validation code is generated for a value of this type
+ self.flags = set() # Map of flags typenames
self.flagBits = dict() # Map of flag bits typename to list of values
# Named tuples to store struct and command data
self.StructType = namedtuple('StructType', ['name', 'value'])
@@ -2943,7 +2953,7 @@ class ParamCheckerOutputGenerator(OutputGenerator):
self.structMembers = []
self.validatedStructs = dict()
self.enumRanges = dict()
- self.flags = dict()
+ self.flags = set()
self.flagBits = dict()
def endFeature(self):
# C-specific
@@ -2961,8 +2971,8 @@ class ParamCheckerOutputGenerator(OutputGenerator):
self.processCmdData()
# Write the declarations for the VkFlags values combining all flag bits
for flag in sorted(self.flags):
- if self.flags[flag]:
- flagBits = flag.replace('Flags', 'FlagBits')
+ flagBits = flag.replace('Flags', 'FlagBits')
+ if flagBits in self.flagBits:
bits = self.flagBits[flagBits]
decl = 'const {} All{} = {}'.format(flag, flagBits, bits[0])
for bit in bits[1:]:
@@ -3001,7 +3011,7 @@ class ParamCheckerOutputGenerator(OutputGenerator):
elif (category == 'handle'):
self.handleTypes.add(name)
elif (category == 'bitmask'):
- self.flags[name] = False
+ self.flags.add(name)
#
# Struct parameter check generation.
# This is a special case of the <type> tag where the contents are
@@ -3212,7 +3222,7 @@ class ParamCheckerOutputGenerator(OutputGenerator):
value = self.structTypes[typename].value
else:
value = self.genVkStructureType(typename)
- #print('Generating {} for {} structure type that was not defined by the current feature'.format(value, typename))
+ self.logMsg('diag', 'ParameterValidation: Generating {} for {} structure type that was not defined by the current feature'.format(value, typename))
return value
#
# Retrieve the value of the len tag
@@ -3388,7 +3398,6 @@ class ParamCheckerOutputGenerator(OutputGenerator):
else:
allFlags = 'All' + flagBitsName
checkExpr.append('skipCall |= validate_flags_array(report_data, "{}", "{}", "{}", "{}", {}, {pf}{}, {pf}{}, {}, {});\n'.format(funcPrintName, lenPrintName, valuePrintName, flagBitsName, allFlags, lenValue.name, value.name, lenValueRequired, valueRequired, pf=prefix))
- self.flags[value.type] = True
return checkExpr
#
# Generate pNext check string
@@ -3530,56 +3539,73 @@ class ParamCheckerOutputGenerator(OutputGenerator):
if lenParam.isoptional:
cvReq = 'false'
#
- # If this is a pointer to a struct with an sType field, verify the type
- if value.type in self.structTypes:
- usedLines += self.makeStructTypeCheck(valuePrefix, value, lenParam, req, cvReq, cpReq, funcName, lenDisplayName, valueDisplayName)
- # If this is an input handle array that is not allowed to contain NULL handles, verify that none of the handles are VK_NULL_HANDLE
- elif value.type in self.handleTypes and value.isconst and not self.isHandleOptional(value, lenParam):
- usedLines += self.makeHandleCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName)
- elif value.type in self.flags and value.isconst:
- usedLines += self.makeFlagsArrayCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName)
- elif value.isbool and value.isconst:
- usedLines.append('skipCall |= validate_bool32_array(report_data, "{}", "{}", "{}", {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, lenParam.name, value.name, cvReq, req, pf=valuePrefix))
- elif value.israngedenum and value.isconst:
- enumRange = self.enumRanges[value.type]
- usedLines.append('skipCall |= validate_ranged_enum_array(report_data, "{}", "{}", "{}", "{}", {}, {}, {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, value.type, enumRange[0], enumRange[1], lenParam.name, value.name, cvReq, req, pf=valuePrefix))
- elif value.name == 'pNext':
- # We need to ignore VkDeviceCreateInfo and VkInstanceCreateInfo, as the loader manipulates them in a way that is not documented in vk.xml
- if not structTypeName in ['VkDeviceCreateInfo', 'VkInstanceCreateInfo']:
- usedLines += self.makeStructNextCheck(valuePrefix, value, funcName, valueDisplayName)
+ # The parameter will not be processes when tagged as 'noautovalidity'
+ # For the pointer to struct case, the struct pointer will not be validated, but any
+ # members not tagged as 'noatuvalidity' will be validated
+ if value.noautovalidity:
+ # Log a diagnostic message when validation cannot be automatically generated and must be implemented manually
+ self.logMsg('diag', 'ParameterValidation: No validation for {} {}'.format(structTypeName if structTypeName else funcName, value.name))
else:
- usedLines += self.makePointerCheck(valuePrefix, value, lenParam, req, cvReq, cpReq, funcName, lenDisplayName, valueDisplayName)
- #
- # If this is a pointer to a struct (input), see if it contains members that need to be checked
- if value.type in self.validatedStructs and value.isconst:
- usedLines.append(self.expandStructPointerCode(valuePrefix, value, lenParam, funcName, valueDisplayName))
+ #
+ # If this is a pointer to a struct with an sType field, verify the type
+ if value.type in self.structTypes:
+ usedLines += self.makeStructTypeCheck(valuePrefix, value, lenParam, req, cvReq, cpReq, funcName, lenDisplayName, valueDisplayName)
+ # If this is an input handle array that is not allowed to contain NULL handles, verify that none of the handles are VK_NULL_HANDLE
+ elif value.type in self.handleTypes and value.isconst and not self.isHandleOptional(value, lenParam):
+ usedLines += self.makeHandleCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName)
+ elif value.type in self.flags and value.isconst:
+ usedLines += self.makeFlagsArrayCheck(valuePrefix, value, lenParam, req, cvReq, funcName, lenDisplayName, valueDisplayName)
+ elif value.isbool and value.isconst:
+ usedLines.append('skipCall |= validate_bool32_array(report_data, "{}", "{}", "{}", {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, lenParam.name, value.name, cvReq, req, pf=valuePrefix))
+ elif value.israngedenum and value.isconst:
+ enumRange = self.enumRanges[value.type]
+ usedLines.append('skipCall |= validate_ranged_enum_array(report_data, "{}", "{}", "{}", "{}", {}, {}, {pf}{}, {pf}{}, {}, {});\n'.format(funcName, lenDisplayName, valueDisplayName, value.type, enumRange[0], enumRange[1], lenParam.name, value.name, cvReq, req, pf=valuePrefix))
+ elif value.name == 'pNext':
+ # We need to ignore VkDeviceCreateInfo and VkInstanceCreateInfo, as the loader manipulates them in a way that is not documented in vk.xml
+ if not structTypeName in ['VkDeviceCreateInfo', 'VkInstanceCreateInfo']:
+ usedLines += self.makeStructNextCheck(valuePrefix, value, funcName, valueDisplayName)
+ else:
+ usedLines += self.makePointerCheck(valuePrefix, value, lenParam, req, cvReq, cpReq, funcName, lenDisplayName, valueDisplayName)
+ #
+ # If this is a pointer to a struct (input), see if it contains members that need to be checked
+ if value.type in self.validatedStructs and value.isconst:
+ usedLines.append(self.expandStructPointerCode(valuePrefix, value, lenParam, funcName, valueDisplayName))
# Non-pointer types
- elif (value.type in self.structTypes) or (value.type in self.validatedStructs):
- if value.type in self.structTypes:
- stype = self.structTypes[value.type]
- usedLines.append('skipCall |= validate_struct_type(report_data, "{}", "{}", "{sv}", &({}{vn}), {sv}, false);\n'.format(
- funcName, valueDisplayName, valuePrefix, vn=value.name, sv=stype.value))
- if value.type in self.validatedStructs:
- memberNamePrefix = '{}{}.'.format(valuePrefix, value.name)
- memberDisplayNamePrefix = '{}.'.format(valueDisplayName)
- usedLines.append(self.expandStructCode(self.validatedStructs[value.type], funcName, memberNamePrefix, memberDisplayNamePrefix, '', []))
- elif value.type in self.handleTypes:
- if not self.isHandleOptional(value, None):
- usedLines.append('skipCall |= validate_required_handle(report_data, "{}", "{}", {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name))
- elif value.type in self.flags:
- flagBitsName = value.type.replace('Flags', 'FlagBits')
- if not flagBitsName in self.flagBits:
- usedLines.append('skipCall |= validate_reserved_flags(report_data, "{}", "{}", {pf}{});\n'.format(funcName, valueDisplayName, value.name, pf=valuePrefix))
+ else:
+ #
+ # The parameter will not be processes when tagged as 'noautovalidity'
+ # For the struct case, the struct type will not be validated, but any
+ # members not tagged as 'noatuvalidity' will be validated
+ if value.noautovalidity:
+ # Log a diagnostic message when validation cannot be automatically generated and must be implemented manually
+ self.logMsg('diag', 'ParameterValidation: No validation for {} {}'.format(structTypeName if structTypeName else funcName, value.name))
else:
- flagsRequired = 'false' if value.isoptional else 'true'
- allFlagsName = 'All' + flagBitsName
- usedLines.append('skipCall |= validate_flags(report_data, "{}", "{}", "{}", {}, {pf}{}, {});\n'.format(funcName, valueDisplayName, flagBitsName, allFlagsName, value.name, flagsRequired, pf=valuePrefix))
- self.flags[value.type] = True
- elif value.isbool:
- usedLines.append('skipCall |= validate_bool32(report_data, "{}", "{}", {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name))
- elif value.israngedenum:
- enumRange = self.enumRanges[value.type]
- usedLines.append('skipCall |= validate_ranged_enum(report_data, "{}", "{}", "{}", {}, {}, {}{});\n'.format(funcName, valueDisplayName, value.type, enumRange[0], enumRange[1], valuePrefix, value.name))
+ if value.type in self.structTypes:
+ stype = self.structTypes[value.type]
+ usedLines.append('skipCall |= validate_struct_type(report_data, "{}", "{}", "{sv}", &({}{vn}), {sv}, false);\n'.format(
+ funcName, valueDisplayName, valuePrefix, vn=value.name, sv=stype.value))
+ elif value.type in self.handleTypes:
+ if not self.isHandleOptional(value, None):
+ usedLines.append('skipCall |= validate_required_handle(report_data, "{}", "{}", {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name))
+ elif value.type in self.flags:
+ flagBitsName = value.type.replace('Flags', 'FlagBits')
+ if not flagBitsName in self.flagBits:
+ usedLines.append('skipCall |= validate_reserved_flags(report_data, "{}", "{}", {pf}{});\n'.format(funcName, valueDisplayName, value.name, pf=valuePrefix))
+ else:
+ flagsRequired = 'false' if value.isoptional else 'true'
+ allFlagsName = 'All' + flagBitsName
+ usedLines.append('skipCall |= validate_flags(report_data, "{}", "{}", "{}", {}, {pf}{}, {});\n'.format(funcName, valueDisplayName, flagBitsName, allFlagsName, value.name, flagsRequired, pf=valuePrefix))
+ elif value.isbool:
+ usedLines.append('skipCall |= validate_bool32(report_data, "{}", "{}", {}{});\n'.format(funcName, valueDisplayName, valuePrefix, value.name))
+ elif value.israngedenum:
+ enumRange = self.enumRanges[value.type]
+ usedLines.append('skipCall |= validate_ranged_enum(report_data, "{}", "{}", "{}", {}, {}, {}{});\n'.format(funcName, valueDisplayName, value.type, enumRange[0], enumRange[1], valuePrefix, value.name))
+ #
+ # If this is a struct, see if it contains members that need to be checked
+ if value.type in self.validatedStructs:
+ memberNamePrefix = '{}{}.'.format(valuePrefix, value.name)
+ memberDisplayNamePrefix = '{}.'.format(valueDisplayName)
+ usedLines.append(self.expandStructCode(self.validatedStructs[value.type], funcName, memberNamePrefix, memberDisplayNamePrefix, '', []))
#
# Append the parameter check to the function body for the current command
if usedLines:
diff --git a/genvk.py b/genvk.py
index 7ea70c28..993477cd 100755
--- a/genvk.py
+++ b/genvk.py
@@ -280,7 +280,7 @@ buildList = [
protectFeature = False,
protectProto = True,
protectProtoStr = 'VK_PROTOTYPES',
- apicall = '',
+ apicall = 'VKAPI_ATTR ',
apientry = 'VKAPI_CALL ',
apientryp = 'VKAPI_PTR *',
alignFuncParam = 48,
diff --git a/glslang_revision b/glslang_revision
index 56c5bed5..ac7412cb 100644
--- a/glslang_revision
+++ b/glslang_revision
@@ -1 +1 @@
-d99524197f3b68dbd6267bd3f4d7e8a0f49167b4
+4678ca9dacfec7a084dbc69bbe568bdad6889f1b
diff --git a/include/vulkan/vk_icd.h b/include/vulkan/vk_icd.h
index fa110f4f..a6493641 100644
--- a/include/vulkan/vk_icd.h
+++ b/include/vulkan/vk_icd.h
@@ -39,7 +39,7 @@ typedef VkResult (VKAPI_PTR *PFN_vkNegotiateLoaderICDInterfaceVersion)(uint32_t
#define ICD_LOADER_MAGIC 0x01CDC0DE
-typedef union _VK_LOADER_DATA {
+typedef union {
uintptr_t loaderMagic;
void *loaderData;
} VK_LOADER_DATA;
@@ -58,7 +58,7 @@ static inline bool valid_loader_magic_value(void *pNewObject) {
* Windows and Linux ICDs will treat VkSurfaceKHR as a pointer to a struct that
* contains the platform-specific connection and surface information.
*/
-typedef enum _VkIcdWsiPlatform {
+typedef enum {
VK_ICD_WSI_PLATFORM_MIR,
VK_ICD_WSI_PLATFORM_WAYLAND,
VK_ICD_WSI_PLATFORM_WIN32,
@@ -67,12 +67,12 @@ typedef enum _VkIcdWsiPlatform {
VK_ICD_WSI_PLATFORM_DISPLAY
} VkIcdWsiPlatform;
-typedef struct _VkIcdSurfaceBase {
+typedef struct {
VkIcdWsiPlatform platform;
} VkIcdSurfaceBase;
#ifdef VK_USE_PLATFORM_MIR_KHR
-typedef struct _VkIcdSurfaceMir {
+typedef struct {
VkIcdSurfaceBase base;
MirConnection *connection;
MirSurface *mirSurface;
@@ -80,7 +80,7 @@ typedef struct _VkIcdSurfaceMir {
#endif // VK_USE_PLATFORM_MIR_KHR
#ifdef VK_USE_PLATFORM_WAYLAND_KHR
-typedef struct _VkIcdSurfaceWayland {
+typedef struct {
VkIcdSurfaceBase base;
struct wl_display *display;
struct wl_surface *surface;
@@ -88,7 +88,7 @@ typedef struct _VkIcdSurfaceWayland {
#endif // VK_USE_PLATFORM_WAYLAND_KHR
#ifdef VK_USE_PLATFORM_WIN32_KHR
-typedef struct _VkIcdSurfaceWin32 {
+typedef struct {
VkIcdSurfaceBase base;
HINSTANCE hinstance;
HWND hwnd;
@@ -96,7 +96,7 @@ typedef struct _VkIcdSurfaceWin32 {
#endif // VK_USE_PLATFORM_WIN32_KHR
#ifdef VK_USE_PLATFORM_XCB_KHR
-typedef struct _VkIcdSurfaceXcb {
+typedef struct {
VkIcdSurfaceBase base;
xcb_connection_t *connection;
xcb_window_t window;
@@ -104,14 +104,14 @@ typedef struct _VkIcdSurfaceXcb {
#endif // VK_USE_PLATFORM_XCB_KHR
#ifdef VK_USE_PLATFORM_XLIB_KHR
-typedef struct _VkIcdSurfaceXlib {
+typedef struct {
VkIcdSurfaceBase base;
Display *dpy;
Window window;
} VkIcdSurfaceXlib;
#endif // VK_USE_PLATFORM_XLIB_KHR
-typedef struct _VkIcdSurfaceDisplay {
+typedef struct {
VkIcdSurfaceBase base;
VkDisplayModeKHR displayMode;
uint32_t planeIndex;
diff --git a/include/vulkan/vk_layer.h b/include/vulkan/vk_layer.h
index cf16b2b7..8b7d82fb 100644
--- a/include/vulkan/vk_layer.h
+++ b/include/vulkan/vk_layer.h
@@ -234,23 +234,6 @@ typedef struct VkLayerInstanceDispatchTable_ {
CreateDisplayPlaneSurfaceKHR;
} VkLayerInstanceDispatchTable;
-// LL node for tree of dbg callback functions
-typedef struct VkLayerDbgFunctionNode_ {
- VkDebugReportCallbackEXT msgCallback;
- PFN_vkDebugReportCallbackEXT pfnMsgCallback;
- VkFlags msgFlags;
- void *pUserData;
- struct VkLayerDbgFunctionNode_ *pNext;
-} VkLayerDbgFunctionNode;
-
-typedef enum VkLayerDbgAction_ {
- VK_DBG_LAYER_ACTION_IGNORE = 0x0,
- VK_DBG_LAYER_ACTION_CALLBACK = 0x1,
- VK_DBG_LAYER_ACTION_LOG_MSG = 0x2,
- VK_DBG_LAYER_ACTION_BREAK = 0x4,
- VK_DBG_LAYER_ACTION_DEBUG_OUTPUT = 0x8,
-} VkLayerDbgAction;
-
// ------------------------------------------------------------------------------------------------
// CreateInstance and CreateDevice support structures
diff --git a/include/vulkan/vulkan.h b/include/vulkan/vulkan.h
index 741da4ce..75afd4a7 100644
--- a/include/vulkan/vulkan.h
+++ b/include/vulkan/vulkan.h
@@ -43,7 +43,7 @@ extern "C" {
#define VK_VERSION_MINOR(version) (((uint32_t)(version) >> 12) & 0x3ff)
#define VK_VERSION_PATCH(version) ((uint32_t)(version) & 0xfff)
// Version of this file
-#define VK_HEADER_VERSION 12
+#define VK_HEADER_VERSION 16
#define VK_NULL_HANDLE 0
@@ -3172,13 +3172,14 @@ VK_DEFINE_NON_DISPATCHABLE_HANDLE(VkSurfaceKHR)
#define VK_KHR_SURFACE_SPEC_VERSION 25
#define VK_KHR_SURFACE_EXTENSION_NAME "VK_KHR_surface"
+#define VK_COLORSPACE_SRGB_NONLINEAR_KHR VK_COLOR_SPACE_SRGB_NONLINEAR_KHR
typedef enum VkColorSpaceKHR {
- VK_COLORSPACE_SRGB_NONLINEAR_KHR = 0,
- VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
- VK_COLOR_SPACE_END_RANGE_KHR = VK_COLORSPACE_SRGB_NONLINEAR_KHR,
- VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLORSPACE_SRGB_NONLINEAR_KHR - VK_COLORSPACE_SRGB_NONLINEAR_KHR + 1),
+ VK_COLOR_SPACE_SRGB_NONLINEAR_KHR = 0,
+ VK_COLOR_SPACE_BEGIN_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ VK_COLOR_SPACE_END_RANGE_KHR = VK_COLOR_SPACE_SRGB_NONLINEAR_KHR,
+ VK_COLOR_SPACE_RANGE_SIZE_KHR = (VK_COLOR_SPACE_SRGB_NONLINEAR_KHR - VK_COLOR_SPACE_SRGB_NONLINEAR_KHR + 1),
VK_COLOR_SPACE_MAX_ENUM_KHR = 0x7FFFFFFF
} VkColorSpaceKHR;
@@ -3854,6 +3855,16 @@ typedef struct VkPipelineRasterizationStateRasterizationOrderAMD {
+#define VK_AMD_shader_trinary_minmax 1
+#define VK_AMD_SHADER_TRINARY_MINMAX_SPEC_VERSION 1
+#define VK_AMD_SHADER_TRINARY_MINMAX_EXTENSION_NAME "VK_AMD_shader_trinary_minmax"
+
+
+#define VK_AMD_shader_explicit_vertex_parameter 1
+#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_SPEC_VERSION 1
+#define VK_AMD_SHADER_EXPLICIT_VERTEX_PARAMETER_EXTENSION_NAME "VK_AMD_shader_explicit_vertex_parameter"
+
+
#define VK_EXT_debug_marker 1
#define VK_EXT_DEBUG_MARKER_SPEC_VERSION 3
#define VK_EXT_DEBUG_MARKER_EXTENSION_NAME "VK_EXT_debug_marker"
@@ -3911,6 +3922,11 @@ VKAPI_ATTR void VKAPI_CALL vkCmdDebugMarkerInsertEXT(
VkDebugMarkerMarkerInfoEXT* pMarkerInfo);
#endif
+#define VK_AMD_gcn_shader 1
+#define VK_AMD_GCN_SHADER_SPEC_VERSION 1
+#define VK_AMD_GCN_SHADER_EXTENSION_NAME "VK_AMD_gcn_shader"
+
+
#ifdef __cplusplus
}
#endif
diff --git a/layers/CMakeLists.txt b/layers/CMakeLists.txt
index 9847cfbd..099b711f 100644
--- a/layers/CMakeLists.txt
+++ b/layers/CMakeLists.txt
@@ -31,9 +31,6 @@ set(LAYER_JSON_FILES
VkLayer_device_limits
)
-set(VK_LAYER_RPATH /usr/lib/x86_64-linux-gnu/vulkan/layer:/usr/lib/i386-linux-gnu/vulkan/layer)
-set(CMAKE_INSTALL_RPATH ${VK_LAYER_RPATH})
-
if (WIN32)
if (NOT (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_CURRENT_BINARY_DIR))
if (CMAKE_GENERATOR MATCHES "^Visual Studio.*")
@@ -145,11 +142,10 @@ run_vk_layer_xml_generate(Threading thread_check.h)
run_vk_layer_generate(unique_objects unique_objects.cpp)
run_vk_layer_xml_generate(ParamChecker parameter_validation.h)
+
# Layer Utils Library
-# For Windows, we use a static lib because the Windows loader has a fairly restrictive loader search
-# path that can't be easily modified to point it to the same directory that contains the layers.
if (WIN32)
- add_library(VkLayer_utils STATIC vk_layer_config.cpp vk_layer_extension_utils.cpp vk_layer_utils.cpp)
+ add_library(VkLayer_utils SHARED vk_layer_config.cpp vk_layer_extension_utils.cpp vk_layer_utils.cpp VkLayer_utils.def)
else()
add_library(VkLayer_utils SHARED vk_layer_config.cpp vk_layer_extension_utils.cpp vk_layer_utils.cpp)
install(TARGETS VkLayer_utils DESTINATION ${PROJECT_BINARY_DIR}/install_staging)
@@ -169,3 +165,24 @@ add_vk_layer(parameter_validation parameter_validation.cpp parameter_validation.
target_include_directories(VkLayer_core_validation PRIVATE ${GLSLANG_SPIRV_INCLUDE_DIR})
target_include_directories(VkLayer_core_validation PRIVATE ${SPIRV_TOOLS_INCLUDE_DIR})
target_link_libraries(VkLayer_core_validation ${SPIRV_TOOLS_LIBRARIES})
+
+if (WIN32)
+ if (CMAKE_GENERATOR MATCHES "^Visual Studio.*")
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/$<CONFIGURATION>/VkLayer_utils.dll COPY_SRC_PATH)
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../demos/$<CONFIGURATION>/ COPY_DST_PATH)
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/$<CONFIGURATION>/ COPY_DST_TEST_PATH)
+ else()
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/VkLayer_utils.dll COPY_SRC_PATH)
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../demos/ COPY_DST_PATH)
+ file(TO_NATIVE_PATH ${CMAKE_CURRENT_BINARY_DIR}/../tests/ COPY_DST_TEST_PATH)
+ endif()
+ # Copy layer utils library to correct locations
+ add_custom_command(TARGET VkLayer_utils
+ POST_BUILD
+ COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_PATH}
+ COMMENT "Copying VkLayer_utils.dll to demos dir")
+ add_custom_command(TARGET VkLayer_utils
+ POST_BUILD
+ COMMAND xcopy /Y /I ${COPY_SRC_PATH} ${COPY_DST_TEST_PATH}
+ COMMENT "Copying VkLayer_utils.dll to demos dir")
+endif()
diff --git a/layers/README.md b/layers/README.md
index c9182c98..f2e93e36 100644
--- a/layers/README.md
+++ b/layers/README.md
@@ -13,80 +13,80 @@ Layer libraries can be written to intercept or hook VK entry points for various
debug and validation purposes. One or more VK entry points can be defined in your Layer
library. Undefined entrypoints in the Layer library will be passed to the next Layer which
may be the driver. Multiple layer libraries can be chained (actually a hierarchy) together.
-vkEnumerateInstanceLayerProperties and vkEnumerateDeviceLayerProperties can be called to list the
-available layers and their properties. Layers can intercept Vulkan instance level entry points
-in which case they are called an Instance Layer. Layers can intercept device entry points
-in which case they are called a Device Layer. Instance level entry points are those with VkInstance
-or VkPhysicalDevice as first parameter. Device level entry points are those with VkDevice, VkCommandBuffer,
-or VkQueue as the first parameter. Layers that want to intercept both instance and device
-level entrypoints are called Global Layers. vkXXXXGetProcAddr is used internally by the Layers and
-Loader to initialize dispatch tables. Device Layers are activated at vkCreateDevice time. Instance
-Layers are activated at vkCreateInstance time. Layers can also be activated via environment variables
-(VK_INSTANCE_LAYERS or VK_DEVICE_LAYERS).
-
-All validation layers work with the DEBUG_REPORT extension to provide the application or user with
-validation feedback. When a validation layer is enabled, it will look at the vk_layer_settings.txt
-file to determine its behavior. Such as outputing to a file, stdout or debug output (Windows). An
-application can also register callback functions via the DEBUG_REPORT extension to receive callbacks
-when the requested validation events happen. Application callbacks happen regardless of the
-settings in vk_layer_settings.txt
+vkEnumerateInstanceLayerProperties can be called to list the
+available layers and their properties. Layers can intercept all Vulkan commands
+that take a dispatchable object as it's first argument. I.e. VkInstance, VkPhysicalDevice,
+VkDevice, VkCommandBuffer, and VkQueue.
+vkXXXXGetProcAddr is used internally by the Layers and Loader to initialize dispatch tables.
+Layers can also be activated via the VK_INSTANCE_LAYERS environment variable.
+
+All validation layers work with the DEBUG_REPORT extension to provide validation feedback.
+When a validation layer is enabled, it will look for a vk_layer_settings.txt file to define
+its loggin behavior, which can include sending output to a file, stdout, or debug output (Windows).
+Applications can also register debug callback functions via the DEBUG_REPORT extension to receive
+callbacks when validation events occur. Application callbacks are independent of settings in a
+vk_layer_settings.txt file which will be carried out separately. If no vk_layer_settings.txt
+file is present and no application callbacks are registered, error messages will be output
+through default logging callbacks.
### Layer library example code
-Note that some layers are code-generated and will therefore exist in the directory (build_dir)/layers
+Note that some layers are code-generated and will therefore exist in the directory `(build_dir)/layers`
--include/vkLayer.h - header file for layer code.
+`include/vkLayer.h` - header file for layer code.
### Layer Details
-For complete details of current validation layers, including all of the validation checks that they perform, please refer to the document layers/vk_validation_layer_details.md. Below is a brief overview of each layer.
+For complete details of current validation layers, including all of the validation checks that they perform, please refer to the document `layers/vk_validation_layer_details.md`. Below is a brief overview of each layer.
### Standard Validation
-This is a meta-layer managed by the loader. (name = VK_LAYER_LUNARG_standard_validation) - specifying this layer name will cause the loader to load the all of the standard validation layers (listed below) in the following optimal order: VK_LAYER_GOOGLE_threading, VK_LAYER_LUNARG_parameter_validation, VK_LAYER_LUNARG_device_limits, VK_LAYER_LUNARG_object_tracker, VK_LAYER_LUNARG_image, VK_LAYER_LUNARG_core_validation, VK_LAYER_LUNARG_swapchain, and VK_LAYER_GOOGLE_unique_objects. Other layers can be specified and the loader will remove duplicates.
+This is a meta-layer managed by the loader. (name = `VK_LAYER_LUNARG_standard_validation`) - specifying this layer name will cause the loader to load the all of the standard validation layers (listed below) in the following optimal order: `VK_LAYER_GOOGLE_threading`, `VK_LAYER_LUNARG_parameter_validation`, `VK_LAYER_LUNARG_device_limits`, `VK_LAYER_LUNARG_object_tracker`, `VK_LAYER_LUNARG_image`, `VK_LAYER_LUNARG_core_validation`,` VK_LAYER_LUNARG_swapchain`, and `VK_LAYER_GOOGLE_unique_objects`. Other layers can be specified and the loader will remove duplicates.
### Object Validation and Statistics
-(build dir)/layers/object_tracker.cpp (name=VK_LAYER_LUNARG_object_tracker) - Track object creation, use, and destruction. As objects are created they are stored in a map. As objects are used the layer verifies they exist in the map, flagging errors for unknown objects. As objects are destroyed they are removed from the map. At vkDestroyDevice() and vkDestroyInstance() times, if any objects have not been destroyed they are reported as leaked objects. If a Dbg callback function is registered this layer will use callback function(s) for reporting, otherwise it will use stdout.
+(build dir)/layers/object_tracker.cpp (name=`VK_LAYER_LUNARG_object_tracker`) - Track object creation, use, and destruction. As objects are created they are stored in a map. As objects are used the layer verifies they exist in the map, flagging errors for unknown objects. As objects are destroyed they are removed from the map. At `vkDestroyDevice()` and `vkDestroyInstance()` times, if any objects have not been destroyed they are reported as leaked objects. If a Dbg callback function is registered this layer will use callback function(s) for reporting, otherwise it will use stdout.
### Validate API State and Shaders
-layers/core\_validation.cpp (name=VK\_LAYER\_LUNARG\_core\_validation) - The core\_validation layer does the bulk of the API validation that requires storing state. Some of the state it tracks includes the Descriptor Set, Pipeline State, Shaders, and dynamic state, and memory objects and bindings. It performs some point validation as states are created and used, and further validation Draw call and QueueSubmit time. Of primary interest is making sure that the resources bound to Descriptor Sets correctly align with the layout specified for the Set. Also, all of the image and buffer layouts are validated to make sure explicit layout transitions are properly managed. Related to memory, core\_validation includes tracking object bindings, memory hazards, and memory object lifetimes. It also validates several other hazard-related issues related to command buffers, fences, and memory mapping. Additionally core\_validation include shader validation (formerly separate shader\_checker layer) that inspects the SPIR-V shader images and fixed function pipeline stages at PSO creation time. It flags errors when inconsistencies are found across interfaces between shader stages. The exact behavior of the checks depends on the pair of pipeline stages involved. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
+layers/core\_validation.cpp (name=`VK_LAYER_LUNARG_core_validation`) - The core\_validation layer does the bulk of the API validation that requires storing state. Some of the state it tracks includes the Descriptor Set, Pipeline State, Shaders, and dynamic state, and memory objects and bindings. It performs some point validation as states are created and used, and further validation Draw call and QueueSubmit time. Of primary interest is making sure that the resources bound to Descriptor Sets correctly align with the layout specified for the Set. Also, all of the image and buffer layouts are validated to make sure explicit layout transitions are properly managed. Related to memory, core\_validation includes tracking object bindings, memory hazards, and memory object lifetimes. It also validates several other hazard-related issues related to command buffers, fences, and memory mapping. Additionally core\_validation include shader validation (formerly separate shader\_checker layer) that inspects the SPIR-V shader images and fixed function pipeline stages at PSO creation time. It flags errors when inconsistencies are found across interfaces between shader stages. The exact behavior of the checks depends on the pair of pipeline stages involved. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
### Check parameters
-layers/parameter_validation.cpp (name=VK_LAYER_LUNARG_parameter_validation) - Check the input parameters to API calls for validity. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
+layers/parameter_validation.cpp (name=`VK_LAYER_LUNARG_parameter_validation`) - Check the input parameters to API calls for validity. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
### Image Validity
-layers/image.cpp (name=VK_LAYER_LUNARG_image) - The image layer is intended to validate image parameters, formats, and correct use. Images are a significant enough area that they were given a separate layer. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
+layers/image.cpp (name=`VK_LAYER_LUNARG_image`) - The image layer is intended to validate image parameters, formats, and correct use. Images are a significant enough area that they were given a separate layer. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
### Check threading
-layers/threading.cpp (name=VK_LAYER_GOOGLE_threading) - Check multithreading of API calls for validity. Currently this checks that only one thread at a time uses an object in free-threaded API calls. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
+layers/threading.cpp (name=`VK_LAYER_GOOGLE_threading`) - Check multithreading of API calls for validity. Currently this checks that only one thread at a time uses an object in free-threaded API calls. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
### Swapchain
-layers/swapchain.cpp (name=VK_LAYER_LUNARG_swapchain) - Check that WSI extensions are being used correctly.
+layers/swapchain.cpp (name=`VK_LAYER_LUNARG_swapchain`) - Check that WSI extensions are being used correctly.
### Device Limitations
-layers/device_limits.cpp (name=VK_LAYER_LUNARG_device_limits) - This layer is intended to capture underlying device features and limitations and then flag errors if an app makes requests for unsupported features or exceeding limitations. This layer is a work in progress and currently only flags some high-level errors without flagging errors on specific feature and limitation. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
+layers/device_limits.cpp (name=`VK_LAYER_LUNARG_device_limits`) - This layer is intended to capture underlying device features and limitations and then flag errors if an app makes requests for unsupported features or exceeding limitations. This layer is a work in progress and currently only flags some high-level errors without flagging errors on specific feature and limitation. If a Dbg callback function is registered, this layer will use callback function(s) for reporting, otherwise uses stdout.
### Unique Objects
-(build dir)/layers/unique_objects.cpp (name=VK_LAYER_GOOGLE_unique_objects) - The Vulkan specification allows objects that have non-unique handles. This makes tracking object lifetimes difficult in that it is unclear which object is being referenced on deletion. The unique_objects layer was created to address this problem. If loaded in the correct position (last, which is closest to the display driver) it will wrap all objects with a unique object representation, allowing proper object lifetime tracking. This layer does no validation on its own, and may not be required for the proper operation of all layers or all platforms. One sign that it is needed is the appearance of errors emitted from the object_tracker layer indicating the use of previously destroyed objects.
+(build dir)/layers/unique_objects.cpp (name=`VK_LAYER_GOOGLE_unique_objects`) - The Vulkan specification allows objects that have non-unique handles. This makes tracking object lifetimes difficult in that it is unclear which object is being referenced on deletion. The unique_objects layer was created to address this problem. If loaded in the correct position (last, which is closest to the display driver) it will alias all objects with a unique object representation, allowing proper object lifetime tracking. This layer does no validation on its own and may not be required for the proper operation of all layers or all platforms. One sign that it is needed is the appearance of errors emitted from the object_tracker layer indicating the use of previously destroyed objects.
## Using Layers
1. Build VK loader using normal steps (cmake and make)
-2. Place libVkLayer_<name>.so in the same directory as your VK test or app:
+2. Place `libVkLayer_<name>.so` or `VkLayer_<name>.dll` in the same directory as your VK test or app:
- cp build/layer/libVkLayer_threading.so build/tests
+ `cp build/layers/libVkLayer_threading.so build/tests` -or-
+ `copy build\layers/VkLayer_threading.dll build\tests`
This is required for the Loader to be able to scan and enumerate your library.
- Alternatively, use the VK\_LAYER\_PATH environment variable to specify where the layer libraries reside.
+ Alternatively, use the `VK_LAYER_PATH` environment variable to specify where the layer libraries reside.
+
+ [Windows Only] The VkLayer_utils.dll will also need to be copied into your app directory or to your
+ system library directory (typically \Windows\System32).
3. Create a vk_layer_settings.txt file in the same directory to specify how your layers should behave.
Model it after the following example: [*vk_layer_settings.txt*](vk_layer_settings.txt)
-4. Specify which Layers to activate by using
-vkCreateDevice and/or vkCreateInstance or environment variables.
+4. Specify which layers to activate using environment variables.
- export VK\_INSTANCE\_LAYERS=VK\_LAYER\_LUNARG\_parameter\_validation:VK\_LAYER\_LUNARG\_core\_validation
- export VK\_DEVICE\_LAYERS=VK\_LAYER\_LUNARG\_parameter\_validation:VK\_LAYER\_LUNARG\_core\_validation
- cd build/tests; ./vkinfo
+ `export VK\_INSTANCE\_LAYERS=VK\_LAYER\_LUNARG\_parameter\_validation:VK\_LAYER\_LUNARG\_core\_validation`
+ `cd build/tests; ./vkinfo`
## Status
diff --git a/layers/VkLayer_utils.def b/layers/VkLayer_utils.def
new file mode 100644
index 00000000..629c7d04
--- /dev/null
+++ b/layers/VkLayer_utils.def
@@ -0,0 +1,47 @@
+;;;; Begin Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+; Vulkan
+;
+; Copyright (c) 2015-2016 The Khronos Group Inc.
+; Copyright (c) 2015-2016 Valve Corporation
+; Copyright (c) 2015-2016 LunarG, Inc.
+;
+; Licensed under the Apache License, Version 2.0 (the "License");
+; you may not use this file except in compliance with the License.
+; You may obtain a copy of the License at
+;
+; http://www.apache.org/licenses/LICENSE-2.0
+;
+; Unless required by applicable law or agreed to in writing, software
+; distributed under the License is distributed on an "AS IS" BASIS,
+; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+; See the License for the specific language governing permissions and
+; limitations under the License.
+;
+; Author: Mark Lobodzinski <mark@LunarG.com>
+;;;; End Copyright Notice ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+; The following is required on Windows for exporting symbols from the DLL
+
+LIBRARY VkLayer_utils
+EXPORTS
+vk_format_is_depth_or_stencil
+vk_format_is_depth_and_stencil
+vk_format_is_stencil_only
+vk_format_is_depth_only
+vk_format_is_norm
+vk_format_is_int
+vk_format_is_uint
+vk_format_is_sint
+vk_format_is_float
+vk_format_is_srgb
+vk_format_is_compressed
+vk_format_get_compatibility_class
+vk_format_get_size
+vk_format_get_channel_count
+vk_safe_modulo
+vk_string_validate
+layer_debug_actions
+util_GetExtensionProperties
+util_GetLayerProperties
+LogMessageInitialized
+SetLogMessageInitialized
diff --git a/layers/core_validation.cpp b/layers/core_validation.cpp
index 51aaf88d..b3635a0b 100644
--- a/layers/core_validation.cpp
+++ b/layers/core_validation.cpp
@@ -65,11 +65,25 @@
#include <android/log.h>
#define LOGCONSOLE(...) ((void)__android_log_print(ANDROID_LOG_INFO, "DS", __VA_ARGS__))
#else
-#define LOGCONSOLE(...) printf(__VA_ARGS__)
+#define LOGCONSOLE(...) \
+ { \
+ printf(__VA_ARGS__); \
+ printf("\n"); \
+ }
#endif
using namespace std;
+// TODO : CB really needs it's own class and files so this is just temp code until that happens
+GLOBAL_CB_NODE::~GLOBAL_CB_NODE() {
+ for (uint32_t i=0; i<VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
+ // Make sure that no sets hold onto deleted CB binding
+ for (auto set : lastBound[i].uniqueBoundSets) {
+ set->RemoveBoundCommandBuffer(this);
+ }
+ }
+}
+
namespace core_validation {
using std::unordered_map;
@@ -88,7 +102,7 @@ struct CMD_POOL_INFO {
struct devExts {
bool wsi_enabled;
- unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> swapchainMap;
+ unordered_map<VkSwapchainKHR, unique_ptr<SWAPCHAIN_NODE>> swapchainMap;
unordered_map<VkImage, VkSwapchainKHR> imageToSwapchainMap;
};
@@ -110,17 +124,17 @@ struct layer_data {
unordered_set<VkCommandBuffer> globalInFlightCmdBuffers;
// Layer specific data
unordered_map<VkSampler, unique_ptr<SAMPLER_NODE>> samplerMap;
- unordered_map<VkImageView, VkImageViewCreateInfo> imageViewMap;
- unordered_map<VkImage, IMAGE_NODE> imageMap;
- unordered_map<VkBufferView, VkBufferViewCreateInfo> bufferViewMap;
- unordered_map<VkBuffer, BUFFER_NODE> bufferMap;
+ unordered_map<VkImageView, unique_ptr<VkImageViewCreateInfo>> imageViewMap;
+ unordered_map<VkImage, unique_ptr<IMAGE_NODE>> imageMap;
+ unordered_map<VkBufferView, unique_ptr<VkBufferViewCreateInfo>> bufferViewMap;
+ unordered_map<VkBuffer, unique_ptr<BUFFER_NODE>> bufferMap;
unordered_map<VkPipeline, PIPELINE_NODE *> pipelineMap;
unordered_map<VkCommandPool, CMD_POOL_INFO> commandPoolMap;
unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> descriptorPoolMap;
unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> setMap;
unordered_map<VkDescriptorSetLayout, cvdescriptorset::DescriptorSetLayout *> descriptorSetLayoutMap;
unordered_map<VkPipelineLayout, PIPELINE_LAYOUT_NODE> pipelineLayoutMap;
- unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> memObjMap;
+ unordered_map<VkDeviceMemory, unique_ptr<DEVICE_MEM_INFO>> memObjMap;
unordered_map<VkFence, FENCE_NODE> fenceMap;
unordered_map<VkQueue, QUEUE_NODE> queueMap;
unordered_map<VkEvent, EVENT_NODE> eventMap;
@@ -247,18 +261,91 @@ struct shader_module {
// TODO : This can be much smarter, using separate locks for separate global data
static std::mutex global_lock;
+// Return ImageViewCreateInfo ptr for specified imageView or else NULL
+VkImageViewCreateInfo *getImageViewData(const layer_data *dev_data, VkImageView image_view) {
+ auto iv_it = dev_data->imageViewMap.find(image_view);
+ if (iv_it == dev_data->imageViewMap.end()) {
+ return nullptr;
+ }
+ return iv_it->second.get();
+}
+// Return sampler node ptr for specified sampler or else NULL
+SAMPLER_NODE *getSamplerNode(const layer_data *dev_data, VkSampler sampler) {
+ auto sampler_it = dev_data->samplerMap.find(sampler);
+ if (sampler_it == dev_data->samplerMap.end()) {
+ return nullptr;
+ }
+ return sampler_it->second.get();
+}
+// Return image node ptr for specified image or else NULL
+IMAGE_NODE *getImageNode(const layer_data *dev_data, VkImage image) {
+ auto img_it = dev_data->imageMap.find(image);
+ if (img_it == dev_data->imageMap.end()) {
+ return nullptr;
+ }
+ return img_it->second.get();
+}
+// Return buffer node ptr for specified buffer or else NULL
+BUFFER_NODE *getBufferNode(const layer_data *dev_data, VkBuffer buffer) {
+ auto buff_it = dev_data->bufferMap.find(buffer);
+ if (buff_it == dev_data->bufferMap.end()) {
+ return nullptr;
+ }
+ return buff_it->second.get();
+}
+// Return swapchain node for specified swapchain or else NULL
+SWAPCHAIN_NODE *getSwapchainNode(const layer_data *dev_data, VkSwapchainKHR swapchain) {
+ auto swp_it = dev_data->device_extensions.swapchainMap.find(swapchain);
+ if (swp_it == dev_data->device_extensions.swapchainMap.end()) {
+ return nullptr;
+ }
+ return swp_it->second.get();
+}
+// Return swapchain for specified image or else NULL
+VkSwapchainKHR getSwapchainFromImage(const layer_data *dev_data, VkImage image) {
+ auto img_it = dev_data->device_extensions.imageToSwapchainMap.find(image);
+ if (img_it == dev_data->device_extensions.imageToSwapchainMap.end()) {
+ return VK_NULL_HANDLE;
+ }
+ return img_it->second;
+}
+// Return buffer node ptr for specified buffer or else NULL
+VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *my_data, VkBufferView buffer_view) {
+ auto bv_it = my_data->bufferViewMap.find(buffer_view);
+ if (bv_it == my_data->bufferViewMap.end()) {
+ return nullptr;
+ }
+ return bv_it->second.get();
+}
+
+FENCE_NODE *getFenceNode(layer_data *dev_data, VkFence fence) {
+ auto it = dev_data->fenceMap.find(fence);
+ if (it == dev_data->fenceMap.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
+QUEUE_NODE *getQueueNode(layer_data *dev_data, VkQueue queue) {
+ auto it = dev_data->queueMap.find(queue);
+ if (it == dev_data->queueMap.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
static VkDeviceMemory *get_object_mem_binding(layer_data *my_data, uint64_t handle, VkDebugReportObjectTypeEXT type) {
switch (type) {
case VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT: {
- auto it = my_data->imageMap.find(VkImage(handle));
- if (it != my_data->imageMap.end())
- return &(*it).second.mem;
+ auto img_node = getImageNode(my_data, VkImage(handle));
+ if (img_node)
+ return &img_node->mem;
break;
}
case VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT: {
- auto it = my_data->bufferMap.find(VkBuffer(handle));
- if (it != my_data->bufferMap.end())
- return &(*it).second.mem;
+ auto buff_node = getBufferNode(my_data, VkBuffer(handle));
+ if (buff_node)
+ return &buff_node->mem;
break;
}
default:
@@ -298,9 +385,9 @@ static bool validate_usage_flags(layer_data *my_data, VkFlags actual, VkFlags de
static bool validate_image_usage_flags(layer_data *dev_data, VkImage image, VkFlags desired, VkBool32 strict,
char const *func_name, char const *usage_string) {
bool skipCall = false;
- auto const image_node = dev_data->imageMap.find(image);
- if (image_node != dev_data->imageMap.end()) {
- skipCall = validate_usage_flags(dev_data, image_node->second.createInfo.usage, desired, strict, (uint64_t)image,
+ auto const image_node = getImageNode(dev_data, image);
+ if (image_node) {
+ skipCall = validate_usage_flags(dev_data, image_node->createInfo.usage, desired, strict, (uint64_t)image,
VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "image", func_name, usage_string);
}
return skipCall;
@@ -312,9 +399,9 @@ static bool validate_image_usage_flags(layer_data *dev_data, VkImage image, VkFl
static bool validate_buffer_usage_flags(layer_data *dev_data, VkBuffer buffer, VkFlags desired, VkBool32 strict,
char const *func_name, char const *usage_string) {
bool skipCall = false;
- auto const buffer_node = dev_data->bufferMap.find(buffer);
- if (buffer_node != dev_data->bufferMap.end()) {
- skipCall = validate_usage_flags(dev_data, buffer_node->second.createInfo.usage, desired, strict, (uint64_t)buffer,
+ auto buffer_node = getBufferNode(dev_data, buffer);
+ if (buffer_node) {
+ skipCall = validate_usage_flags(dev_data, buffer_node->createInfo.usage, desired, strict, (uint64_t)buffer,
VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "buffer", func_name, usage_string);
}
return skipCall;
@@ -322,44 +409,33 @@ static bool validate_buffer_usage_flags(layer_data *dev_data, VkBuffer buffer, V
// Return ptr to info in map container containing mem, or NULL if not found
// Calls to this function should be wrapped in mutex
-static DEVICE_MEM_INFO *get_mem_obj_info(layer_data *dev_data, const VkDeviceMemory mem) {
- auto item = dev_data->memObjMap.find(mem);
- if (item != dev_data->memObjMap.end()) {
- return &(*item).second;
- } else {
+DEVICE_MEM_INFO *getMemObjInfo(const layer_data *dev_data, const VkDeviceMemory mem) {
+ auto mem_it = dev_data->memObjMap.find(mem);
+ if (mem_it == dev_data->memObjMap.end()) {
return NULL;
}
+ return mem_it->second.get();
}
static void add_mem_obj_info(layer_data *my_data, void *object, const VkDeviceMemory mem,
const VkMemoryAllocateInfo *pAllocateInfo) {
assert(object != NULL);
- memcpy(&my_data->memObjMap[mem].allocInfo, pAllocateInfo, sizeof(VkMemoryAllocateInfo));
- // TODO: Update for real hardware, actually process allocation info structures
- my_data->memObjMap[mem].allocInfo.pNext = NULL;
- my_data->memObjMap[mem].object = object;
- my_data->memObjMap[mem].mem = mem;
- my_data->memObjMap[mem].image = VK_NULL_HANDLE;
- my_data->memObjMap[mem].memRange.offset = 0;
- my_data->memObjMap[mem].memRange.size = 0;
- my_data->memObjMap[mem].pData = 0;
- my_data->memObjMap[mem].pDriverData = 0;
- my_data->memObjMap[mem].valid = false;
+ my_data->memObjMap[mem] = unique_ptr<DEVICE_MEM_INFO>(new DEVICE_MEM_INFO(object, mem, pAllocateInfo));
}
static bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, const char *functionName,
VkImage image = VK_NULL_HANDLE) {
if (mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
- auto const image_node = dev_data->imageMap.find(image);
- if (image_node != dev_data->imageMap.end() && !image_node->second.valid) {
+ auto const image_node = getImageNode(dev_data, image);
+ if (image_node && !image_node->valid) {
return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
(uint64_t)(mem), __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM",
"%s: Cannot read invalid swapchain image 0x%" PRIx64 ", please fill the memory before using.",
functionName, (uint64_t)(image));
}
} else {
- DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem);
if (pMemObj && !pMemObj->valid) {
return log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
(uint64_t)(mem), __LINE__, MEMTRACK_INVALID_USAGE_FLAG, "MEM",
@@ -372,12 +448,12 @@ static bool validate_memory_is_valid(layer_data *dev_data, VkDeviceMemory mem, c
static void set_memory_valid(layer_data *dev_data, VkDeviceMemory mem, bool valid, VkImage image = VK_NULL_HANDLE) {
if (mem == MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
- auto image_node = dev_data->imageMap.find(image);
- if (image_node != dev_data->imageMap.end()) {
- image_node->second.valid = valid;
+ auto image_node = getImageNode(dev_data, image);
+ if (image_node) {
+ image_node->valid = valid;
}
} else {
- DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem);
if (pMemObj) {
pMemObj->valid = valid;
}
@@ -394,7 +470,7 @@ static bool update_cmd_buf_and_mem_references(layer_data *dev_data, const VkComm
if (mem != MEMTRACKER_SWAP_CHAIN_IMAGE_KEY) {
// First update CB binding in MemObj mini CB list
- DEVICE_MEM_INFO *pMemInfo = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem);
if (pMemInfo) {
pMemInfo->commandBufferBindings.insert(cb);
// Now update CBInfo's Mem reference list
@@ -412,7 +488,7 @@ static void clear_cmd_buf_and_mem_references(layer_data *dev_data, GLOBAL_CB_NOD
if (pCBNode) {
if (pCBNode->memObjs.size() > 0) {
for (auto mem : pCBNode->memObjs) {
- DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem);
if (pInfo) {
pInfo->commandBufferBindings.erase(pCBNode->commandBuffer);
}
@@ -479,7 +555,7 @@ static bool deleteMemObjInfo(layer_data *my_data, void *object, VkDeviceMemory m
static bool freeMemObjInfo(layer_data *dev_data, void *object, VkDeviceMemory mem, bool internal) {
bool skipCall = false;
// Parse global list to find info w/ mem
- DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem);
if (pInfo) {
if (pInfo->allocInfo.allocationSize == 0 && !internal) {
// TODO: Verify against Valid Use section
@@ -536,7 +612,7 @@ static bool clear_object_binding(layer_data *dev_data, uint64_t handle, VkDebugR
bool skipCall = false;
VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type);
if (pMemBinding) {
- DEVICE_MEM_INFO *pMemObjInfo = get_mem_obj_info(dev_data, *pMemBinding);
+ DEVICE_MEM_INFO *pMemObjInfo = getMemObjInfo(dev_data, *pMemBinding);
// TODO : Make sure this is a reasonable way to reset mem binding
*pMemBinding = VK_NULL_HANDLE;
if (pMemObjInfo) {
@@ -570,9 +646,9 @@ static bool set_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t h
} else {
VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type);
assert(pMemBinding);
- DEVICE_MEM_INFO *pMemInfo = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pMemInfo = getMemObjInfo(dev_data, mem);
if (pMemInfo) {
- DEVICE_MEM_INFO *pPrevBinding = get_mem_obj_info(dev_data, *pMemBinding);
+ DEVICE_MEM_INFO *pPrevBinding = getMemObjInfo(dev_data, *pMemBinding);
if (pPrevBinding != NULL) {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_REBIND_OBJECT,
@@ -584,9 +660,9 @@ static bool set_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uint64_t h
// For image objects, make sure default memory state is correctly set
// TODO : What's the best/correct way to handle this?
if (VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT == type) {
- auto const image_node = dev_data->imageMap.find(VkImage(handle));
- if (image_node != dev_data->imageMap.end()) {
- VkImageCreateInfo ici = image_node->second.createInfo;
+ auto const image_node = getImageNode(dev_data, VkImage(handle));
+ if (image_node) {
+ VkImageCreateInfo ici = image_node->createInfo;
if (ici.usage & (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT)) {
// TODO:: More memory state transition stuff.
}
@@ -614,7 +690,7 @@ static bool set_sparse_mem_binding(layer_data *dev_data, VkDeviceMemory mem, uin
} else {
VkDeviceMemory *pMemBinding = get_object_mem_binding(dev_data, handle, type);
assert(pMemBinding);
- DEVICE_MEM_INFO *pInfo = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pInfo = getMemObjInfo(dev_data, mem);
if (pInfo) {
pInfo->objBindings.insert({handle, type});
// Need to set mem binding for this object
@@ -642,8 +718,6 @@ static bool get_mem_binding_from_object(layer_data *dev_data, const uint64_t han
// Print details of MemObjInfo list
static void print_mem_list(layer_data *dev_data) {
- DEVICE_MEM_INFO *pInfo = NULL;
-
// Early out if info is not requested
if (!(dev_data->report_data->active_flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)) {
return;
@@ -660,17 +734,17 @@ static void print_mem_list(layer_data *dev_data) {
return;
for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) {
- pInfo = &(*ii).second;
+ auto mem_info = (*ii).second.get();
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
- __LINE__, MEMTRACK_NONE, "MEM", " ===MemObjInfo at 0x%p===", (void *)pInfo);
+ __LINE__, MEMTRACK_NONE, "MEM", " ===MemObjInfo at 0x%p===", (void *)mem_info);
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
- __LINE__, MEMTRACK_NONE, "MEM", " Mem object: 0x%" PRIxLEAST64, (uint64_t)(pInfo->mem));
+ __LINE__, MEMTRACK_NONE, "MEM", " Mem object: 0x%" PRIxLEAST64, (uint64_t)(mem_info->mem));
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
__LINE__, MEMTRACK_NONE, "MEM", " Ref Count: " PRINTF_SIZE_T_SPECIFIER,
- pInfo->commandBufferBindings.size() + pInfo->objBindings.size());
- if (0 != pInfo->allocInfo.allocationSize) {
- string pAllocInfoMsg = vk_print_vkmemoryallocateinfo(&pInfo->allocInfo, "MEM(INFO): ");
+ mem_info->commandBufferBindings.size() + mem_info->objBindings.size());
+ if (0 != mem_info->allocInfo.allocationSize) {
+ string pAllocInfoMsg = vk_print_vkmemoryallocateinfo(&mem_info->allocInfo, "MEM(INFO): ");
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
__LINE__, MEMTRACK_NONE, "MEM", " Mem Alloc info:\n%s", pAllocInfoMsg.c_str());
} else {
@@ -680,9 +754,9 @@ static void print_mem_list(layer_data *dev_data) {
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
__LINE__, MEMTRACK_NONE, "MEM", " VK OBJECT Binding list of size " PRINTF_SIZE_T_SPECIFIER " elements:",
- pInfo->objBindings.size());
- if (pInfo->objBindings.size() > 0) {
- for (auto obj : pInfo->objBindings) {
+ mem_info->objBindings.size());
+ if (mem_info->objBindings.size() > 0) {
+ for (auto obj : mem_info->objBindings) {
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
0, __LINE__, MEMTRACK_NONE, "MEM", " VK OBJECT 0x%" PRIx64, obj.handle);
}
@@ -691,9 +765,9 @@ static void print_mem_list(layer_data *dev_data) {
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, 0,
__LINE__, MEMTRACK_NONE, "MEM",
" VK Command Buffer (CB) binding list of size " PRINTF_SIZE_T_SPECIFIER " elements",
- pInfo->commandBufferBindings.size());
- if (pInfo->commandBufferBindings.size() > 0) {
- for (auto cb : pInfo->commandBufferBindings) {
+ mem_info->commandBufferBindings.size());
+ if (mem_info->commandBufferBindings.size() > 0) {
+ for (auto cb : mem_info->commandBufferBindings) {
log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
0, __LINE__, MEMTRACK_NONE, "MEM", " VK CB 0x%p", cb);
}
@@ -1915,7 +1989,7 @@ static bool validate_push_constant_usage(debug_report_data *report_data,
// For given pipelineLayout verify that the set_layout_node at slot.first
// has the requested binding at slot.second and return ptr to that binding
-static VkDescriptorSetLayoutBinding const * get_descriptor_binding(PIPELINE_LAYOUT_NODE *pipelineLayout, descriptor_slot_t slot) {
+static VkDescriptorSetLayoutBinding const * get_descriptor_binding(PIPELINE_LAYOUT_NODE const *pipelineLayout, descriptor_slot_t slot) {
if (!pipelineLayout)
return nullptr;
@@ -1955,7 +2029,7 @@ static bool validate_status(layer_data *my_data, GLOBAL_CB_NODE *pNode, CBStatus
}
// Retrieve pipeline node ptr for given pipeline object
-static PIPELINE_NODE *getPipeline(layer_data const *my_data, const VkPipeline pipeline) {
+static PIPELINE_NODE *getPipeline(layer_data const *my_data, VkPipeline pipeline) {
auto it = my_data->pipelineMap.find(pipeline);
if (it == my_data->pipelineMap.end()) {
return nullptr;
@@ -1963,6 +2037,38 @@ static PIPELINE_NODE *getPipeline(layer_data const *my_data, const VkPipeline pi
return it->second;
}
+static RENDER_PASS_NODE *getRenderPass(layer_data const *my_data, VkRenderPass renderpass) {
+ auto it = my_data->renderPassMap.find(renderpass);
+ if (it == my_data->renderPassMap.end()) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+static FRAMEBUFFER_NODE *getFramebuffer(layer_data *my_data, VkFramebuffer framebuffer) {
+ auto it = my_data->frameBufferMap.find(framebuffer);
+ if (it == my_data->frameBufferMap.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
+cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *my_data, VkDescriptorSetLayout dsLayout) {
+ auto it = my_data->descriptorSetLayoutMap.find(dsLayout);
+ if (it == my_data->descriptorSetLayoutMap.end()) {
+ return nullptr;
+ }
+ return it->second;
+}
+
+static PIPELINE_LAYOUT_NODE const *getPipelineLayout(layer_data const *my_data, VkPipelineLayout pipeLayout) {
+ auto it = my_data->pipelineLayoutMap.find(pipeLayout);
+ if (it == my_data->pipelineLayoutMap.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
// Return true if for a given PSO, the given state enum is dynamic, else return false
static bool isDynamic(const PIPELINE_NODE *pPipeline, const VkDynamicState state) {
if (pPipeline && pPipeline->graphicsPipelineCI.pDynamicState) {
@@ -2047,12 +2153,17 @@ static bool attachment_references_compatible(const uint32_t index, const VkAttac
// For give primary and secondary RenderPass objects, verify that they're compatible
static bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderPass primaryRP, const VkRenderPass secondaryRP,
string &errorMsg) {
- if (my_data->renderPassMap.find(primaryRP) == my_data->renderPassMap.end()) {
+ auto primary_render_pass = getRenderPass(my_data, primaryRP);
+ auto secondary_render_pass = getRenderPass(my_data, secondaryRP);
+
+ if (!primary_render_pass) {
stringstream errorStr;
errorStr << "invalid VkRenderPass (" << primaryRP << ")";
errorMsg = errorStr.str();
return false;
- } else if (my_data->renderPassMap.find(secondaryRP) == my_data->renderPassMap.end()) {
+ }
+
+ if (!secondary_render_pass) {
stringstream errorStr;
errorStr << "invalid VkRenderPass (" << secondaryRP << ")";
errorMsg = errorStr.str();
@@ -2062,8 +2173,8 @@ static bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderP
if (primaryRP == secondaryRP) {
return true;
}
- const VkRenderPassCreateInfo *primaryRPCI = my_data->renderPassMap[primaryRP]->pCreateInfo;
- const VkRenderPassCreateInfo *secondaryRPCI = my_data->renderPassMap[secondaryRP]->pCreateInfo;
+ const VkRenderPassCreateInfo *primaryRPCI = primary_render_pass->pCreateInfo;
+ const VkRenderPassCreateInfo *secondaryRPCI = secondary_render_pass->pCreateInfo;
if (primaryRPCI->subpassCount != secondaryRPCI->subpassCount) {
stringstream errorStr;
errorStr << "RenderPass for primary cmdBuffer has " << primaryRPCI->subpassCount
@@ -2127,22 +2238,22 @@ static bool verify_renderpass_compatibility(layer_data *my_data, const VkRenderP
// pipelineLayout[layoutIndex]
static bool verify_set_layout_compatibility(layer_data *my_data, const cvdescriptorset::DescriptorSet *pSet,
const VkPipelineLayout layout, const uint32_t layoutIndex, string &errorMsg) {
- auto pipeline_layout_it = my_data->pipelineLayoutMap.find(layout);
- if (pipeline_layout_it == my_data->pipelineLayoutMap.end()) {
+ auto pipeline_layout = getPipelineLayout(my_data, layout);
+ if (!pipeline_layout) {
stringstream errorStr;
errorStr << "invalid VkPipelineLayout (" << layout << ")";
errorMsg = errorStr.str();
return false;
}
- if (layoutIndex >= pipeline_layout_it->second.descriptorSetLayouts.size()) {
+ if (layoutIndex >= pipeline_layout->descriptorSetLayouts.size()) {
stringstream errorStr;
- errorStr << "VkPipelineLayout (" << layout << ") only contains " << pipeline_layout_it->second.descriptorSetLayouts.size()
- << " setLayouts corresponding to sets 0-" << pipeline_layout_it->second.descriptorSetLayouts.size() - 1
+ errorStr << "VkPipelineLayout (" << layout << ") only contains " << pipeline_layout->descriptorSetLayouts.size()
+ << " setLayouts corresponding to sets 0-" << pipeline_layout->descriptorSetLayouts.size() - 1
<< ", but you're attempting to bind set to index " << layoutIndex;
errorMsg = errorStr.str();
return false;
}
- auto layout_node = my_data->descriptorSetLayoutMap[pipeline_layout_it->second.descriptorSetLayouts[layoutIndex]];
+ auto layout_node = pipeline_layout->setLayouts[layoutIndex];
return pSet->IsCompatible(layout_node, &errorMsg);
}
@@ -2572,13 +2683,13 @@ static bool validate_compute_pipeline(debug_report_data *report_data, PIPELINE_N
return validate_pipeline_shader_stage(report_data, &pCreateInfo->stage, pPipeline,
&module, &entrypoint, enabledFeatures, shaderModuleMap);
}
-
// Return Set node ptr for specified set or else NULL
-static cvdescriptorset::DescriptorSet *getSetNode(layer_data *my_data, const VkDescriptorSet set) {
- if (my_data->setMap.find(set) == my_data->setMap.end()) {
+cvdescriptorset::DescriptorSet *getSetNode(const layer_data *my_data, VkDescriptorSet set) {
+ auto set_it = my_data->setMap.find(set);
+ if (set_it == my_data->setMap.end()) {
return NULL;
}
- return my_data->setMap[set];
+ return set_it->second;
}
// For the given command buffer, verify and update the state for activeSetBindingsPairs
// This includes:
@@ -2608,20 +2719,6 @@ static bool validate_and_update_drawtime_descriptor_state(
}
return result;
}
-// TODO : This is a temp function that naively updates bound storage images and buffers based on which descriptor sets are bound.
-// When validate_and_update_draw_state() handles compute shaders so that active_slots is correct for compute pipelines, this
-// function can be killed and validate_and_update_draw_state() used instead
-static void update_shader_storage_images_and_buffers(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
- cvdescriptorset::DescriptorSet *pSet = nullptr;
- // For the bound descriptor sets, pull off any storage images and buffers
- // This may be more than are actually updated depending on which are active, but for now this is a stop-gap for compute
- // pipelines
- for (auto set : pCB->lastBound[VK_PIPELINE_BIND_POINT_COMPUTE].uniqueBoundSets) {
- // Get the set node
- pSet = getSetNode(dev_data, set);
- pSet->GetAllStorageUpdates(&pCB->updateBuffers, &pCB->updateImages);
- }
-}
// For given pipeline, return number of MSAA samples, or one if MSAA disabled
static VkSampleCountFlagBits getNumSamples(PIPELINE_NODE const *pipe) {
@@ -2633,25 +2730,75 @@ static VkSampleCountFlagBits getNumSamples(PIPELINE_NODE const *pipe) {
}
// Validate draw-time state related to the PSO
-static bool validatePipelineDrawtimeState(layer_data const *my_data, const GLOBAL_CB_NODE *pCB,
- const VkPipelineBindPoint pipelineBindPoint, PIPELINE_NODE const *pPipeline) {
+static bool validatePipelineDrawtimeState(layer_data const *my_data,
+ LAST_BOUND_STATE const &state,
+ const GLOBAL_CB_NODE *pCB,
+ PIPELINE_NODE const *pPipeline) {
bool skip_call = false;
- if (VK_PIPELINE_BIND_POINT_GRAPHICS == pipelineBindPoint) {
- // Verify that any MSAA request in PSO matches sample# in bound FB
- // Skip the check if rasterization is disabled.
- if (!pPipeline->graphicsPipelineCI.pRasterizationState ||
- (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
- VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline);
- if (pCB->activeRenderPass) {
- const VkRenderPassCreateInfo *render_pass_info = pCB->activeRenderPass->pCreateInfo;
- const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass];
- VkSampleCountFlagBits subpass_num_samples = VkSampleCountFlagBits(0);
- uint32_t i;
-
- const VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState;
- if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) &&
- (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) {
- skip_call |=
+
+ // Verify Vtx binding
+ if (pPipeline->vertexBindingDescriptions.size() > 0) {
+ for (size_t i = 0; i < pPipeline->vertexBindingDescriptions.size(); i++) {
+ if ((pCB->currentDrawData.buffers.size() < (i + 1)) || (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
+ __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
+ "The Pipeline State Object (0x%" PRIxLEAST64
+ ") expects that this Command Buffer's vertex binding Index " PRINTF_SIZE_T_SPECIFIER
+ " should be set via vkCmdBindVertexBuffers.",
+ (uint64_t)state.pipeline, i);
+ }
+ }
+ } else {
+ if (!pCB->currentDrawData.buffers.empty()) {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
+ 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
+ "Vertex buffers are bound to command buffer (0x%" PRIxLEAST64
+ ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").",
+ (uint64_t)pCB->commandBuffer, (uint64_t)state.pipeline);
+ }
+ }
+ // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count.
+ // Skip check if rasterization is disabled or there is no viewport.
+ if ((!pPipeline->graphicsPipelineCI.pRasterizationState ||
+ (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) &&
+ pPipeline->graphicsPipelineCI.pViewportState) {
+ bool dynViewport = isDynamic(pPipeline, VK_DYNAMIC_STATE_VIEWPORT);
+ bool dynScissor = isDynamic(pPipeline, VK_DYNAMIC_STATE_SCISSOR);
+ if (dynViewport) {
+ if (pCB->viewports.size() != pPipeline->graphicsPipelineCI.pViewportState->viewportCount) {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
+ __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
+ "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER
+ ", but PSO viewportCount is %u. These counts must match.",
+ pCB->viewports.size(), pPipeline->graphicsPipelineCI.pViewportState->viewportCount);
+ }
+ }
+ if (dynScissor) {
+ if (pCB->scissors.size() != pPipeline->graphicsPipelineCI.pViewportState->scissorCount) {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
+ __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
+ "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER
+ ", but PSO scissorCount is %u. These counts must match.",
+ pCB->scissors.size(), pPipeline->graphicsPipelineCI.pViewportState->scissorCount);
+ }
+ }
+ }
+
+ // Verify that any MSAA request in PSO matches sample# in bound FB
+ // Skip the check if rasterization is disabled.
+ if (!pPipeline->graphicsPipelineCI.pRasterizationState ||
+ (pPipeline->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
+ VkSampleCountFlagBits pso_num_samples = getNumSamples(pPipeline);
+ if (pCB->activeRenderPass) {
+ const VkRenderPassCreateInfo *render_pass_info = pCB->activeRenderPass->pCreateInfo;
+ const VkSubpassDescription *subpass_desc = &render_pass_info->pSubpasses[pCB->activeSubpass];
+ VkSampleCountFlagBits subpass_num_samples = VkSampleCountFlagBits(0);
+ uint32_t i;
+
+ const safe_VkPipelineColorBlendStateCreateInfo *color_blend_state = pPipeline->graphicsPipelineCI.pColorBlendState;
+ if ((color_blend_state != NULL) && (pCB->activeSubpass == pPipeline->graphicsPipelineCI.subpass) &&
+ (color_blend_state->attachmentCount != subpass_desc->colorAttachmentCount)) {
+ skip_call |=
log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
"Render pass subpass %u mismatch with blending state defined and blend state attachment "
@@ -2659,53 +2806,51 @@ static bool validatePipelineDrawtimeState(layer_data const *my_data, const GLOBA
"must be the same at draw-time.",
pCB->activeSubpass, color_blend_state->attachmentCount, subpass_desc->colorAttachmentCount,
reinterpret_cast<const uint64_t &>(pPipeline->pipeline));
- }
+ }
- for (i = 0; i < subpass_desc->colorAttachmentCount; i++) {
- VkSampleCountFlagBits samples;
+ for (i = 0; i < subpass_desc->colorAttachmentCount; i++) {
+ VkSampleCountFlagBits samples;
- if (subpass_desc->pColorAttachments[i].attachment == VK_ATTACHMENT_UNUSED)
- continue;
+ if (subpass_desc->pColorAttachments[i].attachment == VK_ATTACHMENT_UNUSED)
+ continue;
- samples = render_pass_info->pAttachments[subpass_desc->pColorAttachments[i].attachment].samples;
- if (subpass_num_samples == static_cast<VkSampleCountFlagBits>(0)) {
- subpass_num_samples = samples;
- } else if (subpass_num_samples != samples) {
- subpass_num_samples = static_cast<VkSampleCountFlagBits>(-1);
- break;
- }
+ samples = render_pass_info->pAttachments[subpass_desc->pColorAttachments[i].attachment].samples;
+ if (subpass_num_samples == static_cast<VkSampleCountFlagBits>(0)) {
+ subpass_num_samples = samples;
+ } else if (subpass_num_samples != samples) {
+ subpass_num_samples = static_cast<VkSampleCountFlagBits>(-1);
+ break;
}
- if ((subpass_desc->pDepthStencilAttachment != NULL) &&
- (subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) {
- const VkSampleCountFlagBits samples =
+ }
+ if ((subpass_desc->pDepthStencilAttachment != NULL) &&
+ (subpass_desc->pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED)) {
+ const VkSampleCountFlagBits samples =
render_pass_info->pAttachments[subpass_desc->pDepthStencilAttachment->attachment].samples;
- if (subpass_num_samples == static_cast<VkSampleCountFlagBits>(0))
- subpass_num_samples = samples;
- else if (subpass_num_samples != samples)
- subpass_num_samples = static_cast<VkSampleCountFlagBits>(-1);
- }
+ if (subpass_num_samples == static_cast<VkSampleCountFlagBits>(0))
+ subpass_num_samples = samples;
+ else if (subpass_num_samples != samples)
+ subpass_num_samples = static_cast<VkSampleCountFlagBits>(-1);
+ }
- if (((subpass_desc->colorAttachmentCount > 0) || (subpass_desc->pDepthStencilAttachment != NULL)) &&
- (pso_num_samples != subpass_num_samples)) {
- skip_call |=
+ if (((subpass_desc->colorAttachmentCount > 0) || (subpass_desc->pDepthStencilAttachment != NULL)) &&
+ (pso_num_samples != subpass_num_samples)) {
+ skip_call |=
log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
"Num samples mismatch! At draw-time in Pipeline (0x%" PRIxLEAST64
") with %u samples while current RenderPass (0x%" PRIxLEAST64 ") w/ %u samples!",
reinterpret_cast<const uint64_t &>(pPipeline->pipeline), pso_num_samples,
reinterpret_cast<const uint64_t &>(pCB->activeRenderPass->renderPass), subpass_num_samples);
- }
- } else {
- skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
- reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
- "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!",
- reinterpret_cast<const uint64_t &>(pPipeline->pipeline));
}
+ } else {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT,
+ reinterpret_cast<const uint64_t &>(pPipeline->pipeline), __LINE__, DRAWSTATE_NUM_SAMPLES_MISMATCH, "DS",
+ "No active render pass found at draw-time in Pipeline (0x%" PRIxLEAST64 ")!",
+ reinterpret_cast<const uint64_t &>(pPipeline->pipeline));
}
- // TODO : Add more checks here
- } else {
- // TODO : Validate non-gfx pipeline updates
}
+ // TODO : Add more checks here
+
return skip_call;
}
@@ -2727,18 +2872,12 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE *
// First check flag states
if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint)
result = validate_draw_state_flags(my_data, pCB, pPipe, indexedDraw);
- else {
- // First block of code below to validate active sets should eventually
- // work for the compute case but currently doesn't so return early for now
- // TODO : When active sets in compute shaders are correctly parsed,
- // stop returning early here and handle them in top block below
- return result;
- }
// Now complete other state checks
- // TODO : When Compute shaders are properly parsed, fix this section to validate them as well
if (state.pipelineLayout) {
string errorString;
+ auto pipelineLayout = (bindPoint == VK_PIPELINE_BIND_POINT_GRAPHICS) ? pPipe->graphicsPipelineCI.layout : pPipe->computePipelineCI.layout;
+
// Need a vector (vs. std::set) of active Sets for dynamicOffset validation in case same set bound w/ different offsets
vector<std::tuple<cvdescriptorset::DescriptorSet *, unordered_set<uint32_t>, std::vector<uint32_t> const *>> activeSetBindingsPairs;
for (auto & setBindingPair : pPipe->active_slots) {
@@ -2749,19 +2888,19 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE *
DRAWSTATE_DESCRIPTOR_SET_NOT_BOUND, "DS",
"VkPipeline 0x%" PRIxLEAST64 " uses set #%u but that set is not bound.", (uint64_t)pPipe->pipeline,
setIndex);
- } else if (!verify_set_layout_compatibility(my_data, my_data->setMap[state.boundDescriptorSets[setIndex]],
- pPipe->graphicsPipelineCI.layout, setIndex, errorString)) {
+ } else if (!verify_set_layout_compatibility(my_data, state.boundDescriptorSets[setIndex],
+ pipelineLayout, setIndex, errorString)) {
// Set is bound but not compatible w/ overlapping pipelineLayout from PSO
- VkDescriptorSet setHandle = my_data->setMap[state.boundDescriptorSets[setIndex]]->GetSet();
+ VkDescriptorSet setHandle = state.boundDescriptorSets[setIndex]->GetSet();
result |=
log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
(uint64_t)setHandle, __LINE__, DRAWSTATE_PIPELINE_LAYOUTS_INCOMPATIBLE, "DS",
"VkDescriptorSet (0x%" PRIxLEAST64
") bound as set #%u is not compatible with overlapping VkPipelineLayout 0x%" PRIxLEAST64 " due to: %s",
- (uint64_t)setHandle, setIndex, (uint64_t)pPipe->graphicsPipelineCI.layout, errorString.c_str());
+ (uint64_t)setHandle, setIndex, (uint64_t)pipelineLayout, errorString.c_str());
} else { // Valid set is bound and layout compatible, validate that it's updated
// Pull the set node
- cvdescriptorset::DescriptorSet *pSet = my_data->setMap[state.boundDescriptorSets[setIndex]];
+ cvdescriptorset::DescriptorSet *pSet = state.boundDescriptorSets[setIndex];
// Save vector of all active sets to verify dynamicOffsets below
activeSetBindingsPairs.push_back(std::make_tuple(pSet, setBindingPair.second,
&state.dynamicOffsets[setIndex]));
@@ -2784,59 +2923,10 @@ static bool validate_and_update_draw_state(layer_data *my_data, GLOBAL_CB_NODE *
// For given active slots, verify any dynamic descriptors and record updated images & buffers
result |= validate_and_update_drawtime_descriptor_state(my_data, pCB, activeSetBindingsPairs);
}
- // TODO : If/when compute pipelines/shaders are handled above, code below is only for gfx bind poing
- //if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) {
- // Verify Vtx binding
- if (pPipe->vertexBindingDescriptions.size() > 0) {
- for (size_t i = 0; i < pPipe->vertexBindingDescriptions.size(); i++) {
- if ((pCB->currentDrawData.buffers.size() < (i + 1)) || (pCB->currentDrawData.buffers[i] == VK_NULL_HANDLE)) {
- result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
- "The Pipeline State Object (0x%" PRIxLEAST64
- ") expects that this Command Buffer's vertex binding Index " PRINTF_SIZE_T_SPECIFIER
- " should be set via vkCmdBindVertexBuffers.",
- (uint64_t)state.pipeline, i);
- }
- }
- } else {
- if (!pCB->currentDrawData.buffers.empty()) {
- result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
- 0, __LINE__, DRAWSTATE_VTX_INDEX_OUT_OF_BOUNDS, "DS",
- "Vertex buffers are bound to command buffer (0x%" PRIxLEAST64
- ") but no vertex buffers are attached to this Pipeline State Object (0x%" PRIxLEAST64 ").",
- (uint64_t)pCB->commandBuffer, (uint64_t)state.pipeline);
- }
- }
- // If Viewport or scissors are dynamic, verify that dynamic count matches PSO count.
- // Skip check if rasterization is disabled or there is no viewport.
- if ((!pPipe->graphicsPipelineCI.pRasterizationState ||
- (pPipe->graphicsPipelineCI.pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) &&
- pPipe->graphicsPipelineCI.pViewportState) {
- bool dynViewport = isDynamic(pPipe, VK_DYNAMIC_STATE_VIEWPORT);
- bool dynScissor = isDynamic(pPipe, VK_DYNAMIC_STATE_SCISSOR);
- if (dynViewport) {
- if (pCB->viewports.size() != pPipe->graphicsPipelineCI.pViewportState->viewportCount) {
- result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
- "Dynamic viewportCount from vkCmdSetViewport() is " PRINTF_SIZE_T_SPECIFIER
- ", but PSO viewportCount is %u. These counts must match.",
- pCB->viewports.size(), pPipe->graphicsPipelineCI.pViewportState->viewportCount);
- }
- }
- if (dynScissor) {
- if (pCB->scissors.size() != pPipe->graphicsPipelineCI.pViewportState->scissorCount) {
- result |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_VIEWPORT_SCISSOR_MISMATCH, "DS",
- "Dynamic scissorCount from vkCmdSetScissor() is " PRINTF_SIZE_T_SPECIFIER
- ", but PSO scissorCount is %u. These counts must match.",
- pCB->scissors.size(), pPipe->graphicsPipelineCI.pViewportState->scissorCount);
- }
- }
- }
- //} // end of "if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint) {" block
// Check general pipeline state that needs to be validated at drawtime
- result |= validatePipelineDrawtimeState(my_data, pCB, bindPoint, pPipe);
+ if (VK_PIPELINE_BIND_POINT_GRAPHICS == bindPoint)
+ result |= validatePipelineDrawtimeState(my_data, state, pCB, pPipe);
return result;
}
@@ -2944,13 +3034,13 @@ static bool verifyPipelineCreateState(layer_data *my_data, const VkDevice device
// Ensure the subpass index is valid. If not, then validate_and_capture_pipeline_shader_state
// produces nonsense errors that confuse users. Other layers should already
// emit errors for renderpass being invalid.
- auto rp_data = my_data->renderPassMap.find(pPipeline->graphicsPipelineCI.renderPass);
- if (rp_data != my_data->renderPassMap.end() &&
- pPipeline->graphicsPipelineCI.subpass >= rp_data->second->pCreateInfo->subpassCount) {
+ auto renderPass = getRenderPass(my_data, pPipeline->graphicsPipelineCI.renderPass);
+ if (renderPass &&
+ pPipeline->graphicsPipelineCI.subpass >= renderPass->pCreateInfo->subpassCount) {
skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_PIPELINE_CREATE_STATE, "DS", "Invalid Pipeline CreateInfo State: Subpass index %u "
"is out of range for this renderpass (0..%u)",
- pPipeline->graphicsPipelineCI.subpass, rp_data->second->pCreateInfo->subpassCount - 1);
+ pPipeline->graphicsPipelineCI.subpass, renderPass->pCreateInfo->subpassCount - 1);
}
if (!validate_and_capture_pipeline_shader_state(my_data->report_data, pPipeline, &my_data->phys_dev_properties.features,
@@ -3092,11 +3182,12 @@ static void deletePipelines(layer_data *my_data) {
// Block of code at start here specifically for managing/tracking DSs
// Return Pool node ptr for specified pool or else NULL
-static DESCRIPTOR_POOL_NODE *getPoolNode(layer_data *my_data, const VkDescriptorPool pool) {
- if (my_data->descriptorPoolMap.find(pool) == my_data->descriptorPoolMap.end()) {
+DESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *dev_data, const VkDescriptorPool pool) {
+ auto pool_it = dev_data->descriptorPoolMap.find(pool);
+ if (pool_it == dev_data->descriptorPoolMap.end()) {
return NULL;
}
- return my_data->descriptorPoolMap[pool];
+ return pool_it->second;
}
// Return false if update struct is of valid type, otherwise flag error and return code from callback
@@ -3260,13 +3351,13 @@ bool FindLayouts(const layer_data *my_data, VkImage image, std::vector<VkImageLa
auto sub_data = my_data->imageSubresourceMap.find(image);
if (sub_data == my_data->imageSubresourceMap.end())
return false;
- auto imgIt = my_data->imageMap.find(image);
- if (imgIt == my_data->imageMap.end())
+ auto img_node = getImageNode(my_data, image);
+ if (!img_node)
return false;
bool ignoreGlobal = false;
// TODO: Make this robust for >1 aspect mask. Now it will just say ignore
// potential errors in this case.
- if (sub_data->second.size() >= (imgIt->second.createInfo.arrayLayers * imgIt->second.createInfo.mipLevels + 1)) {
+ if (sub_data->second.size() >= (img_node->createInfo.arrayLayers * img_node->createInfo.mipLevels + 1)) {
ignoreGlobal = true;
}
for (auto imgsubpair : sub_data->second) {
@@ -3342,10 +3433,10 @@ template <class OBJECT, class LAYOUT> void SetLayout(OBJECT *pObject, VkImage im
}
void SetLayout(const layer_data *dev_data, GLOBAL_CB_NODE *pCB, VkImageView imageView, const VkImageLayout &layout) {
- auto image_view_data = dev_data->imageViewMap.find(imageView);
- assert(image_view_data != dev_data->imageViewMap.end());
- const VkImage &image = image_view_data->second.image;
- const VkImageSubresourceRange &subRange = image_view_data->second.subresourceRange;
+ auto iv_data = getImageViewData(dev_data, imageView);
+ assert(iv_data);
+ const VkImage &image = iv_data->image;
+ const VkImageSubresourceRange &subRange = iv_data->subresourceRange;
// TODO: Do not iterate over every possibility - consolidate where possible
for (uint32_t j = 0; j < subRange.levelCount; j++) {
uint32_t level = subRange.baseMipLevel + j;
@@ -3379,116 +3470,9 @@ static bool validateIdleDescriptorSet(const layer_data *my_data, VkDescriptorSet
}
return skip_call;
}
-static void invalidateBoundCmdBuffers(layer_data *dev_data, const cvdescriptorset::DescriptorSet *pSet) {
- // Flag any CBs this set is bound to as INVALID
- for (auto cb : pSet->GetBoundCmdBuffers()) {
- auto cb_node = dev_data->commandBufferMap.find(cb);
- if (cb_node != dev_data->commandBufferMap.end()) {
- cb_node->second->state = CB_INVALID;
- }
- }
-}
-// update DS mappings based on write and copy update arrays
-static bool dsUpdate(layer_data *my_data, VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pWDS,
- uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pCDS) {
- bool skipCall = false;
- // Validate Write updates
- uint32_t i = 0;
- for (i = 0; i < descriptorWriteCount; i++) {
- VkDescriptorSet ds = pWDS[i].dstSet;
- cvdescriptorset::DescriptorSet *pSet = my_data->setMap[ds];
- // Set being updated cannot be in-flight
- if ((skipCall = validateIdleDescriptorSet(my_data, ds, "VkUpdateDescriptorSets")) == true)
- return skipCall;
- // If set is bound to any cmdBuffers, mark them invalid
- invalidateBoundCmdBuffers(my_data, pSet);
- GENERIC_HEADER *pUpdate = (GENERIC_HEADER *)&pWDS[i];
- // First verify valid update struct
- if ((skipCall = validUpdateStruct(my_data, device, pUpdate)) == true) {
- break;
- }
- string error_str;
- if (!pSet->WriteUpdate(my_data->report_data, &pWDS[i], &error_str)) {
- skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
- (uint64_t)(ds), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
- "vkUpdateDescriptorsSets() failed write update for Descriptor Set 0x%" PRIx64 " with error: %s",
- reinterpret_cast<uint64_t &>(ds), error_str.c_str());
- }
- }
- // Now validate copy updates
- for (i = 0; i < descriptorCopyCount; ++i) {
- cvdescriptorset::DescriptorSet *pSrcSet = NULL, *pDstSet = NULL;
- // For each copy make sure that update falls within given layout and that types match
- pSrcSet = my_data->setMap[pCDS[i].srcSet];
- pDstSet = my_data->setMap[pCDS[i].dstSet];
- // Set being updated cannot be in-flight
- if ((skipCall = validateIdleDescriptorSet(my_data, pDstSet->GetSet(), "VkUpdateDescriptorSets")) == true)
- return skipCall;
- invalidateBoundCmdBuffers(my_data, pDstSet);
- std::string error_str;
- if (!pDstSet->CopyUpdate(my_data->report_data, &pCDS[i], pSrcSet, &error_str)) {
- skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
- reinterpret_cast<const uint64_t &>(pCDS[i].dstSet), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
- "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64
- " to Descriptor Set 0x%" PRIx64 " with error: %s",
- reinterpret_cast<const uint64_t &>(pCDS[i].srcSet),
- reinterpret_cast<const uint64_t &>(pCDS[i].dstSet), error_str.c_str());
- }
- }
- return skipCall;
-}
-
-// Verify that given pool has descriptors that are being requested for allocation.
-// NOTE : Calls to this function should be wrapped in mutex
-static bool validate_descriptor_availability_in_pool(layer_data *dev_data, DESCRIPTOR_POOL_NODE *pPoolNode, uint32_t count,
- const VkDescriptorSetLayout *pSetLayouts) {
- bool skipCall = false;
- // Track number of descriptorSets allowable in this pool
- if (pPoolNode->availableSets < count) {
- skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
- reinterpret_cast<uint64_t &>(pPoolNode->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
- "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64
- ". This pool only has %d descriptorSets remaining.",
- count, reinterpret_cast<uint64_t &>(pPoolNode->pool), pPoolNode->availableSets);
- } else {
- pPoolNode->availableSets -= count;
- }
-
- for (uint32_t i = 0; i < count; ++i) {
- auto layout_pair = dev_data->descriptorSetLayoutMap.find(pSetLayouts[i]);
- if (layout_pair == dev_data->descriptorSetLayoutMap.end()) {
- skipCall |=
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
- (uint64_t)pSetLayouts[i], __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
- "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
- (uint64_t)pSetLayouts[i]);
- } else {
- auto &layout_node = layout_pair->second;
- for (uint32_t j = 0; j < layout_node->GetBindingCount(); ++j) {
- const auto &binding_layout = layout_node->GetDescriptorSetLayoutBindingPtrFromIndex(j);
- uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType);
- uint32_t poolSizeCount = binding_layout->descriptorCount;
- if (poolSizeCount > pPoolNode->availableDescriptorTypeCount[typeIndex]) {
- skipCall |= log_msg(
- dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
- reinterpret_cast<const uint64_t &>(pSetLayouts[i]), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
- "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64
- ". This pool only has %d descriptors of this type remaining.",
- poolSizeCount, string_VkDescriptorType(binding_layout->descriptorType), (uint64_t)pPoolNode->pool,
- pPoolNode->availableDescriptorTypeCount[typeIndex]);
- } else { // Decrement available descriptors of this type
- pPoolNode->availableDescriptorTypeCount[typeIndex] -= poolSizeCount;
- }
- }
- }
- }
- return skipCall;
-}
-
-// Free the descriptor set, remove it from setMap and invalidate any cmd buffers that it was bound to
+// Remove set from setMap and delete the set
static void freeDescriptorSet(layer_data *dev_data, cvdescriptorset::DescriptorSet *descriptor_set) {
- invalidateBoundCmdBuffers(dev_data, descriptor_set);
dev_data->setMap.erase(descriptor_set->GetSet());
delete descriptor_set;
}
@@ -3540,7 +3524,6 @@ static GLOBAL_CB_NODE *getCBNode(layer_data const *my_data, const VkCommandBuffe
}
return it->second;
}
-
// Free all CB Nodes
// NOTE : Calls to this function should be wrapped in mutex
static void deleteCommandBuffers(layer_data *my_data) {
@@ -3563,7 +3546,8 @@ bool validateCmdsInCmdBuffer(const layer_data *dev_data, const GLOBAL_CB_NODE *p
if (!pCB->activeRenderPass)
return false;
bool skip_call = false;
- if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS && cmd_type != CMD_EXECUTECOMMANDS) {
+ if (pCB->activeSubpassContents == VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS &&
+ (cmd_type != CMD_EXECUTECOMMANDS && cmd_type != CMD_NEXTSUBPASS && cmd_type != CMD_ENDRENDERPASS)) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_COMMAND_BUFFER, "DS",
"Commands cannot be called in a subpass using secondary command buffers.");
@@ -3658,6 +3642,7 @@ static bool addCmd(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYP
case CMD_UPDATEBUFFER:
case CMD_PIPELINEBARRIER:
case CMD_EXECUTECOMMANDS:
+ case CMD_END:
break;
default:
break;
@@ -3665,6 +3650,7 @@ static bool addCmd(const layer_data *my_data, GLOBAL_CB_NODE *pCB, const CMD_TYP
}
if (pCB->state != CB_RECORDING) {
skipCall |= report_error_no_cb_begin(my_data, pCB->commandBuffer, caller_name);
+ } else {
skipCall |= validateCmdsInCmdBuffer(my_data, pCB, cmd);
CMD_NODE cmdNode = {};
// init cmd node and append to end of cmd LL
@@ -3696,10 +3682,7 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
// Before clearing lastBoundState, remove any CB bindings from all uniqueBoundSets
for (auto set : pCB->lastBound[i].uniqueBoundSets) {
- auto set_node = dev_data->setMap.find(set);
- if (set_node != dev_data->setMap.end()) {
- set_node->second->RemoveBoundCommandBuffer(pCB->commandBuffer);
- }
+ set->RemoveBoundCommandBuffer(pCB);
}
pCB->lastBound[i].reset();
}
@@ -3708,14 +3691,12 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
pCB->activeRenderPass = nullptr;
pCB->activeSubpassContents = VK_SUBPASS_CONTENTS_INLINE;
pCB->activeSubpass = 0;
- pCB->lastSubmittedFence = VK_NULL_HANDLE;
- pCB->lastSubmittedQueue = VK_NULL_HANDLE;
pCB->destroyedSets.clear();
pCB->updatedSets.clear();
pCB->destroyedFramebuffers.clear();
pCB->waitedEvents.clear();
- pCB->semaphores.clear();
pCB->events.clear();
+ pCB->writeEventsBeforeWait.clear();
pCB->waitedEventsBeforeQueryReset.clear();
pCB->queryToStateMap.clear();
pCB->activeQueries.clear();
@@ -3735,13 +3716,13 @@ static void resetCB(layer_data *dev_data, const VkCommandBuffer cb) {
pCB->updateBuffers.clear();
clear_cmd_buf_and_mem_references(dev_data, pCB);
pCB->eventUpdates.clear();
+ pCB->queryUpdates.clear();
// Remove this cmdBuffer's reference from each FrameBuffer's CB ref list
for (auto framebuffer : pCB->framebuffers) {
- auto fbNode = dev_data->frameBufferMap.find(framebuffer);
- if (fbNode != dev_data->frameBufferMap.end()) {
- fbNode->second.referencingCmdBuffers.erase(pCB->commandBuffer);
- }
+ auto fbNode = getFramebuffer(dev_data, framebuffer);
+ if (fbNode)
+ fbNode->referencingCmdBuffers.erase(pCB->commandBuffer);
}
pCB->framebuffers.clear();
pCB->activeFramebuffer = VK_NULL_HANDLE;
@@ -4045,7 +4026,7 @@ VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCall
DEVICE_MEM_INFO *pInfo = NULL;
if (!dev_data->memObjMap.empty()) {
for (auto ii = dev_data->memObjMap.begin(); ii != dev_data->memObjMap.end(); ++ii) {
- pInfo = &(*ii).second;
+ pInfo = (*ii).second.get();
if (pInfo->allocInfo.allocationSize != 0) {
// Valid Usage: All child objects created on device must have been destroyed prior to destroying device
skipCall |=
@@ -4079,10 +4060,8 @@ static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT
// This validates that the initial layout specified in the command buffer for
// the IMAGE is the same
// as the global IMAGE layout
-static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) {
+static bool ValidateCmdBufImageLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
bool skip_call = false;
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
- GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
for (auto cb_image_data : pCB->imageLayoutMap) {
VkImageLayout imageLayout;
if (!FindLayout(dev_data, cb_image_data.first, imageLayout)) {
@@ -4097,7 +4076,7 @@ static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) {
if (cb_image_data.first.hasSubresource) {
skip_call |= log_msg(
dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
- reinterpret_cast<uint64_t &>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
+ reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
"Cannot submit cmd buffer using image (0x%" PRIx64 ") [sub-resource: aspectMask 0x%X array layer %u, mip level %u], "
"with layout %s when first use is %s.",
reinterpret_cast<const uint64_t &>(cb_image_data.first.image), cb_image_data.first.subresource.aspectMask,
@@ -4107,7 +4086,7 @@ static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) {
} else {
skip_call |= log_msg(
dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
- reinterpret_cast<uint64_t &>(cmdBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
+ reinterpret_cast<uint64_t &>(pCB->commandBuffer), __LINE__, DRAWSTATE_INVALID_IMAGE_LAYOUT, "DS",
"Cannot submit cmd buffer using image (0x%" PRIx64 ") with layout %s when "
"first use is %s.",
reinterpret_cast<const uint64_t &>(cb_image_data.first.image), string_VkImageLayout(imageLayout),
@@ -4121,34 +4100,33 @@ static bool ValidateCmdBufImageLayouts(VkCommandBuffer cmdBuffer) {
}
// Track which resources are in-flight by atomically incrementing their "in_use" count
-static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *pCB) {
+static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *pCB, std::vector<VkSemaphore> const &semaphores) {
bool skip_call = false;
for (auto drawDataElement : pCB->drawData) {
for (auto buffer : drawDataElement.buffers) {
- auto buffer_data = my_data->bufferMap.find(buffer);
- if (buffer_data == my_data->bufferMap.end()) {
+ auto buffer_node = getBufferNode(my_data, buffer);
+ if (!buffer_node) {
skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
(uint64_t)(buffer), __LINE__, DRAWSTATE_INVALID_BUFFER, "DS",
"Cannot submit cmd buffer using deleted buffer 0x%" PRIx64 ".", (uint64_t)(buffer));
} else {
- buffer_data->second.in_use.fetch_add(1);
+ buffer_node->in_use.fetch_add(1);
}
}
}
for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
for (auto set : pCB->lastBound[i].uniqueBoundSets) {
- auto setNode = my_data->setMap.find(set);
- if (setNode == my_data->setMap.end()) {
+ if (!my_data->setMap.count(set->GetSet())) {
skip_call |=
log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
(uint64_t)(set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
"Cannot submit cmd buffer using deleted descriptor set 0x%" PRIx64 ".", (uint64_t)(set));
} else {
- setNode->second->in_use.fetch_add(1);
+ set->in_use.fetch_add(1);
}
}
}
- for (auto semaphore : pCB->semaphores) {
+ for (auto semaphore : semaphores) {
auto semaphoreNode = my_data->semaphoreMap.find(semaphore);
if (semaphoreNode == my_data->semaphoreMap.end()) {
skip_call |=
@@ -4170,6 +4148,10 @@ static bool validateAndIncrementResources(layer_data *my_data, GLOBAL_CB_NODE *p
eventNode->second.in_use.fetch_add(1);
}
}
+ for (auto event : pCB->writeEventsBeforeWait) {
+ auto eventNode = my_data->eventMap.find(event);
+ eventNode->second.write_in_use++;
+ }
return skip_call;
}
@@ -4203,25 +4185,22 @@ static inline void removeInFlightCmdBuffer(layer_data *dev_data, VkCommandBuffer
}
}
-static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) {
- GLOBAL_CB_NODE *pCB = getCBNode(my_data, cmdBuffer);
+static void decrementResources(layer_data *my_data, CB_SUBMISSION *submission) {
+ GLOBAL_CB_NODE *pCB = getCBNode(my_data, submission->cb);
for (auto drawDataElement : pCB->drawData) {
for (auto buffer : drawDataElement.buffers) {
- auto buffer_data = my_data->bufferMap.find(buffer);
- if (buffer_data != my_data->bufferMap.end()) {
- buffer_data->second.in_use.fetch_sub(1);
+ auto buffer_node = getBufferNode(my_data, buffer);
+ if (buffer_node) {
+ buffer_node->in_use.fetch_sub(1);
}
}
}
for (uint32_t i = 0; i < VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
for (auto set : pCB->lastBound[i].uniqueBoundSets) {
- auto setNode = my_data->setMap.find(set);
- if (setNode != my_data->setMap.end()) {
- setNode->second->in_use.fetch_sub(1);
- }
+ set->in_use.fetch_sub(1);
}
}
- for (auto semaphore : pCB->semaphores) {
+ for (auto semaphore : submission->semaphores) {
auto semaphoreNode = my_data->semaphoreMap.find(semaphore);
if (semaphoreNode != my_data->semaphoreMap.end()) {
semaphoreNode->second.in_use.fetch_sub(1);
@@ -4233,6 +4212,12 @@ static void decrementResources(layer_data *my_data, VkCommandBuffer cmdBuffer) {
eventNode->second.in_use.fetch_sub(1);
}
}
+ for (auto event : pCB->writeEventsBeforeWait) {
+ auto eventNode = my_data->eventMap.find(event);
+ if (eventNode != my_data->eventMap.end()) {
+ eventNode->second.write_in_use--;
+ }
+ }
for (auto queryStatePair : pCB->queryToStateMap) {
my_data->queryToStateMap[queryStatePair.first] = queryStatePair.second;
}
@@ -4256,12 +4241,12 @@ static bool decrementResources(layer_data *my_data, uint32_t fenceCount, const V
}
decrementResources(my_data, static_cast<uint32_t>(fence_data->second.priorFences.size()),
fence_data->second.priorFences.data());
- for (auto cmdBuffer : fence_data->second.cmdBuffers) {
- decrementResources(my_data, cmdBuffer);
- skip_call |= cleanInFlightCmdBuffer(my_data, cmdBuffer);
- removeInFlightCmdBuffer(my_data, cmdBuffer);
+ for (auto & submission : fence_data->second.submissions) {
+ decrementResources(my_data, &submission);
+ skip_call |= cleanInFlightCmdBuffer(my_data, submission.cb);
+ removeInFlightCmdBuffer(my_data, submission.cb);
}
- fence_data->second.cmdBuffers.clear();
+ fence_data->second.submissions.clear();
fence_data->second.priorFences.clear();
}
for (auto fence_pair : fence_pairs) {
@@ -4274,6 +4259,12 @@ static bool decrementResources(layer_data *my_data, uint32_t fenceCount, const V
queue_pair->second.lastFences.erase(last_fence_data);
}
}
+ for (auto& fence_data : my_data->fenceMap) {
+ auto prior_fence_data =
+ std::find(fence_data.second.priorFences.begin(), fence_data.second.priorFences.end(), fence_pair.first);
+ if (prior_fence_data != fence_data.second.priorFences.end())
+ fence_data.second.priorFences.erase(prior_fence_data);
+ }
}
return skip_call;
}
@@ -4282,12 +4273,12 @@ static bool decrementResources(layer_data *my_data, VkQueue queue) {
bool skip_call = false;
auto queue_data = my_data->queueMap.find(queue);
if (queue_data != my_data->queueMap.end()) {
- for (auto cmdBuffer : queue_data->second.untrackedCmdBuffers) {
- decrementResources(my_data, cmdBuffer);
- skip_call |= cleanInFlightCmdBuffer(my_data, cmdBuffer);
- removeInFlightCmdBuffer(my_data, cmdBuffer);
+ for (auto & submission : queue_data->second.untrackedSubmissions) {
+ decrementResources(my_data, &submission);
+ skip_call |= cleanInFlightCmdBuffer(my_data, submission.cb);
+ removeInFlightCmdBuffer(my_data, submission.cb);
}
- queue_data->second.untrackedCmdBuffers.clear();
+ queue_data->second.untrackedSubmissions.clear();
skip_call |= decrementResources(my_data, static_cast<uint32_t>(queue_data->second.lastFences.size()),
queue_data->second.lastFences.data());
}
@@ -4314,24 +4305,33 @@ static void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQ
fence_node->second.queues.insert(other_queue_data->first);
}
}
+ // TODO: Stealing the untracked CBs out of the signaling queue isn't really
+ // correct. A subsequent submission + wait, or a QWI on that queue, or
+ // another semaphore dependency to a third queue may /all/ provide
+ // suitable proof that the work we're stealing here has completed on the
+ // device, but we've lost that information by moving the tracking between
+ // queues.
if (fence != VK_NULL_HANDLE) {
auto fence_data = dev_data->fenceMap.find(fence);
if (fence_data == dev_data->fenceMap.end()) {
return;
}
- for (auto cmdbuffer : other_queue_data->second.untrackedCmdBuffers) {
- fence_data->second.cmdBuffers.push_back(cmdbuffer);
+ for (auto cmdbuffer : other_queue_data->second.untrackedSubmissions) {
+ fence_data->second.submissions.push_back(cmdbuffer);
}
- other_queue_data->second.untrackedCmdBuffers.clear();
+ other_queue_data->second.untrackedSubmissions.clear();
} else {
- for (auto cmdbuffer : other_queue_data->second.untrackedCmdBuffers) {
- queue_data->second.untrackedCmdBuffers.push_back(cmdbuffer);
+ for (auto cmdbuffer : other_queue_data->second.untrackedSubmissions) {
+ queue_data->second.untrackedSubmissions.push_back(cmdbuffer);
}
- other_queue_data->second.untrackedCmdBuffers.clear();
+ other_queue_data->second.untrackedSubmissions.clear();
}
for (auto eventStagePair : other_queue_data->second.eventToStageMap) {
queue_data->second.eventToStageMap[eventStagePair.first] = eventStagePair.second;
}
+ for (auto queryStatePair : other_queue_data->second.queryToStateMap) {
+ queue_data->second.queryToStateMap[queryStatePair.first] = queryStatePair.second;
+ }
}
// This is the core function for tracking command buffers. There are two primary ways command
@@ -4342,51 +4342,24 @@ static void updateTrackedCommandBuffers(layer_data *dev_data, VkQueue queue, VkQ
// waited on, prior fences on that queue are also considered to have been waited on. When a fence is
// waited on (either via a queue, device or fence), we free the cmd buffers for that fence and
// recursively call with the prior fences.
-static void trackCommandBuffers(layer_data *my_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
- VkFence fence) {
- auto queue_data = my_data->queueMap.find(queue);
- if (fence != VK_NULL_HANDLE) {
- vector<VkFence> prior_fences;
- auto fence_data = my_data->fenceMap.find(fence);
- if (fence_data == my_data->fenceMap.end()) {
- return;
- }
- fence_data->second.cmdBuffers.clear();
- if (queue_data != my_data->queueMap.end()) {
- prior_fences = queue_data->second.lastFences;
- queue_data->second.lastFences.clear();
- queue_data->second.lastFences.push_back(fence);
- for (auto cmdbuffer : queue_data->second.untrackedCmdBuffers) {
- fence_data->second.cmdBuffers.push_back(cmdbuffer);
- }
- queue_data->second.untrackedCmdBuffers.clear();
- }
- fence_data->second.priorFences = prior_fences;
- fence_data->second.needsSignaled = true;
- fence_data->second.queues.insert(queue);
- fence_data->second.in_use.fetch_add(1);
- for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
- const VkSubmitInfo *submit = &pSubmits[submit_idx];
- for (uint32_t i = 0; i < submit->commandBufferCount; ++i) {
- for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) {
- fence_data->second.cmdBuffers.push_back(secondaryCmdBuffer);
- }
- fence_data->second.cmdBuffers.push_back(submit->pCommandBuffers[i]);
- }
- }
- } else {
- if (queue_data != my_data->queueMap.end()) {
- for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
- const VkSubmitInfo *submit = &pSubmits[submit_idx];
- for (uint32_t i = 0; i < submit->commandBufferCount; ++i) {
- for (auto secondaryCmdBuffer : my_data->commandBufferMap[submit->pCommandBuffers[i]]->secondaryCommandBuffers) {
- queue_data->second.untrackedCmdBuffers.push_back(secondaryCmdBuffer);
- }
- queue_data->second.untrackedCmdBuffers.push_back(submit->pCommandBuffers[i]);
- }
- }
- }
- }
+
+
+// Submit a fence to a queue, delimiting previous fences and previous untracked
+// work by it.
+static void
+SubmitFence(QUEUE_NODE *pQueue, FENCE_NODE *pFence)
+{
+ assert(!pFence->priorFences.size());
+ assert(!pFence->submissions.size());
+
+ std::swap(pFence->priorFences, pQueue->lastFences);
+ std::swap(pFence->submissions, pQueue->untrackedSubmissions);
+
+ pFence->queues.insert(pQueue->queue);
+ pFence->needsSignaled = true;
+ pFence->in_use.fetch_add(1);
+
+ pQueue->lastFences.push_back(pFence->fence);
}
static void markCommandBuffersInFlight(layer_data *my_data, VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
@@ -4501,12 +4474,12 @@ static bool validateCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB
return skipCall;
}
-static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB) {
+static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NODE *pCB, std::vector<VkSemaphore> const &semaphores) {
// Track in-use for resources off of primary and any secondary CBs
- bool skipCall = validateAndIncrementResources(dev_data, pCB);
+ bool skipCall = validateAndIncrementResources(dev_data, pCB, semaphores);
if (!pCB->secondaryCommandBuffers.empty()) {
for (auto secondaryCmdBuffer : pCB->secondaryCommandBuffers) {
- skipCall |= validateAndIncrementResources(dev_data, dev_data->commandBufferMap[secondaryCmdBuffer]);
+ skipCall |= validateAndIncrementResources(dev_data, dev_data->commandBufferMap[secondaryCmdBuffer], semaphores);
GLOBAL_CB_NODE *pSubCB = getCBNode(dev_data, secondaryCmdBuffer);
if ((pSubCB->primaryCommandBuffer != pCB->commandBuffer) &&
!(pSubCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT)) {
@@ -4528,32 +4501,60 @@ static bool validatePrimaryCommandBufferState(layer_data *dev_data, GLOBAL_CB_NO
return skipCall;
}
-VKAPI_ATTR VkResult VKAPI_CALL
-QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
+static bool
+ValidateFenceForSubmit(layer_data *dev_data, FENCE_NODE *pFence)
+{
bool skipCall = false;
- GLOBAL_CB_NODE *pCBNode = NULL;
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
- VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- std::unique_lock<std::mutex> lock(global_lock);
- // First verify that fence is not in use
- if (fence != VK_NULL_HANDLE) {
- if ((submitCount != 0) && dev_data->fenceMap[fence].in_use.load()) {
+
+ if (pFence) {
+ if (pFence->in_use.load()) {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
- (uint64_t)(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
- "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(fence));
+ (uint64_t)(pFence->fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
+ "Fence 0x%" PRIx64 " is already in use by another submission.", (uint64_t)(pFence->fence));
}
- if (!dev_data->fenceMap[fence].needsSignaled) {
+
+ if (!pFence->needsSignaled) {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
- reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
+ reinterpret_cast<uint64_t &>(pFence->fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
"Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted",
- reinterpret_cast<uint64_t &>(fence));
+ reinterpret_cast<uint64_t &>(pFence->fence));
}
}
+
+ return skipCall;
+}
+
+
+VKAPI_ATTR VkResult VKAPI_CALL
+QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
+ bool skipCall = false;
+ layer_data *dev_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
+ VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+ std::unique_lock<std::mutex> lock(global_lock);
+
+ auto pQueue = getQueueNode(dev_data, queue);
+ auto pFence = getFenceNode(dev_data, fence);
+ skipCall |= ValidateFenceForSubmit(dev_data, pFence);
+
+ if (skipCall) {
+ return VK_ERROR_VALIDATION_FAILED_EXT;
+ }
+
// TODO : Review these old print functions and clean up as appropriate
print_mem_list(dev_data);
printCBList(dev_data);
- // Update cmdBuffer-related data structs and mark fence in-use
- trackCommandBuffers(dev_data, queue, submitCount, pSubmits, fence);
+
+ // Mark the fence in-use.
+ if (pFence) {
+ SubmitFence(pQueue, pFence);
+ }
+
+ // If a fence is supplied, all the command buffers for this call will be
+ // delimited by that fence. Otherwise, they go in the untracked portion of
+ // the queue, and may end up being delimited by a fence supplied in a
+ // subsequent submission.
+ auto & submitTarget = pFence ? pFence->submissions : pQueue->untrackedSubmissions;
+
// Now verify each individual submit
std::unordered_set<VkQueue> processed_other_queues;
for (uint32_t submit_idx = 0; submit_idx < submitCount; submit_idx++) {
@@ -4597,15 +4598,20 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V
}
}
}
+
+ // TODO: just add one submission per VkSubmitInfo!
for (uint32_t i = 0; i < submit->commandBufferCount; i++) {
- skipCall |= ValidateCmdBufImageLayouts(submit->pCommandBuffers[i]);
- pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]);
+ auto pCBNode = getCBNode(dev_data, submit->pCommandBuffers[i]);
+ skipCall |= ValidateCmdBufImageLayouts(dev_data, pCBNode);
if (pCBNode) {
- pCBNode->semaphores = semaphoreList;
+
+ submitTarget.emplace_back(pCBNode->commandBuffer, semaphoreList);
+ for (auto secondaryCmdBuffer : pCBNode->secondaryCommandBuffers) {
+ submitTarget.emplace_back(secondaryCmdBuffer, semaphoreList);
+ }
+
pCBNode->submitCount++; // increment submit count
- pCBNode->lastSubmittedFence = fence;
- pCBNode->lastSubmittedQueue = queue;
- skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode);
+ skipCall |= validatePrimaryCommandBufferState(dev_data, pCBNode, semaphoreList);
// Call submit-time functions to validate/update state
for (auto &function : pCBNode->validate_functions) {
skipCall |= function();
@@ -4613,6 +4619,9 @@ QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, V
for (auto &function : pCBNode->eventUpdates) {
skipCall |= function(queue);
}
+ for (auto &function : pCBNode->queryUpdates) {
+ skipCall |= function(queue);
+ }
}
}
}
@@ -4665,8 +4674,9 @@ static bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSi
auto mem_element = my_data->memObjMap.find(mem);
if (mem_element != my_data->memObjMap.end()) {
+ auto mem_info = mem_element->second.get();
// It is an application error to call VkMapMemory on an object that is already mapped
- if (mem_element->second.memRange.size != 0) {
+ if (mem_info->memRange.size != 0) {
skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
(uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
"VkMapMemory: Attempting to map memory on an already-mapped object 0x%" PRIxLEAST64, (uint64_t)mem);
@@ -4674,18 +4684,20 @@ static bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSi
// Validate that offset + size is within object's allocationSize
if (size == VK_WHOLE_SIZE) {
- if (offset >= mem_element->second.allocInfo.allocationSize) {
+ if (offset >= mem_info->allocInfo.allocationSize) {
skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP,
- "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64, offset,
- mem_element->second.allocInfo.allocationSize, mem_element->second.allocInfo.allocationSize);
+ "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64
+ " with size of VK_WHOLE_SIZE oversteps total array size 0x%" PRIx64,
+ offset, mem_info->allocInfo.allocationSize, mem_info->allocInfo.allocationSize);
}
} else {
- if ((offset + size) > mem_element->second.allocInfo.allocationSize) {
- skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP,
- "MEM", "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64, offset,
- size + offset, mem_element->second.allocInfo.allocationSize);
+ if ((offset + size) > mem_info->allocInfo.allocationSize) {
+ skipCall =
+ log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
+ (uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
+ "Mapping Memory from 0x%" PRIx64 " to 0x%" PRIx64 " oversteps total array size 0x%" PRIx64, offset,
+ size + offset, mem_info->allocInfo.allocationSize);
}
}
}
@@ -4693,29 +4705,27 @@ static bool validateMemRange(layer_data *my_data, VkDeviceMemory mem, VkDeviceSi
}
static void storeMemRanges(layer_data *my_data, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size) {
- auto mem_element = my_data->memObjMap.find(mem);
- if (mem_element != my_data->memObjMap.end()) {
- MemRange new_range;
- new_range.offset = offset;
- new_range.size = size;
- mem_element->second.memRange = new_range;
+ auto mem_info = getMemObjInfo(my_data, mem);
+ if (mem_info) {
+ mem_info->memRange.offset = offset;
+ mem_info->memRange.size = size;
}
}
static bool deleteMemRanges(layer_data *my_data, VkDeviceMemory mem) {
bool skipCall = false;
- auto mem_element = my_data->memObjMap.find(mem);
- if (mem_element != my_data->memObjMap.end()) {
- if (!mem_element->second.memRange.size) {
+ auto mem_info = getMemObjInfo(my_data, mem);
+ if (mem_info) {
+ if (!mem_info->memRange.size) {
// Valid Usage: memory must currently be mapped
skipCall = log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
(uint64_t)mem, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
"Unmapping Memory without memory being mapped: mem obj 0x%" PRIxLEAST64, (uint64_t)mem);
}
- mem_element->second.memRange.size = 0;
- if (mem_element->second.pData) {
- free(mem_element->second.pData);
- mem_element->second.pData = 0;
+ mem_info->memRange.size = 0;
+ if (mem_info->pData) {
+ free(mem_info->pData);
+ mem_info->pData = 0;
}
}
return skipCall;
@@ -4724,20 +4734,20 @@ static bool deleteMemRanges(layer_data *my_data, VkDeviceMemory mem) {
static char NoncoherentMemoryFillValue = 0xb;
static void initializeAndTrackMemory(layer_data *dev_data, VkDeviceMemory mem, VkDeviceSize size, void **ppData) {
- auto mem_element = dev_data->memObjMap.find(mem);
- if (mem_element != dev_data->memObjMap.end()) {
- mem_element->second.pDriverData = *ppData;
- uint32_t index = mem_element->second.allocInfo.memoryTypeIndex;
+ auto mem_info = getMemObjInfo(dev_data, mem);
+ if (mem_info) {
+ mem_info->pDriverData = *ppData;
+ uint32_t index = mem_info->allocInfo.memoryTypeIndex;
if (dev_data->phys_dev_mem_props.memoryTypes[index].propertyFlags & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
- mem_element->second.pData = 0;
+ mem_info->pData = 0;
} else {
if (size == VK_WHOLE_SIZE) {
- size = mem_element->second.allocInfo.allocationSize;
+ size = mem_info->allocInfo.allocationSize;
}
size_t convSize = (size_t)(size);
- mem_element->second.pData = malloc(2 * convSize);
- memset(mem_element->second.pData, NoncoherentMemoryFillValue, 2 * convSize);
- *ppData = static_cast<char *>(mem_element->second.pData) + (convSize / 2);
+ mem_info->pData = malloc(2 * convSize);
+ memset(mem_info->pData, NoncoherentMemoryFillValue, 2 * convSize);
+ *ppData = static_cast<char *>(mem_info->pData) + (convSize / 2);
}
}
}
@@ -4834,6 +4844,7 @@ VKAPI_ATTR void VKAPI_CALL GetDeviceQueue(VkDevice device, uint32_t queueFamilyI
auto result = dev_data->queues.emplace(*pQueue);
if (result.second == true) {
QUEUE_NODE *pQNode = &dev_data->queueMap[*pQueue];
+ pQNode->queue = *pQueue;
pQNode->device = device;
}
}
@@ -4931,10 +4942,9 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool
VkQueryResultFlags flags) {
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
unordered_map<QueryObject, vector<VkCommandBuffer>> queriesInFlight;
- GLOBAL_CB_NODE *pCB = nullptr;
std::unique_lock<std::mutex> lock(global_lock);
for (auto cmdBuffer : dev_data->globalInFlightCmdBuffers) {
- pCB = getCBNode(dev_data, cmdBuffer);
+ auto pCB = getCBNode(dev_data, cmdBuffer);
for (auto queryStatePair : pCB->queryToStateMap) {
queriesInFlight[queryStatePair.first].push_back(cmdBuffer);
}
@@ -4949,7 +4959,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool
if (queryElement != queriesInFlight.end() && queryToStateElement != dev_data->queryToStateMap.end() &&
queryToStateElement->second) {
for (auto cmdBuffer : queryElement->second) {
- pCB = getCBNode(dev_data, cmdBuffer);
+ auto pCB = getCBNode(dev_data, cmdBuffer);
auto queryEventElement = pCB->waitedEventsBeforeQueryReset.find(query);
if (queryEventElement == pCB->waitedEventsBeforeQueryReset.end()) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
@@ -4968,7 +4978,7 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool
// TODO : Can there be the same query in use by multiple command buffers in flight?
bool make_available = false;
for (auto cmdBuffer : queryElement->second) {
- pCB = getCBNode(dev_data, cmdBuffer);
+ auto pCB = getCBNode(dev_data, cmdBuffer);
make_available |= pCB->queryToStateMap[query];
}
if (!(((flags & VK_QUERY_RESULT_PARTIAL_BIT) || (flags & VK_QUERY_RESULT_WAIT_BIT)) && make_available)) {
@@ -5002,13 +5012,13 @@ VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool
static bool validateIdleBuffer(const layer_data *my_data, VkBuffer buffer) {
bool skip_call = false;
- auto buffer_data = my_data->bufferMap.find(buffer);
- if (buffer_data == my_data->bufferMap.end()) {
+ auto buffer_node = getBufferNode(my_data, buffer);
+ if (!buffer_node) {
skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
(uint64_t)(buffer), __LINE__, DRAWSTATE_DOUBLE_DESTROY, "DS",
"Cannot free buffer 0x%" PRIxLEAST64 " that has not been allocated.", (uint64_t)(buffer));
} else {
- if (buffer_data->second.in_use.load()) {
+ if (buffer_node->in_use.load()) {
skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT,
(uint64_t)(buffer), __LINE__, DRAWSTATE_OBJECT_INUSE, "DS",
"Cannot free buffer 0x%" PRIxLEAST64 " that is in use by a command buffer.", (uint64_t)(buffer));
@@ -5077,14 +5087,14 @@ VKAPI_ATTR void VKAPI_CALL DestroyBuffer(VkDevice device, VkBuffer buffer,
lock.lock();
}
// Clean up memory binding and range information for buffer
- const auto &bufferEntry = dev_data->bufferMap.find(buffer);
- if (bufferEntry != dev_data->bufferMap.end()) {
- const auto &memEntry = dev_data->memObjMap.find(bufferEntry->second.mem);
- if (memEntry != dev_data->memObjMap.end()) {
- remove_memory_ranges(reinterpret_cast<uint64_t &>(buffer), bufferEntry->second.mem, memEntry->second.bufferRanges);
+ auto buff_it = dev_data->bufferMap.find(buffer);
+ if (buff_it != dev_data->bufferMap.end()) {
+ auto mem_info = getMemObjInfo(dev_data, buff_it->second.get()->mem);
+ if (mem_info) {
+ remove_memory_ranges(reinterpret_cast<uint64_t &>(buffer), buff_it->second.get()->mem, mem_info->bufferRanges);
}
clear_object_binding(dev_data, reinterpret_cast<uint64_t &>(buffer), VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
- dev_data->bufferMap.erase(bufferEntry);
+ dev_data->bufferMap.erase(buff_it);
}
}
@@ -5110,11 +5120,11 @@ VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const Vk
const auto &imageEntry = dev_data->imageMap.find(image);
if (imageEntry != dev_data->imageMap.end()) {
// Clean up memory mapping, bindings and range references for image
- auto memEntry = dev_data->memObjMap.find(imageEntry->second.mem);
- if (memEntry != dev_data->memObjMap.end()) {
- remove_memory_ranges(reinterpret_cast<uint64_t &>(image), imageEntry->second.mem, memEntry->second.imageRanges);
+ auto mem_info = getMemObjInfo(dev_data, imageEntry->second.get()->mem);
+ if (mem_info) {
+ remove_memory_ranges(reinterpret_cast<uint64_t &>(image), imageEntry->second.get()->mem, mem_info->imageRanges);
clear_object_binding(dev_data, reinterpret_cast<uint64_t &>(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
- memEntry->second.image = VK_NULL_HANDLE;
+ mem_info->image = VK_NULL_HANDLE;
}
// Remove image from imageMap
dev_data->imageMap.erase(imageEntry);
@@ -5128,6 +5138,20 @@ VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const Vk
}
}
+static bool ValidateMemoryTypes(const layer_data *dev_data, const DEVICE_MEM_INFO *mem_info, const uint32_t memory_type_bits,
+ const char *funcName) {
+ bool skip_call = false;
+ if (((1 << mem_info->allocInfo.memoryTypeIndex) & memory_type_bits) == 0) {
+ skip_call = log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
+ reinterpret_cast<const uint64_t &>(mem_info->mem), __LINE__, MEMTRACK_INVALID_MEM_TYPE, "MT",
+ "%s(): MemoryRequirements->memoryTypeBits (0x%X) for this object type are not compatible with the memory "
+ "type (0x%X) of this memory object 0x%" PRIx64 ".",
+ funcName, memory_type_bits, mem_info->allocInfo.memoryTypeIndex,
+ reinterpret_cast<const uint64_t &>(mem_info->mem));
+ }
+ return skip_call;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL
BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -5137,19 +5161,19 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS
uint64_t buffer_handle = (uint64_t)(buffer);
bool skipCall =
set_mem_binding(dev_data, mem, buffer_handle, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, "vkBindBufferMemory");
- auto buffer_node = dev_data->bufferMap.find(buffer);
- if (buffer_node != dev_data->bufferMap.end()) {
- buffer_node->second.mem = mem;
+ auto buffer_node = getBufferNode(dev_data, buffer);
+ if (buffer_node) {
+ buffer_node->mem = mem;
VkMemoryRequirements memRequirements;
dev_data->device_dispatch_table->GetBufferMemoryRequirements(device, buffer, &memRequirements);
// Track and validate bound memory range information
- const auto &memEntry = dev_data->memObjMap.find(mem);
- if (memEntry != dev_data->memObjMap.end()) {
+ auto mem_info = getMemObjInfo(dev_data, mem);
+ if (mem_info) {
const MEMORY_RANGE range =
- insert_memory_ranges(buffer_handle, mem, memoryOffset, memRequirements, memEntry->second.bufferRanges);
- skipCall |=
- validate_memory_range(dev_data, memEntry->second.imageRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
+ insert_memory_ranges(buffer_handle, mem, memoryOffset, memRequirements, mem_info->bufferRanges);
+ skipCall |= validate_memory_range(dev_data, mem_info->imageRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT);
+ skipCall |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "BindBufferMemory");
}
// Validate memory requirements alignment
@@ -5163,7 +5187,7 @@ BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceS
memoryOffset, memRequirements.alignment);
}
// Validate device limits alignments
- VkBufferUsageFlags usage = dev_data->bufferMap[buffer].createInfo.usage;
+ VkBufferUsageFlags usage = dev_data->bufferMap[buffer].get()->createInfo.usage;
if (usage & (VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
if (vk_safe_modulo(memoryOffset, dev_data->phys_dev_properties.properties.limits.minTexelBufferOffsetAlignment) != 0) {
skipCall |=
@@ -5369,15 +5393,13 @@ DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocatio
// Verify that command buffers in pool are complete (not in-flight)
VkBool32 result = checkAndClearCommandBuffersInFlight(dev_data, commandPool, "destroy command pool with");
// Must remove cmdpool from cmdpoolmap, after removing all cmdbuffers in its list from the commandPoolMap
- if (dev_data->commandPoolMap.find(commandPool) != dev_data->commandPoolMap.end()) {
- for (auto poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.begin();
- poolCb != dev_data->commandPoolMap[commandPool].commandBuffers.end();) {
- clear_cmd_buf_and_mem_references(dev_data, *poolCb);
- auto del_cb = dev_data->commandBufferMap.find(*poolCb);
- delete (*del_cb).second; // delete CB info structure
+ auto pool_it = dev_data->commandPoolMap.find(commandPool);
+ if (pool_it != dev_data->commandPoolMap.end()) {
+ for (auto cb : pool_it->second.commandBuffers) {
+ clear_cmd_buf_and_mem_references(dev_data, cb);
+ auto del_cb = dev_data->commandBufferMap.find(cb);
+ delete del_cb->second; // delete CB info structure
dev_data->commandBufferMap.erase(del_cb); // Remove this command buffer
- poolCb = dev_data->commandPoolMap[commandPool].commandBuffers.erase(
- poolCb); // Remove CB reference from commandPoolMap's list
}
}
dev_data->commandPoolMap.erase(commandPool);
@@ -5425,6 +5447,7 @@ VKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount,
if (fence_item != dev_data->fenceMap.end()) {
fence_item->second.needsSignaled = true;
fence_item->second.queues.clear();
+ fence_item->second.priorFences.clear();
if (fence_item->second.in_use.load()) {
skipCall |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
@@ -5477,7 +5500,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateBuffer(VkDevice device, const VkBufferCreat
if (VK_SUCCESS == result) {
std::lock_guard<std::mutex> lock(global_lock);
// TODO : This doesn't create deep copy of pQueueFamilyIndices so need to fix that if/when we want that data to be valid
- dev_data->bufferMap.insert(std::make_pair(*pBuffer, BUFFER_NODE(pCreateInfo)));
+ dev_data->bufferMap.insert(std::make_pair(*pBuffer, unique_ptr<BUFFER_NODE>(new BUFFER_NODE(pCreateInfo))));
}
return result;
}
@@ -5488,7 +5511,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferV
VkResult result = dev_data->device_dispatch_table->CreateBufferView(device, pCreateInfo, pAllocator, pView);
if (VK_SUCCESS == result) {
std::lock_guard<std::mutex> lock(global_lock);
- dev_data->bufferViewMap[*pView] = VkBufferViewCreateInfo(*pCreateInfo);
+ dev_data->bufferViewMap[*pView] = unique_ptr<VkBufferViewCreateInfo>(new VkBufferViewCreateInfo(*pCreateInfo));
// In order to create a valid buffer view, the buffer must have been created with at least one of the
// following flags: UNIFORM_TEXEL_BUFFER_BIT or STORAGE_TEXEL_BUFFER_BIT
validate_buffer_usage_flags(dev_data, pCreateInfo->buffer,
@@ -5509,7 +5532,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateI
IMAGE_LAYOUT_NODE image_node;
image_node.layout = pCreateInfo->initialLayout;
image_node.format = pCreateInfo->format;
- dev_data->imageMap.insert(std::make_pair(*pImage, IMAGE_NODE(pCreateInfo)));
+ dev_data->imageMap.insert(std::make_pair(*pImage, unique_ptr<IMAGE_NODE>(new IMAGE_NODE(pCreateInfo))));
ImageSubresourcePair subpair = {*pImage, false, VkImageSubresource()};
dev_data->imageSubresourceMap[*pImage].push_back(subpair);
dev_data->imageLayoutMap[subpair] = image_node;
@@ -5520,18 +5543,18 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateI
static void ResolveRemainingLevelsLayers(layer_data *dev_data, VkImageSubresourceRange *range, VkImage image) {
/* expects global_lock to be held by caller */
- auto image_node_it = dev_data->imageMap.find(image);
- if (image_node_it != dev_data->imageMap.end()) {
+ auto image_node = getImageNode(dev_data, image);
+ if (image_node) {
/* If the caller used the special values VK_REMAINING_MIP_LEVELS and
* VK_REMAINING_ARRAY_LAYERS, resolve them now in our internal state to
* the actual values.
*/
if (range->levelCount == VK_REMAINING_MIP_LEVELS) {
- range->levelCount = image_node_it->second.createInfo.mipLevels - range->baseMipLevel;
+ range->levelCount = image_node->createInfo.mipLevels - range->baseMipLevel;
}
if (range->layerCount == VK_REMAINING_ARRAY_LAYERS) {
- range->layerCount = image_node_it->second.createInfo.arrayLayers - range->baseArrayLayer;
+ range->layerCount = image_node->createInfo.arrayLayers - range->baseArrayLayer;
}
}
}
@@ -5544,13 +5567,13 @@ static void ResolveRemainingLevelsLayers(layer_data *dev_data, uint32_t *levels,
*levels = range.levelCount;
*layers = range.layerCount;
- auto image_node_it = dev_data->imageMap.find(image);
- if (image_node_it != dev_data->imageMap.end()) {
+ auto image_node = getImageNode(dev_data, image);
+ if (image_node) {
if (range.levelCount == VK_REMAINING_MIP_LEVELS) {
- *levels = image_node_it->second.createInfo.mipLevels - range.baseMipLevel;
+ *levels = image_node->createInfo.mipLevels - range.baseMipLevel;
}
if (range.layerCount == VK_REMAINING_ARRAY_LAYERS) {
- *layers = image_node_it->second.createInfo.arrayLayers - range.baseArrayLayer;
+ *layers = image_node->createInfo.arrayLayers - range.baseArrayLayer;
}
}
}
@@ -5575,9 +5598,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageVie
if (VK_SUCCESS == result) {
std::lock_guard<std::mutex> lock(global_lock);
- VkImageViewCreateInfo localCI = VkImageViewCreateInfo(*pCreateInfo);
- ResolveRemainingLevelsLayers(dev_data, &localCI.subresourceRange, pCreateInfo->image);
- dev_data->imageViewMap[*pView] = localCI;
+ dev_data->imageViewMap[*pView] = unique_ptr<VkImageViewCreateInfo>(new VkImageViewCreateInfo(*pCreateInfo));
+ ResolveRemainingLevelsLayers(dev_data, &dev_data->imageViewMap[*pView].get()->subresourceRange, pCreateInfo->image);
}
return result;
@@ -5590,6 +5612,7 @@ CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAlloc
if (VK_SUCCESS == result) {
std::lock_guard<std::mutex> lock(global_lock);
auto &fence_node = dev_data->fenceMap[*pFence];
+ fence_node.fence = *pFence;
fence_node.createInfo = *pCreateInfo;
fence_node.needsSignaled = true;
if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) {
@@ -5671,16 +5694,8 @@ CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t
for (i = 0; i < count; i++) {
pPipeNode[i] = new PIPELINE_NODE;
pPipeNode[i]->initGraphicsPipeline(&pCreateInfos[i]);
-
- auto renderpass_it = dev_data->renderPassMap.find(pCreateInfos[i].renderPass);
- if (renderpass_it != dev_data->renderPassMap.end()) {
- pPipeNode[i]->renderPass = renderpass_it->second;
- }
-
- auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(pCreateInfos[i].layout);
- if (pipeline_layout_it != dev_data->pipelineLayoutMap.end()) {
- pPipeNode[i]->pipelineLayout = &pipeline_layout_it->second;
- }
+ pPipeNode[i]->renderPass = getRenderPass(dev_data, pCreateInfos[i].renderPass);
+ pPipeNode[i]->pipelineLayout = getPipelineLayout(dev_data, pCreateInfos[i].layout);
skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode, i);
}
@@ -5724,14 +5739,13 @@ CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t
// Create and initialize internal tracking data structure
pPipeNode[i] = new PIPELINE_NODE;
pPipeNode[i]->initComputePipeline(&pCreateInfos[i]);
-
- auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(pCreateInfos[i].layout);
- if (pipeline_layout_it != dev_data->pipelineLayoutMap.end()) {
- pPipeNode[i]->pipelineLayout = &pipeline_layout_it->second;
- }
+ pPipeNode[i]->pipelineLayout = getPipelineLayout(dev_data, pCreateInfos[i].layout);
// memcpy(&pPipeNode[i]->computePipelineCI, (const void *)&pCreateInfos[i], sizeof(VkComputePipelineCreateInfo));
// TODO: Add Compute Pipeline Verification
+ skipCall |= !validate_compute_pipeline(dev_data->report_data, pPipeNode[i],
+ &dev_data->phys_dev_properties.features,
+ dev_data->shaderModuleMap);
// skipCall |= verifyPipelineCreateState(dev_data, device, pPipeNode[i]);
}
@@ -5891,13 +5905,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineLayout(VkDevice device, const VkPip
plNode.setLayouts.resize(pCreateInfo->setLayoutCount);
for (i = 0; i < pCreateInfo->setLayoutCount; ++i) {
plNode.descriptorSetLayouts[i] = pCreateInfo->pSetLayouts[i];
- auto set_layout_it = dev_data->descriptorSetLayoutMap.find(pCreateInfo->pSetLayouts[i]);
- if (set_layout_it != dev_data->descriptorSetLayoutMap.end()) {
- plNode.setLayouts[i] = set_layout_it->second;
- }
- else {
- plNode.setLayouts[i] = nullptr;
- }
+ plNode.setLayouts[i] = getDescriptorSetLayout(dev_data, pCreateInfo->pSetLayouts[i]);
}
plNode.pushConstantRanges.resize(pCreateInfo->pushConstantRangeCount);
for (i = 0; i < pCreateInfo->pushConstantRangeCount; ++i) {
@@ -5944,133 +5952,140 @@ ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescript
}
return result;
}
+// Ensure the pool contains enough descriptors and descriptor sets to satisfy
+// an allocation request. Fills common_data with the total number of descriptors of each type required,
+// as well as DescriptorSetLayout ptrs used for later update.
+static bool PreCallValidateAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
+ cvdescriptorset::AllocateDescriptorSetsData *common_data) {
+ // All state checks for AllocateDescriptorSets is done in single function
+ return cvdescriptorset::ValidateAllocateDescriptorSets(dev_data->report_data, pAllocateInfo, dev_data, common_data);
+}
+// Allocation state was good and call down chain was made so update state based on allocating descriptor sets
+static void PostCallRecordAllocateDescriptorSets(layer_data *dev_data, const VkDescriptorSetAllocateInfo *pAllocateInfo,
+ VkDescriptorSet *pDescriptorSets,
+ const cvdescriptorset::AllocateDescriptorSetsData *common_data) {
+ // All the updates are contained in a single cvdescriptorset function
+ cvdescriptorset::PerformAllocateDescriptorSets(pAllocateInfo, pDescriptorSets, common_data, &dev_data->descriptorPoolMap,
+ &dev_data->setMap, dev_data);
+}
VKAPI_ATTR VkResult VKAPI_CALL
AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
- bool skipCall = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
-
std::unique_lock<std::mutex> lock(global_lock);
- // Verify that requested descriptorSets are available in pool
- DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool);
- if (!pPoolNode) {
- skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
- (uint64_t)pAllocateInfo->descriptorPool, __LINE__, DRAWSTATE_INVALID_POOL, "DS",
- "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
- (uint64_t)pAllocateInfo->descriptorPool);
- } else { // Make sure pool has all the available descriptors before calling down chain
- skipCall |= validate_descriptor_availability_in_pool(dev_data, pPoolNode, pAllocateInfo->descriptorSetCount,
- pAllocateInfo->pSetLayouts);
- }
+ cvdescriptorset::AllocateDescriptorSetsData common_data(pAllocateInfo->descriptorSetCount);
+ bool skip_call = PreCallValidateAllocateDescriptorSets(dev_data, pAllocateInfo, &common_data);
lock.unlock();
- if (skipCall)
+
+ if (skip_call)
return VK_ERROR_VALIDATION_FAILED_EXT;
+
VkResult result = dev_data->device_dispatch_table->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
+
if (VK_SUCCESS == result) {
lock.lock();
- DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, pAllocateInfo->descriptorPool);
- if (pPoolNode) {
- if (pAllocateInfo->descriptorSetCount == 0) {
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
- pAllocateInfo->descriptorSetCount, __LINE__, DRAWSTATE_NONE, "DS",
- "AllocateDescriptorSets called with 0 count");
- }
- for (uint32_t i = 0; i < pAllocateInfo->descriptorSetCount; i++) {
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
- (uint64_t)pDescriptorSets[i], __LINE__, DRAWSTATE_NONE, "DS", "Created Descriptor Set 0x%" PRIxLEAST64,
- (uint64_t)pDescriptorSets[i]);
- auto layout_pair = dev_data->descriptorSetLayoutMap.find(pAllocateInfo->pSetLayouts[i]);
- if (layout_pair == dev_data->descriptorSetLayoutMap.end()) {
- if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, (uint64_t)pAllocateInfo->pSetLayouts[i],
- __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS", "Unable to find set layout node for layout 0x%" PRIxLEAST64
- " specified in vkAllocateDescriptorSets() call",
- (uint64_t)pAllocateInfo->pSetLayouts[i])) {
- lock.unlock();
- return VK_ERROR_VALIDATION_FAILED_EXT;
- }
- }
- // Create new DescriptorSet instance and add to the pool's unordered_set of DescriptorSets
- cvdescriptorset::DescriptorSet *pNewNode = new cvdescriptorset::DescriptorSet(
- pDescriptorSets[i], layout_pair->second, &dev_data->bufferMap, &dev_data->memObjMap, &dev_data->bufferViewMap,
- &dev_data->samplerMap, &dev_data->imageViewMap, &dev_data->imageMap,
- &dev_data->device_extensions.imageToSwapchainMap, &dev_data->device_extensions.swapchainMap);
- if (NULL == pNewNode) {
- if (log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
- DRAWSTATE_OUT_OF_MEMORY, "DS", "Out of memory while attempting to allocate "
- "cvdescriptorset::DescriptorSet in vkAllocateDescriptorSets()")) {
- lock.unlock();
- return VK_ERROR_VALIDATION_FAILED_EXT;
- }
- } else {
- // Insert set into this pool
- pPoolNode->sets.insert(pNewNode);
- pNewNode->in_use.store(0);
- dev_data->setMap[pDescriptorSets[i]] = pNewNode;
- }
- }
- }
+ PostCallRecordAllocateDescriptorSets(dev_data, pAllocateInfo, pDescriptorSets, &common_data);
lock.unlock();
}
return result;
}
+// Verify state before freeing DescriptorSets
+static bool PreCallValidateFreeDescriptorSets(const layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
+ const VkDescriptorSet *descriptor_sets) {
+ bool skip_call = false;
+ // First make sure sets being destroyed are not currently in-use
+ for (uint32_t i = 0; i < count; ++i)
+ skip_call |= validateIdleDescriptorSet(dev_data, descriptor_sets[i], "vkFreeDescriptorSets");
+
+ DESCRIPTOR_POOL_NODE *pool_node = getPoolNode(dev_data, pool);
+ if (pool_node && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pool_node->createInfo.flags)) {
+ // Can't Free from a NON_FREE pool
+ skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+ reinterpret_cast<uint64_t &>(pool), __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS",
+ "It is invalid to call vkFreeDescriptorSets() with a pool created without setting "
+ "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT.");
+ }
+ return skip_call;
+}
+// Sets have been removed from the pool so update underlying state
+static void PostCallRecordFreeDescriptorSets(layer_data *dev_data, VkDescriptorPool pool, uint32_t count,
+ const VkDescriptorSet *descriptor_sets) {
+ DESCRIPTOR_POOL_NODE *pool_state = getPoolNode(dev_data, pool);
+ // Update available descriptor sets in pool
+ pool_state->availableSets += count;
+
+ // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap
+ for (uint32_t i = 0; i < count; ++i) {
+ auto set_state = dev_data->setMap[descriptor_sets[i]];
+ uint32_t type_index = 0, descriptor_count = 0;
+ for (uint32_t j = 0; j < set_state->GetBindingCount(); ++j) {
+ type_index = static_cast<uint32_t>(set_state->GetTypeFromIndex(j));
+ descriptor_count = set_state->GetDescriptorCountFromIndex(j);
+ pool_state->availableDescriptorTypeCount[type_index] += descriptor_count;
+ }
+ freeDescriptorSet(dev_data, set_state);
+ pool_state->sets.erase(set_state);
+ }
+}
VKAPI_ATTR VkResult VKAPI_CALL
FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, const VkDescriptorSet *pDescriptorSets) {
- bool skipCall = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
// Make sure that no sets being destroyed are in-flight
std::unique_lock<std::mutex> lock(global_lock);
- for (uint32_t i = 0; i < count; ++i)
- skipCall |= validateIdleDescriptorSet(dev_data, pDescriptorSets[i], "vkFreeDescriptorSets");
- DESCRIPTOR_POOL_NODE *pPoolNode = getPoolNode(dev_data, descriptorPool);
- if (pPoolNode && !(VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT & pPoolNode->createInfo.flags)) {
- // Can't Free from a NON_FREE pool
- skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
- (uint64_t)device, __LINE__, DRAWSTATE_CANT_FREE_FROM_NON_FREE_POOL, "DS",
- "It is invalid to call vkFreeDescriptorSets() with a pool created without setting "
- "VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT.");
- }
+ bool skipCall = PreCallValidateFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
lock.unlock();
if (skipCall)
return VK_ERROR_VALIDATION_FAILED_EXT;
VkResult result = dev_data->device_dispatch_table->FreeDescriptorSets(device, descriptorPool, count, pDescriptorSets);
if (VK_SUCCESS == result) {
lock.lock();
-
- // Update available descriptor sets in pool
- pPoolNode->availableSets += count;
-
- // For each freed descriptor add its resources back into the pool as available and remove from pool and setMap
- for (uint32_t i = 0; i < count; ++i) {
- cvdescriptorset::DescriptorSet *pSet = dev_data->setMap[pDescriptorSets[i]]; // getSetNode() without locking
- uint32_t typeIndex = 0, poolSizeCount = 0;
- for (uint32_t j = 0; j < pSet->GetBindingCount(); ++j) {
- typeIndex = static_cast<uint32_t>(pSet->GetTypeFromIndex(j));
- poolSizeCount = pSet->GetDescriptorCountFromIndex(j);
- pPoolNode->availableDescriptorTypeCount[typeIndex] += poolSizeCount;
- }
- freeDescriptorSet(dev_data, pSet);
- pPoolNode->sets.erase(pSet);
- }
+ PostCallRecordFreeDescriptorSets(dev_data, descriptorPool, count, pDescriptorSets);
lock.unlock();
}
- // TODO : Any other clean-up or book-keeping to do here?
return result;
}
+// TODO : This is a Proof-of-concept for core validation architecture
+// Really we'll want to break out these functions to separate files but
+// keeping it all together here to prove out design
+// PreCallValidate* handles validating all of the state prior to calling down chain to UpdateDescriptorSets()
+static bool PreCallValidateUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
+ const VkCopyDescriptorSet *pDescriptorCopies) {
+ // First thing to do is perform map look-ups.
+ // NOTE : UpdateDescriptorSets is somewhat unique in that it's operating on a number of DescriptorSets
+ // so we can't just do a single map look-up up-front, but do them individually in functions below
+
+ // Now make call(s) that validate state, but don't perform state updates in this function
+ // Note, here DescriptorSets is unique in that we don't yet have an instance. Using a helper function in the
+ // namespace which will parse params and make calls into specific class instances
+ return cvdescriptorset::ValidateUpdateDescriptorSets(dev_data->report_data, dev_data, descriptorWriteCount, pDescriptorWrites,
+ descriptorCopyCount, pDescriptorCopies);
+}
+// PostCallRecord* handles recording state updates following call down chain to UpdateDescriptorSets()
+static void PostCallRecordUpdateDescriptorSets(layer_data *dev_data, uint32_t descriptorWriteCount,
+ const VkWriteDescriptorSet *pDescriptorWrites, uint32_t descriptorCopyCount,
+ const VkCopyDescriptorSet *pDescriptorCopies) {
+ cvdescriptorset::PerformUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
+ pDescriptorCopies);
+}
VKAPI_ATTR void VKAPI_CALL
UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
- // dsUpdate will return true only if a bailout error occurs, so we want to call down tree when update returns false
+ // Only map look-up at top level is for device-level layer_data
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
std::unique_lock<std::mutex> lock(global_lock);
- bool rtn = dsUpdate(dev_data, device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
+ bool skip_call = PreCallValidateUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
+ pDescriptorCopies);
lock.unlock();
- if (!rtn) {
+ if (!skip_call) {
dev_data->device_dispatch_table->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
pDescriptorCopies);
+ lock.lock();
+ // Since UpdateDescriptorSets() is void, nothing to check prior to updating state
+ PostCallRecordUpdateDescriptorSets(dev_data, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
+ pDescriptorCopies);
}
}
@@ -6144,9 +6159,9 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo
reinterpret_cast<void *>(commandBuffer));
} else {
string errorString = "";
- auto fbNode = dev_data->frameBufferMap.find(pInfo->framebuffer);
- if (fbNode != dev_data->frameBufferMap.end()) {
- VkRenderPass fbRP = fbNode->second.createInfo.renderPass;
+ auto framebuffer = getFramebuffer(dev_data, pInfo->framebuffer);
+ if (framebuffer) {
+ VkRenderPass fbRP = framebuffer->createInfo.renderPass;
if (!verify_renderpass_compatibility(dev_data, fbRP, pInfo->renderPass, errorString)) {
// renderPass that framebuffer was created with must be compatible with local renderPass
skipCall |=
@@ -6160,7 +6175,7 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo
(uint64_t)(pInfo->framebuffer), (uint64_t)(fbRP), errorString.c_str());
}
// Connect this framebuffer to this cmdBuffer
- fbNode->second.referencingCmdBuffers.insert(pCB->commandBuffer);
+ framebuffer->referencingCmdBuffers.insert(pCB->commandBuffer);
}
}
}
@@ -6177,15 +6192,15 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo
}
}
if (pInfo && pInfo->renderPass != VK_NULL_HANDLE) {
- auto rp_data = dev_data->renderPassMap.find(pInfo->renderPass);
- if (rp_data != dev_data->renderPassMap.end() && rp_data->second && rp_data->second->pCreateInfo) {
- if (pInfo->subpass >= rp_data->second->pCreateInfo->subpassCount) {
+ auto renderPass = getRenderPass(dev_data, pInfo->renderPass);
+ if (renderPass) {
+ if (pInfo->subpass >= renderPass->pCreateInfo->subpassCount) {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
DRAWSTATE_BEGIN_CB_INVALID_STATE, "DS",
"vkBeginCommandBuffer(): Secondary Command Buffers (0x%p) must has a subpass index (%d) "
"that is less than the number of subpasses (%d).",
- (void *)commandBuffer, pInfo->subpass, rp_data->second->pCreateInfo->subpassCount);
+ (void *)commandBuffer, pInfo->subpass, renderPass->pCreateInfo->subpassCount);
}
}
}
@@ -6197,7 +6212,7 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo
"vkBeginCommandBuffer(): Cannot call Begin on CB (0x%" PRIxLEAST64
") in the RECORDING state. Must first call vkEndCommandBuffer().",
(uint64_t)commandBuffer);
- } else if (CB_RECORDED == pCB->state) {
+ } else if (CB_RECORDED == pCB->state || (CB_INVALID == pCB->state && CMD_END == pCB->cmds.back().type)) {
VkCommandPool cmdPool = pCB->createInfo.commandPool;
if (!(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT & dev_data->commandPoolMap[cmdPool].createFlags)) {
skipCall |=
@@ -6219,8 +6234,7 @@ BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo
// If we are a secondary command-buffer and inheriting. Update the items we should inherit.
if ((pCB->createInfo.level != VK_COMMAND_BUFFER_LEVEL_PRIMARY) &&
(pCB->beginInfo.flags & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT)) {
- auto inherited_render_pass_it = dev_data->renderPassMap.find(pCB->beginInfo.pInheritanceInfo->renderPass);
- pCB->activeRenderPass = inherited_render_pass_it != dev_data->renderPassMap.end() ? inherited_render_pass_it->second : nullptr;
+ pCB->activeRenderPass = getRenderPass(dev_data, pCB->beginInfo.pInheritanceInfo->renderPass);
pCB->activeSubpass = pCB->beginInfo.pInheritanceInfo->subpass;
pCB->framebuffers.insert(pCB->beginInfo.pInheritanceInfo->framebuffer);
}
@@ -6251,9 +6265,7 @@ VKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) {
// https://github.com/KhronosGroup/Vulkan-LoaderAndValidationLayers/pull/516#discussion_r63013756
skipCall |= insideRenderPass(dev_data, pCB, "vkEndCommandBuffer");
}
- if (pCB->state != CB_RECORDING) {
- skipCall |= report_error_no_cb_begin(dev_data, commandBuffer, "vkEndCommandBuffer()");
- }
+ skipCall |= addCmd(dev_data, pCB, CMD_END, "vkEndCommandBuffer()");
for (auto query : pCB->activeQueries) {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_QUERY, "DS",
@@ -6503,14 +6515,14 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin
pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1);
pCB->lastBound[pipelineBindPoint].dynamicOffsets.resize(lastSetIndex + 1);
}
- VkDescriptorSet oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex];
+ auto oldFinalBoundSet = pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex];
for (uint32_t i = 0; i < setCount; i++) {
cvdescriptorset::DescriptorSet *pSet = getSetNode(dev_data, pDescriptorSets[i]);
if (pSet) {
- pCB->lastBound[pipelineBindPoint].uniqueBoundSets.insert(pDescriptorSets[i]);
- pSet->BindCommandBuffer(commandBuffer);
+ pCB->lastBound[pipelineBindPoint].uniqueBoundSets.insert(pSet);
+ pSet->BindCommandBuffer(pCB);
pCB->lastBound[pipelineBindPoint].pipelineLayout = layout;
- pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pDescriptorSets[i];
+ pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i + firstSet] = pSet;
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)pDescriptorSets[i], __LINE__,
DRAWSTATE_NONE, "DS", "DS 0x%" PRIxLEAST64 " bound on pipeline %s",
@@ -6603,9 +6615,8 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin
if (firstSet > 0) { // Check set #s below the first bound set
for (uint32_t i = 0; i < firstSet; ++i) {
if (pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i] &&
- !verify_set_layout_compatibility(
- dev_data, dev_data->setMap[pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i]], layout, i,
- errorString)) {
+ !verify_set_layout_compatibility(dev_data, pCB->lastBound[pipelineBindPoint].boundDescriptorSets[i],
+ layout, i, errorString)) {
skipCall |= log_msg(
dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
@@ -6620,16 +6631,16 @@ CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelin
// Check if newly last bound set invalidates any remaining bound sets
if ((pCB->lastBound[pipelineBindPoint].boundDescriptorSets.size() - 1) > (lastSetIndex)) {
if (oldFinalBoundSet &&
- !verify_set_layout_compatibility(dev_data, dev_data->setMap[oldFinalBoundSet], layout, lastSetIndex,
- errorString)) {
+ !verify_set_layout_compatibility(dev_data, oldFinalBoundSet, layout, lastSetIndex, errorString)) {
+ auto old_set = oldFinalBoundSet->GetSet();
skipCall |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, (uint64_t)oldFinalBoundSet, __LINE__,
+ VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, reinterpret_cast<uint64_t &>(old_set), __LINE__,
DRAWSTATE_NONE, "DS", "DescriptorSetDS 0x%" PRIxLEAST64
" previously bound as set #%u is incompatible with set 0x%" PRIxLEAST64
" newly bound as set #%u so set #%u and any subsequent sets were "
"disturbed by newly bound pipelineLayout (0x%" PRIxLEAST64 ")",
- (uint64_t)oldFinalBoundSet, lastSetIndex,
+ reinterpret_cast<uint64_t &>(old_set), lastSetIndex,
(uint64_t)pCB->lastBound[pipelineBindPoint].boundDescriptorSets[lastSetIndex], lastSetIndex,
lastSetIndex + 1, (uint64_t)layout);
pCB->lastBound[pipelineBindPoint].boundDescriptorSets.resize(lastSetIndex + 1);
@@ -6737,10 +6748,10 @@ static bool markStoreImagesAndBuffersAsWritten(layer_data *dev_data, GLOBAL_CB_N
bool skip_call = false;
for (auto imageView : pCB->updateImages) {
- auto iv_data = dev_data->imageViewMap.find(imageView);
- if (iv_data == dev_data->imageViewMap.end())
+ auto iv_data = getImageViewData(dev_data, imageView);
+ if (!iv_data)
continue;
- VkImage image = iv_data->second.image;
+ VkImage image = iv_data->image;
VkDeviceMemory mem;
skip_call |=
get_mem_binding_from_object(dev_data, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem);
@@ -6887,8 +6898,6 @@ VKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
if (pCB) {
skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE);
- // TODO : Call below is temporary until call above can be re-enabled
- update_shader_storage_images_and_buffers(dev_data, pCB);
skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB);
skipCall |= addCmd(dev_data, pCB, CMD_DISPATCH, "vkCmdDispatch()");
skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatch");
@@ -6910,8 +6919,6 @@ CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
if (pCB) {
skipCall |= validate_and_update_draw_state(dev_data, pCB, false, VK_PIPELINE_BIND_POINT_COMPUTE);
- // TODO : Call below is temporary until call above can be re-enabled
- update_shader_storage_images_and_buffers(dev_data, pCB);
skipCall |= markStoreImagesAndBuffersAsWritten(dev_data, pCB);
skipCall |= addCmd(dev_data, pCB, CMD_DISPATCHINDIRECT, "vkCmdDispatchIndirect()");
skipCall |= insideRenderPass(dev_data, pCB, "vkCmdDispatchIndirect");
@@ -7432,6 +7439,9 @@ CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags s
skipCall |= addCmd(dev_data, pCB, CMD_SETEVENT, "vkCmdSetEvent()");
skipCall |= insideRenderPass(dev_data, pCB, "vkCmdSetEvent");
pCB->events.push_back(event);
+ if (!pCB->waitedEvents.count(event)) {
+ pCB->writeEventsBeforeWait.push_back(event);
+ }
std::function<bool(VkQueue)> eventUpdate =
std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, stageMask);
pCB->eventUpdates.push_back(eventUpdate);
@@ -7451,6 +7461,9 @@ CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags
skipCall |= addCmd(dev_data, pCB, CMD_RESETEVENT, "vkCmdResetEvent()");
skipCall |= insideRenderPass(dev_data, pCB, "vkCmdResetEvent");
pCB->events.push_back(event);
+ if (!pCB->waitedEvents.count(event)) {
+ pCB->writeEventsBeforeWait.push_back(event);
+ }
std::function<bool(VkQueue)> eventUpdate =
std::bind(setEventStageMask, std::placeholders::_1, commandBuffer, event, VkPipelineStageFlags(0));
pCB->eventUpdates.push_back(eventUpdate);
@@ -7535,7 +7548,7 @@ static bool ValidateMaskBits(const layer_data *my_data, VkCommandBuffer cmdBuffe
// TODO: Verify against Valid Use
skip_call |=
log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask %d %s are specified when layout is %s.",
+ DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.",
type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
}
} else {
@@ -7605,7 +7618,7 @@ static bool ValidateMaskBitsFromLayouts(const layer_data *my_data, VkCommandBuff
// TODO: Verify against Valid Use section spec
skip_call |=
log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask %d %s are specified when layout is %s.",
+ DRAWSTATE_INVALID_BARRIER, "DS", "Additional bits in %s accessMask 0x%X %s are specified when layout is %s.",
type, accessMask, string_VkAccessFlags(accessMask).c_str(), string_VkImageLayout(layout));
}
break;
@@ -7633,11 +7646,11 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui
}
for (uint32_t i = 0; i < imageMemBarrierCount; ++i) {
auto mem_barrier = &pImageMemBarriers[i];
- auto image_data = dev_data->imageMap.find(mem_barrier->image);
- if (image_data != dev_data->imageMap.end()) {
+ auto image_data = getImageNode(dev_data, mem_barrier->image);
+ if (image_data) {
uint32_t src_q_f_index = mem_barrier->srcQueueFamilyIndex;
uint32_t dst_q_f_index = mem_barrier->dstQueueFamilyIndex;
- if (image_data->second.createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
+ if (image_data->createInfo.sharingMode == VK_SHARING_MODE_CONCURRENT) {
// srcQueueFamilyIndex and dstQueueFamilyIndex must both
// be VK_QUEUE_FAMILY_IGNORED
if ((src_q_f_index != VK_QUEUE_FAMILY_IGNORED) || (dst_q_f_index != VK_QUEUE_FAMILY_IGNORED)) {
@@ -7687,22 +7700,22 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui
"PREINITIALIZED.",
funcName);
}
- auto image_data = dev_data->imageMap.find(mem_barrier->image);
+ auto image_data = getImageNode(dev_data, mem_barrier->image);
VkFormat format = VK_FORMAT_UNDEFINED;
uint32_t arrayLayers = 0, mipLevels = 0;
bool imageFound = false;
- if (image_data != dev_data->imageMap.end()) {
- format = image_data->second.createInfo.format;
- arrayLayers = image_data->second.createInfo.arrayLayers;
- mipLevels = image_data->second.createInfo.mipLevels;
+ if (image_data) {
+ format = image_data->createInfo.format;
+ arrayLayers = image_data->createInfo.arrayLayers;
+ mipLevels = image_data->createInfo.mipLevels;
imageFound = true;
} else if (dev_data->device_extensions.wsi_enabled) {
- auto imageswap_data = dev_data->device_extensions.imageToSwapchainMap.find(mem_barrier->image);
- if (imageswap_data != dev_data->device_extensions.imageToSwapchainMap.end()) {
- auto swapchain_data = dev_data->device_extensions.swapchainMap.find(imageswap_data->second);
- if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) {
- format = swapchain_data->second->createInfo.imageFormat;
- arrayLayers = swapchain_data->second->createInfo.imageArrayLayers;
+ auto imageswap_data = getSwapchainFromImage(dev_data, mem_barrier->image);
+ if (imageswap_data) {
+ auto swapchain_data = getSwapchainNode(dev_data, imageswap_data);
+ if (swapchain_data) {
+ format = swapchain_data->createInfo.imageFormat;
+ arrayLayers = swapchain_data->createInfo.imageArrayLayers;
mipLevels = 1;
imageFound = true;
}
@@ -7766,11 +7779,10 @@ static bool ValidateBarriers(const char *funcName, VkCommandBuffer cmdBuffer, ui
dev_data->phys_dev_properties.queue_family_properties.size());
}
- auto buffer_data = dev_data->bufferMap.find(mem_barrier->buffer);
- if (buffer_data != dev_data->bufferMap.end()) {
- VkDeviceSize buffer_size = (buffer_data->second.createInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO)
- ? buffer_data->second.createInfo.size
- : 0;
+ auto buffer_node = getBufferNode(dev_data, mem_barrier->buffer);
+ if (buffer_node) {
+ VkDeviceSize buffer_size =
+ (buffer_node->createInfo.sType == VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO) ? buffer_node->createInfo.size : 0;
if (mem_barrier->offset >= buffer_size) {
skip_call |= log_msg(
dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
@@ -7816,13 +7828,16 @@ bool validateEventStageMask(VkQueue queue, GLOBAL_CB_NODE *pCB, uint32_t eventCo
}
}
}
- if (sourceStageMask != stageMask) {
- skip_call |=
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- DRAWSTATE_INVALID_EVENT, "DS",
- "Submitting cmdbuffer with call to VkCmdWaitEvents using srcStageMask 0x%x which must be the bitwise OR of the "
- "stageMask parameters used in calls to vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if used with vkSetEvent.",
- sourceStageMask);
+ // TODO: Need to validate that host_bit is only set if set event is called
+ // but set event can be called at any time.
+ if (sourceStageMask != stageMask && sourceStageMask != (stageMask | VK_PIPELINE_STAGE_HOST_BIT)) {
+ skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_EVENT, "DS", "Submitting cmdbuffer with call to VkCmdWaitEvents "
+ "using srcStageMask 0x%X which must be the bitwise "
+ "OR of the stageMask parameters used in calls to "
+ "vkCmdSetEvent and VK_PIPELINE_STAGE_HOST_BIT if "
+ "used with vkSetEvent but instead is 0x%X.",
+ sourceStageMask, stageMask);
}
return skip_call;
}
@@ -7839,7 +7854,7 @@ CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent
if (pCB) {
auto firstEventIndex = pCB->events.size();
for (uint32_t i = 0; i < eventCount; ++i) {
- pCB->waitedEvents.push_back(pEvents[i]);
+ pCB->waitedEvents.insert(pEvents[i]);
pCB->events.push_back(pEvents[i]);
}
std::function<bool(VkQueue)> eventUpdate =
@@ -7885,6 +7900,19 @@ CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageM
pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
}
+bool setQueryState(VkQueue queue, VkCommandBuffer commandBuffer, QueryObject object, bool value) {
+ layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
+ if (pCB) {
+ pCB->queryToStateMap[object] = value;
+ }
+ auto queue_data = dev_data->queueMap.find(queue);
+ if (queue_data != dev_data->queueMap.end()) {
+ queue_data->second.queryToStateMap[object] = value;
+ }
+ return false;
+}
+
VKAPI_ATTR void VKAPI_CALL
CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkFlags flags) {
bool skipCall = false;
@@ -7919,7 +7947,8 @@ VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPoo
} else {
pCB->activeQueries.erase(query);
}
- pCB->queryToStateMap[query] = 1;
+ std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true);
+ pCB->queryUpdates.push_back(queryUpdate);
if (pCB->state == CB_RECORDING) {
skipCall |= addCmd(dev_data, pCB, CMD_ENDQUERY, "VkCmdEndQuery()");
} else {
@@ -7941,7 +7970,8 @@ CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t
for (uint32_t i = 0; i < queryCount; i++) {
QueryObject query = {queryPool, firstQuery + i};
pCB->waitedEventsBeforeQueryReset[query] = pCB->waitedEvents;
- pCB->queryToStateMap[query] = 0;
+ std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, false);
+ pCB->queryUpdates.push_back(queryUpdate);
}
if (pCB->state == CB_RECORDING) {
skipCall |= addCmd(dev_data, pCB, CMD_RESETQUERYPOOL, "VkCmdResetQueryPool()");
@@ -7955,6 +7985,40 @@ CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t
dev_data->device_dispatch_table->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
}
+bool validateQuery(VkQueue queue, GLOBAL_CB_NODE *pCB, VkQueryPool queryPool, uint32_t queryCount, uint32_t firstQuery) {
+ bool skip_call = false;
+ layer_data *dev_data = get_my_data_ptr(get_dispatch_key(pCB->commandBuffer), layer_data_map);
+ auto queue_data = dev_data->queueMap.find(queue);
+ if (queue_data == dev_data->queueMap.end())
+ return false;
+ for (uint32_t i = 0; i < queryCount; i++) {
+ QueryObject query = {queryPool, firstQuery + i};
+ auto query_data = queue_data->second.queryToStateMap.find(query);
+ bool fail = false;
+ if (query_data != queue_data->second.queryToStateMap.end()) {
+ if (!query_data->second) {
+ fail = true;
+ }
+ } else {
+ auto global_query_data = dev_data->queryToStateMap.find(query);
+ if (global_query_data != dev_data->queryToStateMap.end()) {
+ if (!global_query_data->second) {
+ fail = true;
+ }
+ } else {
+ fail = true;
+ }
+ }
+ if (fail) {
+ skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_QUERY, "DS",
+ "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d",
+ reinterpret_cast<uint64_t &>(queryPool), firstQuery + i);
+ }
+ }
+ return skip_call;
+}
+
VKAPI_ATTR void VKAPI_CALL
CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
@@ -7980,15 +8044,9 @@ CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, ui
"vkCmdCopyQueryPoolResults()", "VK_BUFFER_USAGE_TRANSFER_DST_BIT");
#endif
if (pCB) {
- for (uint32_t i = 0; i < queryCount; i++) {
- QueryObject query = {queryPool, firstQuery + i};
- if (!pCB->queryToStateMap[query]) {
- skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_QUERY, "DS",
- "Requesting a copy from query to buffer with invalid query: queryPool 0x%" PRIx64 ", index %d",
- (uint64_t)(queryPool), firstQuery + i);
- }
- }
+ std::function<bool(VkQueue)> queryUpdate =
+ std::bind(validateQuery, std::placeholders::_1, pCB, queryPool, queryCount, firstQuery);
+ pCB->queryUpdates.push_back(queryUpdate);
if (pCB->state == CB_RECORDING) {
skipCall |= addCmd(dev_data, pCB, CMD_COPYQUERYPOOLRESULTS, "vkCmdCopyQueryPoolResults()");
} else {
@@ -8023,8 +8081,8 @@ VKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPip
}
// Check if push constant update is within any of the ranges with the same stage flags specified in pipeline layout.
- auto pipeline_layout_it = dev_data->pipelineLayoutMap.find(layout);
- if (pipeline_layout_it == dev_data->pipelineLayoutMap.end()) {
+ auto pipeline_layout = getPipelineLayout(dev_data, layout);
+ if (!pipeline_layout) {
skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_PUSH_CONSTANTS_ERROR, "DS", "vkCmdPushConstants() Pipeline Layout 0x%" PRIx64 " not found.",
(uint64_t)layout);
@@ -8032,7 +8090,7 @@ VKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPip
// Coalesce adjacent/overlapping pipeline ranges before checking to see if incoming range is
// contained in the pipeline ranges.
// Build a {start, end} span list for ranges with matching stage flags.
- const auto &ranges = pipeline_layout_it->second.pushConstantRanges;
+ const auto &ranges = pipeline_layout->pushConstantRanges;
struct span {
uint32_t start;
uint32_t end;
@@ -8107,7 +8165,8 @@ CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelin
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
if (pCB) {
QueryObject query = {queryPool, slot};
- pCB->queryToStateMap[query] = 1;
+ std::function<bool(VkQueue)> queryUpdate = std::bind(setQueryState, std::placeholders::_1, commandBuffer, query, true);
+ pCB->queryUpdates.push_back(queryUpdate);
if (pCB->state == CB_RECORDING) {
skipCall |= addCmd(dev_data, pCB, CMD_WRITETIMESTAMP, "vkCmdWriteTimestamp()");
} else {
@@ -8119,11 +8178,67 @@ CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelin
dev_data->device_dispatch_table->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
}
+static bool MatchUsage(layer_data *dev_data, uint32_t count, const VkAttachmentReference *attachments,
+ const VkFramebufferCreateInfo *fbci, VkImageUsageFlagBits usage_flag) {
+ bool skip_call = false;
+
+ for (uint32_t attach = 0; attach < count; attach++) {
+ if (attachments[attach].attachment != VK_ATTACHMENT_UNUSED) {
+ // Attachment counts are verified elsewhere, but prevent an invalid access
+ if (attachments[attach].attachment < fbci->attachmentCount) {
+ const VkImageView *image_view = &fbci->pAttachments[attachments[attach].attachment];
+ VkImageViewCreateInfo *ivci = getImageViewData(dev_data, *image_view);
+ if (ivci != nullptr) {
+ const VkImageCreateInfo *ici = &getImageNode(dev_data, ivci->image)->createInfo;
+ if (ici != nullptr) {
+ if ((ici->usage & usage_flag) == 0) {
+ skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
+ (VkDebugReportObjectTypeEXT)0, 0, __LINE__, DRAWSTATE_INVALID_IMAGE_USAGE, "DS",
+ "vkCreateFramebuffer: Framebuffer Attachment (%d) conflicts with the image's "
+ "IMAGE_USAGE flags (%s).",
+ attachments[attach].attachment, string_VkImageUsageFlagBits(usage_flag));
+ }
+ }
+ }
+ }
+ }
+ }
+ return skip_call;
+}
+
+static bool ValidateAttachmentImageUsage(layer_data *dev_data, const VkFramebufferCreateInfo *pCreateInfo) {
+ bool skip_call = false;
+
+ const VkRenderPassCreateInfo *rpci = getRenderPass(dev_data, pCreateInfo->renderPass)->pCreateInfo;
+ if (rpci != nullptr) {
+ for (uint32_t subpass = 0; subpass < rpci->subpassCount; subpass++) {
+ // Verify input attachments:
+ skip_call |= MatchUsage(dev_data, rpci->pSubpasses[subpass].inputAttachmentCount,
+ rpci->pSubpasses[subpass].pInputAttachments, pCreateInfo, VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT);
+ // Verify color attachments:
+ skip_call |= MatchUsage(dev_data, rpci->pSubpasses[subpass].colorAttachmentCount,
+ rpci->pSubpasses[subpass].pColorAttachments, pCreateInfo, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
+ // Verify depth/stencil attachments:
+ if (rpci->pSubpasses[subpass].pDepthStencilAttachment != nullptr) {
+ skip_call |= MatchUsage(dev_data, 1, rpci->pSubpasses[subpass].pDepthStencilAttachment, pCreateInfo,
+ VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
+ }
+ }
+ }
+ return skip_call;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator,
VkFramebuffer *pFramebuffer) {
+ bool skip_call = false;
+ VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- VkResult result = dev_data->device_dispatch_table->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
+
+ skip_call |= ValidateAttachmentImageUsage(dev_data, pCreateInfo);
+ if (skip_call == false) {
+ result = dev_data->device_dispatch_table->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
+ }
if (VK_SUCCESS == result) {
// Shadow create info and store in map
std::lock_guard<std::mutex> lock(global_lock);
@@ -8139,14 +8254,14 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFrameb
}
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
VkImageView view = pCreateInfo->pAttachments[i];
- auto view_data = dev_data->imageViewMap.find(view);
- if (view_data == dev_data->imageViewMap.end()) {
+ auto view_data = getImageViewData(dev_data, view);
+ if (!view_data) {
continue;
}
MT_FB_ATTACHMENT_INFO fb_info;
- get_mem_binding_from_object(dev_data, (uint64_t)(view_data->second.image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ get_mem_binding_from_object(dev_data, (uint64_t)(view_data->image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
&fb_info.mem);
- fb_info.image = view_data->second.image;
+ fb_info.image = view_data->image;
fbNode.attachments.push_back(fb_info);
}
}
@@ -8184,15 +8299,10 @@ static bool CheckDependencyExists(const layer_data *my_data, const int subpass,
auto prev_elem = std::find(node.prev.begin(), node.prev.end(), dependent_subpasses[k]);
auto next_elem = std::find(node.next.begin(), node.next.end(), dependent_subpasses[k]);
if (prev_elem == node.prev.end() && next_elem == node.next.end()) {
- // If no dependency exits an implicit dependency still might. If so, warn and if not throw an error.
+ // If no dependency exits an implicit dependency still might. If not, throw an error.
std::unordered_set<uint32_t> processed_nodes;
- if (FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) ||
- FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes)) {
- skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "A dependency between subpasses %d and %d must exist but only an implicit one is specified.",
- subpass, dependent_subpasses[k]);
- } else {
+ if (!(FindDependency(subpass, dependent_subpasses[k], subpass_to_node, processed_nodes) ||
+ FindDependency(dependent_subpasses[k], subpass, subpass_to_node, processed_nodes))) {
skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
__LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
"A dependency between subpasses %d and %d must exist but one is not specified.", subpass,
@@ -8252,11 +8362,12 @@ bool isRegionOverlapping(VkImageSubresourceRange range1, VkImageSubresourceRange
isRangeOverlapping(range1.baseArrayLayer, range1.layerCount, range2.baseArrayLayer, range2.layerCount));
}
-static bool ValidateDependencies(const layer_data *my_data, const VkRenderPassBeginInfo *pRenderPassBegin,
- const std::vector<DAGNode> &subpass_to_node) {
+static bool ValidateDependencies(const layer_data *my_data, FRAMEBUFFER_NODE const * framebuffer,
+ RENDER_PASS_NODE const * renderPass) {
bool skip_call = false;
- const VkFramebufferCreateInfo *pFramebufferInfo = &my_data->frameBufferMap.at(pRenderPassBegin->framebuffer).createInfo;
- const VkRenderPassCreateInfo *pCreateInfo = my_data->renderPassMap.at(pRenderPassBegin->renderPass)->pCreateInfo;
+ const VkFramebufferCreateInfo *pFramebufferInfo = &framebuffer->createInfo;
+ const VkRenderPassCreateInfo *pCreateInfo = renderPass->pCreateInfo;
+ auto const & subpass_to_node = renderPass->subpassToNode;
std::vector<std::vector<uint32_t>> output_attachment_to_subpass(pCreateInfo->attachmentCount);
std::vector<std::vector<uint32_t>> input_attachment_to_subpass(pCreateInfo->attachmentCount);
std::vector<std::vector<uint32_t>> overlapping_attachments(pCreateInfo->attachmentCount);
@@ -8270,25 +8381,24 @@ static bool ValidateDependencies(const layer_data *my_data, const VkRenderPassBe
overlapping_attachments[j].push_back(i);
continue;
}
- auto view_data_i = my_data->imageViewMap.find(viewi);
- auto view_data_j = my_data->imageViewMap.find(viewj);
- if (view_data_i == my_data->imageViewMap.end() || view_data_j == my_data->imageViewMap.end()) {
+ auto view_data_i = getImageViewData(my_data, viewi);
+ auto view_data_j = getImageViewData(my_data, viewj);
+ if (!view_data_i || !view_data_j) {
continue;
}
- if (view_data_i->second.image == view_data_j->second.image &&
- isRegionOverlapping(view_data_i->second.subresourceRange, view_data_j->second.subresourceRange)) {
+ if (view_data_i->image == view_data_j->image &&
+ isRegionOverlapping(view_data_i->subresourceRange, view_data_j->subresourceRange)) {
overlapping_attachments[i].push_back(j);
overlapping_attachments[j].push_back(i);
continue;
}
- auto image_data_i = my_data->imageMap.find(view_data_i->second.image);
- auto image_data_j = my_data->imageMap.find(view_data_j->second.image);
- if (image_data_i == my_data->imageMap.end() || image_data_j == my_data->imageMap.end()) {
+ auto image_data_i = getImageNode(my_data, view_data_i->image);
+ auto image_data_j = getImageNode(my_data, view_data_j->image);
+ if (!image_data_i || !image_data_j) {
continue;
}
- if (image_data_i->second.mem == image_data_j->second.mem &&
- isRangeOverlapping(image_data_i->second.memOffset, image_data_i->second.memSize, image_data_j->second.memOffset,
- image_data_j->second.memSize)) {
+ if (image_data_i->mem == image_data_j->mem && isRangeOverlapping(image_data_i->memOffset, image_data_i->memSize,
+ image_data_j->memOffset, image_data_j->memSize)) {
overlapping_attachments[i].push_back(j);
overlapping_attachments[j].push_back(i);
}
@@ -8614,22 +8724,28 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP
}
// TODO: Maybe fill list and then copy instead of locking
std::unordered_map<uint32_t, bool> &attachment_first_read = render_pass->attachment_first_read;
- std::unordered_map<uint32_t, VkImageLayout> &attachment_first_layout =
- render_pass->attachment_first_layout;
+ std::unordered_map<uint32_t, VkImageLayout> &attachment_first_layout = render_pass->attachment_first_layout;
for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
const VkSubpassDescription &subpass = pCreateInfo->pSubpasses[i];
if (subpass.pipelineBindPoint != VK_PIPELINE_BIND_POINT_GRAPHICS) {
- skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS.", i);
+ skip_call |=
+ log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_RENDERPASS, "DS",
+ "CreateRenderPass: Pipeline bind point for subpass %d must be VK_PIPELINE_BIND_POINT_GRAPHICS.", i);
}
for (uint32_t j = 0; j < subpass.preserveAttachmentCount; ++j) {
uint32_t attachment = subpass.pPreserveAttachments[j];
- if (attachment >= pCreateInfo->attachmentCount) {
- skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "Preserve attachment %d cannot be greater than the total number of attachments %d.",
- attachment, pCreateInfo->attachmentCount);
+ if (attachment == VK_ATTACHMENT_UNUSED) {
+ skip_call |=
+ log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
+ "CreateRenderPass: Preserve attachment (%d) must not be VK_ATTACHMENT_UNUSED.", j);
+ } else if (attachment >= pCreateInfo->attachmentCount) {
+ skip_call |= log_msg(
+ dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
+ "CreateRenderPass: Preserve attachment %d cannot be greater than the total number of attachments %d.",
+ attachment, pCreateInfo->attachmentCount);
}
}
for (uint32_t j = 0; j < subpass.colorAttachmentCount; ++j) {
@@ -8637,19 +8753,21 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP
if (subpass.pResolveAttachments) {
attachment = subpass.pResolveAttachments[j].attachment;
if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) {
- skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "Color attachment %d cannot be greater than the total number of attachments %d.",
- attachment, pCreateInfo->attachmentCount);
+ skip_call |= log_msg(
+ dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
+ "CreateRenderPass: Resolve attachment %d cannot be greater than the total number of attachments %d.",
+ attachment, pCreateInfo->attachmentCount);
continue;
}
}
attachment = subpass.pColorAttachments[j].attachment;
- if (attachment >= pCreateInfo->attachmentCount) {
- skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "Color attachment %d cannot be greater than the total number of attachments %d.",
- attachment, pCreateInfo->attachmentCount);
+ if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) {
+ skip_call |=
+ log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
+ "CreateRenderPass: Color attachment %d cannot be greater than the total number of attachments %d.",
+ attachment, pCreateInfo->attachmentCount);
continue;
}
if (attachment_first_read.count(attachment))
@@ -8661,8 +8779,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP
uint32_t attachment = subpass.pDepthStencilAttachment->attachment;
if (attachment >= pCreateInfo->attachmentCount) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
- __LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "Depth stencil attachment %d cannot be greater than the total number of attachments %d.",
+ __LINE__, DRAWSTATE_INVALID_ATTACHMENT_INDEX, "DS",
+ "CreateRenderPass: Depth stencil attachment %d cannot be greater than the total number of attachments %d.",
attachment, pCreateInfo->attachmentCount);
continue;
}
@@ -8673,10 +8791,10 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP
}
for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
uint32_t attachment = subpass.pInputAttachments[j].attachment;
- if (attachment >= pCreateInfo->attachmentCount) {
+ if (attachment >= pCreateInfo->attachmentCount && attachment != VK_ATTACHMENT_UNUSED) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
__LINE__, DRAWSTATE_INVALID_RENDERPASS, "DS",
- "Input attachment %d cannot be greater than the total number of attachments %d.",
+ "CreateRenderPass: Input attachment %d cannot be greater than the total number of attachments %d.",
attachment, pCreateInfo->attachmentCount);
continue;
}
@@ -8724,10 +8842,8 @@ static void deleteRenderPasses(layer_data *my_data) {
my_data->renderPassMap.clear();
}
-static bool VerifyFramebufferAndRenderPassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin) {
+static bool VerifyFramebufferAndRenderPassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) {
bool skip_call = false;
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
- GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
const VkRenderPassCreateInfo *pRenderPassInfo = dev_data->renderPassMap[pRenderPassBegin->renderPass]->pCreateInfo;
const VkFramebufferCreateInfo framebufferInfo = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].createInfo;
if (pRenderPassInfo->attachmentCount != framebufferInfo.attachmentCount) {
@@ -8737,10 +8853,10 @@ static bool VerifyFramebufferAndRenderPassLayouts(VkCommandBuffer cmdBuffer, con
}
for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
const VkImageView &image_view = framebufferInfo.pAttachments[i];
- auto image_data = dev_data->imageViewMap.find(image_view);
- assert(image_data != dev_data->imageViewMap.end());
- const VkImage &image = image_data->second.image;
- const VkImageSubresourceRange &subRange = image_data->second.subresourceRange;
+ auto image_data = getImageViewData(dev_data, image_view);
+ assert(image_data);
+ const VkImage &image = image_data->image;
+ const VkImageSubresourceRange &subRange = image_data->subresourceRange;
IMAGE_CMD_BUF_LAYOUT_NODE newNode = {pRenderPassInfo->pAttachments[i].initialLayout,
pRenderPassInfo->pAttachments[i].initialLayout};
// TODO: Do not iterate over every possibility - consolidate where possible
@@ -8769,21 +8885,18 @@ static bool VerifyFramebufferAndRenderPassLayouts(VkCommandBuffer cmdBuffer, con
return skip_call;
}
-static void TransitionSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
+static void TransitionSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin,
const int subpass_index) {
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
- GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
- auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
- if (render_pass_data == dev_data->renderPassMap.end()) {
+ auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass);
+ if (!renderPass)
return;
- }
- const VkRenderPassCreateInfo *pRenderPassInfo = render_pass_data->second->pCreateInfo;
- auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
- if (framebuffer_data == dev_data->frameBufferMap.end()) {
+
+ auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer);
+ if (!framebuffer)
return;
- }
- const VkFramebufferCreateInfo framebufferInfo = framebuffer_data->second.createInfo;
- const VkSubpassDescription &subpass = pRenderPassInfo->pSubpasses[subpass_index];
+
+ const VkFramebufferCreateInfo &framebufferInfo = framebuffer->createInfo;
+ const VkSubpassDescription &subpass = renderPass->pCreateInfo->pSubpasses[subpass_index];
for (uint32_t j = 0; j < subpass.inputAttachmentCount; ++j) {
const VkImageView &image_view = framebufferInfo.pAttachments[subpass.pInputAttachments[j].attachment];
SetLayout(dev_data, pCB, image_view, subpass.pInputAttachments[j].layout);
@@ -8808,21 +8921,18 @@ static bool validatePrimaryCommandBuffer(const layer_data *my_data, const GLOBAL
return skip_call;
}
-static void TransitionFinalSubpassLayouts(VkCommandBuffer cmdBuffer, const VkRenderPassBeginInfo *pRenderPassBegin) {
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(cmdBuffer), layer_data_map);
- GLOBAL_CB_NODE *pCB = getCBNode(dev_data, cmdBuffer);
- auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
- if (render_pass_data == dev_data->renderPassMap.end()) {
+static void TransitionFinalSubpassLayouts(layer_data *dev_data, GLOBAL_CB_NODE *pCB, const VkRenderPassBeginInfo *pRenderPassBegin) {
+ auto renderPass = getRenderPass(dev_data, pRenderPassBegin->renderPass);
+ if (!renderPass)
return;
- }
- const VkRenderPassCreateInfo *pRenderPassInfo = render_pass_data->second->pCreateInfo;
- auto framebuffer_data = dev_data->frameBufferMap.find(pRenderPassBegin->framebuffer);
- if (framebuffer_data == dev_data->frameBufferMap.end()) {
+
+ const VkRenderPassCreateInfo *pRenderPassInfo = renderPass->pCreateInfo;
+ auto framebuffer = getFramebuffer(dev_data, pRenderPassBegin->framebuffer);
+ if (!framebuffer)
return;
- }
- const VkFramebufferCreateInfo framebufferInfo = framebuffer_data->second.createInfo;
+
for (uint32_t i = 0; i < pRenderPassInfo->attachmentCount; ++i) {
- const VkImageView &image_view = framebufferInfo.pAttachments[i];
+ const VkImageView &image_view = framebuffer->createInfo.pAttachments[i];
SetLayout(dev_data, pCB, image_view, pRenderPassInfo->pAttachments[i].finalLayout);
}
}
@@ -8852,62 +8962,54 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
std::unique_lock<std::mutex> lock(global_lock);
GLOBAL_CB_NODE *pCB = getCBNode(dev_data, commandBuffer);
+ auto renderPass = pRenderPassBegin ? getRenderPass(dev_data, pRenderPassBegin->renderPass) : nullptr;
+ auto framebuffer = pRenderPassBegin ? getFramebuffer(dev_data, pRenderPassBegin->framebuffer) : nullptr;
if (pCB) {
- if (pRenderPassBegin && pRenderPassBegin->renderPass) {
-#if MTMERGE
- auto pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
- if (pass_data != dev_data->renderPassMap.end()) {
- RENDER_PASS_NODE* pRPNode = pass_data->second;
- pCB->activeFramebuffer = pRenderPassBegin->framebuffer;
- auto cb_data = dev_data->commandBufferMap.find(commandBuffer);
- for (size_t i = 0; i < pRPNode->attachments.size(); ++i) {
- MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[pRenderPassBegin->framebuffer].attachments[i];
- if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
- if (cb_data != dev_data->commandBufferMap.end()) {
- std::function<bool()> function = [=]() {
- set_memory_valid(dev_data, fb_info.mem, true, fb_info.image);
- return false;
- };
- cb_data->second->validate_functions.push_back(function);
- }
- } else if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE) {
- if (cb_data != dev_data->commandBufferMap.end()) {
- std::function<bool()> function = [=]() {
- set_memory_valid(dev_data, fb_info.mem, false, fb_info.image);
- return false;
- };
- cb_data->second->validate_functions.push_back(function);
- }
- } else if (pRPNode->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_LOAD) {
- if (cb_data != dev_data->commandBufferMap.end()) {
- std::function<bool()> function = [=]() {
- return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image);
- };
- cb_data->second->validate_functions.push_back(function);
- }
- }
- if (pRPNode->attachment_first_read[pRPNode->attachments[i].attachment]) {
- if (cb_data != dev_data->commandBufferMap.end()) {
- std::function<bool()> function = [=]() {
- return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image);
- };
- cb_data->second->validate_functions.push_back(function);
- }
- }
+ if (renderPass) {
+ uint32_t clear_op_count = 0;
+ pCB->activeFramebuffer = pRenderPassBegin->framebuffer;
+ for (size_t i = 0; i < renderPass->attachments.size(); ++i) {
+ MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
+ if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_CLEAR) {
+ ++clear_op_count;
+ std::function<bool()> function = [=]() {
+ set_memory_valid(dev_data, fb_info.mem, true, fb_info.image);
+ return false;
+ };
+ pCB->validate_functions.push_back(function);
+ } else if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_DONT_CARE) {
+ std::function<bool()> function = [=]() {
+ set_memory_valid(dev_data, fb_info.mem, false, fb_info.image);
+ return false;
+ };
+ pCB->validate_functions.push_back(function);
+ } else if (renderPass->attachments[i].load_op == VK_ATTACHMENT_LOAD_OP_LOAD) {
+ std::function<bool()> function = [=]() {
+ return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image);
+ };
+ pCB->validate_functions.push_back(function);
+ }
+ if (renderPass->attachment_first_read[renderPass->attachments[i].attachment]) {
+ std::function<bool()> function = [=]() {
+ return validate_memory_is_valid(dev_data, fb_info.mem, "vkCmdBeginRenderPass()", fb_info.image);
+ };
+ pCB->validate_functions.push_back(function);
}
}
-#endif
+ if (clear_op_count > pRenderPassBegin->clearValueCount) {
+ skipCall |= log_msg(
+ dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT,
+ reinterpret_cast<uint64_t &>(renderPass), __LINE__, DRAWSTATE_RENDERPASS_INCOMPATIBLE, "DS",
+ "In vkCmdBeginRenderPass() the VkRenderPassBeginInfo struct has a clearValueCount of %u but the actual number "
+ "of attachments in renderPass 0x%" PRIx64 " that use VK_ATTACHMENT_LOAD_OP_CLEAR is %u. The clearValueCount "
+ "must therefore be greater than or equal to %u.",
+ pRenderPassBegin->clearValueCount, reinterpret_cast<uint64_t &>(renderPass), clear_op_count, clear_op_count);
+ }
skipCall |= VerifyRenderAreaBounds(dev_data, pRenderPassBegin);
- skipCall |= VerifyFramebufferAndRenderPassLayouts(commandBuffer, pRenderPassBegin);
+ skipCall |= VerifyFramebufferAndRenderPassLayouts(dev_data, pCB, pRenderPassBegin);
skipCall |= insideRenderPass(dev_data, pCB, "vkCmdBeginRenderPass");
- auto render_pass_data = dev_data->renderPassMap.find(pRenderPassBegin->renderPass);
- if (render_pass_data != dev_data->renderPassMap.end()) {
- skipCall |= ValidateDependencies(dev_data, pRenderPassBegin, render_pass_data->second->subpassToNode);
- pCB->activeRenderPass = render_pass_data->second;
- }
- else {
- pCB->activeRenderPass = nullptr;
- }
+ skipCall |= ValidateDependencies(dev_data, framebuffer, renderPass);
+ pCB->activeRenderPass = renderPass;
skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdBeginRenderPass");
skipCall |= addCmd(dev_data, pCB, CMD_BEGINRENDERPASS, "vkCmdBeginRenderPass()");
// This is a shallow copy as that is all that is needed for now
@@ -8916,11 +9018,11 @@ CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *p
pCB->activeSubpassContents = contents;
pCB->framebuffers.insert(pRenderPassBegin->framebuffer);
// Connect this framebuffer to this cmdBuffer
- dev_data->frameBufferMap[pRenderPassBegin->framebuffer].referencingCmdBuffers.insert(pCB->commandBuffer);
+ framebuffer->referencingCmdBuffers.insert(pCB->commandBuffer);
} else {
skipCall |=
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()");
+ log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
+ DRAWSTATE_INVALID_RENDERPASS, "DS", "You cannot use a NULL RenderPass object in vkCmdBeginRenderPass()");
}
}
lock.unlock();
@@ -8939,7 +9041,7 @@ VKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpa
skipCall |= addCmd(dev_data, pCB, CMD_NEXTSUBPASS, "vkCmdNextSubpass()");
pCB->activeSubpass++;
pCB->activeSubpassContents = contents;
- TransitionSubpassLayouts(commandBuffer, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass);
+ TransitionSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo, pCB->activeSubpass);
skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdNextSubpass");
}
lock.unlock();
@@ -8951,38 +9053,35 @@ VKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) {
bool skipCall = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
std::unique_lock<std::mutex> lock(global_lock);
- auto cb_data = dev_data->commandBufferMap.find(commandBuffer);
- if (cb_data != dev_data->commandBufferMap.end()) {
- RENDER_PASS_NODE* pRPNode = cb_data->second->activeRenderPass;
+ auto pCB = getCBNode(dev_data, commandBuffer);
+ if (pCB) {
+ RENDER_PASS_NODE* pRPNode = pCB->activeRenderPass;
+ auto framebuffer = getFramebuffer(dev_data, pCB->activeFramebuffer);
if (pRPNode) {
for (size_t i = 0; i < pRPNode->attachments.size(); ++i) {
- MT_FB_ATTACHMENT_INFO &fb_info = dev_data->frameBufferMap[cb_data->second->activeFramebuffer].attachments[i];
+ MT_FB_ATTACHMENT_INFO &fb_info = framebuffer->attachments[i];
if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_STORE) {
- if (cb_data != dev_data->commandBufferMap.end()) {
- std::function<bool()> function = [=]() {
- set_memory_valid(dev_data, fb_info.mem, true, fb_info.image);
- return false;
- };
- cb_data->second->validate_functions.push_back(function);
- }
+ std::function<bool()> function = [=]() {
+ set_memory_valid(dev_data, fb_info.mem, true, fb_info.image);
+ return false;
+ };
+ pCB->validate_functions.push_back(function);
} else if (pRPNode->attachments[i].store_op == VK_ATTACHMENT_STORE_OP_DONT_CARE) {
- if (cb_data != dev_data->commandBufferMap.end()) {
- std::function<bool()> function = [=]() {
- set_memory_valid(dev_data, fb_info.mem, false, fb_info.image);
- return false;
- };
- cb_data->second->validate_functions.push_back(function);
- }
+ std::function<bool()> function = [=]() {
+ set_memory_valid(dev_data, fb_info.mem, false, fb_info.image);
+ return false;
+ };
+ pCB->validate_functions.push_back(function);
}
}
}
- skipCall |= outsideRenderPass(dev_data, cb_data->second, "vkCmdEndRenderpass");
- skipCall |= validatePrimaryCommandBuffer(dev_data, cb_data->second, "vkCmdEndRenderPass");
- skipCall |= addCmd(dev_data, cb_data->second, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
- TransitionFinalSubpassLayouts(commandBuffer, &cb_data->second->activeRenderPassBeginInfo);
- cb_data->second->activeRenderPass = nullptr;
- cb_data->second->activeSubpass = 0;
- cb_data->second->activeFramebuffer = VK_NULL_HANDLE;
+ skipCall |= outsideRenderPass(dev_data, pCB, "vkCmdEndRenderpass");
+ skipCall |= validatePrimaryCommandBuffer(dev_data, pCB, "vkCmdEndRenderPass");
+ skipCall |= addCmd(dev_data, pCB, CMD_ENDRENDERPASS, "vkCmdEndRenderPass()");
+ TransitionFinalSubpassLayouts(dev_data, pCB, &pCB->activeRenderPassBeginInfo);
+ pCB->activeRenderPass = nullptr;
+ pCB->activeSubpass = 0;
+ pCB->activeFramebuffer = VK_NULL_HANDLE;
}
lock.unlock();
if (!skipCall)
@@ -9100,9 +9199,9 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe
// Early exit if renderPass objects are identical (and therefore compatible)
if (primaryPass == secondaryPass)
return skip_call;
- auto primary_data = dev_data->renderPassMap.find(primaryPass);
- auto secondary_data = dev_data->renderPassMap.find(secondaryPass);
- if (primary_data == dev_data->renderPassMap.end() || primary_data->second == nullptr) {
+ auto primary_render_pass = getRenderPass(dev_data, primaryPass);
+ auto secondary_render_pass = getRenderPass(dev_data, secondaryPass);
+ if (!primary_render_pass) {
skip_call |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
@@ -9110,7 +9209,7 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe
(void *)primaryBuffer, (uint64_t)(primaryPass));
return skip_call;
}
- if (secondary_data == dev_data->renderPassMap.end() || secondary_data->second == nullptr) {
+ if (!secondary_render_pass) {
skip_call |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
@@ -9118,7 +9217,7 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe
(void *)secondaryBuffer, (uint64_t)(secondaryPass));
return skip_call;
}
- if (primary_data->second->pCreateInfo->subpassCount != secondary_data->second->pCreateInfo->subpassCount) {
+ if (primary_render_pass->pCreateInfo->subpassCount != secondary_render_pass->pCreateInfo->subpassCount) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS",
"vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p which has a render pass 0x%" PRIx64
@@ -9127,10 +9226,10 @@ static bool validateRenderPassCompatibility(layer_data *dev_data, VkCommandBuffe
(void *)secondaryBuffer, (uint64_t)(secondaryPass), (uint64_t)(primaryPass));
return skip_call;
}
- bool is_multi = primary_data->second->pCreateInfo->subpassCount > 1;
- for (uint32_t i = 0; i < primary_data->second->pCreateInfo->subpassCount; ++i) {
- skip_call |=
- validateSubpassCompatibility(dev_data, primaryBuffer, primary_data->second, secondaryBuffer, secondary_data->second, i, is_multi);
+ auto subpassCount = primary_render_pass->pCreateInfo->subpassCount;
+ for (uint32_t i = 0; i < subpassCount; ++i) {
+ skip_call |= validateSubpassCompatibility(dev_data, primaryBuffer, primary_render_pass, secondaryBuffer,
+ secondary_render_pass, i, subpassCount > 1);
}
return skip_call;
}
@@ -9151,8 +9250,8 @@ static bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuf
" that is not compatible with the current framebuffer 0x%" PRIx64 ".",
(void *)secondaryBuffer, (uint64_t)(secondary_fb), (uint64_t)(primary_fb));
}
- auto fb_data = dev_data->frameBufferMap.find(secondary_fb);
- if (fb_data == dev_data->frameBufferMap.end()) {
+ auto fb = getFramebuffer(dev_data, secondary_fb);
+ if (!fb) {
skip_call |=
log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
DRAWSTATE_INVALID_SECONDARY_COMMAND_BUFFER, "DS", "vkCmdExecuteCommands() called w/ invalid Cmd Buffer 0x%p "
@@ -9160,7 +9259,7 @@ static bool validateFramebuffer(layer_data *dev_data, VkCommandBuffer primaryBuf
(void *)secondaryBuffer, (uint64_t)(secondary_fb));
return skip_call;
}
- skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb_data->second.createInfo.renderPass,
+ skip_call |= validateRenderPassCompatibility(dev_data, secondaryBuffer, fb->createInfo.renderPass,
secondaryBuffer, pSubCB->beginInfo.pInheritanceInfo->renderPass);
}
return skip_call;
@@ -9317,10 +9416,10 @@ CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBuffersCount,
static bool ValidateMapImageLayouts(VkDevice device, VkDeviceMemory mem) {
bool skip_call = false;
layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- auto mem_data = dev_data->memObjMap.find(mem);
- if ((mem_data != dev_data->memObjMap.end()) && (mem_data->second.image != VK_NULL_HANDLE)) {
+ auto mem_info = getMemObjInfo(dev_data, mem);
+ if ((mem_info) && (mem_info->image != VK_NULL_HANDLE)) {
std::vector<VkImageLayout> layouts;
- if (FindLayouts(dev_data, mem_data->second.image, layouts)) {
+ if (FindLayouts(dev_data, mem_info->image, layouts)) {
for (auto layout : layouts) {
if (layout != VK_IMAGE_LAYOUT_PREINITIALIZED && layout != VK_IMAGE_LAYOUT_GENERAL) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
@@ -9342,7 +9441,7 @@ MapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
std::unique_lock<std::mutex> lock(global_lock);
#if MTMERGESOURCE
- DEVICE_MEM_INFO *pMemObj = get_mem_obj_info(dev_data, mem);
+ DEVICE_MEM_INFO *pMemObj = getMemObjInfo(dev_data, mem);
if (pMemObj) {
pMemObj->valid = true;
if ((dev_data->phys_dev_mem_props.memoryTypes[pMemObj->allocInfo.memoryTypeIndex].propertyFlags &
@@ -9388,26 +9487,28 @@ static bool validateMemoryIsMapped(layer_data *my_data, const char *funcName, ui
const VkMappedMemoryRange *pMemRanges) {
bool skipCall = false;
for (uint32_t i = 0; i < memRangeCount; ++i) {
- auto mem_element = my_data->memObjMap.find(pMemRanges[i].memory);
- if (mem_element != my_data->memObjMap.end()) {
- if (mem_element->second.memRange.offset > pMemRanges[i].offset) {
- skipCall |= log_msg(
- my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
- (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
- "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER ") is less than Memory Object's offset "
- "(" PRINTF_SIZE_T_SPECIFIER ").",
- funcName, static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(mem_element->second.memRange.offset));
- }
- if ((mem_element->second.memRange.size != VK_WHOLE_SIZE) &&
- ((mem_element->second.memRange.offset + mem_element->second.memRange.size) <
- (pMemRanges[i].offset + pMemRanges[i].size))) {
+ auto mem_info = getMemObjInfo(my_data, pMemRanges[i].memory);
+ if (mem_info) {
+ if (mem_info->memRange.offset > pMemRanges[i].offset) {
+ skipCall |=
+ log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT,
+ (uint64_t)pMemRanges[i].memory, __LINE__, MEMTRACK_INVALID_MAP, "MEM",
+ "%s: Flush/Invalidate offset (" PRINTF_SIZE_T_SPECIFIER ") is less than Memory Object's offset "
+ "(" PRINTF_SIZE_T_SPECIFIER ").",
+ funcName, static_cast<size_t>(pMemRanges[i].offset), static_cast<size_t>(mem_info->memRange.offset));
+ }
+
+ const uint64_t my_dataTerminus =
+ (mem_info->memRange.size == VK_WHOLE_SIZE) ? mem_info->allocInfo.allocationSize :
+ (mem_info->memRange.offset + mem_info->memRange.size);
+ if (pMemRanges[i].size != VK_WHOLE_SIZE && (my_dataTerminus < (pMemRanges[i].offset + pMemRanges[i].size))) {
skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, (uint64_t)pMemRanges[i].memory, __LINE__,
MEMTRACK_INVALID_MAP, "MEM", "%s: Flush/Invalidate upper-bound (" PRINTF_SIZE_T_SPECIFIER
") exceeds the Memory Object's upper-bound "
"(" PRINTF_SIZE_T_SPECIFIER ").",
funcName, static_cast<size_t>(pMemRanges[i].offset + pMemRanges[i].size),
- static_cast<size_t>(mem_element->second.memRange.offset + mem_element->second.memRange.size));
+ static_cast<size_t>(my_dataTerminus));
}
}
}
@@ -9418,12 +9519,12 @@ static bool validateAndCopyNoncoherentMemoryToDriver(layer_data *my_data, uint32
const VkMappedMemoryRange *pMemRanges) {
bool skipCall = false;
for (uint32_t i = 0; i < memRangeCount; ++i) {
- auto mem_element = my_data->memObjMap.find(pMemRanges[i].memory);
- if (mem_element != my_data->memObjMap.end()) {
- if (mem_element->second.pData) {
- VkDeviceSize size = mem_element->second.memRange.size;
+ auto mem_info = getMemObjInfo(my_data, pMemRanges[i].memory);
+ if (mem_info) {
+ if (mem_info->pData) {
+ VkDeviceSize size = mem_info->memRange.size;
VkDeviceSize half_size = (size / 2);
- char *data = static_cast<char *>(mem_element->second.pData);
+ char *data = static_cast<char *>(mem_info->pData);
for (auto j = 0; j < half_size; ++j) {
if (data[j] != NoncoherentMemoryFillValue) {
skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
@@ -9440,7 +9541,7 @@ static bool validateAndCopyNoncoherentMemoryToDriver(layer_data *my_data, uint32
(uint64_t)pMemRanges[i].memory);
}
}
- memcpy(mem_element->second.pDriverData, static_cast<void *>(data + (size_t)(half_size)), (size_t)(size));
+ memcpy(mem_info->pDriverData, static_cast<void *>(data + (size_t)(half_size)), (size_t)(size));
}
}
}
@@ -9483,8 +9584,8 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
std::unique_lock<std::mutex> lock(global_lock);
- auto image_node = dev_data->imageMap.find(image);
- if (image_node != dev_data->imageMap.end()) {
+ auto image_node = getImageNode(dev_data, image);
+ if (image_node) {
// Track objects tied to memory
uint64_t image_handle = reinterpret_cast<uint64_t &>(image);
skipCall = set_mem_binding(dev_data, mem, image_handle, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, "vkBindImageMemory");
@@ -9494,12 +9595,12 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V
lock.lock();
// Track and validate bound memory range information
- const auto &memEntry = dev_data->memObjMap.find(mem);
- if (memEntry != dev_data->memObjMap.end()) {
+ auto mem_info = getMemObjInfo(dev_data, mem);
+ if (mem_info) {
const MEMORY_RANGE range =
- insert_memory_ranges(image_handle, mem, memoryOffset, memRequirements, memEntry->second.imageRanges);
- skipCall |=
- validate_memory_range(dev_data, memEntry->second.bufferRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
+ insert_memory_ranges(image_handle, mem, memoryOffset, memRequirements, mem_info->imageRanges);
+ skipCall |= validate_memory_range(dev_data, mem_info->bufferRanges, range, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT);
+ skipCall |= ValidateMemoryTypes(dev_data, mem_info, memRequirements.memoryTypeBits, "vkBindImageMemory");
}
print_mem_list(dev_data);
@@ -9507,10 +9608,10 @@ VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, V
if (!skipCall) {
result = dev_data->device_dispatch_table->BindImageMemory(device, image, mem, memoryOffset);
lock.lock();
- dev_data->memObjMap[mem].image = image;
- image_node->second.mem = mem;
- image_node->second.memOffset = memoryOffset;
- image_node->second.memSize = memRequirements.size;
+ dev_data->memObjMap[mem].get()->image = image;
+ image_node->mem = mem;
+ image_node->memOffset = memoryOffset;
+ image_node->memSize = memRequirements.size;
lock.unlock();
}
} else {
@@ -9531,7 +9632,7 @@ VKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) {
if (event_node != dev_data->eventMap.end()) {
event_node->second.needsSignaled = false;
event_node->second.stageMask = VK_PIPELINE_STAGE_HOST_BIT;
- if (event_node->second.in_use.load()) {
+ if (event_node->second.write_in_use) {
skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT,
reinterpret_cast<const uint64_t &>(event), __LINE__, DRAWSTATE_QUEUE_FORWARD_PROGRESS, "DS",
"Cannot call vkSetEvent() on event 0x%" PRIxLEAST64 " that is already in use by a command buffer.",
@@ -9559,24 +9660,16 @@ QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *p
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skip_call = false;
std::unique_lock<std::mutex> lock(global_lock);
+ auto pFence = getFenceNode(dev_data, fence);
+ auto pQueue = getQueueNode(dev_data, queue);
+
// First verify that fence is not in use
+ skip_call |= ValidateFenceForSubmit(dev_data, pFence);
+
if (fence != VK_NULL_HANDLE) {
- trackCommandBuffers(dev_data, queue, 0, nullptr, fence);
- auto fence_data = dev_data->fenceMap.find(fence);
- if ((bindInfoCount != 0) && fence_data->second.in_use.load()) {
- skip_call |=
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
- reinterpret_cast<uint64_t &>(fence), __LINE__, DRAWSTATE_INVALID_FENCE, "DS",
- "Fence 0x%" PRIx64 " is already in use by another submission.", reinterpret_cast<uint64_t &>(fence));
- }
- if (!fence_data->second.needsSignaled) {
- skip_call |=
- log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT,
- reinterpret_cast<uint64_t &>(fence), __LINE__, MEMTRACK_INVALID_FENCE_STATE, "MEM",
- "Fence 0x%" PRIxLEAST64 " submitted in SIGNALED state. Fences must be reset before being submitted",
- reinterpret_cast<uint64_t &>(fence));
- }
+ SubmitFence(pQueue, pFence);
}
+
for (uint32_t bindIdx = 0; bindIdx < bindInfoCount; ++bindIdx) {
const VkBindSparseInfo &bindInfo = pBindInfo[bindIdx];
// Track objects tied to memory
@@ -9665,6 +9758,7 @@ CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAlloc
std::lock_guard<std::mutex> lock(global_lock);
dev_data->eventMap[*pEvent].needsSignaled = false;
dev_data->eventMap[*pEvent].in_use.store(0);
+ dev_data->eventMap[*pEvent].write_in_use = 0;
dev_data->eventMap[*pEvent].stageMask = VkPipelineStageFlags(0);
}
return result;
@@ -9677,9 +9771,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateSwapchainKHR(VkDevice device, const VkSwapc
VkResult result = dev_data->device_dispatch_table->CreateSwapchainKHR(device, pCreateInfo, pAllocator, pSwapchain);
if (VK_SUCCESS == result) {
- SWAPCHAIN_NODE *psc_node = new SWAPCHAIN_NODE(pCreateInfo);
std::lock_guard<std::mutex> lock(global_lock);
- dev_data->device_extensions.swapchainMap[*pSwapchain] = psc_node;
+ dev_data->device_extensions.swapchainMap[*pSwapchain] = unique_ptr<SWAPCHAIN_NODE>(new SWAPCHAIN_NODE(pCreateInfo));
}
return result;
@@ -9691,10 +9784,10 @@ DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocatio
bool skipCall = false;
std::unique_lock<std::mutex> lock(global_lock);
- auto swapchain_data = dev_data->device_extensions.swapchainMap.find(swapchain);
- if (swapchain_data != dev_data->device_extensions.swapchainMap.end()) {
- if (swapchain_data->second->images.size() > 0) {
- for (auto swapchain_image : swapchain_data->second->images) {
+ auto swapchain_data = getSwapchainNode(dev_data, swapchain);
+ if (swapchain_data) {
+ if (swapchain_data->images.size() > 0) {
+ for (auto swapchain_image : swapchain_data->images) {
auto image_sub = dev_data->imageSubresourceMap.find(swapchain_image);
if (image_sub != dev_data->imageSubresourceMap.end()) {
for (auto imgsubpair : image_sub->second) {
@@ -9710,7 +9803,6 @@ DestroySwapchainKHR(VkDevice device, VkSwapchainKHR swapchain, const VkAllocatio
dev_data->imageMap.erase(swapchain_image);
}
}
- delete swapchain_data->second;
dev_data->device_extensions.swapchainMap.erase(swapchain);
}
lock.unlock();
@@ -9729,8 +9821,8 @@ GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCoun
return result;
std::lock_guard<std::mutex> lock(global_lock);
const size_t count = *pCount;
- auto swapchain_node = dev_data->device_extensions.swapchainMap[swapchain];
- if (!swapchain_node->images.empty()) {
+ auto swapchain_node = getSwapchainNode(dev_data, swapchain);
+ if (swapchain_node && !swapchain_node->images.empty()) {
// TODO : Not sure I like the memcmp here, but it works
const bool mismatch = (swapchain_node->images.size() != count ||
memcmp(&swapchain_node->images[0], pSwapchainImages, sizeof(swapchain_node->images[0]) * count));
@@ -9747,16 +9839,19 @@ GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchain, uint32_t *pCoun
IMAGE_LAYOUT_NODE image_layout_node;
image_layout_node.layout = VK_IMAGE_LAYOUT_UNDEFINED;
image_layout_node.format = swapchain_node->createInfo.imageFormat;
+ // Add imageMap entries for each swapchain image
+ VkImageCreateInfo image_ci = {};
+ image_ci.mipLevels = 1;
+ image_ci.arrayLayers = swapchain_node->createInfo.imageArrayLayers;
+ image_ci.usage = swapchain_node->createInfo.imageUsage;
+ image_ci.format = swapchain_node->createInfo.imageFormat;
+ image_ci.extent.width = swapchain_node->createInfo.imageExtent.width;
+ image_ci.extent.height = swapchain_node->createInfo.imageExtent.height;
+ image_ci.sharingMode = swapchain_node->createInfo.imageSharingMode;
+ dev_data->imageMap[pSwapchainImages[i]] = unique_ptr<IMAGE_NODE>(new IMAGE_NODE(&image_ci));
auto &image_node = dev_data->imageMap[pSwapchainImages[i]];
- image_node.createInfo.mipLevels = 1;
- image_node.createInfo.arrayLayers = swapchain_node->createInfo.imageArrayLayers;
- image_node.createInfo.usage = swapchain_node->createInfo.imageUsage;
- image_node.createInfo.format = swapchain_node->createInfo.imageFormat;
- image_node.createInfo.extent.width = swapchain_node->createInfo.imageExtent.width;
- image_node.createInfo.extent.height = swapchain_node->createInfo.imageExtent.height;
- image_node.createInfo.sharingMode = swapchain_node->createInfo.imageSharingMode;
- image_node.valid = false;
- image_node.mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY;
+ image_node->valid = false;
+ image_node->mem = MEMTRACKER_SWAP_CHAIN_IMAGE_KEY;
swapchain_node->images.push_back(pSwapchainImages[i]);
ImageSubresourcePair subpair = {pSwapchainImages[i], false, VkImageSubresource()};
dev_data->imageSubresourceMap[pSwapchainImages[i]].push_back(subpair);
@@ -9790,10 +9885,9 @@ VKAPI_ATTR VkResult VKAPI_CALL QueuePresentKHR(VkQueue queue, const VkPresentInf
}
VkDeviceMemory mem;
for (uint32_t i = 0; i < pPresentInfo->swapchainCount; ++i) {
- auto swapchain_data = dev_data->device_extensions.swapchainMap.find(pPresentInfo->pSwapchains[i]);
- if (swapchain_data != dev_data->device_extensions.swapchainMap.end() &&
- pPresentInfo->pImageIndices[i] < swapchain_data->second->images.size()) {
- VkImage image = swapchain_data->second->images[pPresentInfo->pImageIndices[i]];
+ auto swapchain_data = getSwapchainNode(dev_data, pPresentInfo->pSwapchains[i]);
+ if (swapchain_data && pPresentInfo->pImageIndices[i] < swapchain_data->images.size()) {
+ VkImage image = swapchain_data->images[pPresentInfo->pImageIndices[i]];
#if MTMERGESOURCE
skip_call |=
get_mem_binding_from_object(dev_data, (uint64_t)(image), VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, &mem);
@@ -9860,7 +9954,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre
VkResult res = pTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (VK_SUCCESS == res) {
std::lock_guard<std::mutex> lock(global_lock);
- res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
+ res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
return res;
}
@@ -9883,6 +9977,24 @@ DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugR
pMsg);
}
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
+ return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
+
+ return VK_ERROR_LAYER_NOT_PRESENT;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
@@ -9961,14 +10073,12 @@ intercept_core_instance_command(const char *name) {
{ "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
{ "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
{ "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
+ { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
+ { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
+ { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
{ "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
};
- // we should never be queried for these commands
- assert(strcmp(name, "vkEnumerateInstanceLayerProperties") &&
- strcmp(name, "vkEnumerateInstanceExtensionProperties") &&
- strcmp(name, "vkEnumerateDeviceLayerProperties"));
-
for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
if (!strcmp(core_instance_commands[i].name, name))
return core_instance_commands[i].proc;
@@ -10159,27 +10269,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu
core_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
}
-// loader-layer interface v0
+// loader-layer interface v0, just wrappers since there is only a layer
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
- return util_GetExtensionProperties(1, core_validation::instance_extensions, pCount, pProperties);
+ return core_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &core_validation::global_layer, pCount, pProperties);
+ return core_validation::EnumerateInstanceLayerProperties(pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &core_validation::global_layer, pCount, pProperties);
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return core_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
- // the layer command handles VK_NULL_HANDLE just fine
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
return core_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
}
@@ -10188,14 +10301,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
}
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
- if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);
- if (!strcmp(funcName, "vkGetInstanceProcAddr"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);
-
return core_validation::GetInstanceProcAddr(instance, funcName);
}
diff --git a/layers/core_validation.h b/layers/core_validation.h
index 783ca98e..d3e7cd4d 100644
--- a/layers/core_validation.h
+++ b/layers/core_validation.h
@@ -58,6 +58,7 @@
#include <unordered_map>
#include <unordered_set>
#include <vector>
+#include <list>
#if MTMERGE
@@ -97,12 +98,6 @@ struct MT_FB_ATTACHMENT_INFO {
VkDeviceMemory mem;
};
-struct MT_PASS_ATTACHMENT_INFO {
- uint32_t attachment;
- VkAttachmentLoadOp load_op;
- VkAttachmentStoreOp store_op;
-};
-
struct MT_DESCRIPTOR_SET_INFO {
std::vector<VkImageView> images;
std::vector<VkBuffer> buffers;
@@ -113,84 +108,21 @@ struct MT_SWAP_CHAIN_INFO {
VkSwapchainCreateInfoKHR createInfo;
std::vector<VkImage> images;
};
-
#endif
-typedef enum _DRAW_TYPE {
- DRAW = 0,
- DRAW_INDEXED = 1,
- DRAW_INDIRECT = 2,
- DRAW_INDEXED_INDIRECT = 3,
- DRAW_BEGIN_RANGE = DRAW,
- DRAW_END_RANGE = DRAW_INDEXED_INDIRECT,
- NUM_DRAW_TYPES = (DRAW_END_RANGE - DRAW_BEGIN_RANGE + 1),
-} DRAW_TYPE;
-typedef struct _SHADER_DS_MAPPING {
+struct SHADER_DS_MAPPING {
uint32_t slotCount;
VkDescriptorSetLayoutCreateInfo *pShaderMappingSlot;
-} SHADER_DS_MAPPING;
+};
-typedef struct _GENERIC_HEADER {
+struct GENERIC_HEADER {
VkStructureType sType;
const void *pNext;
-} GENERIC_HEADER;
+};
-typedef struct _IMAGE_LAYOUT_NODE {
+struct IMAGE_LAYOUT_NODE {
VkImageLayout layout;
VkFormat format;
-} IMAGE_LAYOUT_NODE;
-
-class IMAGE_CMD_BUF_LAYOUT_NODE {
- public:
- IMAGE_CMD_BUF_LAYOUT_NODE() {}
- IMAGE_CMD_BUF_LAYOUT_NODE(VkImageLayout initialLayoutInput, VkImageLayout layoutInput)
- : initialLayout(initialLayoutInput), layout(layoutInput) {}
-
- VkImageLayout initialLayout;
- VkImageLayout layout;
-};
-
-// Store the DAG.
-struct DAGNode {
- uint32_t pass;
- std::vector<uint32_t> prev;
- std::vector<uint32_t> next;
-};
-
-struct RENDER_PASS_NODE {
- VkRenderPass renderPass;
- VkRenderPassCreateInfo const *pCreateInfo;
- std::vector<bool> hasSelfDependency;
- std::vector<DAGNode> subpassToNode;
- std::vector<std::vector<VkFormat>> subpassColorFormats;
- std::vector<MT_PASS_ATTACHMENT_INFO> attachments;
- std::unordered_map<uint32_t, bool> attachment_first_read;
- std::unordered_map<uint32_t, VkImageLayout> attachment_first_layout;
-
- RENDER_PASS_NODE(VkRenderPassCreateInfo const *pCreateInfo) : pCreateInfo(pCreateInfo) {
- uint32_t i;
-
- subpassColorFormats.reserve(pCreateInfo->subpassCount);
- for (i = 0; i < pCreateInfo->subpassCount; i++) {
- const VkSubpassDescription *subpass = &pCreateInfo->pSubpasses[i];
- std::vector<VkFormat> color_formats;
- uint32_t j;
-
- color_formats.reserve(subpass->colorAttachmentCount);
- for (j = 0; j < subpass->colorAttachmentCount; j++) {
- const uint32_t att = subpass->pColorAttachments[j].attachment;
-
- if (att != VK_ATTACHMENT_UNUSED) {
- color_formats.push_back(pCreateInfo->pAttachments[att].format);
- }
- else {
- color_formats.push_back(VK_FORMAT_UNDEFINED);
- }
- }
-
- subpassColorFormats.push_back(color_formats);
- }
- }
};
// Store layouts and pushconstants for PipelineLayout
@@ -216,7 +148,7 @@ class PIPELINE_NODE {
std::vector<VkPipelineColorBlendAttachmentState> attachments;
bool blendConstantsEnabled; // Blend constants enabled for any attachments
RENDER_PASS_NODE *renderPass;
- PIPELINE_LAYOUT_NODE *pipelineLayout;
+ PIPELINE_LAYOUT_NODE const *pipelineLayout;
// Default constructor
PIPELINE_NODE()
@@ -280,11 +212,12 @@ class FENCE_NODE : public BASE_NODE {
public:
using BASE_NODE::in_use;
+ VkFence fence;
VkSwapchainKHR swapchain; // Swapchain that this fence is submitted against or NULL
bool firstTimeFlag; // Fence was created in signaled state, avoid warnings for first use
VkFenceCreateInfo createInfo;
std::unordered_set<VkQueue> queues;
- std::vector<VkCommandBuffer> cmdBuffers;
+ std::vector<CB_SUBMISSION> submissions;
bool needsSignaled;
std::vector<VkFence> priorFences;
@@ -302,12 +235,14 @@ class SEMAPHORE_NODE : public BASE_NODE {
class EVENT_NODE : public BASE_NODE {
public:
using BASE_NODE::in_use;
+ int write_in_use;
bool needsSignaled;
VkPipelineStageFlags stageMask;
};
class QUEUE_NODE {
public:
+ VkQueue queue;
VkDevice device;
std::vector<VkFence> lastFences;
#if MTMERGE
@@ -315,8 +250,9 @@ class QUEUE_NODE {
std::list<VkCommandBuffer> pQueueCommandBuffers;
std::list<VkDeviceMemory> pMemRefList;
#endif
- std::vector<VkCommandBuffer> untrackedCmdBuffers;
+ std::vector<CB_SUBMISSION> untrackedSubmissions;
std::unordered_map<VkEvent, VkPipelineStageFlags> eventToStageMap;
+ std::unordered_map<QueryObject, bool> queryToStateMap; // 0 is unavailable, 1 is available
};
class QUERY_POOL_NODE : public BASE_NODE {
@@ -331,263 +267,8 @@ class FRAMEBUFFER_NODE {
std::vector<MT_FB_ATTACHMENT_INFO> attachments;
};
-typedef struct _DESCRIPTOR_POOL_NODE {
- VkDescriptorPool pool;
- uint32_t maxSets; // Max descriptor sets allowed in this pool
- uint32_t availableSets; // Available descriptor sets in this pool
-
- VkDescriptorPoolCreateInfo createInfo;
- std::unordered_set<cvdescriptorset::DescriptorSet *> sets; // Collection of all sets in this pool
- std::vector<uint32_t> maxDescriptorTypeCount; // Max # of descriptors of each type in this pool
- std::vector<uint32_t> availableDescriptorTypeCount; // Available # of descriptors of each type in this pool
-
- _DESCRIPTOR_POOL_NODE(const VkDescriptorPool pool, const VkDescriptorPoolCreateInfo *pCreateInfo)
- : pool(pool), maxSets(pCreateInfo->maxSets), availableSets(pCreateInfo->maxSets), createInfo(*pCreateInfo),
- maxDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE, 0), availableDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE, 0) {
- if (createInfo.poolSizeCount) { // Shadow type struct from ptr into local struct
- size_t poolSizeCountSize = createInfo.poolSizeCount * sizeof(VkDescriptorPoolSize);
- createInfo.pPoolSizes = new VkDescriptorPoolSize[poolSizeCountSize];
- memcpy((void *)createInfo.pPoolSizes, pCreateInfo->pPoolSizes, poolSizeCountSize);
- // Now set max counts for each descriptor type based on count of that type times maxSets
- uint32_t i = 0;
- for (i = 0; i < createInfo.poolSizeCount; ++i) {
- uint32_t typeIndex = static_cast<uint32_t>(createInfo.pPoolSizes[i].type);
- // Same descriptor types can appear several times
- maxDescriptorTypeCount[typeIndex] += createInfo.pPoolSizes[i].descriptorCount;
- availableDescriptorTypeCount[typeIndex] = maxDescriptorTypeCount[typeIndex];
- }
- } else {
- createInfo.pPoolSizes = NULL; // Make sure this is NULL so we don't try to clean it up
- }
- }
- ~_DESCRIPTOR_POOL_NODE() {
- delete[] createInfo.pPoolSizes;
- // TODO : pSets are currently freed in deletePools function which uses freeShadowUpdateTree function
- // need to migrate that struct to smart ptrs for auto-cleanup
- }
-} DESCRIPTOR_POOL_NODE;
-
-// Cmd Buffer Tracking
-typedef enum _CMD_TYPE {
- CMD_BINDPIPELINE,
- CMD_BINDPIPELINEDELTA,
- CMD_SETVIEWPORTSTATE,
- CMD_SETSCISSORSTATE,
- CMD_SETLINEWIDTHSTATE,
- CMD_SETDEPTHBIASSTATE,
- CMD_SETBLENDSTATE,
- CMD_SETDEPTHBOUNDSSTATE,
- CMD_SETSTENCILREADMASKSTATE,
- CMD_SETSTENCILWRITEMASKSTATE,
- CMD_SETSTENCILREFERENCESTATE,
- CMD_BINDDESCRIPTORSETS,
- CMD_BINDINDEXBUFFER,
- CMD_BINDVERTEXBUFFER,
- CMD_DRAW,
- CMD_DRAWINDEXED,
- CMD_DRAWINDIRECT,
- CMD_DRAWINDEXEDINDIRECT,
- CMD_DISPATCH,
- CMD_DISPATCHINDIRECT,
- CMD_COPYBUFFER,
- CMD_COPYIMAGE,
- CMD_BLITIMAGE,
- CMD_COPYBUFFERTOIMAGE,
- CMD_COPYIMAGETOBUFFER,
- CMD_CLONEIMAGEDATA,
- CMD_UPDATEBUFFER,
- CMD_FILLBUFFER,
- CMD_CLEARCOLORIMAGE,
- CMD_CLEARATTACHMENTS,
- CMD_CLEARDEPTHSTENCILIMAGE,
- CMD_RESOLVEIMAGE,
- CMD_SETEVENT,
- CMD_RESETEVENT,
- CMD_WAITEVENTS,
- CMD_PIPELINEBARRIER,
- CMD_BEGINQUERY,
- CMD_ENDQUERY,
- CMD_RESETQUERYPOOL,
- CMD_COPYQUERYPOOLRESULTS,
- CMD_WRITETIMESTAMP,
- CMD_PUSHCONSTANTS,
- CMD_INITATOMICCOUNTERS,
- CMD_LOADATOMICCOUNTERS,
- CMD_SAVEATOMICCOUNTERS,
- CMD_BEGINRENDERPASS,
- CMD_NEXTSUBPASS,
- CMD_ENDRENDERPASS,
- CMD_EXECUTECOMMANDS,
-} CMD_TYPE;
-// Data structure for holding sequence of cmds in cmd buffer
-typedef struct _CMD_NODE {
- CMD_TYPE type;
- uint64_t cmdNumber;
-} CMD_NODE;
-
-typedef enum _CB_STATE {
- CB_NEW, // Newly created CB w/o any cmds
- CB_RECORDING, // BeginCB has been called on this CB
- CB_RECORDED, // EndCB has been called on this CB
- CB_INVALID // CB had a bound descriptor set destroyed or updated
-} CB_STATE;
-// CB Status -- used to track status of various bindings on cmd buffer objects
-typedef VkFlags CBStatusFlags;
-typedef enum _CBStatusFlagBits {
- // clang-format off
- CBSTATUS_NONE = 0x00000000, // No status is set
- CBSTATUS_VIEWPORT_SET = 0x00000001, // Viewport has been set
- CBSTATUS_LINE_WIDTH_SET = 0x00000002, // Line width has been set
- CBSTATUS_DEPTH_BIAS_SET = 0x00000004, // Depth bias has been set
- CBSTATUS_BLEND_CONSTANTS_SET = 0x00000008, // Blend constants state has been set
- CBSTATUS_DEPTH_BOUNDS_SET = 0x00000010, // Depth bounds state object has been set
- CBSTATUS_STENCIL_READ_MASK_SET = 0x00000020, // Stencil read mask has been set
- CBSTATUS_STENCIL_WRITE_MASK_SET = 0x00000040, // Stencil write mask has been set
- CBSTATUS_STENCIL_REFERENCE_SET = 0x00000080, // Stencil reference has been set
- CBSTATUS_INDEX_BUFFER_BOUND = 0x00000100, // Index buffer has been set
- CBSTATUS_SCISSOR_SET = 0x00000200, // Scissor has been set
- CBSTATUS_ALL = 0x000003FF, // All dynamic state set
- // clang-format on
-} CBStatusFlagBits;
-
typedef struct stencil_data {
uint32_t compareMask;
uint32_t writeMask;
uint32_t reference;
} CBStencilData;
-
-typedef struct _DRAW_DATA { std::vector<VkBuffer> buffers; } DRAW_DATA;
-
-struct ImageSubresourcePair {
- VkImage image;
- bool hasSubresource;
- VkImageSubresource subresource;
-};
-
-bool operator==(const ImageSubresourcePair &img1, const ImageSubresourcePair &img2) {
- if (img1.image != img2.image || img1.hasSubresource != img2.hasSubresource)
- return false;
- return !img1.hasSubresource ||
- (img1.subresource.aspectMask == img2.subresource.aspectMask && img1.subresource.mipLevel == img2.subresource.mipLevel &&
- img1.subresource.arrayLayer == img2.subresource.arrayLayer);
-}
-
-namespace std {
-template <> struct hash<ImageSubresourcePair> {
- size_t operator()(ImageSubresourcePair img) const throw() {
- size_t hashVal = hash<uint64_t>()(reinterpret_cast<uint64_t &>(img.image));
- hashVal ^= hash<bool>()(img.hasSubresource);
- if (img.hasSubresource) {
- hashVal ^= hash<uint32_t>()(reinterpret_cast<uint32_t &>(img.subresource.aspectMask));
- hashVal ^= hash<uint32_t>()(img.subresource.mipLevel);
- hashVal ^= hash<uint32_t>()(img.subresource.arrayLayer);
- }
- return hashVal;
- }
-};
-}
-
-struct QueryObject {
- VkQueryPool pool;
- uint32_t index;
-};
-
-bool operator==(const QueryObject &query1, const QueryObject &query2) {
- return (query1.pool == query2.pool && query1.index == query2.index);
-}
-
-namespace std {
-template <> struct hash<QueryObject> {
- size_t operator()(QueryObject query) const throw() {
- return hash<uint64_t>()((uint64_t)(query.pool)) ^ hash<uint32_t>()(query.index);
- }
-};
-}
-// Track last states that are bound per pipeline bind point (Gfx & Compute)
-struct LAST_BOUND_STATE {
- VkPipeline pipeline;
- VkPipelineLayout pipelineLayout;
- // Track each set that has been bound
- // TODO : can unique be global per CB? (do we care about Gfx vs. Compute?)
- std::unordered_set<VkDescriptorSet> uniqueBoundSets;
- // Ordered bound set tracking where index is set# that given set is bound to
- std::vector<VkDescriptorSet> boundDescriptorSets;
- // one dynamic offset per dynamic descriptor bound to this CB
- std::vector<std::vector<uint32_t>> dynamicOffsets;
-
- void reset() {
- pipeline = VK_NULL_HANDLE;
- pipelineLayout = VK_NULL_HANDLE;
- uniqueBoundSets.clear();
- boundDescriptorSets.clear();
- dynamicOffsets.clear();
- }
-};
-// Cmd Buffer Wrapper Struct
-struct GLOBAL_CB_NODE : public BASE_NODE {
- VkCommandBuffer commandBuffer;
- VkCommandBufferAllocateInfo createInfo;
- VkCommandBufferBeginInfo beginInfo;
- VkCommandBufferInheritanceInfo inheritanceInfo;
- // VkFence fence; // fence tracking this cmd buffer
- VkDevice device; // device this CB belongs to
- uint64_t numCmds; // number of cmds in this CB
- uint64_t drawCount[NUM_DRAW_TYPES]; // Count of each type of draw in this CB
- CB_STATE state; // Track cmd buffer update state
- uint64_t submitCount; // Number of times CB has been submitted
- CBStatusFlags status; // Track status of various bindings on cmd buffer
- std::vector<CMD_NODE> cmds; // vector of commands bound to this command buffer
- // Currently storing "lastBound" objects on per-CB basis
- // long-term may want to create caches of "lastBound" states and could have
- // each individual CMD_NODE referencing its own "lastBound" state
- // VkPipeline lastBoundPipeline;
- // VkPipelineLayout lastBoundPipelineLayout;
- // // Capture unique std::set of descriptorSets that are bound to this CB.
- // std::set<VkDescriptorSet> uniqueBoundSets;
- // vector<VkDescriptorSet> boundDescriptorSets; // Index is set# that given set is bound to
- // Store last bound state for Gfx & Compute pipeline bind points
- LAST_BOUND_STATE lastBound[VK_PIPELINE_BIND_POINT_RANGE_SIZE];
-
- std::vector<VkViewport> viewports;
- std::vector<VkRect2D> scissors;
- VkRenderPassBeginInfo activeRenderPassBeginInfo;
- uint64_t fenceId;
- VkFence lastSubmittedFence;
- VkQueue lastSubmittedQueue;
- RENDER_PASS_NODE *activeRenderPass;
- VkSubpassContents activeSubpassContents;
- uint32_t activeSubpass;
- VkFramebuffer activeFramebuffer;
- std::unordered_set<VkFramebuffer> framebuffers;
- // Track descriptor sets that are destroyed or updated while bound to CB
- // TODO : These data structures relate to tracking resources that invalidate
- // a cmd buffer that references them. Need to unify how we handle these
- // cases so we don't have different tracking data for each type.
- std::unordered_set<VkDescriptorSet> destroyedSets;
- std::unordered_set<VkDescriptorSet> updatedSets;
- std::unordered_set<VkFramebuffer> destroyedFramebuffers;
- std::vector<VkEvent> waitedEvents;
- std::vector<VkSemaphore> semaphores;
- std::vector<VkEvent> events;
- std::unordered_map<QueryObject, std::vector<VkEvent>> waitedEventsBeforeQueryReset;
- std::unordered_map<QueryObject, bool> queryToStateMap; // 0 is unavailable, 1 is available
- std::unordered_set<QueryObject> activeQueries;
- std::unordered_set<QueryObject> startedQueries;
- std::unordered_map<ImageSubresourcePair, IMAGE_CMD_BUF_LAYOUT_NODE> imageLayoutMap;
- std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> imageSubresourceMap;
- std::unordered_map<VkEvent, VkPipelineStageFlags> eventToStageMap;
- std::vector<DRAW_DATA> drawData;
- DRAW_DATA currentDrawData;
- VkCommandBuffer primaryCommandBuffer;
- // Track images and buffers that are updated by this CB at the point of a draw
- std::unordered_set<VkImageView> updateImages;
- std::unordered_set<VkBuffer> updateBuffers;
- // If cmd buffer is primary, track secondary command buffers pending
- // execution
- std::unordered_set<VkCommandBuffer> secondaryCommandBuffers;
- // MTMTODO : Scrub these data fields and merge active sets w/ lastBound as appropriate
- std::vector<std::function<bool()>> validate_functions;
- std::unordered_set<VkDeviceMemory> memObjs;
- std::vector<std::function<bool(VkQueue)>> eventUpdates;
-};
-
diff --git a/layers/core_validation_error_enums.h b/layers/core_validation_error_enums.h
index 03827c2a..bcbdd33b 100644
--- a/layers/core_validation_error_enums.h
+++ b/layers/core_validation_error_enums.h
@@ -24,7 +24,7 @@
#define CORE_VALIDATION_ERROR_ENUMS_H_
// Mem Tracker ERROR codes
-typedef enum _MEM_TRACK_ERROR {
+enum MEM_TRACK_ERROR {
MEMTRACK_NONE, // Used for INFO & other non-error messages
MEMTRACK_INVALID_CB, // Cmd Buffer invalid
MEMTRACK_INVALID_MEM_OBJ, // Invalid Memory Object
@@ -39,10 +39,11 @@ typedef enum _MEM_TRACK_ERROR {
MEMTRACK_REBIND_OBJECT, // Non-sparse object bindings are immutable
MEMTRACK_INVALID_USAGE_FLAG, // Usage flags specified at image/buffer create conflict w/ use of object
MEMTRACK_INVALID_MAP, // Size flag specified at alloc is too small for mapping range
-} MEM_TRACK_ERROR;
+ MEMTRACK_INVALID_MEM_TYPE, // Memory Type mismatch
+};
// Draw State ERROR codes
-typedef enum _DRAW_STATE_ERROR {
+enum DRAW_STATE_ERROR {
// TODO: Remove the comments here or expand them. There isn't any additional information in the
// comments than in the name in almost all cases.
DRAWSTATE_NONE, // Used for INFO & other non-error messages
@@ -136,6 +137,10 @@ typedef enum _DRAW_STATE_ERROR {
// RenderPass is active
DRAWSTATE_NO_ACTIVE_RENDERPASS, // Rendering cmd submitted without an active
// RenderPass
+ DRAWSTATE_INVALID_IMAGE_USAGE, // Image attachment location conflicts with
+ // image's USAGE flags
+ DRAWSTATE_INVALID_ATTACHMENT_INDEX, // Attachment reference contains an index
+ // that is out-of-bounds
DRAWSTATE_DESCRIPTOR_SET_NOT_UPDATED, // DescriptorSet bound but it was
// never updated. This is a warning
// code.
@@ -214,9 +219,9 @@ typedef enum _DRAW_STATE_ERROR {
DRAWSTATE_INVALID_QUEUE_INDEX, // Specified queue index exceeds number
// of queried queue families
DRAWSTATE_PUSH_CONSTANTS_ERROR, // Push constants exceed maxPushConstantSize
-} DRAW_STATE_ERROR;
+};
-typedef enum _SHADER_CHECKER_ERROR {
+enum SHADER_CHECKER_ERROR {
SHADER_CHECKER_NONE,
SHADER_CHECKER_INTERFACE_TYPE_MISMATCH, // Type mismatch between shader stages or shader and pipeline
SHADER_CHECKER_OUTPUT_NOT_CONSUMED, // Entry appears in output interface, but missing in input
@@ -234,6 +239,6 @@ typedef enum _SHADER_CHECKER_ERROR {
SHADER_CHECKER_DESCRIPTOR_NOT_ACCESSIBLE_FROM_STAGE, // Descriptor used by shader, but not accessible from stage
SHADER_CHECKER_FEATURE_NOT_ENABLED, // Shader uses capability requiring a feature not enabled on device
SHADER_CHECKER_BAD_CAPABILITY, // Shader uses capability not supported by Vulkan (OpenCL features)
-} SHADER_CHECKER_ERROR;
+};
-#endif // CORE_VALIDATION_ERROR_ENUMS_H_ \ No newline at end of file
+#endif // CORE_VALIDATION_ERROR_ENUMS_H_
diff --git a/layers/core_validation_types.h b/layers/core_validation_types.h
index 43f7de62..616a2e2c 100644
--- a/layers/core_validation_types.h
+++ b/layers/core_validation_types.h
@@ -48,13 +48,57 @@
#include <atomic>
#include <string.h>
#include <unordered_set>
+#include <unordered_map>
#include <vector>
+#include <functional>
+
+// Fwd declarations
+namespace cvdescriptorset {
+class DescriptorSetLayout;
+class DescriptorSet;
+};
class BASE_NODE {
public:
std::atomic_int in_use;
};
+struct DESCRIPTOR_POOL_NODE {
+ VkDescriptorPool pool;
+ uint32_t maxSets; // Max descriptor sets allowed in this pool
+ uint32_t availableSets; // Available descriptor sets in this pool
+
+ VkDescriptorPoolCreateInfo createInfo;
+ std::unordered_set<cvdescriptorset::DescriptorSet *> sets; // Collection of all sets in this pool
+ std::vector<uint32_t> maxDescriptorTypeCount; // Max # of descriptors of each type in this pool
+ std::vector<uint32_t> availableDescriptorTypeCount; // Available # of descriptors of each type in this pool
+
+ DESCRIPTOR_POOL_NODE(const VkDescriptorPool pool, const VkDescriptorPoolCreateInfo *pCreateInfo)
+ : pool(pool), maxSets(pCreateInfo->maxSets), availableSets(pCreateInfo->maxSets), createInfo(*pCreateInfo),
+ maxDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE, 0), availableDescriptorTypeCount(VK_DESCRIPTOR_TYPE_RANGE_SIZE, 0) {
+ if (createInfo.poolSizeCount) { // Shadow type struct from ptr into local struct
+ size_t poolSizeCountSize = createInfo.poolSizeCount * sizeof(VkDescriptorPoolSize);
+ createInfo.pPoolSizes = new VkDescriptorPoolSize[poolSizeCountSize];
+ memcpy((void *)createInfo.pPoolSizes, pCreateInfo->pPoolSizes, poolSizeCountSize);
+ // Now set max counts for each descriptor type based on count of that type times maxSets
+ uint32_t i = 0;
+ for (i = 0; i < createInfo.poolSizeCount; ++i) {
+ uint32_t typeIndex = static_cast<uint32_t>(createInfo.pPoolSizes[i].type);
+ // Same descriptor types can appear several times
+ maxDescriptorTypeCount[typeIndex] += createInfo.pPoolSizes[i].descriptorCount;
+ availableDescriptorTypeCount[typeIndex] = maxDescriptorTypeCount[typeIndex];
+ }
+ } else {
+ createInfo.pPoolSizes = NULL; // Make sure this is NULL so we don't try to clean it up
+ }
+ }
+ ~DESCRIPTOR_POOL_NODE() {
+ delete[] createInfo.pPoolSizes;
+ // TODO : pSets are currently freed in deletePools function which uses freeShadowUpdateTree function
+ // need to migrate that struct to smart ptrs for auto-cleanup
+ }
+};
+
class BUFFER_NODE : public BASE_NODE {
public:
using BASE_NODE::in_use;
@@ -65,12 +109,12 @@ class BUFFER_NODE : public BASE_NODE {
BUFFER_NODE(const BUFFER_NODE &rh_obj) : mem(rh_obj.mem), createInfo(rh_obj.createInfo) { in_use.store(rh_obj.in_use.load()); };
};
-typedef struct _SAMPLER_NODE {
+struct SAMPLER_NODE {
VkSampler sampler;
VkSamplerCreateInfo createInfo;
- _SAMPLER_NODE(const VkSampler *ps, const VkSamplerCreateInfo *pci) : sampler(*ps), createInfo(*pci){};
-} SAMPLER_NODE;
+ SAMPLER_NODE(const VkSampler *ps, const VkSamplerCreateInfo *pci) : sampler(*ps), createInfo(*pci){};
+};
class IMAGE_NODE : public BASE_NODE {
public:
@@ -131,6 +175,9 @@ struct DEVICE_MEM_INFO {
VkImage image; // If memory is bound to image, this will have VkImage handle, else VK_NULL_HANDLE
MemRange memRange;
void *pData, *pDriverData;
+ DEVICE_MEM_INFO(void *disp_object, const VkDeviceMemory in_mem, const VkMemoryAllocateInfo *p_alloc_info)
+ : object(disp_object), valid(false), mem(in_mem), allocInfo(*p_alloc_info), image(VK_NULL_HANDLE), memRange{}, pData(0),
+ pDriverData(0){};
};
class SWAPCHAIN_NODE {
@@ -147,4 +194,313 @@ class SWAPCHAIN_NODE {
}
~SWAPCHAIN_NODE() { delete[] pQueueFamilyIndices; }
};
-#endif // CORE_VALIDATION_TYPES_H_ \ No newline at end of file
+
+enum DRAW_TYPE {
+ DRAW = 0,
+ DRAW_INDEXED = 1,
+ DRAW_INDIRECT = 2,
+ DRAW_INDEXED_INDIRECT = 3,
+ DRAW_BEGIN_RANGE = DRAW,
+ DRAW_END_RANGE = DRAW_INDEXED_INDIRECT,
+ NUM_DRAW_TYPES = (DRAW_END_RANGE - DRAW_BEGIN_RANGE + 1),
+};
+
+class IMAGE_CMD_BUF_LAYOUT_NODE {
+ public:
+ IMAGE_CMD_BUF_LAYOUT_NODE() {}
+ IMAGE_CMD_BUF_LAYOUT_NODE(VkImageLayout initialLayoutInput, VkImageLayout layoutInput)
+ : initialLayout(initialLayoutInput), layout(layoutInput) {}
+
+ VkImageLayout initialLayout;
+ VkImageLayout layout;
+};
+
+struct MT_PASS_ATTACHMENT_INFO {
+ uint32_t attachment;
+ VkAttachmentLoadOp load_op;
+ VkAttachmentStoreOp store_op;
+};
+
+// Store the DAG.
+struct DAGNode {
+ uint32_t pass;
+ std::vector<uint32_t> prev;
+ std::vector<uint32_t> next;
+};
+
+struct RENDER_PASS_NODE {
+ VkRenderPass renderPass;
+ VkRenderPassCreateInfo const *pCreateInfo;
+ std::vector<bool> hasSelfDependency;
+ std::vector<DAGNode> subpassToNode;
+ std::vector<std::vector<VkFormat>> subpassColorFormats;
+ std::vector<MT_PASS_ATTACHMENT_INFO> attachments;
+ std::unordered_map<uint32_t, bool> attachment_first_read;
+ std::unordered_map<uint32_t, VkImageLayout> attachment_first_layout;
+
+ RENDER_PASS_NODE(VkRenderPassCreateInfo const *pCreateInfo) : pCreateInfo(pCreateInfo) {
+ uint32_t i;
+
+ subpassColorFormats.reserve(pCreateInfo->subpassCount);
+ for (i = 0; i < pCreateInfo->subpassCount; i++) {
+ const VkSubpassDescription *subpass = &pCreateInfo->pSubpasses[i];
+ std::vector<VkFormat> color_formats;
+ uint32_t j;
+
+ color_formats.reserve(subpass->colorAttachmentCount);
+ for (j = 0; j < subpass->colorAttachmentCount; j++) {
+ const uint32_t att = subpass->pColorAttachments[j].attachment;
+
+ if (att != VK_ATTACHMENT_UNUSED) {
+ color_formats.push_back(pCreateInfo->pAttachments[att].format);
+ }
+ else {
+ color_formats.push_back(VK_FORMAT_UNDEFINED);
+ }
+ }
+
+ subpassColorFormats.push_back(color_formats);
+ }
+ }
+};
+
+// Cmd Buffer Tracking
+enum CMD_TYPE {
+ CMD_BINDPIPELINE,
+ CMD_BINDPIPELINEDELTA,
+ CMD_SETVIEWPORTSTATE,
+ CMD_SETSCISSORSTATE,
+ CMD_SETLINEWIDTHSTATE,
+ CMD_SETDEPTHBIASSTATE,
+ CMD_SETBLENDSTATE,
+ CMD_SETDEPTHBOUNDSSTATE,
+ CMD_SETSTENCILREADMASKSTATE,
+ CMD_SETSTENCILWRITEMASKSTATE,
+ CMD_SETSTENCILREFERENCESTATE,
+ CMD_BINDDESCRIPTORSETS,
+ CMD_BINDINDEXBUFFER,
+ CMD_BINDVERTEXBUFFER,
+ CMD_DRAW,
+ CMD_DRAWINDEXED,
+ CMD_DRAWINDIRECT,
+ CMD_DRAWINDEXEDINDIRECT,
+ CMD_DISPATCH,
+ CMD_DISPATCHINDIRECT,
+ CMD_COPYBUFFER,
+ CMD_COPYIMAGE,
+ CMD_BLITIMAGE,
+ CMD_COPYBUFFERTOIMAGE,
+ CMD_COPYIMAGETOBUFFER,
+ CMD_CLONEIMAGEDATA,
+ CMD_UPDATEBUFFER,
+ CMD_FILLBUFFER,
+ CMD_CLEARCOLORIMAGE,
+ CMD_CLEARATTACHMENTS,
+ CMD_CLEARDEPTHSTENCILIMAGE,
+ CMD_RESOLVEIMAGE,
+ CMD_SETEVENT,
+ CMD_RESETEVENT,
+ CMD_WAITEVENTS,
+ CMD_PIPELINEBARRIER,
+ CMD_BEGINQUERY,
+ CMD_ENDQUERY,
+ CMD_RESETQUERYPOOL,
+ CMD_COPYQUERYPOOLRESULTS,
+ CMD_WRITETIMESTAMP,
+ CMD_PUSHCONSTANTS,
+ CMD_INITATOMICCOUNTERS,
+ CMD_LOADATOMICCOUNTERS,
+ CMD_SAVEATOMICCOUNTERS,
+ CMD_BEGINRENDERPASS,
+ CMD_NEXTSUBPASS,
+ CMD_ENDRENDERPASS,
+ CMD_EXECUTECOMMANDS,
+ CMD_END, // Should be last command in any RECORDED cmd buffer
+};
+
+// Data structure for holding sequence of cmds in cmd buffer
+struct CMD_NODE {
+ CMD_TYPE type;
+ uint64_t cmdNumber;
+};
+
+enum CB_STATE {
+ CB_NEW, // Newly created CB w/o any cmds
+ CB_RECORDING, // BeginCB has been called on this CB
+ CB_RECORDED, // EndCB has been called on this CB
+ CB_INVALID // CB had a bound descriptor set destroyed or updated
+};
+
+// CB Status -- used to track status of various bindings on cmd buffer objects
+typedef VkFlags CBStatusFlags;
+enum CBStatusFlagBits {
+ // clang-format off
+ CBSTATUS_NONE = 0x00000000, // No status is set
+ CBSTATUS_VIEWPORT_SET = 0x00000001, // Viewport has been set
+ CBSTATUS_LINE_WIDTH_SET = 0x00000002, // Line width has been set
+ CBSTATUS_DEPTH_BIAS_SET = 0x00000004, // Depth bias has been set
+ CBSTATUS_BLEND_CONSTANTS_SET = 0x00000008, // Blend constants state has been set
+ CBSTATUS_DEPTH_BOUNDS_SET = 0x00000010, // Depth bounds state object has been set
+ CBSTATUS_STENCIL_READ_MASK_SET = 0x00000020, // Stencil read mask has been set
+ CBSTATUS_STENCIL_WRITE_MASK_SET = 0x00000040, // Stencil write mask has been set
+ CBSTATUS_STENCIL_REFERENCE_SET = 0x00000080, // Stencil reference has been set
+ CBSTATUS_INDEX_BUFFER_BOUND = 0x00000100, // Index buffer has been set
+ CBSTATUS_SCISSOR_SET = 0x00000200, // Scissor has been set
+ CBSTATUS_ALL = 0x000003FF, // All dynamic state set
+ // clang-format on
+};
+
+struct QueryObject {
+ VkQueryPool pool;
+ uint32_t index;
+};
+
+inline bool operator==(const QueryObject &query1, const QueryObject &query2) {
+ return (query1.pool == query2.pool && query1.index == query2.index);
+}
+
+namespace std {
+template <> struct hash<QueryObject> {
+ size_t operator()(QueryObject query) const throw() {
+ return hash<uint64_t>()((uint64_t)(query.pool)) ^ hash<uint32_t>()(query.index);
+ }
+};
+}
+struct DRAW_DATA { std::vector<VkBuffer> buffers; };
+
+struct ImageSubresourcePair {
+ VkImage image;
+ bool hasSubresource;
+ VkImageSubresource subresource;
+};
+
+inline bool operator==(const ImageSubresourcePair &img1, const ImageSubresourcePair &img2) {
+ if (img1.image != img2.image || img1.hasSubresource != img2.hasSubresource)
+ return false;
+ return !img1.hasSubresource ||
+ (img1.subresource.aspectMask == img2.subresource.aspectMask && img1.subresource.mipLevel == img2.subresource.mipLevel &&
+ img1.subresource.arrayLayer == img2.subresource.arrayLayer);
+}
+
+namespace std {
+template <> struct hash<ImageSubresourcePair> {
+ size_t operator()(ImageSubresourcePair img) const throw() {
+ size_t hashVal = hash<uint64_t>()(reinterpret_cast<uint64_t &>(img.image));
+ hashVal ^= hash<bool>()(img.hasSubresource);
+ if (img.hasSubresource) {
+ hashVal ^= hash<uint32_t>()(reinterpret_cast<uint32_t &>(img.subresource.aspectMask));
+ hashVal ^= hash<uint32_t>()(img.subresource.mipLevel);
+ hashVal ^= hash<uint32_t>()(img.subresource.arrayLayer);
+ }
+ return hashVal;
+ }
+};
+}
+
+// Track last states that are bound per pipeline bind point (Gfx & Compute)
+struct LAST_BOUND_STATE {
+ VkPipeline pipeline;
+ VkPipelineLayout pipelineLayout;
+ // Track each set that has been bound
+ // TODO : can unique be global per CB? (do we care about Gfx vs. Compute?)
+ std::unordered_set<cvdescriptorset::DescriptorSet *> uniqueBoundSets;
+ // Ordered bound set tracking where index is set# that given set is bound to
+ std::vector<cvdescriptorset::DescriptorSet *> boundDescriptorSets;
+ // one dynamic offset per dynamic descriptor bound to this CB
+ std::vector<std::vector<uint32_t>> dynamicOffsets;
+
+ void reset() {
+ pipeline = VK_NULL_HANDLE;
+ pipelineLayout = VK_NULL_HANDLE;
+ uniqueBoundSets.clear();
+ boundDescriptorSets.clear();
+ dynamicOffsets.clear();
+ }
+};
+// Cmd Buffer Wrapper Struct - TODO : This desperately needs its own class
+struct GLOBAL_CB_NODE : public BASE_NODE {
+ VkCommandBuffer commandBuffer;
+ VkCommandBufferAllocateInfo createInfo;
+ VkCommandBufferBeginInfo beginInfo;
+ VkCommandBufferInheritanceInfo inheritanceInfo;
+ VkDevice device; // device this CB belongs to
+ uint64_t numCmds; // number of cmds in this CB
+ uint64_t drawCount[NUM_DRAW_TYPES]; // Count of each type of draw in this CB
+ CB_STATE state; // Track cmd buffer update state
+ uint64_t submitCount; // Number of times CB has been submitted
+ CBStatusFlags status; // Track status of various bindings on cmd buffer
+ std::vector<CMD_NODE> cmds; // vector of commands bound to this command buffer
+ // Currently storing "lastBound" objects on per-CB basis
+ // long-term may want to create caches of "lastBound" states and could have
+ // each individual CMD_NODE referencing its own "lastBound" state
+ // Store last bound state for Gfx & Compute pipeline bind points
+ LAST_BOUND_STATE lastBound[VK_PIPELINE_BIND_POINT_RANGE_SIZE];
+
+ std::vector<VkViewport> viewports;
+ std::vector<VkRect2D> scissors;
+ VkRenderPassBeginInfo activeRenderPassBeginInfo;
+ RENDER_PASS_NODE *activeRenderPass;
+ VkSubpassContents activeSubpassContents;
+ uint32_t activeSubpass;
+ VkFramebuffer activeFramebuffer;
+ std::unordered_set<VkFramebuffer> framebuffers;
+ // Track descriptor sets that are destroyed or updated while bound to CB
+ // TODO : These data structures relate to tracking resources that invalidate
+ // a cmd buffer that references them. Need to unify how we handle these
+ // cases so we don't have different tracking data for each type.
+ std::unordered_set<cvdescriptorset::DescriptorSet *> destroyedSets;
+ std::unordered_set<cvdescriptorset::DescriptorSet *> updatedSets;
+ std::unordered_set<VkFramebuffer> destroyedFramebuffers;
+ std::unordered_set<VkEvent> waitedEvents;
+ std::vector<VkEvent> writeEventsBeforeWait;
+ std::vector<VkEvent> events;
+ std::unordered_map<QueryObject, std::unordered_set<VkEvent>> waitedEventsBeforeQueryReset;
+ std::unordered_map<QueryObject, bool> queryToStateMap; // 0 is unavailable, 1 is available
+ std::unordered_set<QueryObject> activeQueries;
+ std::unordered_set<QueryObject> startedQueries;
+ std::unordered_map<ImageSubresourcePair, IMAGE_CMD_BUF_LAYOUT_NODE> imageLayoutMap;
+ std::unordered_map<VkImage, std::vector<ImageSubresourcePair>> imageSubresourceMap;
+ std::unordered_map<VkEvent, VkPipelineStageFlags> eventToStageMap;
+ std::vector<DRAW_DATA> drawData;
+ DRAW_DATA currentDrawData;
+ VkCommandBuffer primaryCommandBuffer;
+ // Track images and buffers that are updated by this CB at the point of a draw
+ std::unordered_set<VkImageView> updateImages;
+ std::unordered_set<VkBuffer> updateBuffers;
+ // If cmd buffer is primary, track secondary command buffers pending
+ // execution
+ std::unordered_set<VkCommandBuffer> secondaryCommandBuffers;
+ // MTMTODO : Scrub these data fields and merge active sets w/ lastBound as appropriate
+ std::vector<std::function<bool()>> validate_functions;
+ std::unordered_set<VkDeviceMemory> memObjs;
+ std::vector<std::function<bool(VkQueue)>> eventUpdates;
+ std::vector<std::function<bool(VkQueue)>> queryUpdates;
+
+ ~GLOBAL_CB_NODE();
+};
+
+struct CB_SUBMISSION {
+ CB_SUBMISSION(VkCommandBuffer cb, std::vector<VkSemaphore> const & semaphores)
+ : cb(cb), semaphores(semaphores) {}
+
+ VkCommandBuffer cb;
+ std::vector<VkSemaphore> semaphores;
+};
+
+// Fwd declarations of layer_data and helpers to look-up state from layer_data maps
+namespace core_validation {
+struct layer_data;
+cvdescriptorset::DescriptorSet *getSetNode(const layer_data *, VkDescriptorSet);
+cvdescriptorset::DescriptorSetLayout const *getDescriptorSetLayout(layer_data const *, VkDescriptorSetLayout);
+DESCRIPTOR_POOL_NODE *getPoolNode(const layer_data *, const VkDescriptorPool);
+BUFFER_NODE *getBufferNode(const layer_data *, VkBuffer);
+IMAGE_NODE *getImageNode(const layer_data *, VkImage);
+DEVICE_MEM_INFO *getMemObjInfo(const layer_data *, VkDeviceMemory);
+VkBufferViewCreateInfo *getBufferViewInfo(const layer_data *, VkBufferView);
+SAMPLER_NODE *getSamplerNode(const layer_data *, VkSampler);
+VkImageViewCreateInfo *getImageViewData(const layer_data *, VkImageView);
+VkSwapchainKHR getSwapchainFromImage(const layer_data *, VkImage);
+SWAPCHAIN_NODE *getSwapchainNode(const layer_data *, VkSwapchainKHR);
+}
+
+#endif // CORE_VALIDATION_TYPES_H_
diff --git a/layers/descriptor_sets.cpp b/layers/descriptor_sets.cpp
index 89c44c68..a8e88cf8 100644
--- a/layers/descriptor_sets.cpp
+++ b/layers/descriptor_sets.cpp
@@ -59,6 +59,7 @@ void cvdescriptorset::DescriptorSetLayout::FillBindingSet(std::unordered_set<uin
for (auto binding_index_pair : binding_to_index_map_)
binding_set->insert(binding_index_pair.first);
}
+
VkDescriptorSetLayoutBinding const *
cvdescriptorset::DescriptorSetLayout::GetDescriptorSetLayoutBindingPtrFromBinding(const uint32_t binding) const {
const auto &bi_itr = binding_to_index_map_.find(binding);
@@ -259,18 +260,12 @@ bool cvdescriptorset::DescriptorSetLayout::VerifyUpdateConsistency(uint32_t curr
return true;
}
+cvdescriptorset::AllocateDescriptorSetsData::AllocateDescriptorSetsData(uint32_t count)
+ : required_descriptors_by_type{}, layout_nodes(count, nullptr) {}
+
cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const DescriptorSetLayout *layout,
- const std::unordered_map<VkBuffer, BUFFER_NODE> *buffer_map,
- const std::unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> *memory_map,
- const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> *buffer_view_map,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map,
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map,
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map,
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map)
- : some_update_(false), set_(set), p_layout_(layout), buffer_map_(buffer_map), memory_map_(memory_map),
- buffer_view_map_(buffer_view_map), sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map),
- image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) {
+ const core_validation::layer_data *dev_data)
+ : some_update_(false), set_(set), p_layout_(layout), device_data_(dev_data) {
// Foreach binding, create default descriptors of given type
for (uint32_t i = 0; i < p_layout_->GetBindingCount(); ++i) {
auto type = p_layout_->GetTypeFromIndex(i);
@@ -279,9 +274,9 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D
auto immut_sampler = p_layout_->GetImmutableSamplerPtrFromIndex(i);
for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
if (immut_sampler)
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(new SamplerDescriptor(immut_sampler + di, sampler_map_)));
+ descriptors_.emplace_back(new SamplerDescriptor(immut_sampler + di));
else
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(new SamplerDescriptor(sampler_map_)));
+ descriptors_.emplace_back(new SamplerDescriptor());
}
break;
}
@@ -289,11 +284,9 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D
auto immut = p_layout_->GetImmutableSamplerPtrFromIndex(i);
for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di) {
if (immut)
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(new ImageSamplerDescriptor(
- immut + di, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, sampler_map_)));
+ descriptors_.emplace_back(new ImageSamplerDescriptor(immut + di));
else
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(new ImageSamplerDescriptor(
- image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_, sampler_map_)));
+ descriptors_.emplace_back(new ImageSamplerDescriptor());
}
break;
}
@@ -302,20 +295,19 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D
case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(
- new ImageDescriptor(type, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_)));
+ descriptors_.emplace_back(new ImageDescriptor(type));
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(new TexelDescriptor(type, buffer_view_map_)));
+ descriptors_.emplace_back(new TexelDescriptor(type));
break;
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
for (uint32_t di = 0; di < p_layout_->GetDescriptorCountFromIndex(i); ++di)
- descriptors_.emplace_back(std::unique_ptr<Descriptor>(new BufferDescriptor(type, buffer_map_)));
+ descriptors_.emplace_back(new BufferDescriptor(type));
break;
default:
assert(0); // Bad descriptor type specified
@@ -323,6 +315,16 @@ cvdescriptorset::DescriptorSet::DescriptorSet(const VkDescriptorSet set, const D
}
}
}
+
+cvdescriptorset::DescriptorSet::~DescriptorSet() {
+ InvalidateBoundCmdBuffers();
+ // Remove link to any cmd buffers
+ for (auto cb : bound_cmd_buffers_) {
+ for (uint32_t i=0; i<VK_PIPELINE_BIND_POINT_RANGE_SIZE; ++i) {
+ cb->lastBound[i].uniqueBoundSets.erase(this);
+ }
+ }
+}
// Is this sets underlying layout compatible with passed in layout according to "Pipeline Layout Compatibility" in spec?
bool cvdescriptorset::DescriptorSet::IsCompatible(const DescriptorSetLayout *layout, std::string *error) const {
return layout->IsCompatible(p_layout_, error);
@@ -333,13 +335,13 @@ bool cvdescriptorset::DescriptorSet::IsCompatible(const DescriptorSetLayout *lay
// Return true if state is acceptable, or false and write an error message into error string
bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::unordered_set<uint32_t> &bindings,
const std::vector<uint32_t> &dynamic_offsets, std::string *error) const {
+ auto dyn_offset_index = 0;
for (auto binding : bindings) {
auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(binding);
if (descriptors_[start_idx]->IsImmutableSampler()) {
// Nothing to do for strictly immutable sampler
} else {
auto end_idx = p_layout_->GetGlobalEndIndexFromBinding(binding);
- auto dyn_offset_index = 0;
for (uint32_t i = start_idx; i <= end_idx; ++i) {
if (!descriptors_[i]->updated) {
std::stringstream error_str;
@@ -351,27 +353,27 @@ bool cvdescriptorset::DescriptorSet::ValidateDrawState(const std::unordered_set<
if (GeneralBuffer == descriptors_[i]->GetClass()) {
// Verify that buffers are valid
auto buffer = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetBuffer();
- auto buffer_node = buffer_map_->find(buffer);
- if (buffer_node == buffer_map_->end()) {
+ auto buffer_node = getBufferNode(device_data_, buffer);
+ if (!buffer_node) {
std::stringstream error_str;
error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
<< " references invalid buffer " << buffer << ".";
*error = error_str.str();
return false;
} else {
- auto mem_entry = memory_map_->find(buffer_node->second.mem);
- if (mem_entry == memory_map_->end()) {
+ auto mem_entry = getMemObjInfo(device_data_, buffer_node->mem);
+ if (!mem_entry) {
std::stringstream error_str;
error_str << "Descriptor in binding #" << binding << " at global descriptor index " << i
- << " uses buffer " << buffer << " that references invalid memory "
- << buffer_node->second.mem << ".";
+ << " uses buffer " << buffer << " that references invalid memory " << buffer_node->mem
+ << ".";
*error = error_str.str();
return false;
}
}
if (descriptors_[i]->IsDynamic()) {
// Validate that dynamic offsets are within the buffer
- auto buffer_size = buffer_node->second.createInfo.size;
+ auto buffer_size = buffer_node->createInfo.size;
auto range = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetRange();
auto desc_offset = static_cast<BufferDescriptor *>(descriptors_[i].get())->GetOffset();
auto dyn_offset = dynamic_offsets[dyn_offset_index++];
@@ -424,9 +426,9 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::unordered_
for (uint32_t i = 0; i < p_layout_->GetDescriptorCountFromBinding(binding); ++i) {
if (descriptors_[start_idx + i]->updated) {
auto bufferview = static_cast<TexelDescriptor *>(descriptors_[start_idx + i].get())->GetBufferView();
- const auto &buff_pair = buffer_view_map_->find(bufferview);
- if (buff_pair != buffer_view_map_->end()) {
- buffer_set->insert(buff_pair->second.buffer);
+ auto bv_info = getBufferViewInfo(device_data_, bufferview);
+ if (bv_info) {
+ buffer_set->insert(bv_info->buffer);
num_updates++;
}
}
@@ -443,74 +445,35 @@ uint32_t cvdescriptorset::DescriptorSet::GetStorageUpdates(const std::unordered_
}
return num_updates;
}
-// This is a special case for compute shaders that should eventually be removed once we have proper valid binding info for compute
-// case
-uint32_t cvdescriptorset::DescriptorSet::GetAllStorageUpdates(std::unordered_set<VkBuffer> *buffer_set,
- std::unordered_set<VkImageView> *image_set) const {
- std::unordered_set<uint32_t> binding_set;
- p_layout_->FillBindingSet(&binding_set);
- return GetStorageUpdates(binding_set, buffer_set, image_set);
+// Set is being deleted or updates so invalidate all bound cmd buffers
+void cvdescriptorset::DescriptorSet::InvalidateBoundCmdBuffers() {
+ for (auto cb_node : bound_cmd_buffers_) {
+ cb_node->state = CB_INVALID;
+ }
}
// Perform write update in given update struct
-// If an error occurs, return false and fill in details in error_msg string
-bool cvdescriptorset::DescriptorSet::WriteUpdate(debug_report_data *report_data, const VkWriteDescriptorSet *update,
- std::string *error_msg) {
- auto num_updates = 0;
- // Verify dst binding exists
- if (!p_layout_->HasBinding(update->dstBinding)) {
- std::stringstream error_str;
- error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding << ".";
- *error_msg = error_str.str();
- return false;
- } else {
- // We know that binding is valid, verify update and do update on each descriptor
- auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
- auto type = p_layout_->GetTypeFromBinding(update->dstBinding);
- if (type != update->descriptorType) {
- std::stringstream error_str;
- error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with type "
- << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType);
- *error_msg = error_str.str();
- return false;
- }
- if ((start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) {
- std::stringstream error_str;
- error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with "
- << p_layout_->GetTotalDescriptorCount() << " total descriptors but update of " << update->descriptorCount
- << " descriptors starting at binding offset of "
- << p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding)
- << " combined with update array element offset of " << update->dstArrayElement
- << " oversteps the size of this descriptor set.";
- *error_msg = error_str.str();
- return false;
- }
- // Verify consecutive bindings match (if needed)
- if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount,
- "write update to", set_, error_msg))
- return false;
- // Update is within bounds and consistent so perform update
- for (uint32_t di = 0; di < update->descriptorCount; ++di) {
- // TODO : Can we break this into a set-level "Validate" followed by Descriptor updating itself
- // if the validate passes? That saves us all the map ptrs in each descriptor instance
- if (!descriptors_[start_idx + di]->WriteUpdate(update, di, error_msg)) {
- std::stringstream error_str;
- error_str << "Write update to descriptor at global index " << start_idx + di << " within set " << set_
- << " binding #" << update->dstBinding << " failed with error message: " << error_msg->c_str();
- *error_msg = error_str.str();
- return false;
- }
- ++num_updates;
- }
+void cvdescriptorset::DescriptorSet::PerformWriteUpdate(const VkWriteDescriptorSet *update) {
+ auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
+ // perform update
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ descriptors_[start_idx + di]->WriteUpdate(update, di);
}
- if (num_updates != 0) {
+ if (update->descriptorCount)
some_update_ = true;
- }
- return true;
+
+ InvalidateBoundCmdBuffers();
}
-// Copy update
-bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data, const VkCopyDescriptorSet *update,
- const DescriptorSet *src_set, std::string *error) {
- auto num_updates = 0;
+// Validate Copy update
+bool cvdescriptorset::DescriptorSet::ValidateCopyUpdate(const debug_report_data *report_data, const VkCopyDescriptorSet *update,
+ const DescriptorSet *src_set, std::string *error) {
+ // Verify idle ds
+ if (in_use.load()) {
+ std::stringstream error_str;
+ error_str << "Cannot call vkUpdateDescriptorSets() to perform copy update on descriptor set " << set_
+ << " that is in use by a command buffer.";
+ *error = error_str.str();
+ return false;
+ }
if (!p_layout_->HasBinding(update->dstBinding)) {
std::stringstream error_str;
error_str << "DescriptorSet " << set_ << " does not have copy update dest binding of " << update->dstBinding << ".";
@@ -565,27 +528,43 @@ bool cvdescriptorset::DescriptorSet::CopyUpdate(debug_report_data *report_data,
set_, error))) {
return false;
}
+ // First make sure source descriptors are updated
+ for (uint32_t i = 0; i < update->descriptorCount; ++i) {
+ if (!src_set->descriptors_[src_start_idx + i]) {
+ std::stringstream error_str;
+ error_str << "Attempting copy update from descriptorSet " << src_set << " binding #" << update->srcBinding << " but descriptor at array offset "
+ << update->srcArrayElement + i << " has not been updated.";
+ *error = error_str.str();
+ return false;
+ }
+ }
+ // Update parameters all look good and descriptor updated so verify update contents
+ if (!VerifyCopyUpdateContents(update, src_set, src_type, src_start_idx, error))
+ return false;
+
+ // All checks passed so update is good
+ return true;
+}
+// Perform Copy update
+void cvdescriptorset::DescriptorSet::PerformCopyUpdate(const VkCopyDescriptorSet *update, const DescriptorSet *src_set) {
+ auto src_start_idx = src_set->GetGlobalStartIndexFromBinding(update->srcBinding) + update->srcArrayElement;
+ auto dst_start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
// Update parameters all look good so perform update
for (uint32_t di = 0; di < update->descriptorCount; ++di) {
- if (!descriptors_[dst_start_idx]->CopyUpdate(src_set->descriptors_[src_start_idx].get(), error))
- return false;
- ++num_updates;
+ descriptors_[dst_start_idx + di]->CopyUpdate(src_set->descriptors_[src_start_idx + di].get());
}
- if (num_updates != 0) {
+ if (update->descriptorCount)
some_update_ = true;
- }
- return true;
+
+ InvalidateBoundCmdBuffers();
}
-cvdescriptorset::SamplerDescriptor::SamplerDescriptor(
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map)
- : sampler_(VK_NULL_HANDLE), immutable_(false), sampler_map_(sampler_map) {
+
+cvdescriptorset::SamplerDescriptor::SamplerDescriptor() : sampler_(VK_NULL_HANDLE), immutable_(false) {
updated = false;
descriptor_class = PlainSampler;
};
-cvdescriptorset::SamplerDescriptor::SamplerDescriptor(
- const VkSampler *immut, const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map)
- : sampler_(VK_NULL_HANDLE), immutable_(false), sampler_map_(sampler_map) {
+cvdescriptorset::SamplerDescriptor::SamplerDescriptor(const VkSampler *immut) : sampler_(VK_NULL_HANDLE), immutable_(false) {
updated = false;
descriptor_class = PlainSampler;
if (immut) {
@@ -594,173 +573,158 @@ cvdescriptorset::SamplerDescriptor::SamplerDescriptor(
updated = true;
}
}
-bool cvdescriptorset::ValidateSampler(const VkSampler sampler,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map) {
- return (sampler_map->count(sampler) != 0);
+// Validate given sampler. Currently this only checks to make sure it exists in the samplerMap
+bool cvdescriptorset::ValidateSampler(const VkSampler sampler, const core_validation::layer_data *dev_data) {
+ return (getSamplerNode(dev_data, sampler) != nullptr);
}
-bool cvdescriptorset::ValidateImageUpdate(const VkImageView image_view, const VkImageLayout image_layout,
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map,
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map,
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map,
+
+bool cvdescriptorset::ValidateImageUpdate(VkImageView image_view, VkImageLayout image_layout, VkDescriptorType type,
+ const core_validation::layer_data *dev_data,
std::string *error) {
- auto image_pair = image_view_map->find(image_view);
- if (image_pair == image_view_map->end()) {
+ auto iv_data = getImageViewData(dev_data, image_view);
+ if (!iv_data) {
std::stringstream error_str;
error_str << "Invalid VkImageView: " << image_view;
*error = error_str.str();
return false;
+ }
+ // Validate that imageLayout is compatible with aspect_mask and image format
+ // and validate that image usage bits are correct for given usage
+ VkImageAspectFlags aspect_mask = iv_data->subresourceRange.aspectMask;
+ VkImage image = iv_data->image;
+ VkFormat format = VK_FORMAT_MAX_ENUM;
+ VkImageUsageFlags usage = 0;
+ auto image_node = getImageNode(dev_data, image);
+ if (image_node) {
+ format = image_node->createInfo.format;
+ usage = image_node->createInfo.usage;
} else {
- // Validate that imageLayout is compatible with aspect_mask and image format
- VkImageAspectFlags aspect_mask = image_pair->second.subresourceRange.aspectMask;
- VkImage image = image_pair->second.image;
- VkFormat format = VK_FORMAT_MAX_ENUM;
- auto img_pair = image_map->find(image);
- if (img_pair != image_map->end()) {
- format = img_pair->second.createInfo.format;
- } else {
- // Also need to check the swapchains.
- auto swapchain_pair = image_to_swapchain_map->find(image);
- if (swapchain_pair != image_to_swapchain_map->end()) {
- VkSwapchainKHR swapchain = swapchain_pair->second;
- auto swapchain_pair = swapchain_map->find(swapchain);
- if (swapchain_pair != swapchain_map->end()) {
- format = swapchain_pair->second->createInfo.imageFormat;
- }
+ // Also need to check the swapchains.
+ auto swapchain = getSwapchainFromImage(dev_data, image);
+ if (swapchain) {
+ auto swapchain_node = getSwapchainNode(dev_data, swapchain);
+ if (swapchain_node) {
+ format = swapchain_node->createInfo.imageFormat;
}
}
- if (format == VK_FORMAT_MAX_ENUM) {
+ }
+ // First validate that format and layout are compatible
+ if (format == VK_FORMAT_MAX_ENUM) {
+ std::stringstream error_str;
+ error_str << "Invalid image (" << image << ") in imageView (" << image_view << ").";
+ *error = error_str.str();
+ return false;
+ }
+ bool ds = vk_format_is_depth_or_stencil(format);
+ switch (image_layout) {
+ case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
+ // Only Color bit must be set
+ if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
std::stringstream error_str;
- error_str << "Invalid image (" << image << ") in imageView (" << image_view << ").";
+ error_str << "ImageView (" << image_view << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does "
+ "not have VK_IMAGE_ASPECT_COLOR_BIT set.";
*error = error_str.str();
return false;
- } else {
- bool ds = vk_format_is_depth_or_stencil(format);
- switch (image_layout) {
- case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
- // Only Color bit must be set
- if ((aspect_mask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
- std::stringstream error_str;
- error_str << "ImageView (" << image_view << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but does "
- "not have VK_IMAGE_ASPECT_COLOR_BIT set.";
- *error = error_str.str();
- return false;
- }
- // format must NOT be DS
- if (ds) {
- std::stringstream error_str;
- error_str << "ImageView (" << image_view
- << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
- << string_VkFormat(format) << " which is not a color format.";
- *error = error_str.str();
- return false;
- }
- break;
- case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
- case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
- // Depth or stencil bit must be set, but both must NOT be set
- if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
- if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
- // both must NOT be set
- std::stringstream error_str;
- error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set";
- *error = error_str.str();
- return false;
- }
- } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
- // Neither were set
- std::stringstream error_str;
- error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
- << " but does not have STENCIL or DEPTH aspects set";
- *error = error_str.str();
- return false;
- }
- // format must be DS
- if (!ds) {
- std::stringstream error_str;
- error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
- << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format.";
- *error = error_str.str();
- return false;
- }
- break;
- default:
- // anything to check for other layouts?
- break;
- }
}
- }
- return true;
-}
-bool cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) {
- if (!immutable_) {
- if (!ValidateSampler(update->pImageInfo[index].sampler, sampler_map_)) {
+ // format must NOT be DS
+ if (ds) {
std::stringstream error_str;
- error_str << "Attempted write update to sampler descriptor with invalid sampler: " << update->pImageInfo[index].sampler
- << ".";
+ error_str << "ImageView (" << image_view
+ << ") uses layout VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL but the image format is "
+ << string_VkFormat(format) << " which is not a color format.";
*error = error_str.str();
return false;
}
- sampler_ = update->pImageInfo[index].sampler;
- } else {
- if (!ValidateSampler(sampler_, sampler_map_)) {
+ break;
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL:
+ case VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL:
+ // Depth or stencil bit must be set, but both must NOT be set
+ if (aspect_mask & VK_IMAGE_ASPECT_DEPTH_BIT) {
+ if (aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT) {
+ // both must NOT be set
+ std::stringstream error_str;
+ error_str << "ImageView (" << image_view << ") has both STENCIL and DEPTH aspects set";
+ *error = error_str.str();
+ return false;
+ }
+ } else if (!(aspect_mask & VK_IMAGE_ASPECT_STENCIL_BIT)) {
+ // Neither were set
std::stringstream error_str;
- error_str << "Attempted write update to immutable sampler descriptor which has invalid immutable sampler: " << sampler_
- << ".";
+ error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
+ << " but does not have STENCIL or DEPTH aspects set";
*error = error_str.str();
return false;
}
- // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)?
+ // format must be DS
+ if (!ds) {
+ std::stringstream error_str;
+ error_str << "ImageView (" << image_view << ") has layout " << string_VkImageLayout(image_layout)
+ << " but the image format is " << string_VkFormat(format) << " which is not a depth/stencil format.";
+ *error = error_str.str();
+ return false;
+ }
+ break;
+ default:
+ // anything to check for other layouts?
+ break;
+ }
+ // Now validate that usage flags are correctly set for given type of update
+ std::string error_usage_bit;
+ switch (type) {
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
+ if (!(usage & VK_IMAGE_USAGE_SAMPLED_BIT)) {
+ error_usage_bit = "VK_IMAGE_USAGE_SAMPLED_BIT";
+ }
+ break;
+ }
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
+ if (!(usage & VK_IMAGE_USAGE_STORAGE_BIT)) {
+ error_usage_bit = "VK_IMAGE_USAGE_STORAGE_BIT";
+ }
+ break;
+ }
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT: {
+ if (!(usage & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)) {
+ error_usage_bit = "VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT";
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ if (!error_usage_bit.empty()) {
+ std::stringstream error_str;
+ error_str << "ImageView (" << image_view << ") with usage mask 0x" << usage
+ << " being used for a descriptor update of type " << string_VkDescriptorType(type) << " does not have "
+ << error_usage_bit << " set.";
+ *error = error_str.str();
+ return false;
}
- updated = true;
return true;
}
-bool cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src, std::string *error) {
+void cvdescriptorset::SamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
+ sampler_ = update->pImageInfo[index].sampler;
+ updated = true;
+}
+
+void cvdescriptorset::SamplerDescriptor::CopyUpdate(const Descriptor *src) {
if (!immutable_) {
auto update_sampler = static_cast<const SamplerDescriptor *>(src)->sampler_;
- if (!ValidateSampler(update_sampler, sampler_map_)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
- *error = error_str.str();
- return false;
- }
sampler_ = update_sampler;
- } else {
- if (!ValidateSampler(sampler_, sampler_map_)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to immutable sampler descriptor which has invalid immutable sampler: " << sampler_
- << ".";
- *error = error_str.str();
- return false;
- }
- // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)?
}
updated = true;
- return true;
}
-cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map,
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map,
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map)
- : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED),
- sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map),
- image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) {
+
+cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor()
+ : sampler_(VK_NULL_HANDLE), immutable_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
updated = false;
descriptor_class = ImageSampler;
}
-cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(
- const VkSampler *immut, const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map,
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map,
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map)
- : sampler_(VK_NULL_HANDLE), immutable_(true), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED),
- sampler_map_(sampler_map), image_view_map_(image_view_map), image_map_(image_map),
- image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) {
+cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(const VkSampler *immut)
+ : sampler_(VK_NULL_HANDLE), immutable_(true), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
updated = false;
descriptor_class = ImageSampler;
if (immut) {
@@ -769,134 +733,52 @@ cvdescriptorset::ImageSamplerDescriptor::ImageSamplerDescriptor(
updated = true;
}
}
-bool cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index,
- std::string *error) {
- // First check sampler
- if (!immutable_) {
- if (!ValidateSampler(update->pImageInfo[index].sampler, sampler_map_)) {
- std::stringstream error_str;
- error_str << "Attempted write update to combined image sampler descriptor with invalid sampler: "
- << update->pImageInfo[index].sampler << ".";
- *error = error_str.str();
- return false;
- }
- sampler_ = update->pImageInfo[index].sampler;
- } else {
- if (!ValidateSampler(sampler_, sampler_map_)) {
- std::stringstream error_str;
- error_str << "Attempted write update to combined image sampler descriptor with immutable sampler which has invalid "
- "immutable sampler: "
- << sampler_ << ".";
- *error = error_str.str();
- return false;
- }
- // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)?
- }
- // Now validate images
- auto image_view = update->pImageInfo[index].imageView;
- auto image_layout = update->pImageInfo[index].imageLayout;
- if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_,
- error)) {
- std::stringstream error_str;
- error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str();
- *error = error_str.str();
- return false;
- }
+
+void cvdescriptorset::ImageSamplerDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
updated = true;
- image_view_ = image_view;
- image_layout_ = image_layout;
- return true;
+ const auto &image_info = update->pImageInfo[index];
+ sampler_ = image_info.sampler;
+ image_view_ = image_info.imageView;
+ image_layout_ = image_info.imageLayout;
}
-bool cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src, std::string *error) {
+void cvdescriptorset::ImageSamplerDescriptor::CopyUpdate(const Descriptor *src) {
if (!immutable_) {
auto update_sampler = static_cast<const ImageSamplerDescriptor *>(src)->sampler_;
- if (!ValidateSampler(update_sampler, sampler_map_)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to combined image sampler descriptor with invalid sampler: " << update_sampler
- << ".";
- *error = error_str.str();
- return false;
- }
sampler_ = update_sampler;
- } else {
- if (!ValidateSampler(sampler_, sampler_map_)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to combined image sampler descriptor with immutable sampler that has invalid "
- "immutable sampler: "
- << sampler_ << ".";
- *error = error_str.str();
- return false;
- }
- // TODO : Do we want a way to warn here in case of updating immutable sampler (which can't be updated)?
}
- // Now validate images
auto image_view = static_cast<const ImageSamplerDescriptor *>(src)->image_view_;
auto image_layout = static_cast<const ImageSamplerDescriptor *>(src)->image_layout_;
- if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_,
- error)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str();
- *error = error_str.str();
- return false;
- }
updated = true;
image_view_ = image_view;
image_layout_ = image_layout;
- return true;
}
-cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type,
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map,
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map,
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map)
- : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED), image_view_map_(image_view_map),
- image_map_(image_map), image_to_swapchain_map_(image_to_swapchain_map), swapchain_map_(swapchain_map) {
+cvdescriptorset::ImageDescriptor::ImageDescriptor(const VkDescriptorType type)
+ : storage_(false), image_view_(VK_NULL_HANDLE), image_layout_(VK_IMAGE_LAYOUT_UNDEFINED) {
updated = false;
descriptor_class = Image;
if (VK_DESCRIPTOR_TYPE_STORAGE_IMAGE == type)
storage_ = true;
};
-bool cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) {
- // First validate that the write update is valid
- auto image_view = update->pImageInfo[index].imageView;
- auto image_layout = update->pImageInfo[index].imageLayout;
- if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_,
- error)) {
- std::stringstream error_str;
- error_str << "Attempted write update to image descriptor failed due to: " << error->c_str();
- *error = error_str.str();
- return false;
- }
- // Update is clean so process it
+void cvdescriptorset::ImageDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
updated = true;
- image_view_ = image_view;
- image_layout_ = image_layout;
- return true;
+ const auto &image_info = update->pImageInfo[index];
+ image_view_ = image_info.imageView;
+ image_layout_ = image_info.imageLayout;
}
-bool cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src, std::string *error) {
- // First validate update
+void cvdescriptorset::ImageDescriptor::CopyUpdate(const Descriptor *src) {
auto image_view = static_cast<const ImageDescriptor *>(src)->image_view_;
auto image_layout = static_cast<const ImageDescriptor *>(src)->image_layout_;
- if (!ValidateImageUpdate(image_view, image_layout, image_view_map_, image_map_, image_to_swapchain_map_, swapchain_map_,
- error)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str();
- *error = error_str.str();
- return false;
- }
updated = true;
image_view_ = image_view;
image_layout_ = image_layout;
- return true;
}
-cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type,
- const std::unordered_map<VkBuffer, BUFFER_NODE> *buffer_map)
- : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0), buffer_map_(buffer_map) {
+cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type)
+ : storage_(false), dynamic_(false), buffer_(VK_NULL_HANDLE), offset_(0), range_(0) {
updated = false;
descriptor_class = GeneralBuffer;
if (VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC == type) {
@@ -908,70 +790,501 @@ cvdescriptorset::BufferDescriptor::BufferDescriptor(const VkDescriptorType type,
storage_ = true;
}
}
-bool cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) {
- // First validate bufferinfo
- auto buffer = update->pBufferInfo[index].buffer;
- if (!buffer_map_->count(buffer)) {
- std::stringstream error_str;
- error_str << "Attempted write update to buffer descriptor with invalid buffer: " << buffer;
- *error = error_str.str();
- return false;
- }
+void cvdescriptorset::BufferDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
updated = true;
- buffer_ = buffer;
- offset_ = update->pBufferInfo[index].offset;
- range_ = update->pBufferInfo[index].range;
- return true;
+ const auto &buffer_info = update->pBufferInfo[index];
+ buffer_ = buffer_info.buffer;
+ offset_ = buffer_info.offset;
+ range_ = buffer_info.range;
}
-bool cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src, std::string *error) {
- // First validate bufferinfo
- auto buffer = static_cast<const BufferDescriptor *>(src)->buffer_;
- if (!buffer_map_->count(buffer)) {
- std::stringstream error_str;
- error_str << "Attempted copy update to buffer descriptor with invalid buffer: " << buffer;
- *error = error_str.str();
- return false;
- }
+void cvdescriptorset::BufferDescriptor::CopyUpdate(const Descriptor *src) {
+ auto buff_desc = static_cast<const BufferDescriptor *>(src);
updated = true;
- buffer_ = buffer;
- offset_ = static_cast<const BufferDescriptor *>(src)->offset_;
- range_ = static_cast<const BufferDescriptor *>(src)->range_;
- return true;
+ buffer_ = buff_desc->buffer_;
+ offset_ = buff_desc->offset_;
+ range_ = buff_desc->range_;
}
-cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type,
- const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> *buffer_view_map)
- : buffer_view_(VK_NULL_HANDLE), storage_(false), buffer_view_map_(buffer_view_map) {
+cvdescriptorset::TexelDescriptor::TexelDescriptor(const VkDescriptorType type) : buffer_view_(VK_NULL_HANDLE), storage_(false) {
updated = false;
descriptor_class = TexelBuffer;
if (VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER == type)
storage_ = true;
};
-bool cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index, std::string *error) {
- // First validate buffer view
- auto buffer_view = update->pTexelBufferView[index];
- if (!buffer_view_map_->count(buffer_view)) {
+
+void cvdescriptorset::TexelDescriptor::WriteUpdate(const VkWriteDescriptorSet *update, const uint32_t index) {
+ updated = true;
+ buffer_view_ = update->pTexelBufferView[index];
+}
+
+void cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src) {
+ updated = true;
+ buffer_view_ = static_cast<const TexelDescriptor *>(src)->buffer_view_;
+}
+// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
+// sets, and then calls their respective Validate[Write|Copy]Update functions.
+// If the update hits an issue for which the callback returns "true", meaning that the call down the chain should
+// be skipped, then true is returned.
+// If there is no issue with the update, then false is returned.
+bool cvdescriptorset::ValidateUpdateDescriptorSets(const debug_report_data *report_data,
+ const core_validation::layer_data *dev_data, uint32_t write_count,
+ const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
+ const VkCopyDescriptorSet *p_cds) {
+ bool skip_call = false;
+ // Validate Write updates
+ for (uint32_t i = 0; i < write_count; i++) {
+ auto dest_set = p_wds[i].dstSet;
+ auto set_node = core_validation::getSetNode(dev_data, dest_set);
+ if (!set_node) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
+ reinterpret_cast<uint64_t &>(dest_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
+ "Cannot call vkUpdateDescriptorSets() on descriptor set 0x%" PRIxLEAST64 " that has not been allocated.",
+ reinterpret_cast<uint64_t &>(dest_set));
+ } else {
+ std::string error_str;
+ if (!set_node->ValidateWriteUpdate(report_data, &p_wds[i], &error_str)) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
+ reinterpret_cast<uint64_t &>(dest_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
+ "vkUpdateDescriptorsSets() failed write update validation for Descriptor Set 0x%" PRIx64
+ " with error: %s",
+ reinterpret_cast<uint64_t &>(dest_set), error_str.c_str());
+ }
+ }
+ }
+ // Now validate copy updates
+ for (uint32_t i = 0; i < copy_count; ++i) {
+ auto dst_set = p_cds[i].dstSet;
+ auto src_set = p_cds[i].srcSet;
+ auto src_node = core_validation::getSetNode(dev_data, src_set);
+ auto dst_node = core_validation::getSetNode(dev_data, dst_set);
+ if (!src_node) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
+ reinterpret_cast<uint64_t &>(src_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
+ "Cannot call vkUpdateDescriptorSets() to copy from descriptor set 0x%" PRIxLEAST64
+ " that has not been allocated.",
+ reinterpret_cast<uint64_t &>(src_set));
+ } else if (!dst_node) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
+ reinterpret_cast<uint64_t &>(dst_set), __LINE__, DRAWSTATE_INVALID_DESCRIPTOR_SET, "DS",
+ "Cannot call vkUpdateDescriptorSets() to copy to descriptor set 0x%" PRIxLEAST64
+ " that has not been allocated.",
+ reinterpret_cast<uint64_t &>(dst_set));
+ } else {
+ std::string error_str;
+ if (!dst_node->ValidateCopyUpdate(report_data, &p_cds[i], src_node, &error_str)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT,
+ reinterpret_cast<uint64_t &>(dst_set), __LINE__, DRAWSTATE_INVALID_UPDATE_INDEX, "DS",
+ "vkUpdateDescriptorsSets() failed copy update from Descriptor Set 0x%" PRIx64
+ " to Descriptor Set 0x%" PRIx64 " with error: %s",
+ reinterpret_cast<uint64_t &>(src_set), reinterpret_cast<uint64_t &>(dst_set), error_str.c_str());
+ }
+ }
+ }
+ return skip_call;
+}
+// This is a helper function that iterates over a set of Write and Copy updates, pulls the DescriptorSet* for updated
+// sets, and then calls their respective Perform[Write|Copy]Update functions.
+// Prerequisite : ValidateUpdateDescriptorSets() should be called and return "false" prior to calling PerformUpdateDescriptorSets()
+// with the same set of updates.
+// This is split from the validate code to allow validation prior to calling down the chain, and then update after
+// calling down the chain.
+void cvdescriptorset::PerformUpdateDescriptorSets(const core_validation::layer_data *dev_data, uint32_t write_count,
+ const VkWriteDescriptorSet *p_wds, uint32_t copy_count,
+ const VkCopyDescriptorSet *p_cds) {
+ // Write updates first
+ uint32_t i = 0;
+ for (i = 0; i < write_count; ++i) {
+ auto dest_set = p_wds[i].dstSet;
+ auto set_node = core_validation::getSetNode(dev_data, dest_set);
+ if (set_node) {
+ set_node->PerformWriteUpdate(&p_wds[i]);
+ }
+ }
+ // Now copy updates
+ for (i = 0; i < copy_count; ++i) {
+ auto dst_set = p_cds[i].dstSet;
+ auto src_set = p_cds[i].srcSet;
+ auto src_node = core_validation::getSetNode(dev_data, src_set);
+ auto dst_node = core_validation::getSetNode(dev_data, dst_set);
+ if (src_node && dst_node) {
+ dst_node->PerformCopyUpdate(&p_cds[i], src_node);
+ }
+ }
+}
+// Validate the state for a given write update but don't actually perform the update
+// If an error would occur for this update, return false and fill in details in error_msg string
+bool cvdescriptorset::DescriptorSet::ValidateWriteUpdate(const debug_report_data *report_data, const VkWriteDescriptorSet *update,
+ std::string *error_msg) {
+ // Verify idle ds
+ if (in_use.load()) {
std::stringstream error_str;
- error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view;
- *error = error_str.str();
+ error_str << "Cannot call vkUpdateDescriptorSets() to perform write update on descriptor set " << set_
+ << " that is in use by a command buffer.";
+ *error_msg = error_str.str();
return false;
}
- updated = true;
- buffer_view_ = buffer_view;
+ // Verify dst binding exists
+ if (!p_layout_->HasBinding(update->dstBinding)) {
+ std::stringstream error_str;
+ error_str << "DescriptorSet " << set_ << " does not have binding " << update->dstBinding << ".";
+ *error_msg = error_str.str();
+ return false;
+ }
+ // We know that binding is valid, verify update and do update on each descriptor
+ auto start_idx = p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding) + update->dstArrayElement;
+ auto type = p_layout_->GetTypeFromBinding(update->dstBinding);
+ if (type != update->descriptorType) {
+ std::stringstream error_str;
+ error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with type "
+ << string_VkDescriptorType(type) << " but update type is " << string_VkDescriptorType(update->descriptorType);
+ *error_msg = error_str.str();
+ return false;
+ }
+ if ((start_idx + update->descriptorCount) > p_layout_->GetTotalDescriptorCount()) {
+ std::stringstream error_str;
+ error_str << "Attempting write update to descriptor set " << set_ << " binding #" << update->dstBinding << " with "
+ << p_layout_->GetTotalDescriptorCount() << " total descriptors but update of " << update->descriptorCount
+ << " descriptors starting at binding offset of " << p_layout_->GetGlobalStartIndexFromBinding(update->dstBinding)
+ << " combined with update array element offset of " << update->dstArrayElement
+ << " oversteps the size of this descriptor set.";
+ *error_msg = error_str.str();
+ return false;
+ }
+ // Verify consecutive bindings match (if needed)
+ if (!p_layout_->VerifyUpdateConsistency(update->dstBinding, update->dstArrayElement, update->descriptorCount, "write update to",
+ set_, error_msg))
+ return false;
+ // Update is within bounds and consistent so last step is to validate update contents
+ if (!VerifyWriteUpdateContents(update, start_idx, error_msg)) {
+ std::stringstream error_str;
+ error_str << "Write update to descriptor in set " << set_ << " binding #" << update->dstBinding
+ << " failed with error message: " << error_msg->c_str();
+ *error_msg = error_str.str();
+ return false;
+ }
+ // All checks passed, update is clean
return true;
}
-
-bool cvdescriptorset::TexelDescriptor::CopyUpdate(const Descriptor *src, std::string *error) {
- // First validate buffer view
- auto buffer_view = static_cast<const TexelDescriptor *>(src)->buffer_view_;
- if (!buffer_view_map_->count(buffer_view)) {
+// For the given buffer, verify that its creation parameters are appropriate for the given type
+// If there's an error, update the error string with details and return false, else return true
+bool cvdescriptorset::DescriptorSet::ValidateBufferUpdate(VkBuffer buffer, VkDescriptorType type, std::string *error) const {
+ // First make sure that buffer is valid
+ auto buffer_node = getBufferNode(device_data_, buffer);
+ if (!buffer_node) {
std::stringstream error_str;
- error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view;
+ error_str << "Invalid VkBuffer: " << buffer;
+ *error = error_str.str();
+ return false;
+ }
+ // Verify that usage bits set correctly for given type
+ auto usage = buffer_node->createInfo.usage;
+ std::string error_usage_bit;
+ switch (type) {
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ if (!(usage & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT)) {
+ error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT";
+ }
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
+ if (!(usage & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT)) {
+ error_usage_bit = "VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT";
+ }
+ break;
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ if (!(usage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT)) {
+ error_usage_bit = "VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT";
+ }
+ break;
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
+ if (!(usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT)) {
+ error_usage_bit = "VK_BUFFER_USAGE_STORAGE_BUFFER_BIT";
+ }
+ break;
+ default:
+ break;
+ }
+ if (!error_usage_bit.empty()) {
+ std::stringstream error_str;
+ error_str << "Buffer (" << buffer << ") with usage mask 0x" << usage << " being used for a descriptor update of type "
+ << string_VkDescriptorType(type) << " does not have " << error_usage_bit << " set.";
*error = error_str.str();
return false;
}
- updated = true;
- buffer_view_ = buffer_view;
return true;
-} \ No newline at end of file
+}
+// Verify that the contents of the update are ok, but don't perform actual update
+bool cvdescriptorset::DescriptorSet::VerifyWriteUpdateContents(const VkWriteDescriptorSet *update, const uint32_t index,
+ std::string *error) const {
+ switch (update->descriptorType) {
+ case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ // Validate image
+ auto image_view = update->pImageInfo[di].imageView;
+ auto image_layout = update->pImageInfo[di].imageLayout;
+ if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted write update to combined image sampler descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ // Intentional fall-through to validate sampler
+ }
+ case VK_DESCRIPTOR_TYPE_SAMPLER: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ if (!descriptors_[index + di].get()->IsImmutableSampler()) {
+ if (!ValidateSampler(update->pImageInfo[di].sampler, device_data_)) {
+ std::stringstream error_str;
+ error_str << "Attempted write update to sampler descriptor with invalid sampler: "
+ << update->pImageInfo[di].sampler << ".";
+ *error = error_str.str();
+ return false;
+ }
+ } else {
+ // TODO : Warn here
+ }
+ }
+ break;
+ }
+ case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
+ case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
+ case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto image_view = update->pImageInfo[di].imageView;
+ auto image_layout = update->pImageInfo[di].imageLayout;
+ if (!ValidateImageUpdate(image_view, image_layout, update->descriptorType, device_data_, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted write update to image descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ break;
+ }
+ case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto buffer_view = update->pTexelBufferView[di];
+ auto bv_info = getBufferViewInfo(device_data_, buffer_view);
+ if (!bv_info) {
+ std::stringstream error_str;
+ error_str << "Attempted write update to texel buffer descriptor with invalid buffer view: " << buffer_view;
+ *error = error_str.str();
+ return false;
+ }
+ auto buffer = bv_info->buffer;
+ if (!ValidateBufferUpdate(buffer, update->descriptorType, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted write update to texel buffer descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ break;
+ }
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
+ case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
+ case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto buffer = update->pBufferInfo[di].buffer;
+ if (!ValidateBufferUpdate(buffer, update->descriptorType, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted write update to buffer descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ break;
+ }
+ default:
+ assert(0); // We've already verified update type so should never get here
+ break;
+ }
+ // All checks passed so update contents are good
+ return true;
+}
+// Verify that the contents of the update are ok, but don't perform actual update
+bool cvdescriptorset::DescriptorSet::VerifyCopyUpdateContents(const VkCopyDescriptorSet *update, const DescriptorSet *src_set,
+ VkDescriptorType type, uint32_t index, std::string *error) const {
+ switch (src_set->descriptors_[index]->descriptor_class) {
+ case PlainSampler: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ if (!src_set->descriptors_[index + di]->IsImmutableSampler()) {
+ auto update_sampler = static_cast<SamplerDescriptor *>(src_set->descriptors_[index + di].get())->GetSampler();
+ if (!ValidateSampler(update_sampler, device_data_)) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
+ *error = error_str.str();
+ return false;
+ }
+ } else {
+ // TODO : Warn here
+ }
+ }
+ break;
+ }
+ case ImageSampler: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto img_samp_desc = static_cast<const ImageSamplerDescriptor *>(src_set->descriptors_[index + di].get());
+ // First validate sampler
+ if (!img_samp_desc->IsImmutableSampler()) {
+ auto update_sampler = img_samp_desc->GetSampler();
+ if (!ValidateSampler(update_sampler, device_data_)) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to sampler descriptor with invalid sampler: " << update_sampler << ".";
+ *error = error_str.str();
+ return false;
+ }
+ } else {
+ // TODO : Warn here
+ }
+ // Validate image
+ auto image_view = img_samp_desc->GetImageView();
+ auto image_layout = img_samp_desc->GetImageLayout();
+ if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to combined image sampler descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ }
+ case Image: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto img_desc = static_cast<const ImageDescriptor *>(src_set->descriptors_[index + di].get());
+ auto image_view = img_desc->GetImageView();
+ auto image_layout = img_desc->GetImageLayout();
+ if (!ValidateImageUpdate(image_view, image_layout, type, device_data_, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to image descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ break;
+ }
+ case TexelBuffer: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto buffer_view = static_cast<TexelDescriptor *>(src_set->descriptors_[index + di].get())->GetBufferView();
+ auto bv_info = getBufferViewInfo(device_data_, buffer_view);
+ if (!bv_info) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to texel buffer descriptor with invalid buffer view: " << buffer_view;
+ *error = error_str.str();
+ return false;
+ }
+ auto buffer = bv_info->buffer;
+ if (!ValidateBufferUpdate(buffer, type, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to texel buffer descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ break;
+ }
+ case GeneralBuffer: {
+ for (uint32_t di = 0; di < update->descriptorCount; ++di) {
+ auto buffer = static_cast<BufferDescriptor *>(src_set->descriptors_[index + di].get())->GetBuffer();
+ if (!ValidateBufferUpdate(buffer, type, error)) {
+ std::stringstream error_str;
+ error_str << "Attempted copy update to buffer descriptor failed due to: " << error->c_str();
+ *error = error_str.str();
+ return false;
+ }
+ }
+ break;
+ }
+ default:
+ assert(0); // We've already verified update type so should never get here
+ break;
+ }
+ // All checks passed so update contents are good
+ return true;
+}
+// Verify that the state at allocate time is correct, but don't actually allocate the sets yet
+bool cvdescriptorset::ValidateAllocateDescriptorSets(const debug_report_data *report_data,
+ const VkDescriptorSetAllocateInfo *p_alloc_info,
+ const core_validation::layer_data *dev_data,
+ AllocateDescriptorSetsData *ds_data) {
+ bool skip_call = false;
+
+ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
+ auto layout = getDescriptorSetLayout(dev_data, p_alloc_info->pSetLayouts[i]);
+ if (!layout) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT,
+ reinterpret_cast<const uint64_t &>(p_alloc_info->pSetLayouts[i]), __LINE__, DRAWSTATE_INVALID_LAYOUT, "DS",
+ "Unable to find set layout node for layout 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
+ reinterpret_cast<const uint64_t &>(p_alloc_info->pSetLayouts[i]));
+ } else {
+ ds_data->layout_nodes[i] = layout;
+ // Count total descriptors required per type
+ for (uint32_t j = 0; j < layout->GetBindingCount(); ++j) {
+ const auto &binding_layout = layout->GetDescriptorSetLayoutBindingPtrFromIndex(j);
+ uint32_t typeIndex = static_cast<uint32_t>(binding_layout->descriptorType);
+ ds_data->required_descriptors_by_type[typeIndex] += binding_layout->descriptorCount;
+ }
+ }
+ }
+ auto pool_node = getPoolNode(dev_data, p_alloc_info->descriptorPool);
+ if (!pool_node) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+ reinterpret_cast<const uint64_t &>(p_alloc_info->descriptorPool), __LINE__, DRAWSTATE_INVALID_POOL, "DS",
+ "Unable to find pool node for pool 0x%" PRIxLEAST64 " specified in vkAllocateDescriptorSets() call",
+ reinterpret_cast<const uint64_t &>(p_alloc_info->descriptorPool));
+ } else { // Make sure pool has all the available descriptors before calling down chain
+ // Track number of descriptorSets allowable in this pool
+ if (pool_node->availableSets < p_alloc_info->descriptorSetCount) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+ reinterpret_cast<uint64_t &>(pool_node->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY, "DS",
+ "Unable to allocate %u descriptorSets from pool 0x%" PRIxLEAST64
+ ". This pool only has %d descriptorSets remaining.",
+ p_alloc_info->descriptorSetCount, reinterpret_cast<uint64_t &>(pool_node->pool), pool_node->availableSets);
+ }
+ // Determine whether descriptor counts are satisfiable
+ for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
+ if (ds_data->required_descriptors_by_type[i] > pool_node->availableDescriptorTypeCount[i]) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_POOL_EXT,
+ reinterpret_cast<const uint64_t &>(pool_node->pool), __LINE__, DRAWSTATE_DESCRIPTOR_POOL_EMPTY,
+ "DS", "Unable to allocate %u descriptors of type %s from pool 0x%" PRIxLEAST64
+ ". This pool only has %d descriptors of this type remaining.",
+ ds_data->required_descriptors_by_type[i], string_VkDescriptorType(VkDescriptorType(i)),
+ reinterpret_cast<uint64_t &>(pool_node->pool), pool_node->availableDescriptorTypeCount[i]);
+ }
+ }
+ }
+ return skip_call;
+}
+// Decrement allocated sets from the pool and insert new sets into set_map
+void cvdescriptorset::PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *p_alloc_info,
+ const VkDescriptorSet *descriptor_sets,
+ const AllocateDescriptorSetsData *ds_data,
+ std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> *pool_map,
+ std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *set_map,
+ const core_validation::layer_data *dev_data) {
+ auto pool_state = (*pool_map)[p_alloc_info->descriptorPool];
+ /* Account for sets and individual descriptors allocated from pool */
+ pool_state->availableSets -= p_alloc_info->descriptorSetCount;
+ for (uint32_t i = 0; i < VK_DESCRIPTOR_TYPE_RANGE_SIZE; i++) {
+ pool_state->availableDescriptorTypeCount[i] -= ds_data->required_descriptors_by_type[i];
+ }
+ /* Create tracking object for each descriptor set; insert into
+ * global map and the pool's set.
+ */
+ for (uint32_t i = 0; i < p_alloc_info->descriptorSetCount; i++) {
+ auto new_ds = new cvdescriptorset::DescriptorSet(descriptor_sets[i], ds_data->layout_nodes[i], dev_data);
+
+ pool_state->sets.insert(new_ds);
+ new_ds->in_use.store(0);
+ (*set_map)[descriptor_sets[i]] = new_ds;
+ }
+}
diff --git a/layers/descriptor_sets.h b/layers/descriptor_sets.h
index 4594a695..98ab1447 100644
--- a/layers/descriptor_sets.h
+++ b/layers/descriptor_sets.h
@@ -141,13 +141,13 @@ class DescriptorSetLayout {
*/
// Slightly broader than type, each c++ "class" will has a corresponding "DescriptorClass"
-typedef enum _DescriptorClass { PlainSampler, ImageSampler, Image, TexelBuffer, GeneralBuffer } DescriptorClass;
+enum DescriptorClass { PlainSampler, ImageSampler, Image, TexelBuffer, GeneralBuffer };
class Descriptor {
public:
virtual ~Descriptor(){};
- virtual bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) = 0;
- virtual bool CopyUpdate(const Descriptor *, std::string *) = 0;
+ virtual void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) = 0;
+ virtual void CopyUpdate(const Descriptor *) = 0;
virtual DescriptorClass GetClass() const { return descriptor_class; };
// Special fast-path check for SamplerDescriptors that are immutable
virtual bool IsImmutableSampler() const { return false; };
@@ -160,58 +160,47 @@ class Descriptor {
};
// Shared helper functions - These are useful because the shared sampler image descriptor type
// performs common functions with both sampler and image descriptors so they can share their common functions
-bool ValidateSampler(const VkSampler, const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *);
-bool ValidateImageUpdate(const VkImageView, const VkImageLayout, const std::unordered_map<VkImageView, VkImageViewCreateInfo> *,
- const std::unordered_map<VkImage, IMAGE_NODE> *, const std::unordered_map<VkImage, VkSwapchainKHR> *,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *, std::string *);
+bool ValidateSampler(const VkSampler, const core_validation::layer_data *);
+bool ValidateImageUpdate(VkImageView, VkImageLayout, VkDescriptorType, const core_validation::layer_data *, std::string *);
class SamplerDescriptor : public Descriptor {
public:
- SamplerDescriptor(const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *);
- SamplerDescriptor(const VkSampler *, const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *);
- bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override;
- bool CopyUpdate(const Descriptor *, std::string *) override;
+ SamplerDescriptor();
+ SamplerDescriptor(const VkSampler *);
+ void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
+ void CopyUpdate(const Descriptor *) override;
virtual bool IsImmutableSampler() const override { return immutable_; };
+ VkSampler GetSampler() const { return sampler_; }
private:
// bool ValidateSampler(const VkSampler) const;
VkSampler sampler_;
bool immutable_;
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map_;
};
class ImageSamplerDescriptor : public Descriptor {
public:
- ImageSamplerDescriptor(const std::unordered_map<VkImageView, VkImageViewCreateInfo> *,
- const std::unordered_map<VkImage, IMAGE_NODE> *, const std::unordered_map<VkImage, VkSwapchainKHR> *,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *);
- ImageSamplerDescriptor(const VkSampler *, const std::unordered_map<VkImageView, VkImageViewCreateInfo> *,
- const std::unordered_map<VkImage, IMAGE_NODE> *, const std::unordered_map<VkImage, VkSwapchainKHR> *,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *);
- bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override;
- bool CopyUpdate(const Descriptor *, std::string *) override;
+ ImageSamplerDescriptor();
+ ImageSamplerDescriptor(const VkSampler *);
+ void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
+ void CopyUpdate(const Descriptor *) override;
+ virtual bool IsImmutableSampler() const override { return immutable_; };
+ VkSampler GetSampler() const { return sampler_; }
+ VkImageView GetImageView() const { return image_view_; }
+ VkImageLayout GetImageLayout() const { return image_layout_; }
private:
VkSampler sampler_;
bool immutable_;
VkImageView image_view_;
VkImageLayout image_layout_;
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map_;
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map_;
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map_;
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map_;
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map_;
};
class ImageDescriptor : public Descriptor {
public:
- ImageDescriptor(const VkDescriptorType, const std::unordered_map<VkImageView, VkImageViewCreateInfo> *,
- const std::unordered_map<VkImage, IMAGE_NODE> *, const std::unordered_map<VkImage, VkSwapchainKHR> *,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *);
- bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override;
- bool CopyUpdate(const Descriptor *, std::string *) override;
+ ImageDescriptor(const VkDescriptorType);
+ void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
+ void CopyUpdate(const Descriptor *) override;
virtual bool IsStorage() const override { return storage_; }
VkImageView GetImageView() const { return image_view_; }
VkImageLayout GetImageLayout() const { return image_layout_; }
@@ -220,30 +209,26 @@ class ImageDescriptor : public Descriptor {
bool storage_;
VkImageView image_view_;
VkImageLayout image_layout_;
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map_;
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map_;
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map_;
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map_;
};
class TexelDescriptor : public Descriptor {
public:
- TexelDescriptor(const VkDescriptorType, const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> *);
- bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override;
- bool CopyUpdate(const Descriptor *, std::string *) override;
- VkBufferView GetBufferView() const { return buffer_view_; };
+ TexelDescriptor(const VkDescriptorType);
+ void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
+ void CopyUpdate(const Descriptor *) override;
+ virtual bool IsStorage() const override { return storage_; }
+ VkBufferView GetBufferView() const { return buffer_view_; }
private:
VkBufferView buffer_view_;
bool storage_;
- const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> *buffer_view_map_;
};
class BufferDescriptor : public Descriptor {
public:
- BufferDescriptor(const VkDescriptorType, const std::unordered_map<VkBuffer, BUFFER_NODE> *);
- bool WriteUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) override;
- bool CopyUpdate(const Descriptor *, std::string *) override;
+ BufferDescriptor(const VkDescriptorType);
+ void WriteUpdate(const VkWriteDescriptorSet *, const uint32_t) override;
+ void CopyUpdate(const Descriptor *) override;
virtual bool IsDynamic() const override { return dynamic_; }
virtual bool IsStorage() const override { return storage_; }
VkBuffer GetBuffer() const { return buffer_; }
@@ -256,8 +241,29 @@ class BufferDescriptor : public Descriptor {
VkBuffer buffer_;
VkDeviceSize offset_;
VkDeviceSize range_;
- const std::unordered_map<VkBuffer, BUFFER_NODE> *buffer_map_;
};
+// Structs to contain common elements that need to be shared between Validate* and Perform* calls below
+struct AllocateDescriptorSetsData {
+ uint32_t required_descriptors_by_type[VK_DESCRIPTOR_TYPE_RANGE_SIZE];
+ std::vector<cvdescriptorset::DescriptorSetLayout const *> layout_nodes;
+ AllocateDescriptorSetsData(uint32_t);
+};
+// Helper functions for descriptor set functions that cross multiple sets
+// "Validate" will make sure an update is ok without actually performing it
+bool ValidateUpdateDescriptorSets(const debug_report_data *, const core_validation::layer_data *, uint32_t,
+ const VkWriteDescriptorSet *, uint32_t, const VkCopyDescriptorSet *);
+// "Perform" does the update with the assumption that ValidateUpdateDescriptorSets() has passed for the given update
+void PerformUpdateDescriptorSets(const core_validation::layer_data *, uint32_t, const VkWriteDescriptorSet *, uint32_t,
+ const VkCopyDescriptorSet *);
+// Validate that Allocation state is ok
+bool ValidateAllocateDescriptorSets(const debug_report_data *, const VkDescriptorSetAllocateInfo *,
+ const core_validation::layer_data *, AllocateDescriptorSetsData *);
+// Update state based on allocating new descriptorsets
+void PerformAllocateDescriptorSets(const VkDescriptorSetAllocateInfo *, const VkDescriptorSet *, const AllocateDescriptorSetsData *,
+ std::unordered_map<VkDescriptorPool, DESCRIPTOR_POOL_NODE *> *,
+ std::unordered_map<VkDescriptorSet, cvdescriptorset::DescriptorSet *> *,
+ const core_validation::layer_data *);
+
/*
* DescriptorSet class
*
@@ -278,14 +284,9 @@ class BufferDescriptor : public Descriptor {
*/
class DescriptorSet : public BASE_NODE {
public:
- DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const std::unordered_map<VkBuffer, BUFFER_NODE> *,
- const std::unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> *,
- const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> *,
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *,
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *, const std::unordered_map<VkImage, IMAGE_NODE> *,
- const std::unordered_map<VkImage, VkSwapchainKHR> *,
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *);
- ~DescriptorSet(){};
+ using BASE_NODE::in_use;
+ DescriptorSet(const VkDescriptorSet, const DescriptorSetLayout *, const core_validation::layer_data *);
+ ~DescriptorSet();
// A number of common Get* functions that return data based on layout from which this set was created
uint32_t GetTotalDescriptorCount() const { return p_layout_ ? p_layout_->GetTotalDescriptorCount() : 0; };
uint32_t GetDynamicDescriptorCount() const { return p_layout_ ? p_layout_->GetDynamicDescriptorCount() : 0; };
@@ -315,22 +316,25 @@ class DescriptorSet : public BASE_NODE {
// of objects inserted
uint32_t GetStorageUpdates(const std::unordered_set<uint32_t> &, std::unordered_set<VkBuffer> *,
std::unordered_set<VkImageView> *) const;
- // For all descriptors in a set, add any buffers and images that may be updated to their respective unordered_sets & return
- // number of objects inserted
- uint32_t GetAllStorageUpdates(std::unordered_set<VkBuffer> *, std::unordered_set<VkImageView> *) const;
- // Perform write update based on update struct
- bool WriteUpdate(debug_report_data *, const VkWriteDescriptorSet *, std::string *);
- // Perform copy update, using 'this' set as the dest and the passed-in DescriptorSet as the src
- bool CopyUpdate(debug_report_data *, const VkCopyDescriptorSet *, const DescriptorSet *, std::string *);
+
+ // Descriptor Update functions. These functions validate state and perform update separately
+ // Validate contents of a WriteUpdate
+ bool ValidateWriteUpdate(const debug_report_data *, const VkWriteDescriptorSet *, std::string *);
+ // Perform a WriteUpdate whose contents were just validated using ValidateWriteUpdate
+ void PerformWriteUpdate(const VkWriteDescriptorSet *);
+ // Validate contents of a CopyUpdate
+ bool ValidateCopyUpdate(const debug_report_data *, const VkCopyDescriptorSet *, const DescriptorSet *, std::string *);
+ // Perform a CopyUpdate whose contents were just validated using ValidateCopyUpdate
+ void PerformCopyUpdate(const VkCopyDescriptorSet *, const DescriptorSet *);
const DescriptorSetLayout *GetLayout() const { return p_layout_; };
VkDescriptorSet GetSet() const { return set_; };
// Return unordered_set of all command buffers that this set is bound to
- std::unordered_set<VkCommandBuffer> GetBoundCmdBuffers() const { return bound_cmd_buffers_; }
+ std::unordered_set<GLOBAL_CB_NODE *> GetBoundCmdBuffers() const { return bound_cmd_buffers_; }
// Bind given cmd_buffer to this descriptor set
- void BindCommandBuffer(const VkCommandBuffer cmd_buffer) { bound_cmd_buffers_.insert(cmd_buffer); }
+ void BindCommandBuffer(GLOBAL_CB_NODE *cb_node) { bound_cmd_buffers_.insert(cb_node); }
// If given cmd_buffer is in the bound_cmd_buffers_ set, remove it
- void RemoveBoundCommandBuffer(const VkCommandBuffer cmd_buffer) { bound_cmd_buffers_.erase(cmd_buffer); }
+ void RemoveBoundCommandBuffer(GLOBAL_CB_NODE *cb_node) { bound_cmd_buffers_.erase(cb_node); }
VkSampler const *GetImmutableSamplerPtrFromBinding(const uint32_t index) const {
return p_layout_->GetImmutableSamplerPtrFromBinding(index);
};
@@ -345,23 +349,19 @@ class DescriptorSet : public BASE_NODE {
bool IsUpdated() const { return some_update_; };
private:
- bool ValidateUpdate(const VkWriteDescriptorSet *, const uint32_t, std::string *) const;
+ bool VerifyWriteUpdateContents(const VkWriteDescriptorSet *, const uint32_t, std::string *) const;
+ bool VerifyCopyUpdateContents(const VkCopyDescriptorSet *, const DescriptorSet *, VkDescriptorType, uint32_t,
+ std::string *) const;
+ bool ValidateBufferUpdate(VkBuffer, VkDescriptorType, std::string *) const;
+ // Private helper to set all bound cmd buffers to INVALID state
+ void InvalidateBoundCmdBuffers();
bool some_update_; // has any part of the set ever been updated?
VkDescriptorSet set_;
- uint32_t descriptor_count_; // Count of all descriptors in this set
const DescriptorSetLayout *p_layout_;
- std::unordered_set<VkCommandBuffer> bound_cmd_buffers_;
+ std::unordered_set<GLOBAL_CB_NODE *> bound_cmd_buffers_;
std::vector<std::unique_ptr<Descriptor>> descriptors_;
- // Ptrs to object containers to verify bound data
- const std::unordered_map<VkBuffer, BUFFER_NODE> *buffer_map_;
- const std::unordered_map<VkDeviceMemory, DEVICE_MEM_INFO> *memory_map_;
- const std::unordered_map<VkBufferView, VkBufferViewCreateInfo> *buffer_view_map_;
- const std::unordered_map<VkSampler, std::unique_ptr<SAMPLER_NODE>> *sampler_map_;
- const std::unordered_map<VkImageView, VkImageViewCreateInfo> *image_view_map_;
- // TODO : For next 3 maps all we really need (currently) is an image to format mapping
- const std::unordered_map<VkImage, IMAGE_NODE> *image_map_;
- const std::unordered_map<VkImage, VkSwapchainKHR> *image_to_swapchain_map_;
- const std::unordered_map<VkSwapchainKHR, SWAPCHAIN_NODE *> *swapchain_map_;
+ // Ptr to device data used for various data look-ups
+ const core_validation::layer_data *device_data_;
};
}
#endif // CORE_VALIDATION_DESCRIPTOR_SETS_H_
diff --git a/layers/device_limits.cpp b/layers/device_limits.cpp
index a5b1ca79..f70f421e 100644
--- a/layers/device_limits.cpp
+++ b/layers/device_limits.cpp
@@ -166,15 +166,16 @@ EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, Vk
my_data->instanceState->vkEnumeratePhysicalDevicesState = QUERY_COUNT;
} else {
if (UNCALLED == my_data->instanceState->vkEnumeratePhysicalDevicesState) {
- // Flag error here, shouldn't be calling this without having queried count
+ // Flag warning here. You can call this without having queried the count, but it may not be
+ // robust on platforms with multiple physical devices.
skipCall |=
- log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0,
- __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
- "Invalid call sequence to vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
+ log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0,
+ __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
+ "Call sequence has vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
"call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount.");
} // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
else if (my_data->instanceState->physicalDevicesCount != *pPhysicalDeviceCount) {
- // TODO: Having actual count match count from app is not a requirement, so this can be a warning
+ // Having actual count match count from app is not a requirement, so this can be a warning
skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
"Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count "
@@ -247,9 +248,9 @@ GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t
// Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to
// get count
if (UNCALLED == phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
- "Invalid call sequence to vkGetPhysicalDeviceQueueFamilyProperties() w/ non-NULL "
+ skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
+ VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MISSING_QUERY_COUNT, "DL",
+ "Call sequence has vkGetPhysicalDeviceQueueFamilyProperties() w/ non-NULL "
"pQueueFamilyProperties. You should first call vkGetPhysicalDeviceQueueFamilyProperties() w/ "
"NULL pQueueFamilyProperties to query pCount.");
}
@@ -586,68 +587,13 @@ UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWri
}
}
-VKAPI_ATTR void VKAPI_CALL
-CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
- VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) {
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
-
- // dstOffset is the byte offset into the buffer to start updating and must be a multiple of 4.
- if (dstOffset & 3) {
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
- DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
- "vkCmdUpdateBuffer parameter, VkDeviceSize dstOffset, is not a multiple of 4")) {
- return;
- }
- }
-
- // dataSize is the number of bytes to update, which must be a multiple of 4.
- if (dataSize & 3) {
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
- DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
- "vkCmdUpdateBuffer parameter, VkDeviceSize dataSize, is not a multiple of 4")) {
- return;
- }
- }
-
- dev_data->device_dispatch_table->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
-}
-
-VKAPI_ATTR void VKAPI_CALL
-CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
- layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
-
- // dstOffset is the byte offset into the buffer to start filling and must be a multiple of 4.
- if (dstOffset & 3) {
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
- DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
- "vkCmdFillBuffer parameter, VkDeviceSize dstOffset, is not a multiple of 4")) {
- return;
- }
- }
-
- // size is the number of bytes to fill, which must be a multiple of 4.
- if (size & 3) {
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
- DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
- "vkCmdFillBuffer parameter, VkDeviceSize size, is not a multiple of 4")) {
- return;
- }
- }
-
- dev_data->device_dispatch_table->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
-}
-
VKAPI_ATTR VkResult VKAPI_CALL
CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (VK_SUCCESS == res) {
- res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
+ res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
return res;
}
@@ -670,6 +616,24 @@ DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugR
}
VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
+ return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
+
+ return VK_ERROR_LAYER_NOT_PRESENT;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
@@ -750,14 +714,12 @@ intercept_core_instance_command(const char *name) {
{ "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
{ "vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMemoryProperties) },
{ "vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSparseImageFormatProperties) },
+ { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
+ { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
+ { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
{ "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
};
- // we should never be queried for these commands
- assert(strcmp(name, "vkEnumerateInstanceLayerProperties") &&
- strcmp(name, "vkEnumerateInstanceExtensionProperties") &&
- strcmp(name, "vkEnumerateDeviceLayerProperties"));
-
for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
if (!strcmp(core_instance_commands[i].name, name))
return core_instance_commands[i].proc;
@@ -782,9 +744,7 @@ intercept_core_device_command(const char *name) {
{ "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers) },
{ "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers) },
{ "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer) },
- { "vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer) },
{ "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
- { "vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer) },
{ "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
{ "vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport) },
};
@@ -820,27 +780,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu
device_limits::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
}
-// loader-layer interface v0
+// loader-layer interface v0, just wrappers since there is only a layer
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &device_limits::global_layer, pCount, pProperties);
+ return device_limits::EnumerateInstanceLayerProperties(pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &device_limits::global_layer, pCount, pProperties);
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return device_limits::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
- return util_GetExtensionProperties(1, device_limits::instance_extensions, pCount, pProperties);
+ return device_limits::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
- // the layer command handles VK_NULL_HANDLE just fine
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
return device_limits::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
}
@@ -849,14 +812,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
}
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
- if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);
- if (!strcmp(funcName, "vkGetInstanceProcAddr"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);
-
return device_limits::GetInstanceProcAddr(instance, funcName);
}
diff --git a/layers/device_limits.h b/layers/device_limits.h
index 1eec8ced..44ae17c3 100644
--- a/layers/device_limits.h
+++ b/layers/device_limits.h
@@ -24,12 +24,13 @@
using namespace std;
// Device Limits ERROR codes
-typedef enum _DEV_LIMITS_ERROR {
+enum DEV_LIMITS_ERROR {
DEVLIMITS_NONE, // Used for INFO & other non-error messages
DEVLIMITS_INVALID_INSTANCE, // Invalid instance used
DEVLIMITS_INVALID_PHYSICAL_DEVICE, // Invalid physical device used
DEVLIMITS_INVALID_INHERITED_QUERY, // Invalid use of inherited query
DEVLIMITS_INVALID_ATTACHMENT_COUNT, // Invalid value for the number of attachments
+ DEVLIMITS_MISSING_QUERY_COUNT, // Did not make initial call to an API to query the count
DEVLIMITS_MUST_QUERY_COUNT, // Failed to make initial call to an API to query the count
DEVLIMITS_INVALID_CALL_SEQUENCE, // Flag generic case of an invalid call sequence by the app
DEVLIMITS_INVALID_FEATURE_REQUESTED, // App requested a feature not supported by physical device
@@ -37,23 +38,22 @@ typedef enum _DEV_LIMITS_ERROR {
DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, // Invalid queue requested based on queue family properties
DEVLIMITS_INVALID_UNIFORM_BUFFER_OFFSET, // Uniform buffer offset violates device limit granularity
DEVLIMITS_INVALID_STORAGE_BUFFER_OFFSET, // Storage buffer offset violates device limit granularity
- DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, // Alignment requirement for buffer update is violated
-} DEV_LIMITS_ERROR;
+};
-typedef enum _CALL_STATE {
+enum CALL_STATE{
UNCALLED, // Function has not been called
QUERY_COUNT, // Function called once to query a count
QUERY_DETAILS, // Function called w/ a count to query details
-} CALL_STATE;
+};
-typedef struct _INSTANCE_STATE {
+struct INSTANCE_STATE {
// Track the call state and array size for physical devices
CALL_STATE vkEnumeratePhysicalDevicesState;
uint32_t physicalDevicesCount;
- _INSTANCE_STATE() : vkEnumeratePhysicalDevicesState(UNCALLED), physicalDevicesCount(0){};
-} INSTANCE_STATE;
+ INSTANCE_STATE() : vkEnumeratePhysicalDevicesState(UNCALLED), physicalDevicesCount(0){};
+};
-typedef struct _PHYSICAL_DEVICE_STATE {
+struct PHYSICAL_DEVICE_STATE {
// Track the call state and array sizes for various query functions
CALL_STATE vkGetPhysicalDeviceQueueFamilyPropertiesState;
uint32_t queueFamilyPropertiesCount;
@@ -62,9 +62,9 @@ typedef struct _PHYSICAL_DEVICE_STATE {
CALL_STATE vkGetPhysicalDeviceExtensionPropertiesState;
uint32_t deviceExtensionCount;
CALL_STATE vkGetPhysicalDeviceFeaturesState;
- _PHYSICAL_DEVICE_STATE()
+ PHYSICAL_DEVICE_STATE()
: vkGetPhysicalDeviceQueueFamilyPropertiesState(UNCALLED), queueFamilyPropertiesCount(0),
vkGetPhysicalDeviceLayerPropertiesState(UNCALLED), deviceLayerCount(0),
vkGetPhysicalDeviceExtensionPropertiesState(UNCALLED), deviceExtensionCount(0),
vkGetPhysicalDeviceFeaturesState(UNCALLED){};
-} PHYSICAL_DEVICE_STATE;
+};
diff --git a/layers/image.cpp b/layers/image.cpp
index 2fce6500..116f49f7 100644
--- a/layers/image.cpp
+++ b/layers/image.cpp
@@ -76,13 +76,21 @@ static void init_image(layer_data *my_data, const VkAllocationCallbacks *pAlloca
layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_image");
}
+static IMAGE_STATE const *getImageState(layer_data const *dev_data, VkImage image) {
+ auto it = dev_data->imageMap.find(image);
+ if (it == dev_data->imageMap.end()) {
+ return nullptr;
+ }
+ return &it->second;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL
CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (res == VK_SUCCESS) {
- res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
+ res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
return res;
}
@@ -206,32 +214,13 @@ static const VkLayerProperties global_layer = {
// Start of the Image layer proper
-// Returns TRUE if a format is a depth-compatible format
-bool is_depth_format(VkFormat format) {
- bool result = false;
- switch (format) {
- case VK_FORMAT_D16_UNORM:
- case VK_FORMAT_X8_D24_UNORM_PACK32:
- case VK_FORMAT_D32_SFLOAT:
- case VK_FORMAT_S8_UINT:
- case VK_FORMAT_D16_UNORM_S8_UINT:
- case VK_FORMAT_D24_UNORM_S8_UINT:
- case VK_FORMAT_D32_SFLOAT_S8_UINT:
- result = true;
- break;
- default:
- break;
- }
- return result;
-}
-
static inline uint32_t validate_VkImageLayoutKHR(VkImageLayout input_value) {
return ((validate_VkImageLayout(input_value) == 1) || (input_value == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR));
}
-VKAPI_ATTR VkResult VKAPI_CALL
-CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
- bool skipCall = false;
+VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
+ bool skip_call = false;
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
VkImageFormatProperties ImageFormatProperties;
@@ -243,13 +232,60 @@ CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAlloc
VkFormatProperties properties;
phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFormatProperties(device_data->physicalDevice, pCreateInfo->format,
&properties);
-
if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0)) {
- char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
+ std::stringstream ss;
+ ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
// TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
- skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- IMAGE_FORMAT_UNSUPPORTED, "IMAGE", str);
+ skip_call |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
+ 0, __LINE__, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", "%s", ss.str().c_str());
+ }
+
+ // Validate that format supports usage as color attachment
+ if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
+ if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
+ ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
+ std::stringstream ss;
+ ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
+ << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
+ skip_call |=
+ log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
+ }
+ if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
+ ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
+ std::stringstream ss;
+ ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
+ << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
+ skip_call |=
+ log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
+ }
+ }
+ // Validate that format supports usage as depth/stencil attachment
+ if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
+ if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
+ ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
+ std::stringstream ss;
+ ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
+ << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
+ skip_call |=
+ log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
+ }
+ if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
+ ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
+ std::stringstream ss;
+ ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
+ << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
+ skip_call |=
+ log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
+ }
}
+ } else {
+ skip_call |=
+ log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ IMAGE_INVALID_FORMAT, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED");
}
// Internal call to get format info. Still goes through layers, could potentially go directly to ICD.
@@ -282,9 +318,9 @@ CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAlloc
break;
}
if (failedMinSize) {
- skipCall |=
+ skip_call |=
log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
"CreateImage extents is 0 for at least one required dimension for image of type %d: "
"Width = %d Height = %d Depth = %d.",
pCreateInfo->imageType, pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth);
@@ -293,8 +329,8 @@ CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAlloc
if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
(pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
(pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
"CreateImage extents exceed allowable limits for format: "
"Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
@@ -309,42 +345,42 @@ CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAlloc
~(uint64_t)imageGranularity;
if (totalSize > ImageFormatProperties.maxResourceSize) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
"CreateImage resource size exceeds allowable maximum "
"Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
totalSize, ImageFormatProperties.maxResourceSize);
}
if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
"CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
ImageFormatProperties.maxMipLevels);
}
if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
"CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d",
pCreateInfo->arrayLayers, ImageFormatProperties.maxArrayLayers);
}
if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
+ skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ 0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
"CreateImage samples %s is not supported by format 0x%.8X",
string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts);
}
if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
- skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
- (uint64_t)pImage, __LINE__, IMAGE_INVALID_LAYOUT, "Image",
+ skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ 0, __LINE__, IMAGE_INVALID_LAYOUT, "Image",
"vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
"VK_IMAGE_LAYOUT_PREINITIALIZED");
}
- if (!skipCall) {
+ if (!skip_call) {
result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
}
if (result == VK_SUCCESS) {
@@ -367,23 +403,6 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP
VkRenderPass *pRenderPass) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
bool skipCall = false;
- for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
- if (pCreateInfo->pAttachments[i].format != VK_FORMAT_UNDEFINED) {
- VkFormatProperties properties;
- get_my_data_ptr(get_dispatch_key(my_data->physicalDevice), layer_data_map)
- ->instance_dispatch_table->GetPhysicalDeviceFormatProperties(my_data->physicalDevice,
- pCreateInfo->pAttachments[i].format, &properties);
-
- if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0)) {
- std::stringstream ss;
- ss << "vkCreateRenderPass parameter, VkFormat in pCreateInfo->pAttachments[" << i
- << "], contains unsupported format";
- // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
- skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
- IMAGE_FORMAT_UNSUPPORTED, "IMAGE", "%s", ss.str().c_str());
- }
- }
- }
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
if (!validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].initialLayout) ||
@@ -419,7 +438,7 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderP
// Any depth buffers specified as attachments?
bool depthFormatPresent = false;
for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
- depthFormatPresent |= is_depth_format(pCreateInfo->pAttachments[i].format);
+ depthFormatPresent |= vk_format_is_depth_or_stencil(pCreateInfo->pAttachments[i].format);
}
if (!depthFormatPresent) {
@@ -447,19 +466,19 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageVie
const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
bool skipCall = false;
layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- auto imageEntry = device_data->imageMap.find(pCreateInfo->image);
- if (imageEntry != device_data->imageMap.end()) {
- if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->second.mipLevels) {
+ auto imageEntry = getImageState(device_data, pCreateInfo->image);
+ if (imageEntry) {
+ if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->mipLevels) {
std::stringstream ss;
ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel << " for image "
- << pCreateInfo->image << " that only has " << imageEntry->second.mipLevels << " mip levels.";
+ << pCreateInfo->image << " that only has " << imageEntry->mipLevels << " mip levels.";
skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
}
- if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->second.arraySize) {
+ if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->arraySize) {
std::stringstream ss;
ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image "
- << pCreateInfo->image << " that only has " << imageEntry->second.arraySize << " array layers.";
+ << pCreateInfo->image << " that only has " << imageEntry->arraySize << " array layers.";
skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
}
@@ -476,8 +495,8 @@ VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageVie
IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
}
- VkImageCreateFlags imageFlags = imageEntry->second.flags;
- VkFormat imageFormat = imageEntry->second.format;
+ VkImageCreateFlags imageFlags = imageEntry->flags;
+ VkFormat imageFormat = imageEntry->format;
VkFormat ivciFormat = pCreateInfo->format;
VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask;
@@ -614,6 +633,25 @@ VKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkI
}
}
+ auto image_state = getImageState(device_data, image);
+ if (image_state) {
+ if (vk_format_is_depth_or_stencil(image_state->format)) {
+ char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
+ skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
+ } else if (vk_format_is_compressed(image_state->format)) {
+ char const str[] = "vkCmdClearColorImage called with compressed image.";
+ skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
+ }
+
+ if (!(image_state->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
+ char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT.";
+ skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_USAGE, "IMAGE", str);
+ }
+ }
+
if (!skipCall) {
device_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
}
@@ -637,6 +675,13 @@ CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageL
}
}
+ auto image_state = getImageState(device_data, image);
+ if (image_state && !vk_format_is_depth_or_stencil(image_state->format)) {
+ char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
+ skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
+ reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
+ }
+
if (!skipCall) {
device_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount,
pRanges);
@@ -681,7 +726,7 @@ static bool region_intersects(const VkImageCopy *src, const VkImageCopy *dst, Vk
}
// Returns true if offset and extent exceed image extents
-static bool exceeds_bounds(const VkOffset3D *offset, const VkExtent3D *extent, IMAGE_STATE *image) {
+static bool exceeds_bounds(const VkOffset3D *offset, const VkExtent3D *extent, const IMAGE_STATE *image) {
bool result = false;
// Extents/depths cannot be negative but checks left in for clarity
@@ -693,12 +738,12 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
bool skipCall = false;
layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- auto srcImageEntry = device_data->imageMap.find(srcImage);
- auto dstImageEntry = device_data->imageMap.find(dstImage);
+ auto srcImageEntry = getImageState(device_data, srcImage);
+ auto dstImageEntry = getImageState(device_data, dstImage);
// TODO: This does not cover swapchain-created images. This should fall out when this layer is moved
// into the core_validation layer
- if ((srcImageEntry != device_data->imageMap.end()) && (dstImageEntry != device_data->imageMap.end())) {
+ if (srcImageEntry && dstImageEntry) {
for (uint32_t i = 0; i < regionCount; i++) {
@@ -758,7 +803,7 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
// If either of the calling command's srcImage or dstImage parameters are of VkImageType VK_IMAGE_TYPE_3D,
// the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively
- if (((srcImageEntry->second.imageType == VK_IMAGE_TYPE_3D) || (dstImageEntry->second.imageType == VK_IMAGE_TYPE_3D)) &&
+ if (((srcImageEntry->imageType == VK_IMAGE_TYPE_3D) || (dstImageEntry->imageType == VK_IMAGE_TYPE_3D)) &&
((pRegions[i].srcSubresource.baseArrayLayer != 0) || (pRegions[i].srcSubresource.layerCount != 1) ||
(pRegions[i].dstSubresource.baseArrayLayer != 0) || (pRegions[i].dstSubresource.layerCount != 1))) {
std::stringstream ss;
@@ -770,7 +815,7 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
}
// MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
- if (pRegions[i].srcSubresource.mipLevel >= srcImageEntry->second.mipLevels) {
+ if (pRegions[i].srcSubresource.mipLevel >= srcImageEntry->mipLevels) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i
<< "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
@@ -778,7 +823,7 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
__LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
}
- if (pRegions[i].dstSubresource.mipLevel >= dstImageEntry->second.mipLevels) {
+ if (pRegions[i].dstSubresource.mipLevel >= dstImageEntry->mipLevels) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i
<< "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
@@ -789,20 +834,18 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
// (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
// image was created
- if ((pRegions[i].srcSubresource.baseArrayLayer + pRegions[i].srcSubresource.layerCount) >
- srcImageEntry->second.arraySize) {
+ if ((pRegions[i].srcSubresource.baseArrayLayer + pRegions[i].srcSubresource.layerCount) > srcImageEntry->arraySize) {
std::stringstream ss;
- ss << "vkCmdCopyImage: srcImage arrayLayers was " << srcImageEntry->second.arraySize << " but subRegion[" << i
+ ss << "vkCmdCopyImage: srcImage arrayLayers was " << srcImageEntry->arraySize << " but subRegion[" << i
<< "] baseArrayLayer + layerCount is "
<< (pRegions[i].srcSubresource.baseArrayLayer + pRegions[i].srcSubresource.layerCount);
skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(commandBuffer),
__LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
}
- if ((pRegions[i].dstSubresource.baseArrayLayer + pRegions[i].dstSubresource.layerCount) >
- dstImageEntry->second.arraySize) {
+ if ((pRegions[i].dstSubresource.baseArrayLayer + pRegions[i].dstSubresource.layerCount) > dstImageEntry->arraySize) {
std::stringstream ss;
- ss << "vkCmdCopyImage: dstImage arrayLayers was " << dstImageEntry->second.arraySize << " but subRegion[" << i
+ ss << "vkCmdCopyImage: dstImage arrayLayers was " << dstImageEntry->arraySize << " but subRegion[" << i
<< "] baseArrayLayer + layerCount is "
<< (pRegions[i].dstSubresource.baseArrayLayer + pRegions[i].dstSubresource.layerCount);
skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
@@ -811,7 +854,7 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
}
// The source region specified by a given element of pRegions must be a region that is contained within srcImage
- if (exceeds_bounds(&pRegions[i].srcOffset, &pRegions[i].extent, &srcImageEntry->second)) {
+ if (exceeds_bounds(&pRegions[i].srcOffset, &pRegions[i].extent, srcImageEntry)) {
std::stringstream ss;
ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with";
skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
@@ -820,7 +863,7 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
}
// The destination region specified by a given element of pRegions must be a region that is contained within dstImage
- if (exceeds_bounds(&pRegions[i].dstOffset, &pRegions[i].extent, &dstImageEntry->second)) {
+ if (exceeds_bounds(&pRegions[i].dstOffset, &pRegions[i].extent, dstImageEntry)) {
std::stringstream ss;
ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with";
skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
@@ -832,7 +875,7 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
// must not overlap in memory
if (srcImage == dstImage) {
for (uint32_t j = 0; j < regionCount; j++) {
- if (region_intersects(&pRegions[i], &pRegions[j], srcImageEntry->second.imageType)) {
+ if (region_intersects(&pRegions[i], &pRegions[j], srcImageEntry->imageType)) {
std::stringstream ss;
ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
skipCall |=
@@ -847,16 +890,16 @@ bool cmd_copy_image_valid_usage(VkCommandBuffer commandBuffer, VkImage srcImage,
// The formats of srcImage and dstImage must be compatible. Formats are considered compatible if their texel size in bytes
// is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because
// because both texels are 4 bytes in size. Depth/stencil formats must match exactly.
- if (is_depth_format(srcImageEntry->second.format) || is_depth_format(dstImageEntry->second.format)) {
- if (srcImageEntry->second.format != dstImageEntry->second.format) {
+ if (vk_format_is_depth_or_stencil(srcImageEntry->format) || vk_format_is_depth_or_stencil(dstImageEntry->format)) {
+ if (srcImageEntry->format != dstImageEntry->format) {
char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
skipCall |=
log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
reinterpret_cast<uint64_t &>(commandBuffer), __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
}
} else {
- size_t srcSize = vk_format_get_size(srcImageEntry->second.format);
- size_t destSize = vk_format_get_size(dstImageEntry->second.format);
+ size_t srcSize = vk_format_get_size(srcImageEntry->format);
+ size_t destSize = vk_format_get_size(dstImageEntry->format);
if (srcSize != destSize) {
char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
skipCall |=
@@ -989,13 +1032,13 @@ CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcI
bool skipCall = false;
layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- auto srcImageEntry = device_data->imageMap.find(srcImage);
- auto dstImageEntry = device_data->imageMap.find(dstImage);
+ auto srcImageEntry = getImageState(device_data, srcImage);
+ auto dstImageEntry = getImageState(device_data, dstImage);
- if ((srcImageEntry != device_data->imageMap.end()) && (dstImageEntry != device_data->imageMap.end())) {
+ if (srcImageEntry && dstImageEntry) {
- VkFormat srcFormat = srcImageEntry->second.format;
- VkFormat dstFormat = dstImageEntry->second.format;
+ VkFormat srcFormat = srcImageEntry->format;
+ VkFormat dstFormat = dstImageEntry->format;
// Validate consistency for signed and unsigned formats
if ((vk_format_is_sint(srcFormat) && !vk_format_is_sint(dstFormat)) ||
@@ -1141,8 +1184,8 @@ CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout s
VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
bool skipCall = false;
layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- auto srcImageEntry = device_data->imageMap.find(srcImage);
- auto dstImageEntry = device_data->imageMap.find(dstImage);
+ auto srcImageEntry = getImageState(device_data, srcImage);
+ auto dstImageEntry = getImageState(device_data, dstImage);
// For each region, the number of layers in the image subresource should not be zero
// For each region, src and dest image aspect must be color only
@@ -1174,26 +1217,26 @@ CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout s
}
}
- if ((srcImageEntry != device_data->imageMap.end()) && (dstImageEntry != device_data->imageMap.end())) {
- if (srcImageEntry->second.format != dstImageEntry->second.format) {
+ if (srcImageEntry && dstImageEntry) {
+ if (srcImageEntry->format != dstImageEntry->format) {
char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
skipCall |=
log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
(uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
}
- if (srcImageEntry->second.imageType != dstImageEntry->second.imageType) {
+ if (srcImageEntry->imageType != dstImageEntry->imageType) {
char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
skipCall |=
log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
(uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
}
- if (srcImageEntry->second.samples == VK_SAMPLE_COUNT_1_BIT) {
+ if (srcImageEntry->samples == VK_SAMPLE_COUNT_1_BIT) {
char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
skipCall |=
log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
(uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
}
- if (dstImageEntry->second.samples != VK_SAMPLE_COUNT_1_BIT) {
+ if (dstImageEntry->samples != VK_SAMPLE_COUNT_1_BIT) {
char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
skipCall |=
log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
@@ -1213,11 +1256,11 @@ GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresour
layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
VkFormat format;
- auto imageEntry = device_data->imageMap.find(image);
+ auto imageEntry = getImageState(device_data, image);
// Validate that image aspects match formats
- if (imageEntry != device_data->imageMap.end()) {
- format = imageEntry->second.format;
+ if (imageEntry) {
+ format = imageEntry->format;
if (vk_format_is_color(format)) {
if (pSubresource->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
std::stringstream ss;
@@ -1249,6 +1292,24 @@ GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDevicePro
phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
}
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
+ return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
+
+ return VK_ERROR_LAYER_NOT_PRESENT;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
@@ -1316,15 +1377,13 @@ intercept_core_instance_command(const char *name) {
{ "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
{ "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
{ "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
+ { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
+ { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
+ { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
{ "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
{ "vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties) },
};
- // we should never be queried for these commands
- assert(strcmp(name, "vkEnumerateInstanceLayerProperties") &&
- strcmp(name, "vkEnumerateInstanceExtensionProperties") &&
- strcmp(name, "vkEnumerateDeviceLayerProperties"));
-
for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
if (!strcmp(core_instance_commands[i].name, name))
return core_instance_commands[i].proc;
@@ -1388,27 +1447,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu
image::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
}
-// loader-layer interface v0
+// loader-layer interface v0, just wrappers since there is only a layer
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
- return util_GetExtensionProperties(1, image::instance_extensions, pCount, pProperties);
+ return image::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &image::global_layer, pCount, pProperties);
+ return image::EnumerateInstanceLayerProperties(pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &image::global_layer, pCount, pProperties);
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return image::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
- // the layer command handles VK_NULL_HANDLE just fine
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
return image::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
}
@@ -1417,14 +1479,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
}
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
- if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);
- if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);
- if (!strcmp(funcName, "vkGetInstanceProcAddr"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);
-
return image::GetInstanceProcAddr(instance, funcName);
}
diff --git a/layers/image.h b/layers/image.h
index 66a967ca..6a6c76b3 100644
--- a/layers/image.h
+++ b/layers/image.h
@@ -26,7 +26,7 @@
#include "vk_layer_logging.h"
// Image ERROR codes
-typedef enum _IMAGE_ERROR {
+enum IMAGE_ERROR {
IMAGE_NONE, // Used for INFO & other non-error messages
IMAGE_FORMAT_UNSUPPORTED, // Request to create Image or RenderPass with a format that is not supported
IMAGE_RENDERPASS_INVALID_ATTACHMENT, // Invalid image layouts and/or load/storeOps for an attachment when creating RenderPass
@@ -44,9 +44,10 @@ typedef enum _IMAGE_ERROR {
IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, // Device limits for this format have been exceeded
IMAGE_INVALID_LAYOUT, // Operation specifies an invalid layout
IMAGE_INVALID_EXTENTS, // Operation specifies invalid image extents
-} IMAGE_ERROR;
+ IMAGE_INVALID_USAGE, // Image was created without necessary usage for operation
+};
-typedef struct _IMAGE_STATE {
+struct IMAGE_STATE {
uint32_t mipLevels;
uint32_t arraySize;
VkFormat format;
@@ -54,13 +55,14 @@ typedef struct _IMAGE_STATE {
VkImageType imageType;
VkExtent3D extent;
VkImageCreateFlags flags;
- _IMAGE_STATE()
+ VkImageUsageFlags usage;
+ IMAGE_STATE()
: mipLevels(0), arraySize(0), format(VK_FORMAT_UNDEFINED), samples(VK_SAMPLE_COUNT_1_BIT),
- imageType(VK_IMAGE_TYPE_RANGE_SIZE), extent{}, flags(0){};
- _IMAGE_STATE(const VkImageCreateInfo *pCreateInfo)
+ imageType(VK_IMAGE_TYPE_RANGE_SIZE), extent{}, flags(0), usage(0){};
+ IMAGE_STATE(const VkImageCreateInfo *pCreateInfo)
: mipLevels(pCreateInfo->mipLevels), arraySize(pCreateInfo->arrayLayers), format(pCreateInfo->format),
- samples(pCreateInfo->samples), imageType(pCreateInfo->imageType), extent(pCreateInfo->extent),
- flags(pCreateInfo->flags){};
-} IMAGE_STATE;
+ samples(pCreateInfo->samples), imageType(pCreateInfo->imageType), extent(pCreateInfo->extent), flags(pCreateInfo->flags),
+ usage(pCreateInfo->usage){};
+};
#endif // IMAGE_H
diff --git a/layers/linux/VkLayer_core_validation.json b/layers/linux/VkLayer_core_validation.json
index 0053bd83..4a831d71 100644
--- a/layers/linux/VkLayer_core_validation.json
+++ b/layers/linux/VkLayer_core_validation.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_core_validation",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_core_validation.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_device_limits.json b/layers/linux/VkLayer_device_limits.json
index e89fa2ea..f08813b9 100644
--- a/layers/linux/VkLayer_device_limits.json
+++ b/layers/linux/VkLayer_device_limits.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_device_limits",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_device_limits.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_image.json b/layers/linux/VkLayer_image.json
index 3e0953a1..1ab9b4d7 100644
--- a/layers/linux/VkLayer_image.json
+++ b/layers/linux/VkLayer_image.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_image",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_image.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_object_tracker.json b/layers/linux/VkLayer_object_tracker.json
index f2030cd5..78ba294e 100644
--- a/layers/linux/VkLayer_object_tracker.json
+++ b/layers/linux/VkLayer_object_tracker.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_object_tracker",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_object_tracker.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_parameter_validation.json b/layers/linux/VkLayer_parameter_validation.json
index 04e914df..8f91928c 100644
--- a/layers/linux/VkLayer_parameter_validation.json
+++ b/layers/linux/VkLayer_parameter_validation.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_parameter_validation",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_parameter_validation.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_swapchain.json b/layers/linux/VkLayer_swapchain.json
index 07e12485..4064f7f3 100644
--- a/layers/linux/VkLayer_swapchain.json
+++ b/layers/linux/VkLayer_swapchain.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_swapchain",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_swapchain.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_threading.json b/layers/linux/VkLayer_threading.json
index d8352a7c..18dad2b3 100644
--- a/layers/linux/VkLayer_threading.json
+++ b/layers/linux/VkLayer_threading.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_GOOGLE_threading",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_threading.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "Google Validation Layer",
"instance_extensions": [
diff --git a/layers/linux/VkLayer_unique_objects.json b/layers/linux/VkLayer_unique_objects.json
index 85a438b7..0dae1337 100644
--- a/layers/linux/VkLayer_unique_objects.json
+++ b/layers/linux/VkLayer_unique_objects.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_GOOGLE_unique_objects",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": "./libVkLayer_unique_objects.so",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "Google Validation Layer"
}
diff --git a/layers/object_tracker.h b/layers/object_tracker.h
index c90b0991..333775ae 100644
--- a/layers/object_tracker.h
+++ b/layers/object_tracker.h
@@ -28,8 +28,10 @@
#include "vk_layer_table.h"
#include "vk_layer_utils.h"
+namespace object_tracker {
+
// Object Tracker ERROR codes
-typedef enum _OBJECT_TRACK_ERROR {
+enum OBJECT_TRACK_ERROR {
OBJTRACK_NONE, // Used for INFO & other non-error messages
OBJTRACK_UNKNOWN_OBJECT, // Updating uses of object that's not in global object list
OBJTRACK_INTERNAL_ERROR, // Bug with data tracking within the layer
@@ -37,11 +39,11 @@ typedef enum _OBJECT_TRACK_ERROR {
OBJTRACK_INVALID_OBJECT, // Object used that has never been created
OBJTRACK_DESCRIPTOR_POOL_MISMATCH, // Descriptor Pools specified incorrectly
OBJTRACK_COMMAND_POOL_MISMATCH, // Command Pools specified incorrectly
-} OBJECT_TRACK_ERROR;
+};
// Object Status -- used to track state of individual objects
typedef VkFlags ObjectStatusFlags;
-typedef enum _ObjectStatusFlagBits {
+enum ObjectStatusFlagBits {
OBJSTATUS_NONE = 0x00000000, // No status is set
OBJSTATUS_FENCE_IS_SUBMITTED = 0x00000001, // Fence has been submitted
OBJSTATUS_VIEWPORT_BOUND = 0x00000002, // Viewport state object has been bound
@@ -50,15 +52,15 @@ typedef enum _ObjectStatusFlagBits {
OBJSTATUS_DEPTH_STENCIL_BOUND = 0x00000010, // Viewport state object has been bound
OBJSTATUS_GPU_MEM_MAPPED = 0x00000020, // Memory object is currently mapped
OBJSTATUS_COMMAND_BUFFER_SECONDARY = 0x00000040, // Command Buffer is of type SECONDARY
-} ObjectStatusFlagBits;
+};
-typedef struct _OBJTRACK_NODE {
+struct OBJTRACK_NODE {
uint64_t vkObj; // Object handle
VkDebugReportObjectTypeEXT objType; // Object type identifier
ObjectStatusFlags status; // Object state
uint64_t parentObj; // Parent object
uint64_t belongsTo; // Object Scope -- owning device/instance
-} OBJTRACK_NODE;
+};
// prototype for extension functions
uint64_t objTrackGetObjectCount(VkDevice device);
@@ -69,6 +71,8 @@ typedef uint64_t (*OBJ_TRACK_GET_OBJECT_COUNT)(VkDevice);
typedef uint64_t (*OBJ_TRACK_GET_OBJECTS_OF_TYPE_COUNT)(VkDevice, VkDebugReportObjectTypeEXT);
struct layer_data {
+ VkInstance instance;
+
debug_report_data *report_data;
// TODO: put instance data here
std::vector<VkDebugReportCallbackEXT> logging_callback;
@@ -107,8 +111,6 @@ static uint64_t numObjs[NUM_OBJECT_TYPES] = {0};
static uint64_t numTotalObjs = 0;
std::vector<VkQueueFamilyProperties> queue_family_properties;
-template layer_data *get_my_data_ptr<layer_data>(void *data_key, std::unordered_map<void *, layer_data *> &data_map);
-
//
// Internal Object Tracker Functions
//
@@ -184,10 +186,10 @@ static void createInstanceRegisterExtensions(const VkInstanceCreateInfo *pCreate
}
// Indicate device or instance dispatch table type
-typedef enum _DispTableType {
+enum DispTableType {
DISP_TBL_TYPE_INSTANCE,
DISP_TBL_TYPE_DEVICE,
-} DispTableType;
+};
debug_report_data *mdd(const void *object) {
dispatch_key key = get_dispatch_key(object);
@@ -202,20 +204,19 @@ debug_report_data *mid(VkInstance object) {
}
// For each Queue's doubly linked-list of mem refs
-typedef struct _OT_MEM_INFO {
+struct OT_MEM_INFO {
VkDeviceMemory mem;
- struct _OT_MEM_INFO *pNextMI;
- struct _OT_MEM_INFO *pPrevMI;
-
-} OT_MEM_INFO;
+ OT_MEM_INFO *pNextMI;
+ OT_MEM_INFO *pPrevMI;
+};
// Track Queue information
-typedef struct _OT_QUEUE_INFO {
+struct OT_QUEUE_INFO {
OT_MEM_INFO *pMemRefList;
uint32_t queueNodeIndex;
VkQueue queue;
uint32_t refCount;
-} OT_QUEUE_INFO;
+};
// Global map of structures, one per queue
std::unordered_map<VkQueue, OT_QUEUE_INFO *> queue_info_map;
@@ -618,6 +619,7 @@ VkResult explicit_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const
}
layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+ my_data->instance = *pInstance;
initInstanceTable(*pInstance, fpGetInstanceProcAddr, object_tracker_instance_table_map);
VkLayerInstanceDispatchTable *pInstanceTable = get_dispatch_table(object_tracker_instance_table_map, *pInstance);
@@ -651,12 +653,13 @@ void explicit_GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice gpu, uint3
VkResult explicit_CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkDevice *pDevice) {
std::lock_guard<std::mutex> lock(global_lock);
+ layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
assert(chain_info->u.pLayerInfo);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
- PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+ PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
if (fpCreateDevice == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -669,7 +672,6 @@ VkResult explicit_CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *p
return result;
}
- layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
@@ -1060,3 +1062,5 @@ VkResult explicit_CreateComputePipelines(VkDevice device, VkPipelineCache pipeli
lock.unlock();
return result;
}
+
+} // namespace object_tracker
diff --git a/layers/parameter_validation.cpp b/layers/parameter_validation.cpp
index 20676b4a..4be50316 100644
--- a/layers/parameter_validation.cpp
+++ b/layers/parameter_validation.cpp
@@ -49,9 +49,11 @@
#include "parameter_validation.h"
-using namespace parameter_validation;
+namespace parameter_validation {
struct layer_data {
+ VkInstance instance;
+
debug_report_data *report_data;
std::vector<VkDebugReportCallbackEXT> logging_callback;
@@ -101,23 +103,23 @@ static void init_parameter_validation(layer_data *my_data, const VkAllocationCal
layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_parameter_validation");
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
VkResult result = pTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (result == VK_SUCCESS) {
layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
- result = layer_create_msg_callback(data->report_data, pCreateInfo, pAllocator, pMsgCallback);
+ result = layer_create_msg_callback(data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
- VkDebugReportCallbackEXT msgCallback,
- const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
+ VkDebugReportCallbackEXT msgCallback,
+ const VkAllocationCallbacks *pAllocator) {
VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
pTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
@@ -125,47 +127,18 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkIns
layer_destroy_msg_callback(data->report_data, msgCallback, pAllocator);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDebugReportMessageEXT(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
+DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
+ size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
pTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
}
static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
- return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
-}
-
-static const VkLayerProperties pc_global_layers[] = {{
+static const VkLayerProperties global_layer = {
"VK_LAYER_LUNARG_parameter_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
-}};
-
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties);
-}
-
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
- const char *pLayerName, uint32_t *pCount,
- VkExtensionProperties *pProperties) {
- /* parameter_validation does not have any physical device extensions */
- if (pLayerName == NULL) {
- return get_dispatch_table(pc_instance_table_map, physicalDevice)
- ->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
- } else {
- return util_GetExtensionProperties(0, NULL, pCount, pProperties);
- }
-}
-
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
-
- /* parameter_validation's physical device layers are the same as global */
- return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties);
-}
+};
static bool ValidateEnumerator(VkFormatFeatureFlagBits const &enumerator) {
VkFormatFeatureFlagBits allFlags = (VkFormatFeatureFlagBits)(
@@ -1318,8 +1291,8 @@ static bool validate_queue_family_indices(layer_data *device_data, const char *f
return skip_call;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
@@ -1343,6 +1316,7 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCall
VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, pc_instance_table_map);
+ my_instance_data->instance = *pInstance;
my_instance_data->report_data = debug_report_create_instance(pTable, *pInstance, pCreateInfo->enabledExtensionCount,
pCreateInfo->ppEnabledExtensionNames);
@@ -1391,7 +1365,7 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCall
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
// Grab the key before the instance is destroyed.
dispatch_key key = get_dispatch_key(instance);
bool skipCall = false;
@@ -1437,8 +1411,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
@@ -1456,8 +1430,8 @@ vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount,
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
+VKAPI_ATTR void VKAPI_CALL
+GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
assert(my_data != NULL);
@@ -1469,8 +1443,8 @@ vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFea
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
+VKAPI_ATTR void VKAPI_CALL
+GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
assert(my_data != NULL);
@@ -1483,10 +1457,10 @@ vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat fo
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
- VkImageUsageFlags usage, VkImageCreateFlags flags,
- VkImageFormatProperties *pImageFormatProperties) {
+VKAPI_ATTR VkResult VKAPI_CALL
+GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
+ VkImageUsageFlags usage, VkImageCreateFlags flags,
+ VkImageFormatProperties *pImageFormatProperties) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
@@ -1506,8 +1480,8 @@ vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkForm
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
+VKAPI_ATTR void VKAPI_CALL
+GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
assert(my_data != NULL);
@@ -1519,9 +1493,9 @@ vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceP
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
- VkQueueFamilyProperties *pQueueFamilyProperties) {
+VKAPI_ATTR void VKAPI_CALL
+GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
+ VkQueueFamilyProperties *pQueueFamilyProperties) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
assert(my_data != NULL);
@@ -1535,8 +1509,8 @@ vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
+VKAPI_ATTR void VKAPI_CALL
+GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
assert(my_data != NULL);
@@ -1609,9 +1583,9 @@ void storeCreateDeviceData(VkDevice device, const VkDeviceCreateInfo *pCreateInf
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
- const VkDeviceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
+ const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
/*
* NOTE: We do not validate physicalDevice or any dispatchable
* object as the first parameter. We couldn't get here if it was wrong!
@@ -1647,7 +1621,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice p
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
- PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+ PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
if (fpCreateDevice == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -1681,7 +1655,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice p
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
dispatch_key key = get_dispatch_key(device);
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(key, layer_data_map);
@@ -1721,8 +1695,8 @@ bool PreGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queu
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
+VKAPI_ATTR void VKAPI_CALL
+GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1736,8 +1710,8 @@ vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
+VKAPI_ATTR VkResult VKAPI_CALL
+QueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
@@ -1754,7 +1728,7 @@ vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits,
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) {
+VKAPI_ATTR VkResult VKAPI_CALL QueueWaitIdle(VkQueue queue) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
assert(my_data != NULL);
@@ -1765,7 +1739,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) {
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device) {
+VKAPI_ATTR VkResult VKAPI_CALL DeviceWaitIdle(VkDevice device) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1776,7 +1750,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device)
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
+VKAPI_ATTR VkResult VKAPI_CALL AllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
@@ -1794,8 +1768,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device,
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+FreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1807,8 +1781,8 @@ vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) {
+VKAPI_ATTR VkResult VKAPI_CALL
+MapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -1825,7 +1799,7 @@ vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDevic
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(VkDevice device, VkDeviceMemory memory) {
+VKAPI_ATTR void VKAPI_CALL UnmapMemory(VkDevice device, VkDeviceMemory memory) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1837,8 +1811,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(VkDevice device, VkDevi
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) {
+VKAPI_ATTR VkResult VKAPI_CALL
+FlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -1855,8 +1829,8 @@ vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMa
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) {
+VKAPI_ATTR VkResult VKAPI_CALL
+InvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -1874,8 +1848,8 @@ vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize *pCommittedMemoryInBytes) {
+VKAPI_ATTR void VKAPI_CALL
+GetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize *pCommittedMemoryInBytes) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1887,8 +1861,8 @@ vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
- VkDeviceSize memoryOffset) {
+VKAPI_ATTR VkResult VKAPI_CALL BindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory memory,
+ VkDeviceSize memoryOffset) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -1905,8 +1879,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(VkDevice devic
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory,
- VkDeviceSize memoryOffset) {
+VKAPI_ATTR VkResult VKAPI_CALL BindImageMemory(VkDevice device, VkImage image, VkDeviceMemory memory,
+ VkDeviceSize memoryOffset) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -1923,8 +1897,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
+VKAPI_ATTR void VKAPI_CALL
+GetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1936,8 +1910,8 @@ vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirem
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
+VKAPI_ATTR void VKAPI_CALL
+GetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -1966,9 +1940,9 @@ bool PostGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t *pSparseMemoryRequirementCount,
- VkSparseImageMemoryRequirements *pSparseMemoryRequirements) {
+VKAPI_ATTR void VKAPI_CALL
+GetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t *pSparseMemoryRequirementCount,
+ VkSparseImageMemoryRequirements *pSparseMemoryRequirements) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2001,10 +1975,10 @@ bool PostGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalD
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
- VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
- uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties) {
+VKAPI_ATTR void VKAPI_CALL
+GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
+ VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
+ uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
assert(my_data != NULL);
@@ -2022,8 +1996,8 @@ vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) {
+VKAPI_ATTR VkResult VKAPI_CALL
+QueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
@@ -2040,8 +2014,8 @@ vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2058,7 +2032,7 @@ vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAll
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2070,7 +2044,7 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFen
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
+VKAPI_ATTR VkResult VKAPI_CALL ResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2087,7 +2061,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, ui
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, VkFence fence) {
+VKAPI_ATTR VkResult VKAPI_CALL GetFenceStatus(VkDevice device, VkFence fence) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2104,8 +2078,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device,
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) {
+VKAPI_ATTR VkResult VKAPI_CALL
+WaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2122,7 +2096,7 @@ vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, Vk
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
+VKAPI_ATTR VkResult VKAPI_CALL CreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
@@ -2140,8 +2114,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2153,8 +2127,8 @@ vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCal
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2171,7 +2145,7 @@ vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAll
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2183,7 +2157,7 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device, VkEve
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(VkDevice device, VkEvent event) {
+VKAPI_ATTR VkResult VKAPI_CALL GetEventStatus(VkDevice device, VkEvent event) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2200,7 +2174,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(VkDevice device,
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event) {
+VKAPI_ATTR VkResult VKAPI_CALL SetEvent(VkDevice device, VkEvent event) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2217,7 +2191,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEve
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(VkDevice device, VkEvent event) {
+VKAPI_ATTR VkResult VKAPI_CALL ResetEvent(VkDevice device, VkEvent event) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2234,26 +2208,41 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(VkDevice device, VkE
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateQueryPool(my_data->report_data, pCreateInfo, pAllocator, pQueryPool);
+ skip_call |= parameter_validation_vkCreateQueryPool(device_data->report_data, pCreateInfo, pAllocator, pQueryPool);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfo != nullptr) {
+ // If queryType is VK_QUERY_TYPE_PIPELINE_STATISTICS, pipelineStatistics must be a valid combination of
+ // VkQueryPipelineStatisticFlagBits values
+ if ((pCreateInfo->queryType == VK_QUERY_TYPE_PIPELINE_STATISTICS) && (pCreateInfo->pipelineStatistics != 0) &&
+ ((pCreateInfo->pipelineStatistics & (~AllVkQueryPipelineStatisticFlagBits)) != 0)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ UNRECOGNIZED_VALUE, LayerName, "vkCreateQueryPool: if pCreateInfo->queryType is "
+ "VK_QUERY_TYPE_PIPELINE_STATISTICS, pCreateInfo->pipelineStatistics must be "
+ "a valid combination of VkQueryPipelineStatisticFlagBits values");
+ }
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)->CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
- validate_result(my_data->report_data, "vkCreateQueryPool", result);
+ validate_result(report_data, "vkCreateQueryPool", result);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2265,9 +2254,9 @@ vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCal
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
- uint32_t queryCount, size_t dataSize, void *pData,
- VkDeviceSize stride, VkQueryResultFlags flags) {
+VKAPI_ATTR VkResult VKAPI_CALL GetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
+ uint32_t queryCount, size_t dataSize, void *pData,
+ VkDeviceSize stride, VkQueryResultFlags flags) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2286,39 +2275,54 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(VkDevice de
return result;
}
-bool PreCreateBuffer(layer_data *device_data, const VkBufferCreateInfo *pCreateInfo) {
- if (pCreateInfo != nullptr) {
- if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
- validate_queue_family_indices(device_data, "vkCreateBuffer", "pCreateInfo->pQueueFamilyIndices",
- pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
- }
- }
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
+ VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- return true;
-}
+ skip_call |= parameter_validation_vkCreateBuffer(report_data, pCreateInfo, pAllocator, pBuffer);
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
- VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ if (pCreateInfo != nullptr) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
+ if (pCreateInfo->queueFamilyIndexCount <= 1) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ INVALID_USAGE, LayerName, "vkCreateBuffer: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->queueFamilyIndexCount must be greater than 1");
+ }
- skipCall |= parameter_validation_vkCreateBuffer(my_data->report_data, pCreateInfo, pAllocator, pBuffer);
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
+ // queueFamilyIndexCount uint32_t values
+ if (pCreateInfo->pQueueFamilyIndices == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateBuffer: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
+ "pCreateInfo->queueFamilyIndexCount uint32_t values");
+ }
- if (!skipCall) {
- PreCreateBuffer(my_data, pCreateInfo);
+ // Ensure that the queue family indices were specified at device creation
+ skip_call |= validate_queue_family_indices(device_data, "vkCreateBuffer", "pCreateInfo->pQueueFamilyIndices",
+ pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
+ }
+ }
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
- validate_result(my_data->report_data, "vkCreateBuffer", result);
+ validate_result(report_data, "vkCreateBuffer", result);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2330,8 +2334,8 @@ vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *p
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2348,8 +2352,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(VkDevice devic
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2361,25 +2365,36 @@ vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocation
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skip_call = false;
layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(device_data != NULL);
+ assert(device_data != nullptr);
debug_report_data *report_data = device_data->report_data;
skip_call |= parameter_validation_vkCreateImage(report_data, pCreateInfo, pAllocator, pImage);
if (pCreateInfo != nullptr) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
- // pQueueFamilyIndices must not be NULL
- skip_call |= validate_required_pointer(report_data, "vkCreateImage", "pCreateInfo->pQueueFamilyIndices",
- pCreateInfo->pQueueFamilyIndices);
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, queueFamilyIndexCount must be greater than 1
+ if (pCreateInfo->queueFamilyIndexCount <= 1) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ INVALID_USAGE, LayerName, "vkCreateImage: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->queueFamilyIndexCount must be greater than 1");
+ }
- // queueFamilyIndexCount must be greater than 1
- skip_call |= ValidateGreaterThan(report_data, "vkCreateImage", "pCreateInfo->pQueueFamilyIndices",
- pCreateInfo->queueFamilyIndexCount, 1u);
+ // If sharingMode is VK_SHARING_MODE_CONCURRENT, pQueueFamilyIndices must be a pointer to an array of
+ // queueFamilyIndexCount uint32_t values
+ if (pCreateInfo->pQueueFamilyIndices == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateImage: if pCreateInfo->sharingMode is VK_SHARING_MODE_CONCURRENT, "
+ "pCreateInfo->pQueueFamilyIndices must be a pointer to an array of "
+ "pCreateInfo->queueFamilyIndexCount uint32_t values");
+ }
skip_call |= validate_queue_family_indices(device_data, "vkCreateImage", "pCreateInfo->pQueueFamilyIndices",
pCreateInfo->queueFamilyIndexCount, pCreateInfo->pQueueFamilyIndices);
@@ -2457,7 +2472,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, co
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2483,8 +2498,8 @@ bool PreGetImageSubresourceLayout(VkDevice device, const VkImageSubresource *pSu
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) {
+VKAPI_ATTR void VKAPI_CALL
+GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2498,8 +2513,8 @@ vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubreso
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skip_call = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2560,8 +2575,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2573,9 +2588,9 @@ vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCal
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkShaderModule *pShaderModule) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkShaderModule *pShaderModule) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2593,8 +2608,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(VkDevice dev
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2606,9 +2621,9 @@ vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllo
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkPipelineCache *pPipelineCache) {
+VKAPI_ATTR VkResult VKAPI_CALL CreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkPipelineCache *pPipelineCache) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2626,8 +2641,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(VkDevice de
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2639,8 +2654,8 @@ vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkA
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData) {
+VKAPI_ATTR VkResult VKAPI_CALL
+GetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2657,8 +2672,8 @@ vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *p
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) {
+VKAPI_ATTR VkResult VKAPI_CALL
+MergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2725,25 +2740,363 @@ bool PreCreateGraphicsPipelines(VkDevice device, const VkGraphicsPipelineCreateI
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
- const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
- VkPipeline *pPipelines) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
+ const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
+ VkPipeline *pPipelines) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateGraphicsPipelines(my_data->report_data, pipelineCache, createInfoCount, pCreateInfos,
- pAllocator, pPipelines);
+ skip_call |= parameter_validation_vkCreateGraphicsPipelines(report_data, pipelineCache, createInfoCount, pCreateInfos,
+ pAllocator, pPipelines);
- if (!skipCall) {
+ if (pCreateInfos != nullptr) {
+ for (uint32_t i = 0; i < createInfoCount; ++i) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfos[i].pTessellationState == nullptr) {
+ if (pCreateInfos[i].pStages != nullptr) {
+ // If pStages includes a tessellation control shader stage and a tessellation evaluation shader stage,
+ // pTessellationState must not be NULL
+ bool has_control = false;
+ bool has_eval = false;
+
+ for (uint32_t stage_index = 0; stage_index < pCreateInfos[i].stageCount; ++stage_index) {
+ if (pCreateInfos[i].pStages[stage_index].stage == VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
+ has_control = true;
+ } else if (pCreateInfos[i].pStages[stage_index].stage == VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
+ has_eval = true;
+ }
+ }
+
+ if (has_control && has_eval) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pStages includes a tessellation "
+ "control shader stage and a tessellation evaluation shader stage, "
+ "pCreateInfos[%d].pTessellationState must not be NULL",
+ i, i);
+ }
+ }
+ } else {
+ skip_call |=
+ validate_struct_pnext(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pTessellationState->pNext",
+ NULL, pCreateInfos[i].pTessellationState->pNext, 0, NULL);
+
+ skip_call |=
+ validate_reserved_flags(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pTessellationState->flags",
+ pCreateInfos[i].pTessellationState->flags);
+
+ if (pCreateInfos[i].pTessellationState->sType != VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pTessellationState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO",
+ i);
+ }
+ }
+
+ if (pCreateInfos[i].pViewportState == nullptr) {
+ // If the rasterizerDiscardEnable member of pRasterizationState is VK_FALSE, pViewportState must be a pointer to a
+ // valid VkPipelineViewportStateCreateInfo structure
+ if ((pCreateInfos[i].pRasterizationState != nullptr) &&
+ (pCreateInfos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE)) {
+ skip_call |= log_msg(
+ report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pRasterizationState->rasterizerDiscardEnable is VK_FALSE, "
+ "pCreateInfos[%d].pViewportState must be a pointer to a valid VkPipelineViewportStateCreateInfo structure",
+ i, i);
+ }
+ } else {
+ skip_call |=
+ validate_struct_pnext(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pViewportState->pNext", NULL,
+ pCreateInfos[i].pViewportState->pNext, 0, NULL);
+
+ skip_call |=
+ validate_reserved_flags(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pViewportState->flags",
+ pCreateInfos[i].pViewportState->flags);
+
+ if (pCreateInfos[i].pViewportState->sType != VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pViewportState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO",
+ i);
+ }
+
+ if (pCreateInfos[i].pDynamicState != nullptr) {
+ bool has_dynamic_viewport = false;
+ bool has_dynamic_scissor = false;
+
+ for (uint32_t state_index = 0; state_index < pCreateInfos[i].pDynamicState->dynamicStateCount; ++state_index) {
+ if (pCreateInfos[i].pDynamicState->pDynamicStates[state_index] == VK_DYNAMIC_STATE_VIEWPORT) {
+ has_dynamic_viewport = true;
+ } else if (pCreateInfos[i].pDynamicState->pDynamicStates[state_index] == VK_DYNAMIC_STATE_SCISSOR) {
+ has_dynamic_scissor = true;
+ }
+ }
+
+ // viewportCount must be greater than 0
+ // TODO: viewportCount must be 1 when multiple_viewport feature is not enabled
+ if (pCreateInfos[i].pViewportState->viewportCount == 0) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates "
+ "contains VK_DYNAMIC_STATE_VIEWPORT, pCreateInfos[%d].pViewportState->viewportCount "
+ "must be greater than 0",
+ i, i);
+ }
+
+ // If no element of the pDynamicStates member of pDynamicState is VK_DYNAMIC_STATE_VIEWPORT, the pViewports
+ // member of pViewportState must be a pointer to an array of pViewportState->viewportCount VkViewport structures
+ if (!has_dynamic_viewport && (pCreateInfos[i].pViewportState->pViewports == nullptr)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates contains "
+ "VK_DYNAMIC_STATE_VIEWPORT, pCreateInfos[%d].pViewportState->pViewports must not be NULL",
+ i, i);
+ }
+
+ // scissorCount must be greater than 0
+ // TODO: scissorCount must be 1 when multiple_viewport feature is not enabled
+ if (pCreateInfos[i].pViewportState->scissorCount == 0) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates "
+ "contains VK_DYNAMIC_STATE_SCISSOR, pCreateInfos[%d].pViewportState->scissorCount "
+ "must be greater than 0",
+ i, i);
+ }
+
+ // If no element of the pDynamicStates member of pDynamicState is VK_DYNAMIC_STATE_SCISSOR, the pScissors member
+ // of pViewportState must be a pointer to an array of pViewportState->scissorCount VkRect2D structures
+ if (!has_dynamic_scissor && (pCreateInfos[i].pViewportState->pScissors == nullptr)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkCreateGraphicsPipelines: if pCreateInfos[%d].pDynamicState->pDynamicStates contains "
+ "VK_DYNAMIC_STATE_SCISSOR, pCreateInfos[%d].pViewportState->pScissors must not be NULL",
+ i, i);
+ }
+ }
+ }
+
+ if (pCreateInfos[i].pMultisampleState == nullptr) {
+ // If the rasterizerDiscardEnable member of pRasterizationState is VK_FALSE, pMultisampleState must be a pointer to
+ // a valid VkPipelineMultisampleStateCreateInfo structure
+ if ((pCreateInfos[i].pRasterizationState != nullptr) &&
+ pCreateInfos[i].pRasterizationState->rasterizerDiscardEnable == VK_FALSE) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ REQUIRED_PARAMETER, LayerName, "vkCreateGraphicsPipelines: if "
+ "pCreateInfos[%d].pRasterizationState->rasterizerDiscardEnable is "
+ "VK_FALSE, pCreateInfos[%d].pMultisampleState must not be NULL",
+ i, i);
+ }
+ } else {
+ skip_call |=
+ validate_struct_pnext(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pMultisampleState->pNext",
+ NULL, pCreateInfos[i].pMultisampleState->pNext, 0, NULL);
+
+ skip_call |=
+ validate_reserved_flags(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pMultisampleState->flags",
+ pCreateInfos[i].pMultisampleState->flags);
+
+ skip_call |= validate_bool32(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pMultisampleState->sampleShadingEnable",
+ pCreateInfos[i].pMultisampleState->sampleShadingEnable);
+
+ skip_call |= validate_array(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pMultisampleState->rasterizationSamples",
+ "pCreateInfos[i].pMultisampleState->pSampleMask", pCreateInfos[i].pMultisampleState->rasterizationSamples,
+ pCreateInfos[i].pMultisampleState->pSampleMask, true, false);
+
+ skip_call |= validate_bool32(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pMultisampleState->alphaToCoverageEnable",
+ pCreateInfos[i].pMultisampleState->alphaToCoverageEnable);
+
+ skip_call |=
+ validate_bool32(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pMultisampleState->alphaToOneEnable",
+ pCreateInfos[i].pMultisampleState->alphaToOneEnable);
+
+ if (pCreateInfos[i].pMultisampleState->sType != VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pMultisampleState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO",
+ i);
+ }
+ }
+
+ // TODO: Conditional NULL check based on rasterizerDiscardEnable and subpass
+ if (pCreateInfos[i].pDepthStencilState != nullptr) {
+ skip_call |=
+ validate_struct_pnext(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->pNext",
+ NULL, pCreateInfos[i].pDepthStencilState->pNext, 0, NULL);
+
+ skip_call |=
+ validate_reserved_flags(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->flags",
+ pCreateInfos[i].pDepthStencilState->flags);
+
+ skip_call |=
+ validate_bool32(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->depthTestEnable",
+ pCreateInfos[i].pDepthStencilState->depthTestEnable);
+
+ skip_call |= validate_bool32(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pDepthStencilState->depthWriteEnable",
+ pCreateInfos[i].pDepthStencilState->depthWriteEnable);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->depthCompareOp", "VkCompareOp",
+ VK_COMPARE_OP_BEGIN_RANGE, VK_COMPARE_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->depthCompareOp);
+
+ skip_call |= validate_bool32(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pDepthStencilState->depthBoundsTestEnable",
+ pCreateInfos[i].pDepthStencilState->depthBoundsTestEnable);
+
+ skip_call |= validate_bool32(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pDepthStencilState->stencilTestEnable",
+ pCreateInfos[i].pDepthStencilState->stencilTestEnable);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->front.failOp", "VkStencilOp",
+ VK_STENCIL_OP_BEGIN_RANGE, VK_STENCIL_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->front.failOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->front.passOp", "VkStencilOp",
+ VK_STENCIL_OP_BEGIN_RANGE, VK_STENCIL_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->front.passOp);
+
+ skip_call |= validate_ranged_enum(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pDepthStencilState->front.depthFailOp", "VkStencilOp",
+ VK_STENCIL_OP_BEGIN_RANGE, VK_STENCIL_OP_END_RANGE,
+ pCreateInfos[i].pDepthStencilState->front.depthFailOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->front.compareOp", "VkCompareOp",
+ VK_COMPARE_OP_BEGIN_RANGE, VK_COMPARE_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->front.compareOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->back.failOp", "VkStencilOp",
+ VK_STENCIL_OP_BEGIN_RANGE, VK_STENCIL_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->back.failOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->back.passOp", "VkStencilOp",
+ VK_STENCIL_OP_BEGIN_RANGE, VK_STENCIL_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->back.passOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->back.depthFailOp", "VkStencilOp",
+ VK_STENCIL_OP_BEGIN_RANGE, VK_STENCIL_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->back.depthFailOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pDepthStencilState->back.compareOp", "VkCompareOp",
+ VK_COMPARE_OP_BEGIN_RANGE, VK_COMPARE_OP_END_RANGE, pCreateInfos[i].pDepthStencilState->back.compareOp);
+
+ if (pCreateInfos[i].pDepthStencilState->sType != VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pDepthStencilState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO",
+ i);
+ }
+ }
+
+ // TODO: Conditional NULL check based on rasterizerDiscardEnable and subpass
+ if (pCreateInfos[i].pColorBlendState != nullptr) {
+ skip_call |=
+ validate_struct_pnext(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pColorBlendState->pNext", NULL,
+ pCreateInfos[i].pColorBlendState->pNext, 0, NULL);
+
+ skip_call |=
+ validate_reserved_flags(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pColorBlendState->flags",
+ pCreateInfos[i].pColorBlendState->flags);
+
+ skip_call |=
+ validate_bool32(report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pColorBlendState->logicOpEnable",
+ pCreateInfos[i].pColorBlendState->logicOpEnable);
+
+ skip_call |= validate_array(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pColorBlendState->attachmentCount",
+ "pCreateInfos[i].pColorBlendState->pAttachments", pCreateInfos[i].pColorBlendState->attachmentCount,
+ pCreateInfos[i].pColorBlendState->pAttachments, false, true);
+
+ if (pCreateInfos[i].pColorBlendState->pAttachments != NULL) {
+ for (uint32_t attachmentIndex = 0; attachmentIndex < pCreateInfos[i].pColorBlendState->attachmentCount;
+ ++attachmentIndex) {
+ skip_call |= validate_bool32(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].blendEnable",
+ pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].blendEnable);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].srcColorBlendFactor", "VkBlendFactor",
+ VK_BLEND_FACTOR_BEGIN_RANGE, VK_BLEND_FACTOR_END_RANGE,
+ pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].srcColorBlendFactor);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].dstColorBlendFactor", "VkBlendFactor",
+ VK_BLEND_FACTOR_BEGIN_RANGE, VK_BLEND_FACTOR_END_RANGE,
+ pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].dstColorBlendFactor);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].colorBlendOp", "VkBlendOp", VK_BLEND_OP_BEGIN_RANGE,
+ VK_BLEND_OP_END_RANGE, pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].colorBlendOp);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].srcAlphaBlendFactor", "VkBlendFactor",
+ VK_BLEND_FACTOR_BEGIN_RANGE, VK_BLEND_FACTOR_END_RANGE,
+ pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].srcAlphaBlendFactor);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].dstAlphaBlendFactor", "VkBlendFactor",
+ VK_BLEND_FACTOR_BEGIN_RANGE, VK_BLEND_FACTOR_END_RANGE,
+ pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].dstAlphaBlendFactor);
+
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].alphaBlendOp", "VkBlendOp", VK_BLEND_OP_BEGIN_RANGE,
+ VK_BLEND_OP_END_RANGE, pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].alphaBlendOp);
+
+ skip_call |=
+ validate_flags(report_data, "vkCreateGraphicsPipelines",
+ "pCreateInfos[i].pColorBlendState->pAttachments[i].colorWriteMask",
+ "VkColorComponentFlagBits", AllVkColorComponentFlagBits,
+ pCreateInfos[i].pColorBlendState->pAttachments[attachmentIndex].colorWriteMask, false);
+ }
+ }
+
+ if (pCreateInfos[i].pColorBlendState->sType != VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, INVALID_STRUCT_STYPE, LayerName,
+ "vkCreateGraphicsPipelines: parameter pCreateInfos[%d].pColorBlendState->sType must be "
+ "VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO",
+ i);
+ }
+
+ // If logicOpEnable is VK_TRUE, logicOp must be a valid VkLogicOp value
+ if (pCreateInfos[i].pColorBlendState->logicOpEnable == VK_TRUE) {
+ skip_call |= validate_ranged_enum(
+ report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pColorBlendState->logicOp", "VkLogicOp",
+ VK_LOGIC_OP_BEGIN_RANGE, VK_LOGIC_OP_END_RANGE, pCreateInfos[i].pColorBlendState->logicOp);
+ }
+ }
+ }
+ }
+
+ if (!skip_call) {
PreCreateGraphicsPipelines(device, pCreateInfos);
result = get_dispatch_table(pc_device_table_map, device)
->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
- validate_result(my_data->report_data, "vkCreateGraphicsPipelines", result);
+ validate_result(report_data, "vkCreateGraphicsPipelines", result);
}
return result;
@@ -2761,10 +3114,10 @@ bool PreCreateComputePipelines(VkDevice device, const VkComputePipelineCreateInf
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
- const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
- VkPipeline *pPipelines) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
+ const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
+ VkPipeline *pPipelines) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2785,8 +3138,8 @@ vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2798,9 +3151,9 @@ vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallba
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
- VkPipelineLayout *pPipelineLayout) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
+ VkPipelineLayout *pPipelineLayout) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2818,8 +3171,8 @@ vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreat
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2831,26 +3184,45 @@ vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != NULL);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateSampler(my_data->report_data, pCreateInfo, pAllocator, pSampler);
+ skip_call |= parameter_validation_vkCreateSampler(report_data, pCreateInfo, pAllocator, pSampler);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pCreateInfo != nullptr) {
+ // If compareEnable is VK_TRUE, compareOp must be a valid VkCompareOp value
+ if (pCreateInfo->compareEnable == VK_TRUE) {
+ skip_call |= validate_ranged_enum(report_data, "vkCreateSampler", "pCreateInfo->compareOp", "VkCompareOp",
+ VK_COMPARE_OP_BEGIN_RANGE, VK_COMPARE_OP_END_RANGE, pCreateInfo->compareOp);
+ }
+
+ // If any of addressModeU, addressModeV or addressModeW are VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, borderColor must be a
+ // valid VkBorderColor value
+ if ((pCreateInfo->addressModeU == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
+ (pCreateInfo->addressModeV == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) ||
+ (pCreateInfo->addressModeW == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER)) {
+ skip_call |= validate_ranged_enum(report_data, "vkCreateSampler", "pCreateInfo->borderColor", "VkBorderColor",
+ VK_BORDER_COLOR_BEGIN_RANGE, VK_BORDER_COLOR_END_RANGE, pCreateInfo->borderColor);
+ }
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)->CreateSampler(device, pCreateInfo, pAllocator, pSampler);
- validate_result(my_data->report_data, "vkCreateSampler", result);
+ validate_result(report_data, "vkCreateSampler", result);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2862,28 +3234,66 @@ vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkCreateDescriptorSetLayout(my_data->report_data, pCreateInfo, pAllocator, pSetLayout);
+ skip_call |= parameter_validation_vkCreateDescriptorSetLayout(report_data, pCreateInfo, pAllocator, pSetLayout);
+
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if ((pCreateInfo != nullptr) && (pCreateInfo->pBindings != nullptr)) {
+ for (uint32_t i = 0; i < pCreateInfo->bindingCount; ++i) {
+ if (pCreateInfo->pBindings[i].descriptorCount != 0) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER or VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, and descriptorCount
+ // is not 0 and pImmutableSamplers is not NULL, pImmutableSamplers must be a pointer to an array of descriptorCount
+ // valid VkSampler handles
+ if (((pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
+ (pCreateInfo->pBindings[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER)) &&
+ (pCreateInfo->pBindings[i].pImmutableSamplers != nullptr)) {
+ for (uint32_t descriptor_index = 0; descriptor_index < pCreateInfo->pBindings[i].descriptorCount;
+ ++descriptor_index) {
+ if (pCreateInfo->pBindings[i].pImmutableSamplers[descriptor_index] == VK_NULL_HANDLE) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName, "vkCreateDescriptorSetLayout: required parameter "
+ "pCreateInfo->pBindings[%d].pImmutableSamplers[%d]"
+ " specified as VK_NULL_HANDLE",
+ i, descriptor_index);
+ }
+ }
+ }
- if (!skipCall) {
+ // If descriptorCount is not 0, stageFlags must be a valid combination of VkShaderStageFlagBits values
+ if ((pCreateInfo->pBindings[i].stageFlags != 0) &&
+ ((pCreateInfo->pBindings[i].stageFlags & (~AllVkShaderStageFlagBits)) != 0)) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ UNRECOGNIZED_VALUE, LayerName,
+ "vkCreateDescriptorSetLayout: if pCreateInfo->pBindings[%d].descriptorCount is not 0, "
+ "pCreateInfo->pBindings[%d].stageFlags must be a valid combination of VkShaderStageFlagBits values",
+ i, i);
+ }
+ }
+ }
+ }
+
+ if (!skip_call) {
result =
get_dispatch_table(pc_device_table_map, device)->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
- validate_result(my_data->report_data, "vkCreateDescriptorSetLayout", result);
+ validate_result(report_data, "vkCreateDescriptorSetLayout", result);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2895,9 +3305,9 @@ vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSe
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
- VkDescriptorPool *pDescriptorPool) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
+ VkDescriptorPool *pDescriptorPool) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2917,8 +3327,8 @@ vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreat
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -2930,8 +3340,8 @@ vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
+VKAPI_ATTR VkResult VKAPI_CALL
+ResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2948,8 +3358,8 @@ vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescri
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
+VKAPI_ATTR VkResult VKAPI_CALL
+AllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -2966,44 +3376,139 @@ vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAl
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
- uint32_t descriptorSetCount,
- const VkDescriptorSet *pDescriptorSets) {
+VKAPI_ATTR VkResult VKAPI_CALL FreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
+ uint32_t descriptorSetCount,
+ const VkDescriptorSet *pDescriptorSets) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkFreeDescriptorSets(my_data->report_data, descriptorPool, descriptorSetCount, pDescriptorSets);
+ skip_call |= parameter_validation_vkFreeDescriptorSets(report_data, descriptorPool, descriptorSetCount, pDescriptorSets);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ // This is an array of handles, where the elements are allowed to be VK_NULL_HANDLE, and does not require any validation beyond
+ // validate_array()
+ skip_call |= validate_array(report_data, "vkFreeDescriptorSets", "descriptorSetCount", "pDescriptorSets", descriptorSetCount,
+ pDescriptorSets, true, true);
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, device)
->FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
- validate_result(my_data->report_data, "vkFreeDescriptorSets", result);
+ validate_result(report_data, "vkFreeDescriptorSets", result);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
- uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+VKAPI_ATTR void VKAPI_CALL
+UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
+ uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != NULL);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkUpdateDescriptorSets(my_data->report_data, descriptorWriteCount, pDescriptorWrites,
- descriptorCopyCount, pDescriptorCopies);
+ skip_call |= parameter_validation_vkUpdateDescriptorSets(report_data, descriptorWriteCount, pDescriptorWrites,
+ descriptorCopyCount, pDescriptorCopies);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ if (pDescriptorWrites != NULL) {
+ for (uint32_t i = 0; i < descriptorWriteCount; ++i) {
+ // descriptorCount must be greater than 0
+ if (pDescriptorWrites[i].descriptorCount == 0) {
+ skip_call |=
+ log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
+ REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: parameter pDescriptorWrites[%d].descriptorCount must be greater than 0", i);
+ }
+
+ if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
+ // VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
+ // pImageInfo must be a pointer to an array of descriptorCount valid VkDescriptorImageInfo structures
+ if (pDescriptorWrites[i].pImageInfo == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: if pDescriptorWrites[%d].descriptorType is "
+ "VK_DESCRIPTOR_TYPE_SAMPLER, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, "
+ "VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or "
+ "VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, pDescriptorWrites[%d].pImageInfo must not be NULL",
+ i, i);
+ } else if (pDescriptorWrites[i].descriptorType != VK_DESCRIPTOR_TYPE_SAMPLER) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
+ // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE or VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, the imageView and imageLayout
+ // members of any given element of pImageInfo must be a valid VkImageView and VkImageLayout, respectively
+ for (uint32_t descriptor_index = 0; descriptor_index < pDescriptorWrites[i].descriptorCount;
+ ++descriptor_index) {
+ skip_call |= validate_required_handle(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pImageInfo[i].imageView",
+ pDescriptorWrites[i].pImageInfo[descriptor_index].imageView);
+ skip_call |= validate_ranged_enum(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pImageInfo[i].imageLayout", "VkImageLayout",
+ VK_IMAGE_LAYOUT_BEGIN_RANGE, VK_IMAGE_LAYOUT_END_RANGE,
+ pDescriptorWrites[i].pImageInfo[descriptor_index].imageLayout);
+ }
+ }
+ } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
+ // VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, pBufferInfo must be a
+ // pointer to an array of descriptorCount valid VkDescriptorBufferInfo structures
+ if (pDescriptorWrites[i].pBufferInfo == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: if pDescriptorWrites[%d].descriptorType is "
+ "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, "
+ "VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC or VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC, "
+ "pDescriptorWrites[%d].pBufferInfo must not be NULL",
+ i, i);
+ } else {
+ for (uint32_t descriptorIndex = 0; descriptorIndex < pDescriptorWrites[i].descriptorCount; ++descriptorIndex) {
+ skip_call |= validate_required_handle(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pBufferInfo[i].buffer",
+ pDescriptorWrites[i].pBufferInfo[descriptorIndex].buffer);
+ }
+ }
+ } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER) ||
+ (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)) {
+ // If descriptorType is VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
+ // pTexelBufferView must be a pointer to an array of descriptorCount valid VkBufferView handles
+ if (pDescriptorWrites[i].pTexelBufferView == nullptr) {
+ skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
+ __LINE__, REQUIRED_PARAMETER, LayerName,
+ "vkUpdateDescriptorSets: if pDescriptorWrites[%d].descriptorType is "
+ "VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER or VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, "
+ "pDescriptorWrites[%d].pTexelBufferView must not be NULL",
+ i, i);
+ } else {
+ for (uint32_t descriptor_index = 0; descriptor_index < pDescriptorWrites[i].descriptorCount;
+ ++descriptor_index) {
+ skip_call |= validate_required_handle(report_data, "vkUpdateDescriptorSets",
+ "pDescriptorWrites[i].pTexelBufferView[i]",
+ pDescriptorWrites[i].pTexelBufferView[descriptor_index]);
+ }
+ }
+ }
+ }
+ }
+
+ if (!skip_call) {
get_dispatch_table(pc_device_table_map, device)
->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
+VKAPI_ATTR VkResult VKAPI_CALL CreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
VkFramebuffer *pFramebuffer) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
@@ -3021,8 +3526,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(VkDevice devi
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -3034,9 +3539,9 @@ vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocat
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkRenderPass *pRenderPass) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkRenderPass *pRenderPass) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -3053,8 +3558,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice devic
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -3066,8 +3571,8 @@ vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocation
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D *pGranularity) {
+VKAPI_ATTR void VKAPI_CALL
+GetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D *pGranularity) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -3079,9 +3584,9 @@ vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator,
- VkCommandPool *pCommandPool) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator,
+ VkCommandPool *pCommandPool) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -3101,8 +3606,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(VkDevice devi
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
assert(my_data != NULL);
@@ -3114,8 +3619,8 @@ vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocat
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
+VKAPI_ATTR VkResult VKAPI_CALL
+ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -3132,8 +3637,8 @@ vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolRese
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
+VKAPI_ATTR VkResult VKAPI_CALL
+AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
@@ -3150,40 +3655,71 @@ vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAl
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
- uint32_t commandBufferCount,
- const VkCommandBuffer *pCommandBuffers) {
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
- assert(my_data != NULL);
+VKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
+ uint32_t commandBufferCount,
+ const VkCommandBuffer *pCommandBuffers) {
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkFreeCommandBuffers(my_data->report_data, commandPool, commandBufferCount, pCommandBuffers);
+ skip_call |= parameter_validation_vkFreeCommandBuffers(report_data, commandPool, commandBufferCount, pCommandBuffers);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ // This is an array of handles, where the elements are allowed to be VK_NULL_HANDLE, and does not require any validation beyond
+ // validate_array()
+ skip_call |= validate_array(report_data, "vkFreeCommandBuffers", "commandBufferCount", "pCommandBuffers", commandBufferCount,
+ pCommandBuffers, true, true);
+
+ if (!skip_call) {
get_dispatch_table(pc_device_table_map, device)
->FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
}
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
+VKAPI_ATTR VkResult VKAPI_CALL
+BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
- bool skipCall = false;
- layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
- assert(my_data != NULL);
+ bool skip_call = false;
+ layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
+ assert(device_data != nullptr);
+ debug_report_data *report_data = device_data->report_data;
- skipCall |= parameter_validation_vkBeginCommandBuffer(my_data->report_data, pBeginInfo);
+ skip_call |= parameter_validation_vkBeginCommandBuffer(report_data, pBeginInfo);
- if (!skipCall) {
+ // Validation for parameters excluded from the generated validation code due to a 'noautovalidity' tag in vk.xml
+ // TODO: pBeginInfo->pInheritanceInfo must not be NULL if commandBuffer is a secondary command buffer
+ skip_call |= validate_struct_type(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo",
+ "VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO", pBeginInfo->pInheritanceInfo,
+ VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO, false);
+
+ if (pBeginInfo->pInheritanceInfo != NULL) {
+ skip_call |= validate_struct_pnext(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo->pNext", NULL,
+ pBeginInfo->pInheritanceInfo->pNext, 0, NULL);
+
+ skip_call |= validate_bool32(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo->occlusionQueryEnable",
+ pBeginInfo->pInheritanceInfo->occlusionQueryEnable);
+
+ // TODO: This only needs to be validated when the inherited queries feature is enabled
+ // skip_call |= validate_flags(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo->queryFlags",
+ // "VkQueryControlFlagBits", AllVkQueryControlFlagBits, pBeginInfo->pInheritanceInfo->queryFlags, false);
+
+ // TODO: This must be 0 if the pipeline statistics queries feature is not enabled
+ skip_call |= validate_flags(report_data, "vkBeginCommandBuffer", "pBeginInfo->pInheritanceInfo->pipelineStatistics",
+ "VkQueryPipelineStatisticFlagBits", AllVkQueryPipelineStatisticFlagBits,
+ pBeginInfo->pInheritanceInfo->pipelineStatistics, false);
+ }
+
+ if (!skip_call) {
result = get_dispatch_table(pc_device_table_map, commandBuffer)->BeginCommandBuffer(commandBuffer, pBeginInfo);
- validate_result(my_data->report_data, "vkBeginCommandBuffer", result);
+ validate_result(report_data, "vkBeginCommandBuffer", result);
}
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
+VKAPI_ATTR VkResult VKAPI_CALL EndCommandBuffer(VkCommandBuffer commandBuffer) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3194,8 +3730,8 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffe
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
+VKAPI_ATTR VkResult VKAPI_CALL
+ResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3211,8 +3747,8 @@ vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags fl
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
+VKAPI_ATTR void VKAPI_CALL
+CmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3224,8 +3760,8 @@ vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBin
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3238,8 +3774,8 @@ vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3251,17 +3787,17 @@ vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t s
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
+VKAPI_ATTR void VKAPI_CALL CmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetLineWidth(commandBuffer, lineWidth);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
get_dispatch_table(pc_device_table_map, commandBuffer)
->CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
+VKAPI_ATTR void VKAPI_CALL CmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3273,13 +3809,13 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(VkCommandBuffe
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3291,8 +3827,8 @@ vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags fac
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3304,8 +3840,8 @@ vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceM
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3317,10 +3853,10 @@ vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceM
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
- uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
- uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
+VKAPI_ATTR void VKAPI_CALL
+CmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
+ uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
+ uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3335,8 +3871,8 @@ vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipel
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
+VKAPI_ATTR void VKAPI_CALL
+CmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3348,9 +3884,9 @@ vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSiz
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
- uint32_t bindingCount, const VkBuffer *pBuffers,
- const VkDeviceSize *pOffsets) {
+VKAPI_ATTR void VKAPI_CALL CmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
+ uint32_t bindingCount, const VkBuffer *pBuffers,
+ const VkDeviceSize *pOffsets) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3384,23 +3920,23 @@ bool PreCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t in
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
- uint32_t firstVertex, uint32_t firstInstance) {
+VKAPI_ATTR void VKAPI_CALL CmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
+ uint32_t firstVertex, uint32_t firstInstance) {
PreCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
get_dispatch_table(pc_device_table_map, commandBuffer)
->CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
- uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
- uint32_t firstInstance) {
+VKAPI_ATTR void VKAPI_CALL CmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
+ uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
+ uint32_t firstInstance) {
get_dispatch_table(pc_device_table_map, commandBuffer)
->CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+VKAPI_ATTR void VKAPI_CALL
+CmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3412,8 +3948,8 @@ vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize o
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
+VKAPI_ATTR void VKAPI_CALL
+CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3426,12 +3962,12 @@ vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDevic
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
+VKAPI_ATTR void VKAPI_CALL CmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
get_dispatch_table(pc_device_table_map, commandBuffer)->CmdDispatch(commandBuffer, x, y, z);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
+VKAPI_ATTR void VKAPI_CALL
+CmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3443,8 +3979,8 @@ vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSi
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
- uint32_t regionCount, const VkBufferCopy *pRegions) {
+VKAPI_ATTR void VKAPI_CALL CmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
+ uint32_t regionCount, const VkBufferCopy *pRegions) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3478,9 +4014,9 @@ bool PreCmdCopyImage(VkCommandBuffer commandBuffer, const VkImageCopy *pRegions)
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
- VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
+VKAPI_ATTR void VKAPI_CALL
+CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3517,9 +4053,9 @@ bool PreCmdBlitImage(VkCommandBuffer commandBuffer, const VkImageBlit *pRegions)
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
- VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
+VKAPI_ATTR void VKAPI_CALL
+CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3550,9 +4086,9 @@ bool PreCmdCopyBufferToImage(VkCommandBuffer commandBuffer, const VkBufferImageC
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
- VkImage dstImage, VkImageLayout dstImageLayout,
- uint32_t regionCount, const VkBufferImageCopy *pRegions) {
+VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
+ VkImage dstImage, VkImageLayout dstImageLayout,
+ uint32_t regionCount, const VkBufferImageCopy *pRegions) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3583,9 +4119,9 @@ bool PreCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, const VkBufferImageC
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
- VkImageLayout srcImageLayout, VkBuffer dstBuffer,
- uint32_t regionCount, const VkBufferImageCopy *pRegions) {
+VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
+ VkImageLayout srcImageLayout, VkBuffer dstBuffer,
+ uint32_t regionCount, const VkBufferImageCopy *pRegions) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3601,36 +4137,73 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffe
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
- VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) {
- bool skipCall = false;
+VKAPI_ATTR void VKAPI_CALL CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
+ VkDeviceSize dataSize, const uint32_t *pData) {
+ bool skip_call = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
- skipCall |= parameter_validation_vkCmdUpdateBuffer(my_data->report_data, dstBuffer, dstOffset, dataSize, pData);
+ skip_call |= parameter_validation_vkCmdUpdateBuffer(my_data->report_data, dstBuffer, dstOffset, dataSize, pData);
- if (!skipCall) {
+ if (dstOffset & 3) {
+ skip_call |=
+ log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, INVALID_USAGE,
+ "PARAMCHECK", "CmdUpdateBuffer parameter, VkDeviceSize dstOffset (0x%" PRIxLEAST64 "), is not a multiple of 4",
+ dstOffset);
+ }
+
+ if ((dataSize <= 0) || (dataSize > 65536)) {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
+ INVALID_USAGE, "PARAMCHECK", "CmdUpdateBuffer parameter, VkDeviceSize dataSize (0x%" PRIxLEAST64
+ "), must be greater than zero and less than or equal to 65536",
+ dataSize);
+ } else if (dataSize & 3) {
+ skip_call |=
+ log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, INVALID_USAGE,
+ "PARAMCHECK", "CmdUpdateBuffer parameter, VkDeviceSize dataSize (0x%" PRIxLEAST64 "), is not a multiple of 4",
+ dataSize);
+ }
+
+ if (!skip_call) {
get_dispatch_table(pc_device_table_map, commandBuffer)
->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
- bool skipCall = false;
+VKAPI_ATTR void VKAPI_CALL CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset,
+ VkDeviceSize size, uint32_t data) {
+ bool skip_call = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
- skipCall |= parameter_validation_vkCmdFillBuffer(my_data->report_data, dstBuffer, dstOffset, size, data);
+ skip_call |= parameter_validation_vkCmdFillBuffer(my_data->report_data, dstBuffer, dstOffset, size, data);
- if (!skipCall) {
+ if (dstOffset & 3) {
+ skip_call |= log_msg(
+ my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, INVALID_USAGE, "DL",
+ "vkCmdFillBuffer parameter, VkDeviceSize dstOffset (0x%" PRIxLEAST64 "), is not a multiple of 4", dstOffset);
+ }
+
+ if (size != VK_WHOLE_SIZE) {
+ if (size <= 0) {
+ skip_call |= log_msg(
+ my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__, INVALID_USAGE,
+ "DL", "vkCmdFillBuffer parameter, VkDeviceSize size (0x%" PRIxLEAST64 "), must be greater than zero", size);
+ } else if (size & 3) {
+ skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
+ INVALID_USAGE, "DL",
+ "vkCmdFillBuffer parameter, VkDeviceSize size (0x%" PRIxLEAST64 "), is not a multiple of 4", size);
+ }
+ }
+
+ if (!skip_call) {
get_dispatch_table(pc_device_table_map, commandBuffer)->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
- VkImageLayout imageLayout, const VkClearColorValue *pColor,
- uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
+VKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
+ VkImageLayout imageLayout, const VkClearColorValue *pColor,
+ uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3643,10 +4216,10 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
- const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
- const VkImageSubresourceRange *pRanges) {
+VKAPI_ATTR void VKAPI_CALL
+CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
+ const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
+ const VkImageSubresourceRange *pRanges) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3660,9 +4233,9 @@ vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImag
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
- const VkClearAttachment *pAttachments, uint32_t rectCount,
- const VkClearRect *pRects) {
+VKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
+ const VkClearAttachment *pAttachments, uint32_t rectCount,
+ const VkClearRect *pRects) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3698,9 +4271,9 @@ bool PreCmdResolveImage(VkCommandBuffer commandBuffer, const VkImageResolve *pRe
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
- VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
+VKAPI_ATTR void VKAPI_CALL
+CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
+ VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3716,8 +4289,8 @@ vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+VKAPI_ATTR void VKAPI_CALL
+CmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3729,8 +4302,8 @@ vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
+VKAPI_ATTR void VKAPI_CALL
+CmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3742,11 +4315,11 @@ vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFla
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask,
- VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
- uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
+VKAPI_ATTR void VKAPI_CALL
+CmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask,
+ VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3762,11 +4335,11 @@ vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEven
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
- VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
- uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
- uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
+VKAPI_ATTR void VKAPI_CALL
+CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
+ VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
+ uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+ uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3782,8 +4355,8 @@ vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStag
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
+VKAPI_ATTR void VKAPI_CALL
+CmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3795,7 +4368,7 @@ vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t s
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
+VKAPI_ATTR void VKAPI_CALL CmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3807,8 +4380,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(VkCommandBuffer command
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
+VKAPI_ATTR void VKAPI_CALL
+CmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3828,8 +4401,8 @@ bool PostCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBit
return true;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
- VkQueryPool queryPool, uint32_t query) {
+VKAPI_ATTR void VKAPI_CALL CmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage,
+ VkQueryPool queryPool, uint32_t query) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3843,9 +4416,9 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(VkCommandBuffer c
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
- VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
+VKAPI_ATTR void VKAPI_CALL
+CmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
+ VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3859,9 +4432,9 @@ vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool,
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
- VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
- const void *pValues) {
+VKAPI_ATTR void VKAPI_CALL CmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
+ VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
+ const void *pValues) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3874,8 +4447,8 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(VkCommandBuffer co
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents) {
+VKAPI_ATTR void VKAPI_CALL
+CmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3887,7 +4460,7 @@ vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
+VKAPI_ATTR void VKAPI_CALL CmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3899,12 +4472,12 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer comm
}
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
+VKAPI_ATTR void VKAPI_CALL CmdEndRenderPass(VkCommandBuffer commandBuffer) {
get_dispatch_table(pc_device_table_map, commandBuffer)->CmdEndRenderPass(commandBuffer);
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
+VKAPI_ATTR void VKAPI_CALL
+CmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
bool skipCall = false;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
assert(my_data != NULL);
@@ -3917,288 +4490,294 @@ vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount,
}
}
-VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
+ return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
+
+ return VK_ERROR_LAYER_NOT_PRESENT;
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName, uint32_t *pCount,
+ VkExtensionProperties *pProperties) {
+ /* parameter_validation does not have any physical device extensions */
+ if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
+ return util_GetExtensionProperties(0, NULL, pCount, pProperties);
+
+ assert(physicalDevice);
+
+ return get_dispatch_table(pc_instance_table_map, physicalDevice)
+ ->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
+}
+
+static PFN_vkVoidFunction
+intercept_core_instance_command(const char *name);
+
+static PFN_vkVoidFunction
+intercept_core_device_command(const char *name);
+
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
+ assert(device);
+
layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
if (validate_string(data->report_data, "vkGetDeviceProcAddr", "funcName", funcName)) {
return NULL;
}
- if (!strcmp(funcName, "vkGetDeviceProcAddr"))
- return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
- if (!strcmp(funcName, "vkDestroyDevice"))
- return (PFN_vkVoidFunction)vkDestroyDevice;
- if (!strcmp(funcName, "vkGetDeviceQueue"))
- return (PFN_vkVoidFunction)vkGetDeviceQueue;
- if (!strcmp(funcName, "vkQueueSubmit"))
- return (PFN_vkVoidFunction)vkQueueSubmit;
- if (!strcmp(funcName, "vkQueueWaitIdle"))
- return (PFN_vkVoidFunction)vkQueueWaitIdle;
- if (!strcmp(funcName, "vkDeviceWaitIdle"))
- return (PFN_vkVoidFunction)vkDeviceWaitIdle;
- if (!strcmp(funcName, "vkAllocateMemory"))
- return (PFN_vkVoidFunction)vkAllocateMemory;
- if (!strcmp(funcName, "vkFreeMemory"))
- return (PFN_vkVoidFunction)vkFreeMemory;
- if (!strcmp(funcName, "vkMapMemory"))
- return (PFN_vkVoidFunction)vkMapMemory;
- if (!strcmp(funcName, "vkUnmapMemory"))
- return (PFN_vkVoidFunction)vkUnmapMemory;
- if (!strcmp(funcName, "vkFlushMappedMemoryRanges"))
- return (PFN_vkVoidFunction)vkFlushMappedMemoryRanges;
- if (!strcmp(funcName, "vkInvalidateMappedMemoryRanges"))
- return (PFN_vkVoidFunction)vkInvalidateMappedMemoryRanges;
- if (!strcmp(funcName, "vkGetDeviceMemoryCommitment"))
- return (PFN_vkVoidFunction)vkGetDeviceMemoryCommitment;
- if (!strcmp(funcName, "vkBindBufferMemory"))
- return (PFN_vkVoidFunction)vkBindBufferMemory;
- if (!strcmp(funcName, "vkBindImageMemory"))
- return (PFN_vkVoidFunction)vkBindImageMemory;
- if (!strcmp(funcName, "vkCreateFence"))
- return (PFN_vkVoidFunction)vkCreateFence;
- if (!strcmp(funcName, "vkDestroyFence"))
- return (PFN_vkVoidFunction)vkDestroyFence;
- if (!strcmp(funcName, "vkResetFences"))
- return (PFN_vkVoidFunction)vkResetFences;
- if (!strcmp(funcName, "vkGetFenceStatus"))
- return (PFN_vkVoidFunction)vkGetFenceStatus;
- if (!strcmp(funcName, "vkWaitForFences"))
- return (PFN_vkVoidFunction)vkWaitForFences;
- if (!strcmp(funcName, "vkCreateSemaphore"))
- return (PFN_vkVoidFunction)vkCreateSemaphore;
- if (!strcmp(funcName, "vkDestroySemaphore"))
- return (PFN_vkVoidFunction)vkDestroySemaphore;
- if (!strcmp(funcName, "vkCreateEvent"))
- return (PFN_vkVoidFunction)vkCreateEvent;
- if (!strcmp(funcName, "vkDestroyEvent"))
- return (PFN_vkVoidFunction)vkDestroyEvent;
- if (!strcmp(funcName, "vkGetEventStatus"))
- return (PFN_vkVoidFunction)vkGetEventStatus;
- if (!strcmp(funcName, "vkSetEvent"))
- return (PFN_vkVoidFunction)vkSetEvent;
- if (!strcmp(funcName, "vkResetEvent"))
- return (PFN_vkVoidFunction)vkResetEvent;
- if (!strcmp(funcName, "vkCreateQueryPool"))
- return (PFN_vkVoidFunction)vkCreateQueryPool;
- if (!strcmp(funcName, "vkDestroyQueryPool"))
- return (PFN_vkVoidFunction)vkDestroyQueryPool;
- if (!strcmp(funcName, "vkGetQueryPoolResults"))
- return (PFN_vkVoidFunction)vkGetQueryPoolResults;
- if (!strcmp(funcName, "vkCreateBuffer"))
- return (PFN_vkVoidFunction)vkCreateBuffer;
- if (!strcmp(funcName, "vkDestroyBuffer"))
- return (PFN_vkVoidFunction)vkDestroyBuffer;
- if (!strcmp(funcName, "vkCreateBufferView"))
- return (PFN_vkVoidFunction)vkCreateBufferView;
- if (!strcmp(funcName, "vkDestroyBufferView"))
- return (PFN_vkVoidFunction)vkDestroyBufferView;
- if (!strcmp(funcName, "vkCreateImage"))
- return (PFN_vkVoidFunction)vkCreateImage;
- if (!strcmp(funcName, "vkDestroyImage"))
- return (PFN_vkVoidFunction)vkDestroyImage;
- if (!strcmp(funcName, "vkGetImageSubresourceLayout"))
- return (PFN_vkVoidFunction)vkGetImageSubresourceLayout;
- if (!strcmp(funcName, "vkCreateImageView"))
- return (PFN_vkVoidFunction)vkCreateImageView;
- if (!strcmp(funcName, "vkDestroyImageView"))
- return (PFN_vkVoidFunction)vkDestroyImageView;
- if (!strcmp(funcName, "vkCreateShaderModule"))
- return (PFN_vkVoidFunction)vkCreateShaderModule;
- if (!strcmp(funcName, "vkDestroyShaderModule"))
- return (PFN_vkVoidFunction)vkDestroyShaderModule;
- if (!strcmp(funcName, "vkCreatePipelineCache"))
- return (PFN_vkVoidFunction)vkCreatePipelineCache;
- if (!strcmp(funcName, "vkDestroyPipelineCache"))
- return (PFN_vkVoidFunction)vkDestroyPipelineCache;
- if (!strcmp(funcName, "vkGetPipelineCacheData"))
- return (PFN_vkVoidFunction)vkGetPipelineCacheData;
- if (!strcmp(funcName, "vkMergePipelineCaches"))
- return (PFN_vkVoidFunction)vkMergePipelineCaches;
- if (!strcmp(funcName, "vkCreateGraphicsPipelines"))
- return (PFN_vkVoidFunction)vkCreateGraphicsPipelines;
- if (!strcmp(funcName, "vkCreateComputePipelines"))
- return (PFN_vkVoidFunction)vkCreateComputePipelines;
- if (!strcmp(funcName, "vkDestroyPipeline"))
- return (PFN_vkVoidFunction)vkDestroyPipeline;
- if (!strcmp(funcName, "vkCreatePipelineLayout"))
- return (PFN_vkVoidFunction)vkCreatePipelineLayout;
- if (!strcmp(funcName, "vkDestroyPipelineLayout"))
- return (PFN_vkVoidFunction)vkDestroyPipelineLayout;
- if (!strcmp(funcName, "vkCreateSampler"))
- return (PFN_vkVoidFunction)vkCreateSampler;
- if (!strcmp(funcName, "vkDestroySampler"))
- return (PFN_vkVoidFunction)vkDestroySampler;
- if (!strcmp(funcName, "vkCreateDescriptorSetLayout"))
- return (PFN_vkVoidFunction)vkCreateDescriptorSetLayout;
- if (!strcmp(funcName, "vkDestroyDescriptorSetLayout"))
- return (PFN_vkVoidFunction)vkDestroyDescriptorSetLayout;
- if (!strcmp(funcName, "vkCreateDescriptorPool"))
- return (PFN_vkVoidFunction)vkCreateDescriptorPool;
- if (!strcmp(funcName, "vkDestroyDescriptorPool"))
- return (PFN_vkVoidFunction)vkDestroyDescriptorPool;
- if (!strcmp(funcName, "vkResetDescriptorPool"))
- return (PFN_vkVoidFunction)vkResetDescriptorPool;
- if (!strcmp(funcName, "vkAllocateDescriptorSets"))
- return (PFN_vkVoidFunction)vkAllocateDescriptorSets;
- if (!strcmp(funcName, "vkCmdSetViewport"))
- return (PFN_vkVoidFunction)vkCmdSetViewport;
- if (!strcmp(funcName, "vkCmdSetScissor"))
- return (PFN_vkVoidFunction)vkCmdSetScissor;
- if (!strcmp(funcName, "vkCmdSetLineWidth"))
- return (PFN_vkVoidFunction)vkCmdSetLineWidth;
- if (!strcmp(funcName, "vkCmdSetDepthBias"))
- return (PFN_vkVoidFunction)vkCmdSetDepthBias;
- if (!strcmp(funcName, "vkCmdSetBlendConstants"))
- return (PFN_vkVoidFunction)vkCmdSetBlendConstants;
- if (!strcmp(funcName, "vkCmdSetDepthBounds"))
- return (PFN_vkVoidFunction)vkCmdSetDepthBounds;
- if (!strcmp(funcName, "vkCmdSetStencilCompareMask"))
- return (PFN_vkVoidFunction)vkCmdSetStencilCompareMask;
- if (!strcmp(funcName, "vkCmdSetStencilWriteMask"))
- return (PFN_vkVoidFunction)vkCmdSetStencilWriteMask;
- if (!strcmp(funcName, "vkCmdSetStencilReference"))
- return (PFN_vkVoidFunction)vkCmdSetStencilReference;
- if (!strcmp(funcName, "vkAllocateCommandBuffers"))
- return (PFN_vkVoidFunction)vkAllocateCommandBuffers;
- if (!strcmp(funcName, "vkFreeCommandBuffers"))
- return (PFN_vkVoidFunction)vkFreeCommandBuffers;
- if (!strcmp(funcName, "vkBeginCommandBuffer"))
- return (PFN_vkVoidFunction)vkBeginCommandBuffer;
- if (!strcmp(funcName, "vkEndCommandBuffer"))
- return (PFN_vkVoidFunction)vkEndCommandBuffer;
- if (!strcmp(funcName, "vkResetCommandBuffer"))
- return (PFN_vkVoidFunction)vkResetCommandBuffer;
- if (!strcmp(funcName, "vkCmdBindPipeline"))
- return (PFN_vkVoidFunction)vkCmdBindPipeline;
- if (!strcmp(funcName, "vkCmdBindDescriptorSets"))
- return (PFN_vkVoidFunction)vkCmdBindDescriptorSets;
- if (!strcmp(funcName, "vkCmdBindVertexBuffers"))
- return (PFN_vkVoidFunction)vkCmdBindVertexBuffers;
- if (!strcmp(funcName, "vkCmdBindIndexBuffer"))
- return (PFN_vkVoidFunction)vkCmdBindIndexBuffer;
- if (!strcmp(funcName, "vkCmdDraw"))
- return (PFN_vkVoidFunction)vkCmdDraw;
- if (!strcmp(funcName, "vkCmdDrawIndexed"))
- return (PFN_vkVoidFunction)vkCmdDrawIndexed;
- if (!strcmp(funcName, "vkCmdDrawIndirect"))
- return (PFN_vkVoidFunction)vkCmdDrawIndirect;
- if (!strcmp(funcName, "vkCmdDrawIndexedIndirect"))
- return (PFN_vkVoidFunction)vkCmdDrawIndexedIndirect;
- if (!strcmp(funcName, "vkCmdDispatch"))
- return (PFN_vkVoidFunction)vkCmdDispatch;
- if (!strcmp(funcName, "vkCmdDispatchIndirect"))
- return (PFN_vkVoidFunction)vkCmdDispatchIndirect;
- if (!strcmp(funcName, "vkCmdCopyBuffer"))
- return (PFN_vkVoidFunction)vkCmdCopyBuffer;
- if (!strcmp(funcName, "vkCmdCopyImage"))
- return (PFN_vkVoidFunction)vkCmdCopyImage;
- if (!strcmp(funcName, "vkCmdBlitImage"))
- return (PFN_vkVoidFunction)vkCmdBlitImage;
- if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
- return (PFN_vkVoidFunction)vkCmdCopyBufferToImage;
- if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
- return (PFN_vkVoidFunction)vkCmdCopyImageToBuffer;
- if (!strcmp(funcName, "vkCmdUpdateBuffer"))
- return (PFN_vkVoidFunction)vkCmdUpdateBuffer;
- if (!strcmp(funcName, "vkCmdFillBuffer"))
- return (PFN_vkVoidFunction)vkCmdFillBuffer;
- if (!strcmp(funcName, "vkCmdClearColorImage"))
- return (PFN_vkVoidFunction)vkCmdClearColorImage;
- if (!strcmp(funcName, "vkCmdResolveImage"))
- return (PFN_vkVoidFunction)vkCmdResolveImage;
- if (!strcmp(funcName, "vkCmdSetEvent"))
- return (PFN_vkVoidFunction)vkCmdSetEvent;
- if (!strcmp(funcName, "vkCmdResetEvent"))
- return (PFN_vkVoidFunction)vkCmdResetEvent;
- if (!strcmp(funcName, "vkCmdWaitEvents"))
- return (PFN_vkVoidFunction)vkCmdWaitEvents;
- if (!strcmp(funcName, "vkCmdPipelineBarrier"))
- return (PFN_vkVoidFunction)vkCmdPipelineBarrier;
- if (!strcmp(funcName, "vkCmdBeginQuery"))
- return (PFN_vkVoidFunction)vkCmdBeginQuery;
- if (!strcmp(funcName, "vkCmdEndQuery"))
- return (PFN_vkVoidFunction)vkCmdEndQuery;
- if (!strcmp(funcName, "vkCmdResetQueryPool"))
- return (PFN_vkVoidFunction)vkCmdResetQueryPool;
- if (!strcmp(funcName, "vkCmdWriteTimestamp"))
- return (PFN_vkVoidFunction)vkCmdWriteTimestamp;
- if (!strcmp(funcName, "vkCmdCopyQueryPoolResults"))
- return (PFN_vkVoidFunction)vkCmdCopyQueryPoolResults;
- if (!strcmp(funcName, "vkCreateFramebuffer"))
- return (PFN_vkVoidFunction)vkCreateFramebuffer;
- if (!strcmp(funcName, "vkDestroyFramebuffer"))
- return (PFN_vkVoidFunction)vkDestroyFramebuffer;
- if (!strcmp(funcName, "vkCreateRenderPass"))
- return (PFN_vkVoidFunction)vkCreateRenderPass;
- if (!strcmp(funcName, "vkDestroyRenderPass"))
- return (PFN_vkVoidFunction)vkDestroyRenderPass;
- if (!strcmp(funcName, "vkGetRenderAreaGranularity"))
- return (PFN_vkVoidFunction)vkGetRenderAreaGranularity;
- if (!strcmp(funcName, "vkCreateCommandPool"))
- return (PFN_vkVoidFunction)vkCreateCommandPool;
- if (!strcmp(funcName, "vkDestroyCommandPool"))
- return (PFN_vkVoidFunction)vkDestroyCommandPool;
- if (!strcmp(funcName, "vkResetCommandPool"))
- return (PFN_vkVoidFunction)vkResetCommandPool;
- if (!strcmp(funcName, "vkCmdBeginRenderPass"))
- return (PFN_vkVoidFunction)vkCmdBeginRenderPass;
- if (!strcmp(funcName, "vkCmdNextSubpass"))
- return (PFN_vkVoidFunction)vkCmdNextSubpass;
-
- if (device == NULL) {
- return NULL;
- }
+ PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
+ if (proc)
+ return proc;
if (get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr == NULL)
return NULL;
return get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr(device, funcName);
}
-VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
- if (!strcmp(funcName, "vkGetInstanceProcAddr"))
- return (PFN_vkVoidFunction)vkGetInstanceProcAddr;
- if (!strcmp(funcName, "vkCreateInstance"))
- return (PFN_vkVoidFunction)vkCreateInstance;
- if (!strcmp(funcName, "vkDestroyInstance"))
- return (PFN_vkVoidFunction)vkDestroyInstance;
- if (!strcmp(funcName, "vkCreateDevice"))
- return (PFN_vkVoidFunction)vkCreateDevice;
- if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
- return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices;
- if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceProperties;
- if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceFeatures;
- if (!strcmp(funcName, "vkGetPhysicalDeviceFormatProperties"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceFormatProperties;
- if (!strcmp(funcName, "vkGetPhysicalDeviceImageFormatProperties"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceImageFormatProperties;
- if (!strcmp(funcName, "vkGetPhysicalDeviceSparseImageFormatProperties"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceSparseImageFormatProperties;
- if (!strcmp(funcName, "vkGetPhysicalDeviceQueueFamilyProperties"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceQueueFamilyProperties;
- if (!strcmp(funcName, "vkGetPhysicalDeviceMemoryProperties"))
- return (PFN_vkVoidFunction)vkGetPhysicalDeviceMemoryProperties;
- if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
- return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
- if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
- return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
- if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
- return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
- if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
- return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
-
- if (instance == NULL) {
- return NULL;
- }
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
+ PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
+ if (!proc)
+ proc = intercept_core_device_command(funcName);
+ if (proc)
+ return proc;
+
+ assert(instance);
layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
- PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
- if (fptr)
- return fptr;
+ proc = debug_report_get_instance_proc_addr(data->report_data, funcName);
+ if (proc)
+ return proc;
if (get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr == NULL)
return NULL;
return get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
}
+
+static PFN_vkVoidFunction
+intercept_core_instance_command(const char *name) {
+ static const struct {
+ const char *name;
+ PFN_vkVoidFunction proc;
+ } core_instance_commands[] = {
+ { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
+ { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
+ { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
+ { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
+ { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
+ { "vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties) },
+ { "vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFeatures) },
+ { "vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFormatProperties) },
+ { "vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceImageFormatProperties) },
+ { "vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSparseImageFormatProperties) },
+ { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
+ { "vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMemoryProperties) },
+ { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
+ { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
+ { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
+ { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
+ if (!strcmp(core_instance_commands[i].name, name))
+ return core_instance_commands[i].proc;
+ }
+
+ return nullptr;
+}
+
+static PFN_vkVoidFunction
+intercept_core_device_command(const char *name) {
+ static const struct {
+ const char *name;
+ PFN_vkVoidFunction proc;
+ } core_device_commands[] = {
+ { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
+ { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
+ { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
+ { "vkQueueSubmit", reinterpret_cast<PFN_vkVoidFunction>(QueueSubmit) },
+ { "vkQueueWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(QueueWaitIdle) },
+ { "vkDeviceWaitIdle", reinterpret_cast<PFN_vkVoidFunction>(DeviceWaitIdle) },
+ { "vkAllocateMemory", reinterpret_cast<PFN_vkVoidFunction>(AllocateMemory) },
+ { "vkFreeMemory", reinterpret_cast<PFN_vkVoidFunction>(FreeMemory) },
+ { "vkMapMemory", reinterpret_cast<PFN_vkVoidFunction>(MapMemory) },
+ { "vkUnmapMemory", reinterpret_cast<PFN_vkVoidFunction>(UnmapMemory) },
+ { "vkFlushMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(FlushMappedMemoryRanges) },
+ { "vkInvalidateMappedMemoryRanges", reinterpret_cast<PFN_vkVoidFunction>(InvalidateMappedMemoryRanges) },
+ { "vkGetDeviceMemoryCommitment", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceMemoryCommitment) },
+ { "vkBindBufferMemory", reinterpret_cast<PFN_vkVoidFunction>(BindBufferMemory) },
+ { "vkBindImageMemory", reinterpret_cast<PFN_vkVoidFunction>(BindImageMemory) },
+ { "vkCreateFence", reinterpret_cast<PFN_vkVoidFunction>(CreateFence) },
+ { "vkDestroyFence", reinterpret_cast<PFN_vkVoidFunction>(DestroyFence) },
+ { "vkResetFences", reinterpret_cast<PFN_vkVoidFunction>(ResetFences) },
+ { "vkGetFenceStatus", reinterpret_cast<PFN_vkVoidFunction>(GetFenceStatus) },
+ { "vkWaitForFences", reinterpret_cast<PFN_vkVoidFunction>(WaitForFences) },
+ { "vkCreateSemaphore", reinterpret_cast<PFN_vkVoidFunction>(CreateSemaphore) },
+ { "vkDestroySemaphore", reinterpret_cast<PFN_vkVoidFunction>(DestroySemaphore) },
+ { "vkCreateEvent", reinterpret_cast<PFN_vkVoidFunction>(CreateEvent) },
+ { "vkDestroyEvent", reinterpret_cast<PFN_vkVoidFunction>(DestroyEvent) },
+ { "vkGetEventStatus", reinterpret_cast<PFN_vkVoidFunction>(GetEventStatus) },
+ { "vkSetEvent", reinterpret_cast<PFN_vkVoidFunction>(SetEvent) },
+ { "vkResetEvent", reinterpret_cast<PFN_vkVoidFunction>(ResetEvent) },
+ { "vkCreateQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CreateQueryPool) },
+ { "vkDestroyQueryPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyQueryPool) },
+ { "vkGetQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(GetQueryPoolResults) },
+ { "vkCreateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateBuffer) },
+ { "vkDestroyBuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyBuffer) },
+ { "vkCreateBufferView", reinterpret_cast<PFN_vkVoidFunction>(CreateBufferView) },
+ { "vkDestroyBufferView", reinterpret_cast<PFN_vkVoidFunction>(DestroyBufferView) },
+ { "vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage) },
+ { "vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage) },
+ { "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) },
+ { "vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView) },
+ { "vkDestroyImageView", reinterpret_cast<PFN_vkVoidFunction>(DestroyImageView) },
+ { "vkCreateShaderModule", reinterpret_cast<PFN_vkVoidFunction>(CreateShaderModule) },
+ { "vkDestroyShaderModule", reinterpret_cast<PFN_vkVoidFunction>(DestroyShaderModule) },
+ { "vkCreatePipelineCache", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineCache) },
+ { "vkDestroyPipelineCache", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineCache) },
+ { "vkGetPipelineCacheData", reinterpret_cast<PFN_vkVoidFunction>(GetPipelineCacheData) },
+ { "vkMergePipelineCaches", reinterpret_cast<PFN_vkVoidFunction>(MergePipelineCaches) },
+ { "vkCreateGraphicsPipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateGraphicsPipelines) },
+ { "vkCreateComputePipelines", reinterpret_cast<PFN_vkVoidFunction>(CreateComputePipelines) },
+ { "vkDestroyPipeline", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipeline) },
+ { "vkCreatePipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(CreatePipelineLayout) },
+ { "vkDestroyPipelineLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyPipelineLayout) },
+ { "vkCreateSampler", reinterpret_cast<PFN_vkVoidFunction>(CreateSampler) },
+ { "vkDestroySampler", reinterpret_cast<PFN_vkVoidFunction>(DestroySampler) },
+ { "vkCreateDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorSetLayout) },
+ { "vkDestroyDescriptorSetLayout", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorSetLayout) },
+ { "vkCreateDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(CreateDescriptorPool) },
+ { "vkDestroyDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyDescriptorPool) },
+ { "vkResetDescriptorPool", reinterpret_cast<PFN_vkVoidFunction>(ResetDescriptorPool) },
+ { "vkAllocateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(AllocateDescriptorSets) },
+ { "vkFreeDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(FreeDescriptorSets) },
+ { "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
+ { "vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport) },
+ { "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
+ { "vkCmdSetLineWidth", reinterpret_cast<PFN_vkVoidFunction>(CmdSetLineWidth) },
+ { "vkCmdSetDepthBias", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBias) },
+ { "vkCmdSetBlendConstants", reinterpret_cast<PFN_vkVoidFunction>(CmdSetBlendConstants) },
+ { "vkCmdSetDepthBounds", reinterpret_cast<PFN_vkVoidFunction>(CmdSetDepthBounds) },
+ { "vkCmdSetStencilCompareMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilCompareMask) },
+ { "vkCmdSetStencilWriteMask", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilWriteMask) },
+ { "vkCmdSetStencilReference", reinterpret_cast<PFN_vkVoidFunction>(CmdSetStencilReference) },
+ { "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers) },
+ { "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers) },
+ { "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer) },
+ { "vkEndCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(EndCommandBuffer) },
+ { "vkResetCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandBuffer) },
+ { "vkCmdBindPipeline", reinterpret_cast<PFN_vkVoidFunction>(CmdBindPipeline) },
+ { "vkCmdBindDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(CmdBindDescriptorSets) },
+ { "vkCmdBindVertexBuffers", reinterpret_cast<PFN_vkVoidFunction>(CmdBindVertexBuffers) },
+ { "vkCmdBindIndexBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdBindIndexBuffer) },
+ { "vkCmdDraw", reinterpret_cast<PFN_vkVoidFunction>(CmdDraw) },
+ { "vkCmdDrawIndexed", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexed) },
+ { "vkCmdDrawIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndirect) },
+ { "vkCmdDrawIndexedIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDrawIndexedIndirect) },
+ { "vkCmdDispatch", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatch) },
+ { "vkCmdDispatchIndirect", reinterpret_cast<PFN_vkVoidFunction>(CmdDispatchIndirect) },
+ { "vkCmdCopyBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBuffer) },
+ { "vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage) },
+ { "vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage) },
+ { "vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage) },
+ { "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer) },
+ { "vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer) },
+ { "vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer) },
+ { "vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage) },
+ { "vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage) },
+ { "vkCmdSetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdSetEvent) },
+ { "vkCmdResetEvent", reinterpret_cast<PFN_vkVoidFunction>(CmdResetEvent) },
+ { "vkCmdWaitEvents", reinterpret_cast<PFN_vkVoidFunction>(CmdWaitEvents) },
+ { "vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier) },
+ { "vkCmdBeginQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginQuery) },
+ { "vkCmdEndQuery", reinterpret_cast<PFN_vkVoidFunction>(CmdEndQuery) },
+ { "vkCmdResetQueryPool", reinterpret_cast<PFN_vkVoidFunction>(CmdResetQueryPool) },
+ { "vkCmdWriteTimestamp", reinterpret_cast<PFN_vkVoidFunction>(CmdWriteTimestamp) },
+ { "vkCmdCopyQueryPoolResults", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyQueryPoolResults) },
+ { "vkCreateFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(CreateFramebuffer) },
+ { "vkDestroyFramebuffer", reinterpret_cast<PFN_vkVoidFunction>(DestroyFramebuffer) },
+ { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
+ { "vkDestroyRenderPass", reinterpret_cast<PFN_vkVoidFunction>(DestroyRenderPass) },
+ { "vkGetRenderAreaGranularity", reinterpret_cast<PFN_vkVoidFunction>(GetRenderAreaGranularity) },
+ { "vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool) },
+ { "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool) },
+ { "vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool) },
+ { "vkCmdBeginRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CmdBeginRenderPass) },
+ { "vkCmdNextSubpass", reinterpret_cast<PFN_vkVoidFunction>(CmdNextSubpass) },
+ };
+
+ for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
+ if (!strcmp(core_device_commands[i].name, name))
+ return core_device_commands[i].proc;
+ }
+
+ return nullptr;
+}
+
+} // namespace parameter_validation
+
+// vk_layer_logging.h expects these to be defined
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
+ return parameter_validation::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
+ VkDebugReportCallbackEXT msgCallback,
+ const VkAllocationCallbacks *pAllocator) {
+ parameter_validation::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
+ size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+ parameter_validation::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+}
+
+// loader-layer interface v0
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ return parameter_validation::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return parameter_validation::EnumerateInstanceLayerProperties(pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return parameter_validation::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName, uint32_t *pCount,
+ VkExtensionProperties *pProperties) {
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return parameter_validation::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
+ return parameter_validation::GetDeviceProcAddr(dev, funcName);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
+ return parameter_validation::GetInstanceProcAddr(instance, funcName);
+}
diff --git a/layers/parameter_validation_utils.h b/layers/parameter_validation_utils.h
index 1683f31f..effd0530 100644
--- a/layers/parameter_validation_utils.h
+++ b/layers/parameter_validation_utils.h
@@ -717,8 +717,8 @@ static std::string get_result_description(VkResult result) {
case VK_INCOMPLETE: return "a return array was too small for the result";
case VK_ERROR_OUT_OF_HOST_MEMORY: return "a host memory allocation has failed";
case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "a device memory allocation has failed";
- case VK_ERROR_INITIALIZATION_FAILED: return "the logical device has been lost";
- case VK_ERROR_DEVICE_LOST: return "initialization of an object has failed";
+ case VK_ERROR_INITIALIZATION_FAILED: return "initialization of an object has failed";
+ case VK_ERROR_DEVICE_LOST: return "the logical device has been lost";
case VK_ERROR_MEMORY_MAP_FAILED: return "mapping of a memory object has failed";
case VK_ERROR_LAYER_NOT_PRESENT: return "the specified layer does not exist";
case VK_ERROR_EXTENSION_NOT_PRESENT: return "the specified extension does not exist";
diff --git a/layers/swapchain.cpp b/layers/swapchain.cpp
index f49c8bca..440c6d03 100644
--- a/layers/swapchain.cpp
+++ b/layers/swapchain.cpp
@@ -1486,9 +1486,9 @@ static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateI
}
}
// Log the message that we've built up:
- skipCall |= debug_report_log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, __LINE__,
- SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME, errorString.c_str());
+ skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
+ reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, LAYER_NAME,
+ "%s", errorString.c_str());
}
// Validate pCreateInfo->compositeAlpha has one bit set (1st two
// lines of if-statement), which bit is also set in
@@ -1515,17 +1515,17 @@ static bool validateCreateSwapchainKHR(VkDevice device, const VkSwapchainCreateI
}
}
// Log the message that we've built up:
- skipCall |= debug_report_log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
- VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, (uint64_t)device, 0,
- SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, LAYER_NAME, errorString.c_str());
+ skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
+ reinterpret_cast<uint64_t &>(device), __LINE__, SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA,
+ LAYER_NAME, "%s", errorString.c_str());
}
- // Validate pCreateInfo->imageArraySize against
- // VkSurfaceCapabilitiesKHR::maxImageArraySize:
+ // Validate pCreateInfo->imageArrayLayers against
+ // VkSurfaceCapabilitiesKHR::maxImageArrayLayers:
if ((pCreateInfo->imageArrayLayers < 1) || (pCreateInfo->imageArrayLayers > pCapabilities->maxImageArrayLayers)) {
skipCall |= LOG_ERROR(VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT, device, "VkDevice",
- SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, "%s() called with a non-supported "
- "pCreateInfo->imageArraySize (i.e. %d). "
- "Minimum value is 1, maximum value is %d.",
+ SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, "%s() called with a non-supported "
+ "pCreateInfo->imageArrayLayers (i.e. %d). "
+ "Minimum value is 1, maximum value is %d.",
fn, pCreateInfo->imageArrayLayers, pCapabilities->maxImageArrayLayers);
}
// Validate pCreateInfo->imageUsage against
@@ -2099,7 +2099,7 @@ CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCre
my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (VK_SUCCESS == result) {
std::lock_guard<std::mutex> lock(global_lock);
- result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
+ result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
return result;
}
@@ -2121,6 +2121,24 @@ DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugR
pMsg);
}
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &swapchain_layer, pCount, pProperties);
+}
+
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ if (pLayerName && !strcmp(pLayerName, swapchain_layer.layerName))
+ return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
+
+ return VK_ERROR_LAYER_NOT_PRESENT;
+}
+
VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
@@ -2204,15 +2222,13 @@ intercept_core_instance_command(const char *name) {
{ "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
{ "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
{ "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
+ { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
+ { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
+ { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
{ "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
{ "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
};
- // we should never be queried for these commands
- assert(strcmp(name, "vkEnumerateInstanceLayerProperties") &&
- strcmp(name, "vkEnumerateInstanceExtensionProperties") &&
- strcmp(name, "vkEnumerateDeviceLayerProperties"));
-
for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
if (!strcmp(core_instance_commands[i].name, name))
return core_instance_commands[i].proc;
@@ -2331,27 +2347,30 @@ vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebu
swapchain::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
}
-// loader-layer interface v0
+// loader-layer interface v0, just wrappers since there is only a layer
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
- return util_GetExtensionProperties(ARRAY_SIZE(swapchain::instance_extensions), swapchain::instance_extensions, pCount, pProperties);
+ return swapchain::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &swapchain::swapchain_layer, pCount, pProperties);
+ return swapchain::EnumerateInstanceLayerProperties(pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(1, &swapchain::swapchain_layer, pCount, pProperties);
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return swapchain::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
}
VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
const char *pLayerName, uint32_t *pCount,
VkExtensionProperties *pProperties) {
- // the layer command handles VK_NULL_HANDLE just fine
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
return swapchain::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
}
@@ -2360,14 +2379,5 @@ VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkD
}
VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
- if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateDeviceLayerProperties);
- if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkEnumerateInstanceExtensionProperties);
- if (!strcmp(funcName, "vkGetInstanceProcAddr"))
- return reinterpret_cast<PFN_vkVoidFunction>(vkGetInstanceProcAddr);
-
return swapchain::GetInstanceProcAddr(instance, funcName);
}
diff --git a/layers/swapchain.h b/layers/swapchain.h
index 3348d623..ec1e39b3 100644
--- a/layers/swapchain.h
+++ b/layers/swapchain.h
@@ -31,7 +31,7 @@
using namespace std;
// Swapchain ERROR codes
-typedef enum _SWAPCHAIN_ERROR {
+enum SWAPCHAIN_ERROR {
SWAPCHAIN_INVALID_HANDLE, // Handle used that isn't currently valid
SWAPCHAIN_NULL_POINTER, // Pointer set to NULL, instead of being a valid pointer
SWAPCHAIN_EXT_NOT_ENABLED_BUT_USED, // Did not enable WSI extension, but called WSI function
@@ -45,7 +45,7 @@ typedef enum _SWAPCHAIN_ERROR {
SWAPCHAIN_CREATE_SWAP_EXTENTS_NO_MATCH_WIN, // Called vkCreateSwapchainKHR() with imageExtent that doesn't match window's extent
SWAPCHAIN_CREATE_SWAP_BAD_PRE_TRANSFORM, // Called vkCreateSwapchainKHR() with a non-supported preTransform
SWAPCHAIN_CREATE_SWAP_BAD_COMPOSITE_ALPHA, // Called vkCreateSwapchainKHR() with a non-supported compositeAlpha
- SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_SIZE, // Called vkCreateSwapchainKHR() with a non-supported imageArraySize
+ SWAPCHAIN_CREATE_SWAP_BAD_IMG_ARRAY_LAYERS, // Called vkCreateSwapchainKHR() with a non-supported imageArrayLayers
SWAPCHAIN_CREATE_SWAP_BAD_IMG_USAGE_FLAGS, // Called vkCreateSwapchainKHR() with a non-supported imageUsageFlags
SWAPCHAIN_CREATE_SWAP_BAD_IMG_COLOR_SPACE, // Called vkCreateSwapchainKHR() with a non-supported imageColorSpace
SWAPCHAIN_CREATE_SWAP_BAD_IMG_FORMAT, // Called vkCreateSwapchainKHR() with a non-supported imageFormat
@@ -74,7 +74,7 @@ typedef enum _SWAPCHAIN_ERROR {
SWAPCHAIN_SURFACE_NOT_SUPPORTED_WITH_QUEUE, // A surface is not supported by a given queueFamilyIndex, as seen by
// vkGetPhysicalDeviceSurfaceSupportKHR()
SWAPCHAIN_NO_SYNC_FOR_ACQUIRE, // vkAcquireNextImageKHR should be called with a valid semaphore and/or fence
-} SWAPCHAIN_ERROR;
+};
// The following is for logging error messages:
#define LAYER_NAME (char *) "Swapchain"
@@ -138,25 +138,16 @@ typedef enum _SWAPCHAIN_ERROR {
// info that is used for validating the WSI extensions.
// Forward declarations:
-struct _SwpInstance;
-struct _SwpSurface;
-struct _SwpPhysicalDevice;
-struct _SwpDevice;
-struct _SwpSwapchain;
-struct _SwpImage;
-struct _SwpQueue;
-
-typedef _SwpInstance SwpInstance;
-typedef _SwpSurface SwpSurface;
-;
-typedef _SwpPhysicalDevice SwpPhysicalDevice;
-typedef _SwpDevice SwpDevice;
-typedef _SwpSwapchain SwpSwapchain;
-typedef _SwpImage SwpImage;
-typedef _SwpQueue SwpQueue;
+struct SwpInstance;
+struct SwpSurface;
+struct SwpPhysicalDevice;
+struct SwpDevice;
+struct SwpSwapchain;
+struct SwpImage;
+struct SwpQueue;
// Create one of these for each VkInstance:
-struct _SwpInstance {
+struct SwpInstance {
// The actual handle for this VkInstance:
VkInstance instance;
@@ -198,7 +189,7 @@ struct _SwpInstance {
};
// Create one of these for each VkSurfaceKHR:
-struct _SwpSurface {
+struct SwpSurface {
// The actual handle for this VkSurfaceKHR:
VkSurfaceKHR surface;
@@ -224,7 +215,7 @@ struct _SwpSurface {
};
// Create one of these for each VkPhysicalDevice within a VkInstance:
-struct _SwpPhysicalDevice {
+struct SwpPhysicalDevice {
// The actual handle for this VkPhysicalDevice:
VkPhysicalDevice physicalDevice;
@@ -263,7 +254,7 @@ struct _SwpPhysicalDevice {
};
// Create one of these for each VkDevice within a VkInstance:
-struct _SwpDevice {
+struct SwpDevice {
// The actual handle for this VkDevice:
VkDevice device;
@@ -282,7 +273,7 @@ struct _SwpDevice {
};
// Create one of these for each VkImage within a VkSwapchainKHR:
-struct _SwpImage {
+struct SwpImage {
// The actual handle for this VkImage:
VkImage image;
@@ -295,7 +286,7 @@ struct _SwpImage {
};
// Create one of these for each VkSwapchainKHR within a VkDevice:
-struct _SwpSwapchain {
+struct SwpSwapchain {
// The actual handle for this VkSwapchainKHR:
VkSwapchainKHR swapchain;
@@ -315,7 +306,7 @@ struct _SwpSwapchain {
};
// Create one of these for each VkQueue within a VkDevice:
-struct _SwpQueue {
+struct SwpQueue {
// The actual handle for this VkQueue:
VkQueue queue;
diff --git a/layers/threading.cpp b/layers/threading.cpp
index 4d9fca0d..c69a8b62 100644
--- a/layers/threading.cpp
+++ b/layers/threading.cpp
@@ -39,13 +39,15 @@
#include "thread_check.h"
+namespace threading {
+
static void initThreading(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "google_threading");
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
assert(chain_info->u.pLayerInfo);
@@ -63,6 +65,7 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCall
return result;
layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+ my_data->instance = *pInstance;
my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
@@ -77,7 +80,7 @@ vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCall
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
dispatch_key key = get_dispatch_key(instance);
layer_data *my_data = get_my_data_ptr(key, layer_data_map);
VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
@@ -116,14 +119,15 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance
layer_data_map.erase(key);
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
+ layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
assert(chain_info->u.pLayerInfo);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
- PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+ PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
if (fpCreateDevice == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -136,7 +140,6 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice g
return result;
}
- layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
// Setup device dispatch table
@@ -147,7 +150,7 @@ VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice g
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
dispatch_key key = get_dispatch_key(device);
layer_data *dev_data = get_my_data_ptr(key, layer_data_map);
startWriteObject(dev_data, device);
@@ -159,51 +162,50 @@ VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, cons
static const VkExtensionProperties threading_extensions[] = {
{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
-VK_LAYER_EXPORT VkResult VKAPI_CALL
-vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
- return util_GetExtensionProperties(ARRAY_SIZE(threading_extensions), threading_extensions, pCount, pProperties);
-}
-
-static const VkLayerProperties globalLayerProps[] = {{
+static const VkLayerProperties layerProps = {
"VK_LAYER_GOOGLE_threading",
VK_LAYER_API_VERSION, // specVersion
1, "Google Validation Layer",
-}};
+};
-VK_LAYER_EXPORT VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(ARRAY_SIZE(globalLayerProps), globalLayerProps, pCount, pProperties);
+static inline PFN_vkVoidFunction layer_intercept_proc(const char *name) {
+ for (int i = 0; i < sizeof(procmap) / sizeof(procmap[0]); i++) {
+ if (!strcmp(name, procmap[i].name))
+ return procmap[i].pFunc;
+ }
+ return NULL;
}
-static const VkLayerProperties deviceLayerProps[] = {{
- "VK_LAYER_GOOGLE_threading",
- VK_LAYER_API_VERSION, // specVersion
- 1, "Google Validation Layer",
-}};
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &layerProps, pCount, pProperties);
+}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
- const char *pLayerName, uint32_t *pCount,
- VkExtensionProperties *pProperties) {
- if (pLayerName == NULL) {
- dispatch_key key = get_dispatch_key(physicalDevice);
- layer_data *my_data = get_my_data_ptr(key, layer_data_map);
- return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
- } else {
- // Threading layer does not have any device extensions
- return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
- }
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ return util_GetLayerProperties(1, &layerProps, pCount, pProperties);
}
-VK_LAYER_EXPORT VkResult VKAPI_CALL
-vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
- return util_GetLayerProperties(ARRAY_SIZE(deviceLayerProps), deviceLayerProps, pCount, pProperties);
+VKAPI_ATTR VkResult VKAPI_CALL
+EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ if (pLayerName && !strcmp(pLayerName, layerProps.layerName))
+ return util_GetExtensionProperties(1, threading_extensions, pCount, pProperties);
+
+ return VK_ERROR_LAYER_NOT_PRESENT;
}
-static inline PFN_vkVoidFunction layer_intercept_proc(const char *name) {
- for (int i = 0; i < sizeof(procmap) / sizeof(procmap[0]); i++) {
- if (!strcmp(name, procmap[i].name))
- return procmap[i].pFunc;
- }
- return NULL;
+VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName, uint32_t *pCount,
+ VkExtensionProperties *pProperties) {
+ // Threading layer does not have any device extensions
+ if (pLayerName && !strcmp(pLayerName, layerProps.layerName))
+ return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
+
+ assert(physicalDevice);
+
+ dispatch_key key = get_dispatch_key(physicalDevice);
+ layer_data *my_data = get_my_data_ptr(key, layer_data_map);
+ return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
}
static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name) {
@@ -212,31 +214,30 @@ static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)
name += 2;
if (!strcmp(name, "CreateInstance"))
- return (PFN_vkVoidFunction)vkCreateInstance;
+ return (PFN_vkVoidFunction)CreateInstance;
if (!strcmp(name, "DestroyInstance"))
- return (PFN_vkVoidFunction)vkDestroyInstance;
- if (!strcmp(name, "EnumerateInstanceExtensionProperties"))
- return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
+ return (PFN_vkVoidFunction)DestroyInstance;
if (!strcmp(name, "EnumerateInstanceLayerProperties"))
- return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
- if (!strcmp(name, "EnumerateDeviceExtensionProperties"))
- return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
+ return (PFN_vkVoidFunction)EnumerateInstanceLayerProperties;
+ if (!strcmp(name, "EnumerateInstanceExtensionProperties"))
+ return (PFN_vkVoidFunction)EnumerateInstanceExtensionProperties;
if (!strcmp(name, "EnumerateDeviceLayerProperties"))
- return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
+ return (PFN_vkVoidFunction)EnumerateDeviceLayerProperties;
+ if (!strcmp(name, "EnumerateDeviceExtensionProperties"))
+ return (PFN_vkVoidFunction)EnumerateDeviceExtensionProperties;
if (!strcmp(name, "CreateDevice"))
- return (PFN_vkVoidFunction)vkCreateDevice;
+ return (PFN_vkVoidFunction)CreateDevice;
if (!strcmp(name, "GetInstanceProcAddr"))
- return (PFN_vkVoidFunction)vkGetInstanceProcAddr;
+ return (PFN_vkVoidFunction)GetInstanceProcAddr;
return NULL;
}
-VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
PFN_vkVoidFunction addr;
layer_data *dev_data;
- if (device == VK_NULL_HANDLE) {
- return NULL;
- }
+
+ assert(device);
addr = layer_intercept_proc(funcName);
if (addr)
@@ -250,18 +251,18 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice devic
return pTable->GetDeviceProcAddr(device, funcName);
}
-VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
+VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
PFN_vkVoidFunction addr;
layer_data *my_data;
addr = layer_intercept_instance_proc(funcName);
+ if (!addr)
+ addr = layer_intercept_proc(funcName);
if (addr) {
return addr;
}
- if (instance == VK_NULL_HANDLE) {
- return NULL;
- }
+ assert(instance);
my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
@@ -276,22 +277,22 @@ VK_LAYER_EXPORT PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance i
return pTable->GetInstanceProcAddr(instance, funcName);
}
-VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
-vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
- const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
+VKAPI_ATTR VkResult VKAPI_CALL
+CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
startReadObject(my_data, instance);
VkResult result =
my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
if (VK_SUCCESS == result) {
- result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
+ result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
}
finishReadObject(my_data, instance);
return result;
}
-VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
-vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator) {
+VKAPI_ATTR void VKAPI_CALL
+DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT callback, const VkAllocationCallbacks *pAllocator) {
layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
startReadObject(my_data, instance);
startWriteObject(my_data, callback);
@@ -301,8 +302,8 @@ vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT ca
finishWriteObject(my_data, callback);
}
-VkResult VKAPI_CALL
-vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
+VKAPI_ATTR VkResult VKAPI_CALL
+AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
dispatch_key key = get_dispatch_key(device);
layer_data *my_data = get_my_data_ptr(key, layer_data_map);
VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
@@ -325,8 +326,8 @@ vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAl
return result;
}
-void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
- const VkCommandBuffer *pCommandBuffers) {
+VKAPI_ATTR void VKAPI_CALL FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount,
+ const VkCommandBuffer *pCommandBuffers) {
dispatch_key key = get_dispatch_key(device);
layer_data *my_data = get_my_data_ptr(key, layer_data_map);
VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
@@ -346,3 +347,60 @@ void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
command_pool_map.erase(pCommandBuffers[index]);
}
}
+
+} // namespace threading
+
+// vk_layer_logging.h expects these to be defined
+
+VKAPI_ATTR VkResult VKAPI_CALL
+vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
+ const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
+ return threading::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
+}
+
+VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
+ VkDebugReportCallbackEXT msgCallback,
+ const VkAllocationCallbacks *pAllocator) {
+ threading::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
+}
+
+VKAPI_ATTR void VKAPI_CALL
+vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
+ size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
+ threading::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
+}
+
+// loader-layer interface v0, just wrappers since there is only a layer
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
+ return threading::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
+ return threading::EnumerateInstanceLayerProperties(pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
+vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return threading::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
+ const char *pLayerName, uint32_t *pCount,
+ VkExtensionProperties *pProperties) {
+ // the layer command handles VK_NULL_HANDLE just fine internally
+ assert(physicalDevice == VK_NULL_HANDLE);
+ return threading::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
+ return threading::GetDeviceProcAddr(dev, funcName);
+}
+
+VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
+ return threading::GetInstanceProcAddr(instance, funcName);
+}
diff --git a/layers/threading.h b/layers/threading.h
index 96175394..c3db3468 100644
--- a/layers/threading.h
+++ b/layers/threading.h
@@ -34,11 +34,11 @@
#endif
// Draw State ERROR codes
-typedef enum _THREADING_CHECKER_ERROR {
+enum THREADING_CHECKER_ERROR {
THREADING_CHECKER_NONE, // Used for INFO & other non-error messages
THREADING_CHECKER_MULTIPLE_THREADS, // Object used simultaneously by multiple threads
THREADING_CHECKER_SINGLE_THREAD_REUSE, // Object used simultaneously by recursion in single thread
-} THREADING_CHECKER_ERROR;
+};
struct object_use_data {
loader_platform_thread_id thread;
@@ -189,6 +189,8 @@ template <typename T> class counter {
};
struct layer_data {
+ VkInstance instance;
+
debug_report_data *report_data;
std::vector<VkDebugReportCallbackEXT> logging_callback;
VkLayerDispatchTable *device_dispatch_table;
diff --git a/layers/unique_objects.h b/layers/unique_objects.h
index 6c2c2e3c..9abf240c 100644
--- a/layers/unique_objects.h
+++ b/layers/unique_objects.h
@@ -39,10 +39,14 @@
#include "vk_safe_struct.h"
#include "vk_layer_utils.h"
+namespace unique_objects {
+
// All increments must be guarded by global_lock
static uint64_t global_unique_id = 1;
struct layer_data {
+ VkInstance instance;
+
bool wsi_enabled;
std::unordered_map<uint64_t, uint64_t> unique_id_mapping; // Map uniqueID to actual object handle
VkPhysicalDevice gpu;
@@ -160,6 +164,8 @@ VkResult explicit_CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const
return result;
}
+ layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
+ my_data->instance = *pInstance;
initInstanceTable(*pInstance, fpGetInstanceProcAddr, unique_objects_instance_table_map);
createInstanceRegisterExtensions(pCreateInfo, *pInstance);
@@ -192,12 +198,13 @@ static void createDeviceRegisterExtensions(const VkDeviceCreateInfo *pCreateInfo
VkResult explicit_CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
VkDevice *pDevice) {
+ layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
assert(chain_info->u.pLayerInfo);
PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
- PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
+ PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
if (fpCreateDevice == NULL) {
return VK_ERROR_INITIALIZATION_FAILED;
}
@@ -393,3 +400,5 @@ VkResult explicit_GetSwapchainImagesKHR(VkDevice device, VkSwapchainKHR swapchai
}
return result;
}
+
+} // namespace unique_objects
diff --git a/layers/vk_layer_config.cpp b/layers/vk_layer_config.cpp
index d67f4053..d1f61e1e 100644
--- a/layers/vk_layer_config.cpp
+++ b/layers/vk_layer_config.cpp
@@ -19,6 +19,7 @@
* Author: Jon Ashburn <jon@lunarg.com>
* Author: Courtney Goeltzenleuchter <courtney@LunarG.com>
* Author: Tobin Ehlis <tobin@lunarg.com>
+ * Author: Mark Lobodzinski <mark@lunarg.com>
**************************************************************************/
#include <fstream>
#include <string>
@@ -31,6 +32,17 @@
#define MAX_CHARS_PER_LINE 4096
+// Flag for ONE-TIME debug output initialization
+static bool log_message_initialized = false;
+
+// Accessor functions to ensure the correct instance of the shared flag gets used
+bool LogMessageInitialized() {
+ return log_message_initialized;
+}
+void SetLogMessageInitialized() {
+ log_message_initialized = true;
+}
+
class ConfigFile {
public:
ConfigFile();
@@ -48,50 +60,10 @@ class ConfigFile {
static ConfigFile g_configFileObj;
-static VkLayerDbgAction stringToDbgAction(const char *_enum) {
- // only handles single enum values
- if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_IGNORE"))
- return VK_DBG_LAYER_ACTION_IGNORE;
- else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_LOG_MSG"))
- return VK_DBG_LAYER_ACTION_LOG_MSG;
-#ifdef WIN32
- else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"))
- return VK_DBG_LAYER_ACTION_DEBUG_OUTPUT;
-#endif
- else if (!strcmp(_enum, "VK_DBG_LAYER_ACTION_BREAK"))
- return VK_DBG_LAYER_ACTION_BREAK;
- return (VkLayerDbgAction)0;
-}
-
-static VkFlags stringToDbgReportFlags(const char *_enum) {
- // only handles single enum values
- if (!strcmp(_enum, "VK_DEBUG_REPORT_INFO"))
- return VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
- else if (!strcmp(_enum, "VK_DEBUG_REPORT_WARN"))
- return VK_DEBUG_REPORT_WARNING_BIT_EXT;
- else if (!strcmp(_enum, "VK_DEBUG_REPORT_PERF_WARN"))
- return VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
- else if (!strcmp(_enum, "VK_DEBUG_REPORT_ERROR"))
- return VK_DEBUG_REPORT_ERROR_BIT_EXT;
- else if (!strcmp(_enum, "VK_DEBUG_REPORT_DEBUG"))
- return VK_DEBUG_REPORT_DEBUG_BIT_EXT;
- return (VkFlags)0;
-}
-
-static unsigned int convertStringEnumVal(const char *_enum) {
- unsigned int ret;
-
- ret = stringToDbgAction(_enum);
- if (ret)
- return ret;
-
- return stringToDbgReportFlags(_enum);
-}
-
const char *getLayerOption(const char *_option) { return g_configFileObj.getOption(_option); }
// If option is NULL or stdout, return stdout, otherwise try to open option
-// as a filename. If successful, return file handle, otherwise stdout
+// as a filename. If successful, return file handle, otherwise stdout
FILE *getLayerLogOutput(const char *_option, const char *layerName) {
FILE *log_output = NULL;
if (!_option || !strcmp("stdout", _option))
@@ -110,64 +82,84 @@ FILE *getLayerLogOutput(const char *_option, const char *layerName) {
return log_output;
}
-VkDebugReportFlagsEXT getLayerOptionFlags(const char *_option, uint32_t optionDefault) {
- VkDebugReportFlagsEXT flags = optionDefault;
- const char *option = (g_configFileObj.getOption(_option));
-
- /* parse comma-separated options */
- while (option) {
- const char *p = strchr(option, ',');
- size_t len;
-
- if (p)
- len = p - option;
- else
- len = strlen(option);
-
- if (len > 0) {
- if (strncmp(option, "warn", len) == 0) {
- flags |= VK_DEBUG_REPORT_WARNING_BIT_EXT;
- } else if (strncmp(option, "info", len) == 0) {
- flags |= VK_DEBUG_REPORT_INFORMATION_BIT_EXT;
- } else if (strncmp(option, "perf", len) == 0) {
- flags |= VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
- } else if (strncmp(option, "error", len) == 0) {
- flags |= VK_DEBUG_REPORT_ERROR_BIT_EXT;
- } else if (strncmp(option, "debug", len) == 0) {
- flags |= VK_DEBUG_REPORT_DEBUG_BIT_EXT;
- }
+// Map option strings to flag enum values
+VkFlags GetLayerOptionFlags(std::string _option, std::unordered_map<std::string, VkFlags> const &enum_data,
+ uint32_t option_default) {
+ VkDebugReportFlagsEXT flags = option_default;
+ std::string option_list = g_configFileObj.getOption(_option.c_str());
+
+ while (option_list.length() != 0) {
+
+ // Find length of option string
+ std::size_t option_length = option_list.find(",");
+ if (option_length == option_list.npos) {
+ option_length = option_list.size();
}
- if (!p)
- break;
+ // Get first option in list
+ const std::string option = option_list.substr(0, option_length);
- option = p + 1;
- }
- return flags;
-}
+ auto enum_value = enum_data.find(option);
+ if (enum_value != enum_data.end()) {
+ flags |= enum_value->second;
+ }
-bool getLayerOptionEnum(const char *_option, uint32_t *optionDefault) {
- bool res;
- const char *option = (g_configFileObj.getOption(_option));
- if (option != NULL) {
- *optionDefault = convertStringEnumVal(option);
- res = false;
- } else {
- res = true;
+ // Remove first option from option_list
+ option_list.erase(0, option_length);
+ // Remove possible comma separator
+ std::size_t char_position = option_list.find(",");
+ if (char_position == 0) {
+ option_list.erase(char_position, 1);
+ }
+ // Remove possible space
+ char_position = option_list.find(" ");
+ if (char_position == 0) {
+ option_list.erase(char_position, 1);
+ }
}
- return res;
-}
-
-void setLayerOptionEnum(const char *_option, const char *_valEnum) {
- unsigned int val = convertStringEnumVal(_valEnum);
- char strVal[24];
- snprintf(strVal, 24, "%u", val);
- g_configFileObj.setOption(_option, strVal);
+ return flags;
}
void setLayerOption(const char *_option, const char *_val) { g_configFileObj.setOption(_option, _val); }
-ConfigFile::ConfigFile() : m_fileIsParsed(false) {}
+// Constructor for ConfigFile. Initialize layers to log error messages to stdout by default. If a vk_layer_settings file is present,
+// its settings will override the defaults.
+ConfigFile::ConfigFile() : m_fileIsParsed(false) {
+ m_valueMap["lunarg_device_limits.report_flags"] = "error";
+ m_valueMap["lunarg_core_validation.report_flags"] = "error";
+ m_valueMap["lunarg_image.report_flags"] = "error";
+ m_valueMap["lunarg_object_tracker.report_flags"] = "error";
+ m_valueMap["lunarg_parameter_validation.report_flags"] = "error";
+ m_valueMap["lunarg_swapchain.report_flags"] = "error";
+ m_valueMap["google_threading.report_flags"] = "error";
+
+#ifdef WIN32
+ // For Windows, enable message logging AND OutputDebugString
+ m_valueMap["lunarg_device_limits.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+ m_valueMap["lunarg_core_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+ m_valueMap["lunarg_image.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+ m_valueMap["lunarg_object_tracker.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+ m_valueMap["lunarg_parameter_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+ m_valueMap["lunarg_swapchain.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+ m_valueMap["google_threading.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG,VK_DBG_LAYER_ACTION_DEBUG_OUTPUT";
+#else // WIN32
+ m_valueMap["lunarg_device_limits.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+ m_valueMap["lunarg_core_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+ m_valueMap["lunarg_image.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+ m_valueMap["lunarg_object_tracker.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+ m_valueMap["lunarg_parameter_validation.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+ m_valueMap["lunarg_swapchain.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+ m_valueMap["google_threading.debug_action"] = "VK_DBG_LAYER_ACTION_DEFAULT,VK_DBG_LAYER_ACTION_LOG_MSG";
+#endif // WIN32
+
+ m_valueMap["lunarg_device_limits.log_filename"] = "stdout";
+ m_valueMap["lunarg_core_validation.log_filename"] = "stdout";
+ m_valueMap["lunarg_image.log_filename"] = "stdout";
+ m_valueMap["lunarg_object_tracker.log_filename"] = "stdout";
+ m_valueMap["lunarg_parameter_validation.log_filename"] = "stdout";
+ m_valueMap["lunarg_swapchain.log_filename"] = "stdout";
+ m_valueMap["google_threading.log_filename"] = "stdout";
+}
ConfigFile::~ConfigFile() {}
@@ -178,7 +170,7 @@ const char *ConfigFile::getOption(const std::string &_option) {
}
if ((it = m_valueMap.find(_option)) == m_valueMap.end())
- return NULL;
+ return "";
else
return it->second.c_str();
}
@@ -196,11 +188,12 @@ void ConfigFile::parseFile(const char *filename) {
char buf[MAX_CHARS_PER_LINE];
m_fileIsParsed = true;
- m_valueMap.clear();
file.open(filename);
- if (!file.good())
+ if (!file.good()) {
return;
+ }
+
// read tokens from the file and form option, value pairs
file.getline(buf, MAX_CHARS_PER_LINE);
diff --git a/layers/vk_layer_config.h b/layers/vk_layer_config.h
index 92865f69..097ba42c 100644
--- a/layers/vk_layer_config.h
+++ b/layers/vk_layer_config.h
@@ -15,9 +15,12 @@
* limitations under the License.
*
* Author: Jon Ashburn <jon@lunarg.com>
+ * Author: Mark Lobodzinski <mark@lunarg.com>
**************************************************************************/
#pragma once
#include "vulkan/vulkan.h"
+#include "vulkan/vk_layer.h"
+#include <unordered_map>
#include <stdbool.h>
#include <stdio.h>
@@ -25,14 +28,44 @@
extern "C" {
#endif
+// Definitions for Debug Actions
+typedef enum VkLayerDbgActionBits {
+ VK_DBG_LAYER_ACTION_IGNORE = 0x00000000,
+ VK_DBG_LAYER_ACTION_CALLBACK = 0x00000001,
+ VK_DBG_LAYER_ACTION_LOG_MSG = 0x00000002,
+ VK_DBG_LAYER_ACTION_BREAK = 0x00000004,
+ VK_DBG_LAYER_ACTION_DEBUG_OUTPUT = 0x00000008,
+ VK_DBG_LAYER_ACTION_DEFAULT = 0x40000000,
+} VkLayerDbgActionBits;
+typedef VkFlags VkLayerDbgActionFlags;
+
+const std::unordered_map<std::string, VkFlags> debug_actions_option_definitions = {
+ {std::string("VK_DBG_LAYER_ACTION_IGNORE"), VK_DBG_LAYER_ACTION_IGNORE},
+ {std::string("VK_DBG_LAYER_ACTION_CALLBACK"), VK_DBG_LAYER_ACTION_CALLBACK},
+ {std::string("VK_DBG_LAYER_ACTION_LOG_MSG"), VK_DBG_LAYER_ACTION_LOG_MSG},
+ {std::string("VK_DBG_LAYER_ACTION_BREAK"), VK_DBG_LAYER_ACTION_BREAK},
+#if WIN32
+ {std::string("VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"), VK_DBG_LAYER_ACTION_DEBUG_OUTPUT},
+#endif
+ {std::string("VK_DBG_LAYER_ACTION_DEFAULT"), VK_DBG_LAYER_ACTION_DEFAULT}};
+
+const std::unordered_map<std::string, VkFlags> report_flags_option_definitions = {
+ {std::string("warn"), VK_DEBUG_REPORT_WARNING_BIT_EXT},
+ {std::string("info"), VK_DEBUG_REPORT_INFORMATION_BIT_EXT},
+ {std::string("perf"), VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT},
+ {std::string("error"), VK_DEBUG_REPORT_ERROR_BIT_EXT},
+ {std::string("debug"), VK_DEBUG_REPORT_DEBUG_BIT_EXT}};
+
const char *getLayerOption(const char *_option);
FILE *getLayerLogOutput(const char *_option, const char *layerName);
-VkDebugReportFlagsEXT getLayerOptionFlags(const char *_option, uint32_t optionDefault);
-bool getLayerOptionEnum(const char *_option, uint32_t *optionDefault);
+VkFlags GetLayerOptionFlags(std::string _option, std::unordered_map<std::string, VkFlags> const &enum_data,
+ uint32_t option_default);
void setLayerOption(const char *_option, const char *_val);
-void setLayerOptionEnum(const char *_option, const char *_valEnum);
void print_msg_flags(VkFlags msgFlags, char *msg_flags);
+bool LogMessageInitialized();
+void SetLogMessageInitialized();
+
#ifdef __cplusplus
}
#endif
diff --git a/layers/vk_layer_logging.h b/layers/vk_layer_logging.h
index dd80dfe3..28363133 100644
--- a/layers/vk_layer_logging.h
+++ b/layers/vk_layer_logging.h
@@ -22,6 +22,7 @@
#ifndef LAYER_LOGGING_H
#define LAYER_LOGGING_H
+#include "vk_loader_layer.h"
#include "vk_layer_config.h"
#include "vk_layer_data.h"
#include "vk_layer_table.h"
@@ -32,9 +33,11 @@
#include <stdbool.h>
#include <stdio.h>
#include <unordered_map>
+#include <vector>
typedef struct _debug_report_data {
- VkLayerDbgFunctionNode *g_pDbgFunctionHead;
+ VkLayerDbgFunctionNode *debug_callback_list;
+ VkLayerDbgFunctionNode *default_debug_callback_list;
VkFlags active_flags;
bool g_DEBUG_REPORT;
} debug_report_data;
@@ -42,12 +45,116 @@ typedef struct _debug_report_data {
template debug_report_data *get_my_data_ptr<debug_report_data>(void *data_key,
std::unordered_map<void *, debug_report_data *> &data_map);
+// Forward Declarations
+static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags,
+ VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode,
+ const char *pLayerPrefix, const char *pMsg);
+
+// Add a debug message callback node structure to the specified callback linked list
+static inline void AddDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
+ VkLayerDbgFunctionNode *new_node) {
+
+ new_node->pNext = *list_head;
+ *list_head = new_node;
+}
+
+// Remove specified debug message callback node structure from the specified callback linked list
+static inline void RemoveDebugMessageCallback(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head,
+ VkDebugReportCallbackEXT callback) {
+ VkLayerDbgFunctionNode *cur_callback = *list_head;
+ VkLayerDbgFunctionNode *prev_callback = cur_callback;
+ bool matched = false;
+
+ debug_data->active_flags = 0;
+ while (cur_callback) {
+ if (cur_callback->msgCallback == callback) {
+ matched = true;
+ prev_callback->pNext = cur_callback->pNext;
+ if (*list_head == cur_callback) {
+ *list_head = cur_callback->pNext;
+ }
+ debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ reinterpret_cast<uint64_t &>(cur_callback->msgCallback), 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT,
+ "DebugReport", "Destroyed callback");
+ } else {
+ matched = false;
+ debug_data->active_flags |= cur_callback->msgFlags;
+ }
+ prev_callback = cur_callback;
+ cur_callback = cur_callback->pNext;
+ if (matched) {
+ free(prev_callback);
+ }
+ }
+}
+
+// Removes all debug callback function nodes from the specified callback linked lists and frees their resources
+static inline void RemoveAllMessageCallbacks(debug_report_data *debug_data, VkLayerDbgFunctionNode **list_head) {
+ VkLayerDbgFunctionNode *current_callback = *list_head;
+ VkLayerDbgFunctionNode *prev_callback = current_callback;
+
+ while (current_callback) {
+ prev_callback = current_callback->pNext;
+ debug_report_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
+ (uint64_t)current_callback->msgCallback, 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "DebugReport",
+ "Debug Report callbacks not removed before DestroyInstance");
+ free(current_callback);
+ current_callback = prev_callback;
+ }
+ *list_head = NULL;
+}
+
+static inline bool OutputLogMsgHeader(const debug_report_data *debug_data, VkFlags msgFlags) {
+ bool output = false;
+ VkLayerDbgFunctionNode *pTrav =
+ (debug_data->debug_callback_list != NULL) ? debug_data->debug_callback_list : debug_data->default_debug_callback_list;
+
+ while (pTrav) {
+ const char *message_header = "Legend:\n\n"
+ "*******************************************************************************************\n"
+ "* Vulkan Validation Layer Debug Output *\n"
+ "* *\n"
+ "* Debug Output Type Definitions: *\n"
+ "* ------------------------------ *\n"
+ "* ERROR: Errors are output when a validation layer detects that some application behavior *\n"
+ "* has violated the Vulkan Specification. When an error is encountered it is *\n"
+ "* recommended that the user callback function return 'true' for optimal *\n"
+ "* validation results. Any validation error may result in undefined behavior and *\n"
+ "* errors should be corrected as they are encountered for best results. *\n"
+ "* WARN: Warnings are output in cases where mistakes are commonly made and do NOT *\n"
+ "* necessarily indicate that an app has violated the Vulkan Specification. *\n"
+ "* Warnings basically translate to 'Did you really mean to do this?' *\n"
+ "* PERF: Performance Warnings are output in cases where a possible inefficiency has been *\n"
+ "* detected. These also do NOT imply that the specification was violated. *\n"
+ "* INFO: These log messages are for informational purposes only. For instance, the *\n"
+ "* core_validation layer can print out lists of memory objects and their bindings *\n"
+ "* which may help with debugging or improving application efficiency. *\n"
+ "*******************************************************************************************\n";
+
+ if (pTrav->msgFlags & msgFlags) {
+ pTrav->pfnMsgCallback(VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT, 0, 0,
+ VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "", message_header, pTrav->pUserData);
+ output |= true;
+ }
+ pTrav = pTrav->pNext;
+ }
+ return output;
+}
+
// Utility function to handle reporting
-static inline bool debug_report_log_msg(debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
- uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix,
- const char *pMsg) {
+static inline bool debug_report_log_msg(const debug_report_data *debug_data, VkFlags msgFlags,
+ VkDebugReportObjectTypeEXT objectType, uint64_t srcObject, size_t location, int32_t msgCode,
+ const char *pLayerPrefix, const char *pMsg) {
bool bail = false;
- VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
+ VkLayerDbgFunctionNode *pTrav =
+ (debug_data->debug_callback_list != NULL) ? debug_data->debug_callback_list : debug_data->default_debug_callback_list;
+
+ if ((LogMessageInitialized() == false) && (strcmp(pLayerPrefix, "DebugReport") != 0)) {
+ if (OutputLogMsgHeader(debug_data, msgFlags) == true) {
+ SetLogMessageInitialized();
+ }
+ }
+
while (pTrav) {
if (pTrav->msgFlags & msgFlags) {
if (pTrav->pfnMsgCallback(msgFlags, objectType, srcObject, location, msgCode, pLayerPrefix, pMsg, pTrav->pUserData)) {
@@ -77,51 +184,42 @@ debug_report_create_instance(VkLayerInstanceDispatchTable *table, VkInstance ins
memset(debug_data, 0, sizeof(debug_report_data));
for (uint32_t i = 0; i < extension_count; i++) {
- /* TODO: Check other property fields */
+ // TODO: Check other property fields
if (strcmp(ppEnabledExtensions[i], VK_EXT_DEBUG_REPORT_EXTENSION_NAME) == 0) {
debug_data->g_DEBUG_REPORT = true;
}
}
+
return debug_data;
}
static inline void layer_debug_report_destroy_instance(debug_report_data *debug_data) {
- VkLayerDbgFunctionNode *pTrav;
- VkLayerDbgFunctionNode *pTravNext;
-
- if (!debug_data) {
- return;
- }
-
- pTrav = debug_data->g_pDbgFunctionHead;
- /* Clear out any leftover callbacks */
- while (pTrav) {
- pTravNext = pTrav->pNext;
-
- debug_report_log_msg(debug_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
- (uint64_t)pTrav->msgCallback, 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "DebugReport",
- "Debug Report callbacks not removed before DestroyInstance");
-
- free(pTrav);
- pTrav = pTravNext;
+ if (debug_data) {
+ RemoveAllMessageCallbacks(debug_data, &debug_data->default_debug_callback_list);
+ RemoveAllMessageCallbacks(debug_data, &debug_data->debug_callback_list);
+ free(debug_data);
}
- debug_data->g_pDbgFunctionHead = NULL;
-
- free(debug_data);
}
static inline debug_report_data *layer_debug_report_create_device(debug_report_data *instance_debug_data, VkDevice device) {
- /* DEBUG_REPORT shares data between Instance and Device,
- * so just return instance's data pointer */
+ // DEBUG_REPORT shares data between Instance and Device,
+ // so just return instance's data pointer
return instance_debug_data;
}
-static inline void layer_debug_report_destroy_device(VkDevice device) { /* Nothing to do since we're using instance data record */ }
+static inline void layer_debug_report_destroy_device(VkDevice device) {
+ // Nothing to do since we're using instance data record
+}
-static inline VkResult layer_create_msg_callback(debug_report_data *debug_data,
+static inline void layer_destroy_msg_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
+ const VkAllocationCallbacks *pAllocator) {
+ RemoveDebugMessageCallback(debug_data, &debug_data->debug_callback_list, callback);
+ RemoveDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, callback);
+}
+
+static inline VkResult layer_create_msg_callback(debug_report_data *debug_data, bool default_callback,
const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pCallback) {
- /* TODO: Use app allocator */
VkLayerDbgFunctionNode *pNewDbgFuncNode = (VkLayerDbgFunctionNode *)malloc(sizeof(VkLayerDbgFunctionNode));
if (!pNewDbgFuncNode)
return VK_ERROR_OUT_OF_HOST_MEMORY;
@@ -133,9 +231,12 @@ static inline VkResult layer_create_msg_callback(debug_report_data *debug_data,
pNewDbgFuncNode->pfnMsgCallback = pCreateInfo->pfnCallback;
pNewDbgFuncNode->msgFlags = pCreateInfo->flags;
pNewDbgFuncNode->pUserData = pCreateInfo->pUserData;
- pNewDbgFuncNode->pNext = debug_data->g_pDbgFunctionHead;
- debug_data->g_pDbgFunctionHead = pNewDbgFuncNode;
+ if (default_callback) {
+ AddDebugMessageCallback(debug_data, &debug_data->default_debug_callback_list, pNewDbgFuncNode);
+ } else {
+ AddDebugMessageCallback(debug_data, &debug_data->debug_callback_list, pNewDbgFuncNode);
+ }
debug_data->active_flags |= pCreateInfo->flags;
debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
@@ -143,36 +244,6 @@ static inline VkResult layer_create_msg_callback(debug_report_data *debug_data,
return VK_SUCCESS;
}
-static inline void layer_destroy_msg_callback(debug_report_data *debug_data, VkDebugReportCallbackEXT callback,
- const VkAllocationCallbacks *pAllocator) {
- VkLayerDbgFunctionNode *pTrav = debug_data->g_pDbgFunctionHead;
- VkLayerDbgFunctionNode *pPrev = pTrav;
- bool matched;
-
- debug_data->active_flags = 0;
- while (pTrav) {
- if (pTrav->msgCallback == callback) {
- matched = true;
- pPrev->pNext = pTrav->pNext;
- if (debug_data->g_pDbgFunctionHead == pTrav) {
- debug_data->g_pDbgFunctionHead = pTrav->pNext;
- }
- debug_report_log_msg(debug_data, VK_DEBUG_REPORT_DEBUG_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEBUG_REPORT_EXT,
- (uint64_t)pTrav->msgCallback, 0, VK_DEBUG_REPORT_ERROR_CALLBACK_REF_EXT, "DebugReport",
- "Destroyed callback");
- } else {
- matched = false;
- debug_data->active_flags |= pTrav->msgFlags;
- }
- pPrev = pTrav;
- pTrav = pTrav->pNext;
- if (matched) {
- /* TODO: Use pAllocator */
- free(pPrev);
- }
- }
-}
-
static inline PFN_vkVoidFunction debug_report_get_instance_proc_addr(debug_report_data *debug_data, const char *funcName) {
if (!debug_data || !debug_data->g_DEBUG_REPORT) {
return NULL;
@@ -253,7 +324,7 @@ static VkResult layer_enable_tmp_callbacks(debug_report_data *debug_data, uint32
VkDebugReportCallbackCreateInfoEXT *infos, VkDebugReportCallbackEXT *callbacks) {
VkResult rtn = VK_SUCCESS;
for (uint32_t i = 0; i < num_callbacks; i++) {
- rtn = layer_create_msg_callback(debug_data, &infos[i], NULL, &callbacks[i]);
+ rtn = layer_create_msg_callback(debug_data, false, &infos[i], NULL, &callbacks[i]);
if (rtn != VK_SUCCESS) {
for (uint32_t j = 0; j < i; j++) {
layer_destroy_msg_callback(debug_data, callbacks[j], NULL);
@@ -273,14 +344,12 @@ static void layer_disable_tmp_callbacks(debug_report_data *debug_data, uint32_t
}
}
-/*
- * Checks if the message will get logged.
- * Allows layer to defer collecting & formating data if the
- * message will be discarded.
- */
+// Checks if the message will get logged.
+// Allows layer to defer collecting & formating data if the
+// message will be discarded.
static inline bool will_log_msg(debug_report_data *debug_data, VkFlags msgFlags) {
if (!debug_data || !(debug_data->active_flags & msgFlags)) {
- /* message is not wanted */
+ // Message is not wanted
return false;
}
@@ -302,21 +371,19 @@ static inline int vasprintf(char **strp, char const *fmt, va_list ap) {
}
#endif
-/*
- * Output log message via DEBUG_REPORT
- * Takes format and variable arg list so that output string
- * is only computed if a message needs to be logged
- */
+// Output log message via DEBUG_REPORT
+// Takes format and variable arg list so that output string
+// is only computed if a message needs to be logged
#ifndef WIN32
-static inline bool log_msg(debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format, ...)
__attribute__((format(printf, 8, 9)));
#endif
-static inline bool log_msg(debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
+static inline bool log_msg(const debug_report_data *debug_data, VkFlags msgFlags, VkDebugReportObjectTypeEXT objectType,
uint64_t srcObject, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *format,
...) {
if (!debug_data || !(debug_data->active_flags & msgFlags)) {
- /* message is not wanted */
+ // Message is not wanted
return false;
}
@@ -324,7 +391,7 @@ static inline bool log_msg(debug_report_data *debug_data, VkFlags msgFlags, VkDe
va_start(argptr, format);
char *str;
if (-1 == vasprintf(&str, format, argptr)) {
- /* on failure, glibc vasprintf leaves str undefined */
+ // On failure, glibc vasprintf leaves str undefined
str = nullptr;
}
va_end(argptr);
diff --git a/layers/vk_layer_settings.txt b/layers/vk_layer_settings.txt
index d83b8326..aef2f311 100644
--- a/layers/vk_layer_settings.txt
+++ b/layers/vk_layer_settings.txt
@@ -1,4 +1,5 @@
# This is an example vk_layer_settings.txt file.
+#
# This file allows for per-layer settings which can dynamically affect layer
# behavior. Comments in this file are denoted with the "#" char.
# Settings lines are of the form "<LayerIdentifier>.<SettingName> = <SettingValue>"
@@ -26,6 +27,9 @@
# VK_DBG_LAYER_ACTION_CALLBACK - Call user defined callback function(s) that
# have been registered via the VK_EXT_LUNARG_debug_report extension. Since
# app must register callback, this is a NOOP for the settings file.
+# VK_DBG_LAYER_DEBUG_OUTPUT [Windows only] - Log a txt message using the Windows
+# OutputDebugString function -- messages will show up in Visual Studio output
+# window, for instance.
# VK_DBG_LAYER_ACTION_BREAK - Trigger a breakpoint.
#
# REPORT_FLAGS:
@@ -33,8 +37,9 @@
# <LayerIdentifier>.report_flags : This is a comma-delineated list of options telling
# the layer what types of messages it should report back. Options are:
# info - Report informational messages
-# warn - Report warnings of using the API in an unrecommended manner which may
-# also lead to undefined behavior
+# warn - Report warnings from using the API in a manner which may lead to undefined
+# behavior or to warn the user of common trouble spots. A warning does NOT
+# necessarily signify illegal application behavior.
# perf - Report using the API in a way that may cause suboptimal performance
# error - Report errors in API usage
# debug - For layer development. Report messages for debugging layer behavior
diff --git a/layers/vk_layer_utils.cpp b/layers/vk_layer_utils.cpp
index eafe236c..d028ca65 100644
--- a/layers/vk_layer_utils.cpp
+++ b/layers/vk_layer_utils.cpp
@@ -25,11 +25,11 @@
#include "vk_layer_config.h"
#include "vk_layer_utils.h"
-typedef struct _VULKAN_FORMAT_INFO {
+struct VULKAN_FORMAT_INFO {
size_t size;
uint32_t channel_count;
VkFormatCompatibilityClass format_class;
-} VULKAN_FORMAT_INFO;
+};
// Set up data structure with number of bytes and number of channels
// for each Vulkan format.
@@ -604,11 +604,20 @@ VkStringErrorFlags vk_string_validate(const int max_length, const char *utf8) {
return result;
}
+// Debug callbacks get created in three ways:
+// o Application-defined debug callbacks
+// o Through settings in a vk_layer_settings.txt file
+// o By default, if neither an app-defined debug callback nor a vk_layer_settings.txt file is present
+//
+// At layer initialization time, default logging callbacks are created to output layer error messages.
+// If a vk_layer_settings.txt file is present its settings will override any default settings.
+//
+// If a vk_layer_settings.txt file is present and an application defines a debug callback, both callbacks
+// will be active. If no vk_layer_settings.txt file is present, creating an application-defined debug
+// callback will cause the default callbacks to be unregisterd and removed.
void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugReportCallbackEXT> &logging_callback,
- const VkAllocationCallbacks *pAllocator, const char *layer_identifier) {
+ const VkAllocationCallbacks *pAllocator, const char *layer_identifier) {
- uint32_t report_flags = 0;
- uint32_t debug_action = 0;
VkDebugReportCallbackEXT callback = VK_NULL_HANDLE;
std::string report_flags_key = layer_identifier;
@@ -618,9 +627,11 @@ void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugRepo
debug_action_key.append(".debug_action");
log_filename_key.append(".log_filename");
- // initialize layer options
- report_flags = getLayerOptionFlags(report_flags_key.c_str(), 0);
- getLayerOptionEnum(debug_action_key.c_str(), (uint32_t *)&debug_action);
+ // Initialize layer options
+ VkDebugReportFlagsEXT report_flags = GetLayerOptionFlags(report_flags_key, report_flags_option_definitions, 0);
+ VkLayerDbgActionFlags debug_action = GetLayerOptionFlags(debug_action_key, debug_actions_option_definitions, 0);
+ // Flag as default if these settings are not from a vk_layer_settings.txt file
+ bool default_layer_callback = (debug_action & VK_DBG_LAYER_ACTION_DEFAULT) ? true : false;
if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) {
const char *log_filename = getLayerOption(log_filename_key.c_str());
@@ -631,10 +642,12 @@ void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugRepo
dbgCreateInfo.flags = report_flags;
dbgCreateInfo.pfnCallback = log_callback;
dbgCreateInfo.pUserData = (void *)log_output;
- layer_create_msg_callback(report_data, &dbgCreateInfo, pAllocator, &callback);
+ layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
logging_callback.push_back(callback);
}
+ callback = VK_NULL_HANDLE;
+
if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
VkDebugReportCallbackCreateInfoEXT dbgCreateInfo;
memset(&dbgCreateInfo, 0, sizeof(dbgCreateInfo));
@@ -642,7 +655,7 @@ void layer_debug_actions(debug_report_data *report_data, std::vector<VkDebugRepo
dbgCreateInfo.flags = report_flags;
dbgCreateInfo.pfnCallback = win32_debug_output_msg;
dbgCreateInfo.pUserData = NULL;
- layer_create_msg_callback(report_data, &dbgCreateInfo, pAllocator, &callback);
+ layer_create_msg_callback(report_data, default_layer_callback, &dbgCreateInfo, pAllocator, &callback);
logging_callback.push_back(callback);
}
}
diff --git a/layers/vk_validation_layer_details.md b/layers/vk_validation_layer_details.md
index d6bc7cc4..e026b138 100644
--- a/layers/vk_validation_layer_details.md
+++ b/layers/vk_validation_layer_details.md
@@ -36,8 +36,8 @@ The Draw State portion of the core validation layer tracks state leading into Dr
| Valid Command Buffer Reset | Can only reset individual command buffer that was allocated from a pool with VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT set | INVALID_COMMAND_BUFFER_RESET | vkBeginCommandBuffer vkResetCommandBuffer | CommandBufferResetErrors | None |
| PSO Bound | Verify that a properly created and valid pipeline object is bound to the CommandBuffer specified in these calls | NO_PIPELINE_BOUND | vkCmdBindDescriptorSets vkCmdBindVertexBuffers | PipelineNotBound | This check is currently more related to VK_LAYER_LUNARG_core_validation internal data structures and less about verifying that PSO is bound at all appropriate points in API. For API purposes, need to make sure this is checked at Draw time and any other relevant calls. |
| Valid DescriptorPool | Verifies that the descriptor set pool object was properly created and is valid | INVALID_POOL | vkResetDescriptorPool vkAllocateDescriptorSets | TODO | This is just an internal layer data structure check. VK_LAYER_LUNARG_parameter_validation or VK_LAYER_LUNARG_object_tracker should really catch bad DSPool |
-| Valid DescriptorSet | Validate that descriptor set was properly created and is currently valid | INVALID_SET | vkCmdBindDescriptorSets | TODO | Is this needed other places (like Update/Clear descriptors) |
-| Valid DescriptorSetLayout | Flag DescriptorSetLayout object that was not properly created | INVALID_LAYOUT | vkAllocateDescriptorSets | TODO | Anywhere else to check this? |
+| Valid DescriptorSet | Validate that descriptor set was properly created and is currently valid | INVALID_SET | vkCmdBindDescriptorSets | InvalidDescriptorSet | Is this needed other places (like Update/Clear descriptors) |
+| Valid DescriptorSetLayout | Flag DescriptorSetLayout object that was not properly created | INVALID_LAYOUT | vkAllocateDescriptorSets | InvalidDescriptorSetLayout | Anywhere else to check this? |
| Valid RenderArea | Flag renderArea field that is outside of the framebuffer | INVALID_RENDER_AREA | vkCmdBeginRenderPass | TODO | Anywhere else to check this? |
| Valid Pipeline | Flag VkPipeline object that was not properly created, or case when Draw/Dispatch is bound to cmd buffer without a pipeline being bound | INVALID_PIPELINE | vkCmdBindPipeline | InvalidPipeline | NA |
| Valid PipelineLayout | Flag VkPipelineLayout object that was not properly created | INVALID_PIPELINE_LAYOUT | vkCmdBindPipeline | TODO | Write test for this case |
@@ -51,24 +51,24 @@ The Draw State portion of the core validation layer tracks state leading into Dr
| Valid Secondary CommandBuffer | Validates that no primary command buffers are sent to vkCmdExecuteCommands() are | INVALID_SECONDARY_COMMAND_BUFFER | vkCmdExecuteCommands | ExecuteCommandsPrimaryCB | NA |
| Invalid Descriptor Set | Invalid Descriptor Set used. Either never created or already destroyed. | INVALID_DESCRIPTOR_SET | vkQueueSubmit | TODO | Create Test |
| Descriptor Type | Verify Descriptor type in bound descriptor set layout matches descriptor type specified in update. This also includes mismatches in the TYPES of copied descriptors. | DESCRIPTOR_TYPE_MISMATCH | vkUpdateDescriptorSets | DSTypeMismatch CopyDescriptorUpdateErrors | NA |
-| Descriptor StageFlags | Verify all descriptors within a single write update have the same stageFlags | DESCRIPTOR_STAGEFLAGS_MISMATCH | vkUpdateDescriptorSets | TODO | Test this case |
+| Descriptor StageFlags | Verify all descriptors within a single write update have the same stageFlags | DESCRIPTOR_STAGEFLAGS_MISMATCH | vkUpdateDescriptorSets | WriteDescriptorSetIntegrityCheck | |
| DS Update Size | DS update out of bounds for given layout section. | DESCRIPTOR_UPDATE_OUT_OF_BOUNDS | vkUpdateDescriptorSets | DSUpdateOutOfBounds CopyDescriptorUpdateErrors | NA |
| Descriptor Pool empty | Attempt to allocate descriptor type from descriptor pool when no more of that type are available to be allocated. | DESCRIPTOR_POOL_EMPTY | vkAllocateDescriptorSets | AllocDescriptorFromEmptyPool | NA |
| Free from NON_FREE Pool | It's invalid to call vkFreeDescriptorSets() on Sets that were allocated from a Pool created with NON_FREE usage. | CANT_FREE_FROM_NON_FREE_POOL | vkFreeDescriptorSets | TODO | NA |
-| DS Update Index | DS update binding too large for layout binding count. | INVALID_UPDATE_INDEX | vkUpdateDescriptorSets | InvalidDSUpdateIndex CopyDescriptorUpdateErrors | NA |
+| DS Update Index | DS update binding too large for layout binding count. | INVALID_UPDATE_INDEX | vkUpdateDescriptorSets | InvalidDSUpdateIndex CopyDescriptorUpdateErrors DSUsageBitsErrors | NA |
| DS Update Type | Verifies that structs in DS Update tree are properly created, currently valid, and of the right type | INVALID_UPDATE_STRUCT | vkUpdateDescriptorSets | InvalidDSUpdateStruct | NA |
| MSAA Sample Count | Verifies that Pipeline, RenderPass, and Subpass sample counts are consistent | NUM_SAMPLES_MISMATCH | vkCmdBindPipeline vkCmdBeginRenderPass vkCmdNextSubpass | NumSamplesMismatch | NA |
-| Dynamic Viewport State Binding | Verify that viewport dynamic state bound to Cmd Buffer at Draw time | VIEWPORT_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
-| Dynamic Scissor State Binding | Verify that scissor dynamic state bound to Cmd Buffer at Draw time | SCISSOR_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
-| Dynamic Line Width State Binding | Verify that line width dynamic state bound to Cmd Buffer at draw time when required | LINE_WIDTH_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
-| Dynamic Depth Bias State Binding | Verify that depth bias dynamic state bound when depth enabled | DEPTH_BIAS_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
-| Dynamic Blend State Binding | Verify that blend dynamic state bound when color blend enabled | BLEND_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
-| Dynamic Depth Bounds State Binding | Verify that depth bounds dynamic state bound when depth enabled | DEPTH_BOUNDS_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
-| Dynamic Stencil State Binding | Verify that stencil dynamic state bound when depth enabled | STENCIL_NOT_BOUND | vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStatesNotBound | NA |
+| Dynamic Viewport State Binding | Verify that viewport dynamic state bound to Cmd Buffer at Draw time | VIEWPORT_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicViewportNotBound | NA |
+| Dynamic Scissor State Binding | Verify that scissor dynamic state bound to Cmd Buffer at Draw time | SCISSOR_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicScissorNotBound | NA |
+| Dynamic Line Width State Binding | Verify that line width dynamic state bound to Cmd Buffer at draw time when required | LINE_WIDTH_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicLineWidthNotBound | NA |
+| Dynamic Depth Bias State Binding | Verify that depth bias dynamic state bound when depth enabled | DEPTH_BIAS_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicDepthBiasNotBound | NA |
+| Dynamic Blend State Binding | Verify that blend dynamic state bound when color blend enabled | BLEND_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamiBlendConstantsNotBound | NA |
+| Dynamic Depth Bounds State Binding | Verify that depth bounds dynamic state bound when depth enabled | DEPTH_BOUNDS_NOT_BOUND |vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicDepthBoundsNotBound | NA |
+| Dynamic Stencil State Binding | Verify that stencil dynamic state bound when depth enabled | STENCIL_NOT_BOUND | vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DynamicStencilReadNotBound DynamicStencilWriteNotBound DynamicStencilRefNotBound | NA |
| RenderPass misuse | Tests for the following: that vkCmdDispatch, vkCmdDispatchIndirect, vkCmdCopyBuffer, vkCmdCopyImage, vkCmdBlitImage, vkCmdCopyBufferToImage, vkCmdCopyImageToBuffer, vkCmdUpdateBuffer, vkCmdFillBuffer, vkCmdClearColorImage, vkCmdClearDepthStencilImage, vkCmdResolveImage, vkCmdSetEvent, vkCmdResetEvent, vkCmdResetQueryPool, vkCmdCopyQueryPoolResults, vkCmdBeginRenderPass, vkEndCommandBuffer are not called during an active Renderpass, and that binding compute descriptor sets or pipelines does not take place during an active Renderpass | INVALID_RENDERPASS_CMD | vkCmdBindPipeline vkCmdBindDescriptorSets vkCmdDispatch vkCmdDispatchIndirect vkCmdCopyBuffer vkCmdCopyImage vkCmdBlitImage vkCmdCopyBufferToImage vkCmdCopyImageToBuffer vkCmdUpdateBuffer vkCmdFillBuffer vkCmdClearColorImage vkCmdClearDepthStencilImage vkCmdResolveImage vkCmdSetEvent vkCmdResetEvent vkCmdResetQueryPool vkCmdCopyQueryPoolResults vkCmdBeginRenderPass vkEndCommandBuffer | RenderPassWithinRenderPass UpdateBufferWithinRenderPass ClearColorImageWithinRenderPass ClearDepthStencilImageWithinRenderPass FillBufferWithinRenderPass EndCommandBufferWithinRenderPass | NA |
| Correct use of RenderPass | Validates that the following rendering commands are issued inside an active RenderPass: vkCmdDraw, vkCmdDrawIndexed, vkCmdDrawIndirect, vkCmdDrawIndexedIndirect, vkCmdClearAttachments, vkCmdNextSubpass, vkCmdEndRenderPass | NO_ACTIVE_RENDERPASS | vkCmdBindPipeline vkCmdBindDescriptorSets vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect vkCmdClearAttachments vkCmdNextSubpass vkCmdEndRenderPass | ClearColorAttachmentsOutsideRenderPass | NA |
| Valid RenderPass | Flag error if attempt made to Begin/End/Continue a NULL or otherwise invalid RenderPass object | INVALID_RENDERPASS | vkCmdBeginRenderPass vkCmdEndRenderPass vkBeginCommandBuffer | NullRenderPass | NA |
-| RenderPass Compatibility | Verify that active renderpass is compatible with renderpass specified in secondary command buffer, and that renderpass specified for a framebuffer is compatible with renderpass specified in secondary command buffer | RENDERPASS_INCOMPATIBLE | vkCmdExecuteCommands vkBeginCommandBuffer | TODO | None |
+| RenderPass Compatibility | Verify that active renderpass is compatible with renderpass specified in secondary command buffer, and that renderpass specified for a framebuffer is compatible with renderpass specified in secondary command buffer. Also that parameters for BeginRenderpass are compatible with actual renderpass. | RENDERPASS_INCOMPATIBLE | vkCmdExecuteCommands vkBeginCommandBuffer vkCmdBeginRenderPass | RenderPassClearOpMismatch | Need to write some more tests to cover all of these cases. |
| Framebuffer Compatibility | If a framebuffer is passed to secondary command buffer in vkBeginCommandBuffer, then it must match active renderpass (if any) at time of vkCmdExecuteCommands | FRAMEBUFFER_INCOMPATIBLE | vkCmdExecuteCommands | TODO | None |
| DescriptorSet Updated | Warn user if DescriptorSet bound that was never updated and is not empty. Trigger error at draw time if a set being used was never updated. | DESCRIPTOR_SET_NOT_UPDATED | vkCmdBindDescriptorSets vkCmdDraw vkCmdDrawIndexed vkCmdDrawIndirect vkCmdDrawIndexedIndirect | DescriptorSetCompatibility | NA |
| DescriptorSet Bound | Error if DescriptorSet not bound that is used by currently bound VkPipeline at draw time | DESCRIPTOR_SET_NOT_BOUND | vkCmdBindDescriptorSets | DescriptorSetNotUpdated | NA |
@@ -79,11 +79,11 @@ The Draw State portion of the core validation layer tracks state leading into Dr
| Viewport and Scissors match | In PSO viewportCount and scissorCount must match. Also for each count that is non-zero, there corresponding data array ptr should be non-NULL. | VIEWPORT_SCISSOR_MISMATCH | vkCreateGraphicsPipelines vkCmdSetViewport vkCmdSetScissor | TODO | Implement validation test |
| Valid Image Aspects for descriptor Updates | When updating ImageView for Descriptor Sets with layout of DEPTH_STENCIL type, the Image Aspect must not have both the DEPTH and STENCIL aspects set, but must have one of the two set. For COLOR_ATTACHMENT, aspect must have COLOR_BIT set. | INVALID_IMAGE_ASPECT | vkUpdateDescriptorSets | DepthStencilImageViewWithColorAspectBitError | This test hits Image layer error, but tough to create case that that skips that error and gets to VK_LAYER_LUNARG_core_validaton draw state error. |
| Valid sampler descriptor Updates | An invalid sampler is used when updating SAMPLER descriptor. | SAMPLER_DESCRIPTOR_ERROR | vkUpdateDescriptorSets | SampleDescriptorUpdateError | Currently only making sure sampler handle is known, can add further validation for sampler parameters |
-| Immutable sampler update consistency | Within a single write update, all sampler updates must use either immutable samplers or non-immutable samplers, but not a combination of both. | INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE | vkUpdateDescriptorSets | TODO | Write a test for this case |
+| Immutable sampler update consistency | Within a single write update, all sampler updates must use either immutable samplers or non-immutable samplers, but not a combination of both. | INCONSISTENT_IMMUTABLE_SAMPLER_UPDATE | vkUpdateDescriptorSets | WriteDescriptorSetIntegrityCheck | |
| Valid imageView descriptor Updates | An invalid imageView is used when updating *_IMAGE or *_ATTACHMENT descriptor. | IMAGEVIEW_DESCRIPTOR_ERROR | vkUpdateDescriptorSets | ImageViewDescriptorUpdateError | Currently only making sure imageView handle is known, can add further validation for imageView and underlying image parameters |
| Valid bufferView descriptor Updates | An invalid bufferView is used when updating *_TEXEL_BUFFER descriptor. | BUFFERVIEW_DESCRIPTOR_ERROR | vkUpdateDescriptorSets | InvalidBufferViewObject | Currently only making sure bufferView handle is known, can add further validation for bufferView parameters |
-| Valid bufferInfo descriptor Updates | An invalid bufferInfo is used when updating *_UNIFORM_BUFFER* or *_STORAGE_BUFFER* descriptor. | BUFFERINFO_DESCRIPTOR_ERROR | vkUpdateDescriptorSets | TODO | Implement validation test |
-| Attachment References in Subpass | Attachment reference must be present in active subpass | MISSING_ATTACHMENT_REFERENCE | vkCmdClearAttachments | TODO | Currently only making sure bufferInfo has buffer whose handle is known, can add further validation for bufferInfo parameters |
+| Valid bufferInfo descriptor Updates | An invalid bufferInfo is used when updating *_UNIFORM_BUFFER* or *_STORAGE_BUFFER* descriptor. | BUFFERINFO_DESCRIPTOR_ERROR | vkUpdateDescriptorSets | WriteDescriptorSetIntegrityCheck | |
+| Attachment References in Subpass | Attachment reference must be present in active subpass | MISSING_ATTACHMENT_REFERENCE | vkCmdClearAttachments | MissingClearAttachment | Currently only making sure bufferInfo has buffer whose handle is known, can add further validation for bufferInfo parameters |
| Verify Image Layouts | Validate correct image layouts for presents, image transitions, command buffers and renderpasses | INVALID_IMAGE_LAYOUT | vkCreateRenderPass vkMapMemory vkQueuePresentKHR vkQueueSubmit vkCmdCopyImage vkCmdCopyImageToBuffer vkCmdWaitEvents VkCmdPipelineBarrier | InvalidImageLayout MapMemWithoutHostVisibleBit | None |
| Verify Memory Access Flags/Memory Barriers | Validate correct access flags for memory barriers | INVALID_BARRIER | vkCmdWaitEvents vkCmdPipelineBarrier | InvalidBarriers | None |
| Verify Memory Buffer Not Deleted | Validate Command Buffer not submitted with deleted memory buffer | INVALID_BUFFER | vkQueueSubmit | TODO | None |
@@ -103,20 +103,16 @@ The Draw State portion of the core validation layer tracks state leading into Dr
| Valid Logic Operations | If logicOpEnable is VK_TRUE, logicOp must be a valid VkLogicOp value | INVALID_LOGIC_OP | vkCreateGraphicsPipelines | TODO | Create test |
| QueueFamilyIndex is Valid | Validates that QueueFamilyIndices are less an the number of QueueFamilies | INVALID_QUEUE_INDEX | vkCmdWaitEvents vkCmdPipelineBarrier vkCreateBuffer vkCreateImage | TODO | Create test |
| Push Constants | Validate that the size of push constant ranges and updates does not exceed maxPushConstantSize | PUSH_CONSTANTS_ERROR | vkCreatePipelineLayout vkCmdPushConstants | TODO | Create test |
+| Attachment Image Usage | Validate that Image attachment location does not conflict with the image's USAGE flags | INVALID_IMAGE_USAGE | vkCreateFramebuffer | AttachmentUsageMismatch | NA |
+| Attachment Image Index | Validate that Image attachment references are appropriate and not out-of-bounds | INVALID_ATTACHMENT_INDEX | vkCreateRenderPass vkCreateFramebuffer | UnusedPreserveAttachment | NA |
| NA | Enum used for informational messages | NONE | | TODO | None |
| NA | Enum used for errors in the layer itself. This does not indicate an app issue, but instead a bug in the layer. | INTERNAL_ERROR | | TODO | None |
| NA | Enum used when VK_LAYER_LUNARG_core_validation attempts to allocate memory for its own internal use and is unable to. | OUT_OF_MEMORY | | TODO | None |
| NA | Enum used when VK_LAYER_LUNARG_core_validation attempts to allocate memory for its own internal use and is unable to. | OUT_OF_MEMORY | | TODO | None |
### VK_LAYER_LUNARG_core_validation Draw State Pending Work
-Additional Draw State-related checks to be added:
- 1. Lifetime validation (See [bug 13383](https://cvs.khronos.org/bugzilla/show_bug.cgi?id=13383))
- 2. GetRenderAreaGranularity - The pname:renderPass parameter must be the same as the one given in the sname:VkRenderPassBeginInfo structure for which the render area is relevant.
- 3. Update Gfx Pipe Create Info shadowing to remove new/delete and instead use unique_ptrs for auto clean-up
- 4. Add validation for Pipeline Derivatives (see Pipeline Derivatives) section of the spec
-
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
### VK_LAYER_LUNARG_core_validation Shader Checker Details Table
@@ -144,10 +140,8 @@ It flags errors when inconsistencies are found across interfaces between shader
| NA | Enum used for informational messages | NONE | | TODO | None |
### VK_LAYER_LUNARG_core_validation Shader Checker Pending Work
-- Additional test cases for variously broken SPIRV images
-- Validation of a single SPIRV image in isolation (the spec describes many constraints)
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
### VK_LAYER_LUNARG_core_validation Memory Tracker Details Table
The Mem Tracker portion of the VK_LAYER_LUNARG_core_validation layer tracks memory objects and references and validates that they are managed correctly by the application. This includes tracking object bindings, memory hazards, and memory object lifetimes. Several other hazard-related issues related to command buffers, fences, and memory mapping are also validated in this layer segment.
@@ -166,16 +160,13 @@ The Mem Tracker portion of the VK_LAYER_LUNARG_core_validation layer tracks memo
| Immutable Memory Binding | Validates that non-sparse memory bindings are immutable, so objects are not re-boundt | REBIND_OBJECT | vkBindBufferMemory, vkBindImageMemory | RebindMemory | NA |
| Image/Buffer Usage bits | Verify correct USAGE bits set based on how Images and Buffers are used | INVALID_USAGE_FLAG | vkCreateImage, vkCreateBuffer, vkCreateBufferView, vkCmdCopyBuffer, vkCmdCopyQueryPoolResults, vkCmdCopyImage, vkCmdBlitImage, vkCmdCopyBufferToImage, vkCmdCopyImageToBuffer, vkCmdUpdateBuffer, vkCmdFillBuffer | InvalidUsageBits | NA |
| Memory Map Range Checks | Validates that Memory Mapping Requests are valid for the Memory Object (in-range, not currently mapped on Map, currently mapped on UnMap, size is non-zero) | INVALID_MAP | vkMapMemory | InvalidMemoryMapping | NA |
+| Memory Type Index Checks | Validates that specified memory type indices are valid | INVALID_MEM_TYPE | vkBindImageMemory vkBindBufferMemory | BindImageInvalidMemoryType | NA |
| NA | Enum used for informational messages | NONE | | TODO | None |
| NA | Enum used for errors in the layer itself. This does not indicate an app issue, but instead a bug in the layer. | INTERNAL_ERROR | | TODO | None |
### VK_LAYER_LUNARG_core_validation Memory Tracker Pending Work and Enhancements
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
-1. Consolidate error messages and make them consistent
-2. Add validation for maximum memory references, maximum object counts, and object leaks
-3. Warn on image/buffer deletion if USAGE bits were set that were not needed
-4. Modify INVALID_FENCE_STATE to be WARNINGs instead of ERROR
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_LUNARG_parameter_validation
@@ -187,7 +178,7 @@ The VK_LAYER_LUNARG_parameter_validation layer validates parameter values and fl
| Check | Overview | ENUM * | Relevant API | Testname | Notes/TODO |
| ----- | -------- | ---------------- | ------------ | -------- | ---------- |
-| Valid Usage | Verifies that the value of a parameter is consistent with the valid usage criteria defined in the Vulkan specification | INVALID_USAGE | | TODO | NA |
+| Valid Usage | Verifies that the value of a parameter is consistent with the valid usage criteria defined in the Vulkan specification | INVALID_USAGE | vkCmdUpdateBuffer vkCmdFillBuffer | FillBufferAlignment UpdateBufferAlignment | NA |
| Valid VkStructureType Value | Verifies that the sType field of a Vulkan structure contains the value expected for a structure of that type | INVALID_STRUCT_STYPE | | InvalidStructSType | NA |
| Valid Structure pNext Value | Verifies that the pNext field of a Vulkan structure references a value that is compatible with a structure of that type or is NULL when a structure of that type has no compatible pNext values | INVALID_STRUCT_PNEXT | | InvalidStructPNext | NA |
| Required Parameter | Verifies that a required parameter was not specified as 0 or NULL | REQUIRED_PARAMETER | | RequiredParameter | NA |
@@ -197,19 +188,8 @@ The VK_LAYER_LUNARG_parameter_validation layer validates parameter values and fl
| NA | Enum used for informational messages | NONE | | TODO | None |
### VK_LAYER_LUNARG_parameter_validation Pending Work
-Additional work to be done
-
- 1. Source2 was creating a VK_FORMAT_R8_SRGB texture (and image view) which was not supported by the underlying implementation (rendersystemtest imageformat test). Checking that formats are supported by the implementation is something the validation layer could do using the VK_FORMAT_INFO_TYPE_PROPERTIES query. There are probably a bunch of checks here you could be doing around vkCreateImage formats along with whether image/color/depth attachment views are valid. I’m not sure how much of this is already there.
- 2. From AMD: we were using an image view with a swizzle of VK_COLOR_COMPONENT_FORMAT_A with a BC1_RGB texture, which is not valid because the texture does not have an alpha channel. In general, should validate that the swizzles do not reference components not in the texture format.
- 3. When querying VK_PHYSICAL_DEVICE_INFO_TYPE_QUEUE_PROPERTIES must provide enough memory for all the queues on the device (not just 1 when device has multiple queues).
- 4. INT & FLOAT bordercolors. Border color int/float selection must match associated texture format.
- 5. Flag error on VkBufferCreateInfo if buffer size is 0
- 6. VkImageViewCreateInfo.format must be set
- 7. For vkCreateGraphicsPipelines, correctly handle array of pCreateInfos and array of pStages within each element of pCreatInfos
- 8. Check for valid VkIndexType in vkCmdBindIndexBuffer() should be in PreCmdBindIndexBuffer() call
- 9. Check for valid VkPipelineBindPoint in vkCmdBindPipeline() & vkCmdBindDescriptorSets() should be in PreCmdBindPipeline() & PreCmdBindDescriptorSets() calls respectively.
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_LUNARG_image
@@ -232,16 +212,18 @@ DETAILS TABLE PENDING
| Image Type Mismatch | Verify that Image commands with source and dest images use matching types | MISMATCHED_IMAGE_TYPE | vkCmdCopyImage vkCmdResolveImage | ResolveImageTypeMismatch | NA |
| Image Format Mismatch | Verify that Image commands with source and dest images use matching formats | MISMATCHED_IMAGE_FORMAT | vkCmdCopyImage vkCmdResolveImage | CopyImageDepthStencilFormatMismatch ResolveImageFormatMismatch | NA |
| Resolve Sample Count | Verifies that source and dest images sample counts are valid | INVALID_RESOLVE_SAMPLES | vkCmdResolveImage | ResolveImageHighSampleCount ResolveImageLowSampleCount | NA |
-| Verify Format | Verifies the formats are valid for this image operation | INVALID_FORMAT | vkCreateImageView vkCmdBlitImage | ImageLayerViewTests | NA |
+| Verify Format | Verifies the formats are valid for this image operation | INVALID_FORMAT | vkCreateImageView vkCmdBlitImage | ImageLayerViewTests ClearImageErrors | NA |
| Verify Correct Image Filter| Verifies that specified filter is valid | INVALID_FILTER | vkCmdBlitImage | MiscImageLayerTests | NA |
| Verify Correct Image Settings | Verifies that values are valid for a given resource or subresource | INVALID_IMAGE_RESOURCE | vkCmdPipelineBarrier | MiscImageLayerTests | NA |
| Verify Image Format Limits | Verifies that image creation parameters are with the device format limits | INVALID_FORMAT_LIMITS_VIOLATION | vkCreateImage | ImageFormatLimits | NA |
| Verify Layout | Verifies the layouts are valid for this image operation | INVALID_LAYOUT | vkCreateImage vkCmdClearColorImage | TODO | ImageFormatLimits |
| Verify Image Extents | Validates that image extent limits are not invalid | INVALID_EXTENTS | vkCmdCopyImage | CopyImageLayerCountMismatch | NA |
+| Verify Usage | Verifies the image was created with usage valid for this image operation | INVALID_USAGE | vkCmdClearColorImage | TODO | ClearImageErrors |
| NA | Enum used for informational messages | NONE | | TODO | None |
### VK_LAYER_LUNARG_image Pending Work
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_LUNARG_object_tracker
@@ -263,12 +245,7 @@ The VK_LAYER_LUNARG_object_tracker layer maintains a record of all Vulkan object
### VK_LAYER_LUNARG_object_tracker Pending Work
- 1. Verify images have CmdPipelineBarrier layouts matching new layout parameters to Cmd*Image* functions
- 2. For specific object instances that are allowed to be NULL, update object validation to verify that such objects are either NULL or valid
- 3. Verify cube array VkImageView objects use subresourceRange.arraySize (or effective arraySize when VK_REMAINING_ARRAY_SLICES is specified) that is a multiple of 6.
- 4. Make object maps specific to instance and device. Objects may only be used with matching instance or device.
-
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_GOOGLE_threading
@@ -304,7 +281,8 @@ It cannot insure that there is no latent race condition.
| NA | Enum used for informational messages | NONE | | TODO | None |
### VK_LAYER_GOOGLE_threading Pending Work
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_LUNARG_device_limits
@@ -325,22 +303,19 @@ For the second category of errors, VK_LAYER_LUNARG_device_limits stores its own
| Valid physical device | Enum used for informational messages | INVALID_PHYSICAL_DEVICE | vkEnumeratePhysicalDevices | TODO | VK_LAYER_LUNARG_object_tracker should also catch this so if we made sure VK_LAYER_LUNARG_object_tracker was always on top, we could avoid this check |
| Valid inherited query | If an invalid inherited query is used, this error will be flagged | INVALID_INHERITED_QUERY | vkBeginCommandBuffer | TODO | None |
| Valid attachment count | If the number of attachments exceeds the device max, this error will be flagged | INVALID_ATTACHMENT_COUNT | vkCreateRenderPass | TODO | None |
+| Query count checked | Signifies that a query call such as vkEnumeratePhysicalDevices or vkGetPhysicalDeviceQueueFamilyProperties has been called without querying the count | MISSING_QUERY_COUNT | vkEnumeratePhysicalDevices vkGetPhysicalDeviceQueueFamilyProperties | TODO | None |
| Querying array counts | For API calls where an array count should be queried with an initial call and a NULL array pointer, verify that such a call was made before making a call with non-null array pointer. | MUST_QUERY_COUNT | vkEnumeratePhysicalDevices vkGetPhysicalDeviceQueueFamilyProperties | TODO | Create focused test |
| Array count value | For API calls where an array of details is queried, verify that the size of the requested array matches the size of the array supported by the device. | COUNT_MISMATCH | vkEnumeratePhysicalDevices vkGetPhysicalDeviceQueueFamilyProperties | TODO | Create focused test |
| Queue Creation | When creating/requesting queues, make sure that QueueFamilyPropertiesIndex and index/count within that queue family are valid. | INVALID_QUEUE_CREATE_REQUEST | vkGetDeviceQueue vkCreateDevice | TODO | Create focused test |
| API Call Sequencing | This is a general error indicating that an app did not use vkGetPhysicalDevice* and other such query calls, but rather made an assumption about device capabilities. | INVALID_CALL_SEQUENCE | vkCreateDevice | TODO | Add validation test |
| Feature Request | Attempting to vkCreateDevice with a feature that is not supported by the underlying physical device. | INVALID_FEATURE_REQUESTED | vkCreateDevice | TODO | Add validation test |
-| Alignment | When updating a buffer, data should be aligned on 4 byte boundaries | INVALID_BUFFER_UPDATE_ALIGNMENT | vkCmdUpdateBuffer | UpdateBufferAlignment | NA |
-| Alignment | When filling a buffer, data should be aligned on 4 byte boundaries | INVALID_BUFFER_UPDATE_ALIGNMENT | vkCmdFillBuffer | UpdateBufferAlignment | NA |
| Storage Buffer Alignment | Storage Buffer offsets must agree with offset alignment device limit | INVALID_STORAGE_BUFFER_OFFSET | vkBindBufferMemory vkUpdateDescriptorSets | TODO | Create test |
| Uniform Buffer Alignment | Uniform Buffer offsets must agree with offset alignment device limit | INVALID_UNIFORM_BUFFER_OFFSET | vkBindBufferMemory vkUpdateDescriptorSets | TODO | Create test |
| NA | Enum used for informational messages | NONE | | TODO | None |
### VK_LAYER_LUNARG_device_limits Pending Work
- 1. For all Formats, call vkGetPhysicalDeviceFormatProperties to pull their properties for the underlying device. After that point, if the app attempts to use any formats in violation of those properties, flag errors (this is done for Images).
-
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_LUNARG_swapchain
@@ -363,7 +338,7 @@ This layer is a work in progress. VK_LAYER_LUNARG_swapchain layer is intended to
| vkCreateSwapchainKHR(pCreateInfo->imageExtent) | Validates vkCreateSwapchainKHR(pCreateInfo->imageExtent) when window has a fixed size | CREATE_SWAP_EXTENTS_NO_MATCH_WIN | vkCreateSwapchainKHR | TODO | None |
| vkCreateSwapchainKHR(pCreateInfo->preTransform) | Validates vkCreateSwapchainKHR(pCreateInfo->preTransform) | CREATE_SWAP_BAD_PRE_TRANSFORM | vkCreateSwapchainKHR | TODO | None |
| vkCreateSwapchainKHR(pCreateInfo->compositeAlpha) | Validates vkCreateSwapchainKHR(pCreateInfo->compositeAlpha) | CREATE_SWAP_BAD_COMPOSITE_ALPHA | vkCreateSwapchainKHR | TODO | None |
-| vkCreateSwapchainKHR(pCreateInfo->imageArraySize) | Validates vkCreateSwapchainKHR(pCreateInfo->imageArraySize) | CREATE_SWAP_BAD_IMG_ARRAY_SIZE | vkCreateSwapchainKHR | TODO | None |
+| vkCreateSwapchainKHR(pCreateInfo->imageArrayLayers) | Validates vkCreateSwapchainKHR(pCreateInfo->imageArrayLayers) | CREATE_SWAP_BAD_IMG_ARRAY_LAYERS | vkCreateSwapchainKHR | TODO | None |
| vkCreateSwapchainKHR(pCreateInfo->imageUsageFlags) | Validates vkCreateSwapchainKHR(pCreateInfo->imageUsageFlags) | CREATE_SWAP_BAD_IMG_USAGE_FLAGS | vkCreateSwapchainKHR | TODO | None |
| vkCreateSwapchainKHR(pCreateInfo->imageColorSpace) | Validates vkCreateSwapchainKHR(pCreateInfo->imageColorSpace) | CREATE_SWAP_BAD_IMG_COLOR_SPACE | vkCreateSwapchainKHR | TODO | None |
| vkCreateSwapchainKHR(pCreateInfo->imageFormat) | Validates vkCreateSwapchainKHR(pCreateInfo->imageFormat) | CREATE_SWAP_BAD_IMG_FORMAT | vkCreateSwapchainKHR | TODO | None |
@@ -403,24 +378,11 @@ Note: The following platform-specific functions are not mentioned above, because
- vkGetPhysicalDeviceXlibPresentationSupportKHR
### VK_LAYER_LUNARG_Swapchain Pending Work
-Additional checks to be added to VK_LAYER_LUNARG_swapchain
-
- 1. Check that the queue used for presenting was checked/valid during vkGetPhysicalDeviceSurfaceSupportKHR.
- 2. One issue that has already come up is correct UsageFlags for WSI SwapChains and SurfaceProperties.
- 3. Tons of other stuff including semaphore and synchronization validation.
- See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
+See the Khronos github repository for Vulkan-LoaderAndValidationLayers for additional pending issues, or to submit new validation requests
## VK_LAYER_GOOGLE_unique_objects
### VK_LAYER_GOOGLE_unique_objects Overview
-The unique_objects is not a validation layer but a helper layer that assists with validation. The Vulkan specification allows objects that have non-unique handles. This makes tracking object lifetimes difficult in that it is unclear which object is being referenced upon deletion. The unique_objects layer addresses this by wrapping all objects with a unique object representation allowing proper object lifetime tracking. This layer does no validation on its own and may not be required for the proper operation of all layers or all platforms. One sign that it is needed is the appearance of many errors from the object_tracker layer indicating the use of previously destroyed objects. For optimal effectiveness this layer should be loaded last (to reside in the layer chain closest to the display driver and farthest from the application).
-
-
-## General Pending Work
-A place to capture general validation work to be done. This includes new checks that don't clearly fit into the above layers.
-
- 1. For Upcoming Dynamic State overhaul (if approved): If dynamic state value that is consumed is never set prior to consumption, flag an error
- 2. For Upcoming Dynamic State overhaul (if approved): If dynamic state that was bound as "static" in current PSO is attempted to be set with vkCmdSet* flag an error
- 3. Need to check VkShaderCreateInfo.stage is being set properly (Issue reported by Dan G)
+The unique_objects utility layer that assists with validation. The Vulkan specification allows objects to have non-unique handles. This makes tracking object lifetimes difficult in that it is unclear which object is being referenced upon deletion. The unique_objects layer addresses this by aliasing all objects with a unique identifier allowing proper object lifetime tracking. This layer does no validation on its own and may not be required for the proper operation of all layers or all platforms. One sign that it is needed is the appearance of many errors from the object_tracker layer indicating the use of previously destroyed objects. For optimal effectiveness this layer should be loaded last (to reside in the layer chain closest to the display driver and farthest from the application).
diff --git a/layers/windows/VkLayer_core_validation.json b/layers/windows/VkLayer_core_validation.json
index 01139ae6..bbb38aae 100644
--- a/layers/windows/VkLayer_core_validation.json
+++ b/layers/windows/VkLayer_core_validation.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_core_validation",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_core_validation.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_device_limits.json b/layers/windows/VkLayer_device_limits.json
index 71d5ca9e..e5e437de 100644
--- a/layers/windows/VkLayer_device_limits.json
+++ b/layers/windows/VkLayer_device_limits.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_device_limits",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_device_limits.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_image.json b/layers/windows/VkLayer_image.json
index 58f64731..39b7d238 100644
--- a/layers/windows/VkLayer_image.json
+++ b/layers/windows/VkLayer_image.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_image",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_image.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_object_tracker.json b/layers/windows/VkLayer_object_tracker.json
index 1f539049..7cb22f90 100644
--- a/layers/windows/VkLayer_object_tracker.json
+++ b/layers/windows/VkLayer_object_tracker.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_object_tracker",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_object_tracker.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_parameter_validation.json b/layers/windows/VkLayer_parameter_validation.json
index 496945be..72c5cb6f 100644
--- a/layers/windows/VkLayer_parameter_validation.json
+++ b/layers/windows/VkLayer_parameter_validation.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_parameter_validation",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_parameter_validation.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_swapchain.json b/layers/windows/VkLayer_swapchain.json
index 53f749ed..a93b5da0 100644
--- a/layers/windows/VkLayer_swapchain.json
+++ b/layers/windows/VkLayer_swapchain.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_LUNARG_swapchain",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_swapchain.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "LunarG Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_threading.json b/layers/windows/VkLayer_threading.json
index a915ea14..53e96e26 100644
--- a/layers/windows/VkLayer_threading.json
+++ b/layers/windows/VkLayer_threading.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_GOOGLE_threading",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_threading.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "Google Validation Layer",
"instance_extensions": [
diff --git a/layers/windows/VkLayer_unique_objects.json b/layers/windows/VkLayer_unique_objects.json
index e77e4377..bdcde04f 100644
--- a/layers/windows/VkLayer_unique_objects.json
+++ b/layers/windows/VkLayer_unique_objects.json
@@ -2,9 +2,9 @@
"file_format_version" : "1.0.0",
"layer" : {
"name": "VK_LAYER_GOOGLE_unique_objects",
- "type": "INSTANCE",
+ "type": "GLOBAL",
"library_path": ".\\VkLayer_unique_objects.dll",
- "api_version": "1.0.11",
+ "api_version": "1.0.16",
"implementation_version": "1",
"description": "Google Validation Layer"
}
diff --git a/loader/CMakeLists.txt b/loader/CMakeLists.txt
index d9f99cc1..15577b8a 100644
--- a/loader/CMakeLists.txt
+++ b/loader/CMakeLists.txt
@@ -17,6 +17,7 @@ set(NORMAL_LOADER_SRCS
loader.c
loader.h
vk_loader_platform.h
+ vk_loader_layer.h
trampoline.c
wsi.c
wsi.h
@@ -37,6 +38,14 @@ set (OPT_LOADER_SRCS
set (LOADER_SRCS ${NORMAL_LOADER_SRCS} ${OPT_LOADER_SRCS})
if (WIN32)
+ # 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()
+
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_CRT_SECURE_NO_WARNINGS")
# Build dev_ext_trampoline.c with -O2 to allow tail-call optimization.
# Build other C files with normal options
@@ -72,6 +81,6 @@ else()
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wpointer-arith")
add_library(vulkan SHARED ${LOADER_SRCS})
- set_target_properties(vulkan PROPERTIES SOVERSION "1" VERSION "1.0.12")
+ set_target_properties(vulkan PROPERTIES SOVERSION "1" VERSION "1.0.13")
target_link_libraries(vulkan -ldl -lpthread -lm)
endif()
diff --git a/loader/LoaderAndLayerInterface.md b/loader/LoaderAndLayerInterface.md
index 91094a06..e11923a8 100644
--- a/loader/LoaderAndLayerInterface.md
+++ b/loader/LoaderAndLayerInterface.md
@@ -151,24 +151,26 @@ Vulkan commands, but may offer extensions that do. A common use of layers is
for API validation. A developer can use validation layers during application
development, but during production the layers can be disabled by the
application. Thus, eliminating the overhead of validating the application's
-usage of the API. Layers discovered by the loader can be reported to the
-application via vkEnumerateInstanceLayerProperties and
-vkEnumerateDeviceLayerProperties, for instance and device layers respectively.
-Instance layers are enabled at vkCreateInstance; device layers are enabled at
-vkCreateDevice. For example, the ppEnabledLayerNames array in the
-VkDeviceCreateInfo structure is used by the application to list the device
-layer names to be enabled at vkCreateDevice. At vkCreateInstance and
+usage of the API. Layers discovered by the loader are reported to the
+application via vkEnumerateInstanceLayerProperties.
+Layers are enabled at vkCreateInstance and are active for all Vulkan commands
+that using the given VkIstance and any of it's child objects.
+For example, the ppEnabledLayerNames array in the
+VkInstanceCreateInfo structure is used by the application to list the
+layer names to be enabled at vkCreateInstance. At vkCreateInstance and
vkCreateDevice, the loader will construct call chains that include the
-application specified (enabled) layers. Order is important in the
+application specified (enabled) layers. vkCreateDevice will use the layers
+specified at vkCreateInstance. vkEnumerateDeviceLayerProperties and
+device layers are deprecated. Order is important in the
ppEnabledLayerNames array; array element 0 is the topmost (closest to the
application) layer inserted in the chain and the last array element is closest
to the driver.
Developers may want to enable layers that are not enabled by the given
-application they are using. On Linux and Windows, the environment variables
-“VK\_INSTANCE\_LAYERS” and “VK\_DEVICE\_LAYERS” can be used to enable
+application they are using. On Linux and Windows, the environment variable
+“VK\_INSTANCE\_LAYERS” can be used to enable
additional layers which are not specified (enabled) by the application at
-vkCreateInstance/vkCreateDevice. VK\_INSTANCE\_LAYERS is a colon
+vkCreateInstance. VK\_INSTANCE\_LAYERS is a colon
(Linux)/semi-colon (Windows) separated list of layer names to enable. Order is
relevant with the first layer in the list being the topmost layer (closest to
the application) and the last layer in the list being the bottommost layer
@@ -180,20 +182,13 @@ layers. Layers specified via environment variable are topmost (closest to the
application) while layers specified by the application are bottommost.
An example of using these environment variables to activate the validation
-layer VK\_LAYER\_LUNARG\_param\_checker on Windows or Linux is as follows:
+layer VK\_LAYER\_LUNARG\_parameter\_validation on Windows or Linux is as follows:
```
> $ export VK_INSTANCE_LAYERS=VK_LAYER_LUNARG_parameter_validation
-> $ export VK_DEVICE_LAYERS=VK_LAYER_LUNARG_parameter_validation
```
-**Note**: Many layers, including all LunarG validation layers are “global”
-(i.e. both instance and device) layers and *must* be enabled on both the
-instance and device chains to function properly. This is required for “global”
-layers regardless of which method is used to enable the layer (application or
-environment variable).
-
Some platforms, including Linux and Windows, support layers which are enabled
automatically by the loader rather than explicitly by the application (or via
environment variable). Explicit layers are those layers enabled by the
@@ -698,6 +693,7 @@ Vulkan layer interface with the loader
#### Windows
+<a name="ManifestFileExample"></a>
##### Properly-Installed Layers
In order to find properly-installed layers, the Vulkan loader will use a
@@ -737,105 +733,47 @@ full pathname to the manifest file.
The Vulkan loader will open each info file to obtain information about the
layer, including the name or pathname of a shared library (".dll") file.
-This manifest file is in the JSON format and contains the following
-information:
-
-- (required) "file\_format\_version" - same as for ICDs, except that the format
-version can vary independently for ICDs and layers.
-
-- (required) "name" - layer name
-
-- (required) "type" - which layer chains should the layer be activated on.
-Allowable values are "INSTANCE", "DEVICE", "GLOBAL". Global means activate on
-both device and instance chains.
-
-- (required) "library\_path" - filename / full path / relative path to the
-library file
-
-- (required) "api\_version" - same as for ICDs.
-
-- (required) "implementation\_version" - layer version, a single number
-increasing with backward compatible changes.
-
-- (required) "description" - informative description of the layer.
-
-- (optional) "device\_extensions" or "instance\_extensions" - array of
-extension information as follows
-
- - (required) extension "name" - Vulkan registered name
-
- - (required) extension "spec\_version" - extension specification version, a
-single number, increasing with backward compatible changes.
-
- - (required for device\_extensions with entry points) extension
-"entrypoints" - array of device extension entry points; not used for instance
-extensions
-
-- (sometimes required) "functions" - mapping list of function entry points. If
-multiple layers exist within the same shared library (or if a layer is in the
-same shared library as an ICD), this must be specified to allow each layer to
-have its own vkGet\*ProcAddr entry points that can be found by the loader. At
-this time, only the following two functions are required:
-
- - "vkGetInstanceProcAddr" name
-
- - "vkGetDeviceProcAddr" name
-
-- (optional for implicit layers) "enable\_environment" requirement(s) -
-environment variable and value required to enable an implicit layer. This
-environment variable (which should vary with each "version" of the layer, as in
-"ENABLE\_LAYER\_FOO\_1") must be set to the given value or else the implicit
-layer is not loaded. This is for application environments (e.g. Steam) which
-want to enable a layer(s) only for applications that they launch, and allows
-for applications run outside of an application environment to not get that
-implicit layer(s).
-
-- (required for implicit layers) "disable\_environment" requirement(s) -
-environment variable and value required to disable an implicit layer. Note: in
-rare cases of an application not working with an implicit layer, the
-application can set this environment variable (before calling Vulkan functions)
-in order to "blacklist" the layer. This environment variable (which should vary
-with each "version" of the layer, as in "DISABLE\_LAYER\_FOO\_1") must be set
-(not particularly to any value). If both the "enable\_environment" and
-"disable\_environment" variables are set, the implicit layer is disabled.
-
-For example:
+This manifest file is in the JSON format as shown in the following example.
+See the section [Layer Library Manifest File](#LayerLibraryManifestFile) for more information about each of the nodes in the JSON file.
```
{
-"file_format_version" : "1.0.0",
-"layer": {
- "name": "VK_LAYER_LUNARG_OverlayLayer",
- "type": "DEVICE",
- "library_path": "vkOverlayLayer.dll"
- "api_version" : "1.0.5",
- "implementation_version" : "2",
- "description" : "LunarG HUD layer",
- "functions": {
- "vkGetInstanceProcAddr": "OverlayLayer_GetInstanceProcAddr",
- "vkGetDeviceProcAddr": "OverlayLayer_GetDeviceProcAddr"
- },
- "instance_extensions": [
- {
- "name": "VK_debug_report_EXT",
- "spec_version": "1"
- },
- {
- "name": "VK_VENDOR_DEBUG_X",
- "spec_version": "3"
- }
- ],
- "device_extensions": [
- {
- "name": "VK_DEBUG_MARKER_EXT",
- "spec_version": "1",
- "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
- }
- ],
- "disable_environment": {
- "DISABLE_LAYER_OVERLAY_1": ""
- }
-}
+ "file_format_version" : "1.0.0",
+ "layer": {
+ "name": "VK_LAYER_LUNARG_overlay",
+ "type": "INSTANCE",
+ "library_path": "vkOverlayLayer.dll"
+ "api_version" : "1.0.5",
+ "implementation_version" : "2",
+ "description" : "LunarG HUD layer",
+ "functions": {
+ "vkGetInstanceProcAddr": "OverlayLayer_GetInstanceProcAddr",
+ "vkGetDeviceProcAddr": "OverlayLayer_GetDeviceProcAddr"
+ },
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_debug_report",
+ "spec_version": "1"
+ },
+ {
+ "name": "VK_VENDOR_ext_x",
+ "spec_version": "3"
+ }
+ ],
+ "device_extensions": [
+ {
+ "name": "VK_EXT_debug_marker",
+ "spec_version": "1",
+ "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
+ }
+ ],
+ "enable_environment": {
+ "ENABLE_LAYER_OVERLAY_1": "1"
+ }
+ "disable_environment": {
+ "DISABLE_LAYER_OVERLAY_1": ""
+ }
+ }
}
```
@@ -848,6 +786,34 @@ application files). If the layer is specified via a filename, the shared
library lives in the system's DLL search path (e.g. in the
"C:\\Windows\\System32" folder).
+If defining multiple layers in a single JSON file prior to "file\_format\_version"
+1.0.1, you would simply define multiple "layer" objects. However, this is not
+valid JSON syntax. Instead, you should now define "file\_format\_version"
+1.0.1 (or newer) and use the new "layers" array object as seen in the
+following example:
+
+```
+{
+ "file_format_version" : "1.0.1",
+ "layers": [
+ {
+ "name": "VK_LAYER_layer_name1",
+ "type": "INSTANCE",
+ ...
+ },
+ {
+ "name": "VK_LAYER_layer_name2",
+ "type": "INSTANCE",
+ ...
+ }
+ ]
+}
+```
+
+You could use the "layers" array object to define a single layer, as long as
+your "file\_format\_version" is defined to at least 1.0.1. It is functionally the
+same as using a single "layer" object.
+
There are no rules about the name of the text files (except the .json suffix).
There are no rules about the name of the layer shared library files.
@@ -906,102 +872,47 @@ installed from Linux-distribution-provided packages. The
"/etc/vulkan/\*\_layer.d" directories are for layers that are installed from
non-Linux-distribution-provided packages.
-The information file is in the JSON format and contains the following
-information:
-
-- (required) "file\_format\_version" – same as for ICDs, except that the format
-version can vary independently for ICDs and layers.
-
-- (required) "name" - layer name
-
-- (required) "type" - which layer chains should the layer be activated on.
-Allowable values are "INSTANCE", "DEVICE", "GLOBAL". Global means activate on
-both device and instance chains.
-
-- (required) "library\_path" - filename / full path / relative path to the text
-file
-
-- (required) "api\_version" – same as for ICDs.
-
-- (required) "implementation\_version" – layer version, a single number
-increasing with backward compatible changes.
-
-- (required) "description" – informative description of the layer.
-
-- (optional) "device\_extensions" or "instance\_extensions" - array of
-extension information as follows
-
- - (required) extension "name" - Vulkan registered name
-
- - (required) extension "spec\_version" - extension specification version, a
-single number, increasing with backward compatible changes.
-
- - (required for device extensions with entry points) extension
-"entrypoints" - array of device extension entry points; not used for instance
-extensions
-
-- (sometimes required) "functions" - mapping list of function entry points. If
-multiple layers exist within the same shared library (or if a layer is in the
-same shared library as an ICD), this must be specified to allow each layer to
-have its own vkGet\*ProcAddr entry points that can be found by the loader. At
-this time, only the following two functions are required:
- - "vkGetInstanceProcAddr" name
- - "vkGetDeviceProcAddr" name
+This manifest file is in the JSON format as shown in the following example.
+See the section [Layer Library Manifest File](#LayerLibraryManifestFile) for more information about each of the nodes in the JSON file.
-- (optional for implicit layers) "enable\_environment" requirement(s) -
-environment variable and value required to enable an implicit layer. This
-environment variable (which should vary with each "version" of the layer, as in
-"ENABLE\_LAYER\_FOO\_1") must be set to the given value or else the implicit
-layer is not loaded. This is for application environments (e.g. Steam) which
-want to enable a layer(s) only for applications that they launch, and allows
-for applications run outside of an application environment to not get that
-implicit layer(s).
-
-- (required for implicit layers) "disable\_environment" requirement(s) -
-environment variable and value required to disable an implicit layer. Note: in
-rare cases of an application not working with an implicit layer, the
-application can set this environment variable (before calling Vulkan functions)
-in order to "blacklist" the layer. This environment variable (which should vary
-with each "version" of the layer, as in "DISABLE\_LAYER\_FOO\_1") must be set
-(not particularly to any value). If both the "enable\_environment" and
-"disable\_environment" variables are set, the implicit layer is disabled.
-
-For example:
```
{
-"file_format_version" : "1.0.0",
-"layer": {
- "name": "VK_LAYER_LUNARG_OverlayLayer",
- "type": "DEVICE",
- "library_path": "vkOverlayLayer.dll"
- "api_version" : "1.0.5",
- "implementation_version" : "2",
- "description" : "LunarG HUD layer",
- "functions": {
- "vkGetInstanceProcAddr": "OverlayLayer_GetInstanceProcAddr",
- "vkGetDeviceProcAddr": "OverlayLayer_GetDeviceProcAddr"
- },
- "instance_extensions": [
- {
- "name": "VK_debug_report_EXT",
- "spec_version": "1"
- },
- {
- "name": "VK_VENDOR_DEBUG_X",
- "spec_version": "3"
- }
- ],
- "device_extensions": [
- {
- "name": "VK_DEBUG_MARKER_EXT",
- "spec_version": "1",
- "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
- }
- ],
- "disable_environment": {
- "DISABLE_LAYER_OVERLAY_1": ""
- }
-}
+ "file_format_version" : "1.0.0",
+ "layer": {
+ "name": "VK_LAYER_LUNARG_overlay",
+ "type": "INSTANCE",
+ "library_path": "libvkOverlayLayer.so"
+ "api_version" : "1.0.5",
+ "implementation_version" : "2",
+ "description" : "LunarG HUD layer",
+ "functions": {
+ "vkGetInstanceProcAddr": "OverlayLayer_GetInstanceProcAddr",
+ "vkGetDeviceProcAddr": "OverlayLayer_GetDeviceProcAddr"
+ },
+ "instance_extensions": [
+ {
+ "name": "VK_EXT_debug_report",
+ "spec_version": "1"
+ },
+ {
+ "name": "VK_VENDOR_ext_x",
+ "spec_version": "3"
+ }
+ ],
+ "device_extensions": [
+ {
+ "name": "VK_EXT_debug_marker",
+ "spec_version": "1",
+ "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
+ }
+ ],
+ "enable_environment": {
+ "ENABLE_LAYER_OVERLAY_1": "1"
+ },
+ "disable_environment": {
+ "DISABLE_LAYER_OVERLAY_1": ""
+ }
+ }
}
```
The "library\_path" specifies either a filename, a relative pathname, or a full
@@ -1040,7 +951,7 @@ NOTE: these environment variables will be ignored for suid programs.
The recommended way to enable layers is for applications
to programatically enable them. The layers are provided by the application
and must live in the application's library folder. The application
-enables the layers at vkCreateInstance and vkCreateDevice as any Vulkan
+enables the layers at vkCreateInstance as any Vulkan
application would.
An application enabled for debug has more options. It can enumerate and enable
layers located in /data/local/vulkan/debug.
@@ -1060,12 +971,11 @@ to layer module with the loader and or the ICD being the bottom most command.
Call chains are constructed at both the instance level and the device level by
the loader with cooperation from the layer libraries. Instance call chains are
constructed by the loader when layers are enabled at vkCreateInstance. Device
-call chains are constructed by the loader when layers are enabled at
+call chains are constructed by the loader when layers are enabled, by the loader, at
vkCreateDevice. A layer can intercept Vulkan instance commands, device commands
or both. For a layer to intercept instance commands, it must participate in the
instance call chain. For a layer to intercept device commands, it must
-participate in the device chain. Layers which participate in intercepting calls
-in both the instance and device chains are called global layers.
+participate in the device chain.
Normally, when a layer intercepts a given Vulkan command, it will call down the
instance or device chain as needed. The loader and all layer libraries that
@@ -1094,7 +1004,7 @@ the above lists may be extended in the future.
#### Layer Library Interface
A layer library is a container of layers. This section defines an extensible
-manifest file interface or programming interface to discover layers contained in layer libraries.
+interface to discover layers contained in layer libraries.
The extensible programming interface is used on Android only. For Windows and Linux,
the layer manifest JSON files are used.
@@ -1121,113 +1031,151 @@ should use memory allocators if the layer is intended to run in a production
environment, such as an implicit layer that is always enabled. That will
allow applications to include the layer's memory usage.
+`vkEnumerateInstanceLayerProperties` must enumerate and only enumerate the
+layer itself.
+
+`vkEnumerateInstanceExtensionProperties` must handle the case where
+`pLayerName` is itself. It must return `VK_ERROR_LAYER_NOT_PRESENT`
+otherwise, including when `pLayerName` is `NULL`.
+
+`vkEnumerateDeviceLayerProperties` is deprecated and may be omitted. The
+behavior is undefined.
+
`vkEnumerateDeviceExtensionProperties` must handle the case where `pLayerName`
-is `NULL`, usually by chaining to other layers.
+is itself. In other cases, it should normally chain to other layers.
-`vkGetInstanceProcAddr` can intercept a command by returning a function
-pointer different from what would be returned through chaining.
+`vkCreateInstance` must not generate an error for unrecognized layer names and
+extension names. It may assume the layer names and extension names have been
+validated.
-`vkGetDeviceProcAddr` can intercept a command by returning a function pointer
-different from what would be returned through chaining.
+`vkGetInstanceProcAddr` intercepts a Vulkan command by returning a local entry point,
+otherwise it returns the value obtained by calling down the instance chain.
+ These commands must be intercepted
+ - vkGetInstanceProcAddr
+ - vkCreateInstance
+ - vkCreateDevice (only required for any device-level chaining)
-`vkCreateInstance` must not generate an error for unrecognized layer names,
-extension names, and `pNext` structs. It may assume the layer names and
-extension names have been validated.
+ For compatibility with older layer libraries,
+ - when `pName` is `vkCreateDevice`, it ignores `instance`.
+
+`vkGetDeviceProcAddr` intercepts a Vulkan command by returning a local entry point,
+otherwise it returns the value obtained by calling down the device chain.
-`vkCreateDevice` must not generate an error for unrecognized layer names,
-extension names, and `pNext` structs. It may assume the layer names and
-extension names have been validated.
+The specification requires `NULL` to be returned from `vkGetInstanceProcAddr` and
+`vkGetDeviceProcAddr` for disabled commands. A layer may return `NULL` itself or
+rely on the following layers to do so.
[\*]: The intention is for layers to have a well-defined baseline behavior.
Some of the conventions or rules, for example, may be considered abuses of the
specification.
-###### Layer Library Interface Version 0 (Android)
+##### Layer Library API Version 0
+
+A layer library supporting interface version 0 must define and export these
+introspection functions, unrelated to any Vulkan command despite the names,
+signatures, and other similarities:
-An Android layer library supporting interface version 0 must define and export these
-functions, unrelated to any Vulkan command despite the names, signatures, and
-other similarities:
+ - `vkEnumerateInstanceLayerProperties` enumerates all layers in a layer
+ library. This function never fails.
- - `vkEnumerateInstanceLayerProperties` enumerates all instance layers in a
- layer library. This function never fails.
+ When a layer library contains only one layer, this function may be an alias
+ to the layer's `vkEnumerateInstanceLayerProperties`.
- `vkEnumerateInstanceExtensionProperties` enumerates instance extensions of
- instance layers in a layer library. `pLayerName` is always a valid
- instance layer name. This function never fails.
+ layers in a layer library. `pLayerName` is always a valid layer name.
+ This function never fails.
- - `vkEnumerateDeviceLayerProperties` enumerates all device layers in a layer
- library. `physicalDevice` is always `VK_NULL_HANDLE`. This function never
- fails.
+ When a layer library contains only one layer, this function may be an alias
+ to the layer's `vkEnumerateInstanceExtensionProperties`.
+
+ - `vkEnumerateDeviceLayerProperties` enumerates a subset (can be full,
+ proper, or empty subset) of layers in a layer library. `physicalDevice` is
+ always `VK_NULL_HANDLE`. This function never fails.
+
+ If a layer is not enumerated by this function, it will not participate in
+ device command interception.
- `vkEnumerateDeviceExtensionProperties` enumerates device extensions of
- device layers in a layer library. `physicalDevice` is always
- `VK_NULL_HANDLE`. `pLayerName` is always a valid device layer name. This
- function never fails.
-
- - `<layerName>GetInstanceProcAddr` behaves as if `<layerName>`'s
- `vkGetInstanceProcAddr` is called, except
-
- - when `pName` is `vkEnumerateInstanceLayerProperties`,
- `vkEnumerateInstanceExtensionProperties`, or
- `vkEnumerateDeviceLayerProperties` (but _not_
- `vkEnumerateDeviceExtensionProperties`), it returns a function pointer to
- the function of the same name defined by this interface.
- - when `pName` is `vkGetInstanceProcAddr`, it returns a function pointer
- to itself.
- - when `pName` is `vkCreateDevice`, it ignores `instance`.
- - when `pName` is a device command defined by Vulkan 1.0 or
- `VK_KHR_swapchain` (but _not_ other device commands), it may chain to
- other layers without intercepting. A loader should avoid querying such
- device commands.
+ layers in a layer library. `physicalDevice` is always `VK_NULL_HANDLE`.
+ `pLayerName` is always a valid layer name. This function never fails.
+
+The introspection functions are not used by the desktop loader.
+
+It must also define and export these functions one for each layer in the library:
+
+ - `<layerName>GetInstanceProcAddr(instance, pName)` behaves identically to a layer's vkGetInstanceProcAddr except it is exported.
When a layer library contains only one layer, this function may
alternatively be named `vkGetInstanceProcAddr`.
- - `<layerName>GetDeviceProcAddr` behaves as if `<layerName>`'s
- `vkGetDeviceProcAddr` is called.
+ - `<layerName>GetDeviceProcAddr` behaves identically to a layer's vkGetDeviceProcAddr except it is exported.
When a layer library contains only one layer, this function may
alternatively be named `vkGetDeviceProcAddr`.
-All contained layers must support [`vk_layer.h`][]. They do not need to
-implement commands that are not queryable. They are recommended not to export
-any command.
+All layers contained within a library must support [`vk_layer.h`][]. They do not need to
+implement commands that they do not intercept. They are recommended not to export
+any commands.
-###### Layer Library Interface Version 0 (Windows and Linux)
+<a name="LayerLibraryManifestFile"></a>
+##### Layer Library Manifest File Version 0
On Windows and Linux (desktop), the loader uses manifest files to discover
layer libraries and layers. The desktop loader doesn't directly query the
-layer library except during chaining. On Android, the loader queries the layer libraries directly as outlined above.
+layer library except during chaining.
+On Android, the loader queries the layer libraries via the introspection functions as outlined above.
The layer libraries and the manifest files must be kept in sync.
-The following table associates the desktop JSON nodes with the Android layer library queries. It also indicates requirements.
+The following table associates the desktop JSON nodes with the layer library introspection queries. It also indicates requirements.
-| Property | JSON node | Android library query | Notes |
+| Property | JSON node | Introspection query | Notes |
|----------|-----------|-----------------------|-------|
-| layers in library | layer | vkEnumerate*LayerProperties | one node required for each layer in the library |
-|layer name | name | vkEnumerate*LayerProperties | one node is required |
-| layer type | type | vkEnumerate*LayerProperties | one node is required |
+| file version | file_format_version | N/A | one node required per JSON file |
+| layers in library | layer | vkEnumerateInstanceLayerProperties | one node required per layer |
+| layer name | name | vkEnumerateInstanceLayerProperties | one node is required |
+| layer type | type | vkEnumerate*LayerProperties | see Note 1 |
| library location | library_path | N/A | one node is required |
-| vulkan spec version | api_version | vkEnumerate*LayerProperties | one node is required |
-| layer implementation version | api_version | vkEnumerate*LayerProperties | one node is required |
-| layer description | description | vkEnumerate*LayerProperties | one node is required |
-| chaining functions | functions | vkGet*ProcAddr | see Note 1 |
-| instance extensions | instance_extensions | vkEnumerateInstanceExtensionProperties | see Note 2 |
-| device extensions | device_extensions | vkEnumerateDeviceExtensionProperties | see Note 3 |
-
-Note 1: The "functions" node is required if the layer is using alternative
-names for vkGetInstanceProcAddr or vkGetDeviceProcAddr. vkGetInstanceProcAddr is
-required for all layer types. vkGetDeviceProcAddr is required for
-device or global (both instance and device) layers. See further requirements below.
-
-Note 2: One "instance_extensions" node with an array of 1 or more elements
+| vulkan spec version | api_version | vkEnumerateInstanceLayerProperties | one node is required |
+| layer implementation version | api_version | vkEnumerateInstanceLayerProperties | see Note 2 |
+| layer description | description | vkEnumerateInstanceLayerProperties | one node is required |
+| chaining functions | functions | vkGet*ProcAddr | see Note 3 |
+| instance extensions | instance_extensions | vkEnumerateInstanceExtensionProperties | see Note 4 |
+| device extensions | device_extensions | vkEnumerateDeviceExtensionProperties | see Note 5 |
+| enable implicit | enable_environment | N/A | See Note 6 |
+| disable implicit | enable_environment | N/A | See Note 7 |
+
+"file\_format\_version" is used to indicate the valid JSON syntax of the file.
+As nodes are added or deleted which would change the parsing of this file,
+the file_format_version should change. This version
+is NOT the same as the layer library interface version. The interface version is a superset
+of the "file_format_version" and includes the semantics of the nodes in the JSON file.
+For interface version 0 the file format version must be "1.0.0"
+
+Note 1: Prior to deprecation, the "type" node was used to indicate which layer chain(s)
+to activate the layer upon: instance, device, or both.
+Distinct instance and device layers are deprecated; there are now just layers.
+Allowable values for type (both before and after deprecation) are "INSTANCE", "GLOBAL" and, "DEVICE."
+"DEVICE" layers are skipped over by the loader as if they were not found.
+Thus, layers must have a type of "GLOBAL" or "INSTANCE" for the loader to include the layer in the enumerated instance layer list.
+
+"library\_path" is the filename, full path, or relative path to the library file.
+See [Manifest File Example](# ManifestFileExample) section for more details.
+
+Note 2: One "implementation\_version" node is required per layer. This node gives the layer version, a single number
+increasing with backward uncompatible changes.
+
+Note 3: The "functions" node is required if the layer is using alternative
+names for vkGetInstanceProcAddr or vkGetDeviceProcAddr. vkGetInstanceProcAddr and vkGetDeviceProcAddr
+are required for all layers. See further requirements in the Layer Library API section above.
+
+Note 4: One "instance_extensions" node with an array of one or more elements
required if any instance
extensions are supported by a layer, otherwise the node is optional. Each
element of the array must have the nodes "name" and "spec_version" which
correspond to VkExtensionProperties "extensionName" and "specVersion"
respectively.
-Note 3: One "device_extensions" node with an array of 1 or more elements
+Note 5: One "device_extensions" node with an array of one or more elements
required if any device
extensions are supported by a layer, otherwise the node is optional. Each
element of the array must have the nodes "name" and "spec_version" which
@@ -1237,55 +1185,39 @@ must have the node "entrypoints" if the device extension adds Vulkan API command
otherwise this node is not required.
The "entrypoint" node is an array of the names of all entrypoints added by the
supported extension.
+```
+ "device_extensions": [
+ {
+ "name": "VK_EXT_debug_marker",
+ "spec_version": "1",
+ "entrypoints": ["vkCmdDbgMarkerBegin", "vkCmdDbgMarkerEnd"]
+ }
+ ```
-The manifest file nodes "file_format_version", "disable_environment", and
-"enable_environment" have no corresponding equivalent in the Vulkan API nor
-in the Android layer library interface.
+Note 6: The "enable\_environment" node is only for implicit layers only. It is optional for implicit layers.
+This node gives an environment variable and value required to enable an implicit layer. This
+environment variable (which should vary with each "version" of the layer) must be set to the
+given value or else the implicit layer is not loaded. This is for application environments (e.g. Steam) which
+want to enable a layer(s) only for applications that they launch, and allows
+for applications run outside of an application environment to not get that
+implicit layer(s).
-"file_format_version" is used to indicate the valid JSON syntax of the file.
-As nodes are added or deleted which would change the parsing of this file,
-the file_format_version should change. This version
-is NOT the same as the interface version. The interface version is a superset
-of the "file_format_version" and includes the semantics of the nodes in the JSON file. For interface version 0 the file format version must be "1.0.0"
-
-"disable_environment" (required) and "enable_evironment" (optional) are for implicit layers as previously described.
-
-vkGetInstanceProcAddr requirements:
--Irregardless of the name, this function must be implemented and exported in the library for all layers.
--This function must return
-the local entry points for all instance level Vulkan commands it intercepts. At
-a minimum, this includes vkGetInstanceProcAddr and vkCreateInstance.
-Optionally, this function may return intercepted device level
-Vulkan commands.
--Vulkan commands that a layer doesn't intercept must be passed to the next
-entity in the chain. That is, the next layer/ICD's GetInstanceProcAddr must be called.
--Currently this function must be able to handle a VkInstance parameter equal
-to NULL for instance level commands it intercepts including vkCreateDevice.
-
-VkGetDeviceProcAddr requirements:
--Irregardless of the name, a layer intercepting device level Vulkan commands
-(aka a device level layer) must implement vkGetDeviceProcAddr type of function.
--This vkGetDeviceProcAddr type function must be exported by the layer library.
--This function must return the entry points for all device level Vulkan
-commands it intercepts. At a minimum, this includes vkGetDeviceProcAddr and vkCreateDevice.
--Vulkan commands that a layer doesn't intercept must be passed to the next
-entity in the chain. That is, the next layer/ICD's GetDeviceProcAddr must be called.
-
-There are no requirements on the names of the intercepting functions a layer
-implements except those listed above for vkGetInstanceProcAddr and
-vkGetDeviceProcAddr. Layers do not need to implement commands that are not going to be intercepted.
-
-All layers within a library must support [`vk_layer.h`][].
-[`vk_layer.h`]: ../include/vulkan/vk_layer.h
-
-#### Layer intercept requirements
+Note 7: The "disable\_environment" node is only for implicit layers only. It is required for implicit layers.
+This node gives an environment variable and value required to disable an implicit layer. In
+rare cases of an application not working with an implicit layer, the
+application can set this environment variable (before calling Vulkan commands)
+in order to "blacklist" the layer. This environment variable (which should vary
+with each "version" of the layer) must be set (not particularly to any value).
+If both the "enable\_environment" and
+"disable\_environment" variables are set, the implicit layer is disabled.
+
+#### Layer Dispatch Interface Version 0
+##### Layer intercept requirements
- Layers intercept a Vulkan command by defining a C/C++ function with signature
identical to the Vulkan API for that command.
-- An instance layer must intercept at least vkGetInstanceProcAddr and
-vkCreateInstance. A device layer must intercept at least vkGetInstanceProcAddr, vkGetDeviceProcAddr and vkCreateDevice.
-- Other than the two vkGet*ProcAddr, all other functions intercepted by a layer
-need NOT be exported by the layer.
+- A layer must intercept at least vkGetInstanceProcAddr and
+vkCreateInstance. Additionally, a layer would also intercept vkGetDeviceProcAddr and vkCreateDevice to participate in the device chain.
- For any Vulkan command a layer intercepts which has a non-void return value,
an appropriate value must be returned by the layer intercept function.
- The layer intercept function must call down the chain to the corresponding
@@ -1299,7 +1231,7 @@ want to add a call to vkQueueWaitIdle after calling down the chain for
vkQueueSubmit. Any additional calls inserted by a layer must be on the same
chain. They should call down the chain.
-#### Distributed dispatching requirements
+##### Distributed dispatching requirements
- For each entry point a layer intercepts, it must keep track of the entry
point residing in the next entity in the chain it will call down into. In other
@@ -1317,7 +1249,7 @@ functions.
vkGetDeviceProcAddr to call down the chain for unknown (i.e. non-intercepted)
functions.
-#### Layer dispatch initialization
+##### Layer dispatch initialization
- A layer initializes its instance dispatch table within its vkCreateInstance
function.
@@ -1359,7 +1291,7 @@ the VkInstanceCreateInfo/VkDeviceCreateInfo structure.
Get*ProcAddr function once for each Vulkan command needed in your dispatch
table
-#### Example code for CreateInstance
+##### Example code for CreateInstance
```cpp
VkResult vkCreateInstance(
@@ -1400,7 +1332,7 @@ VkResult vkCreateInstance(
}
```
-#### Example code for CreateDevice
+##### Example code for CreateDevice
```cpp
VkResult
diff --git a/loader/cJSON.c b/loader/cJSON.c
index f28eadb7..fc3ba049 100644
--- a/loader/cJSON.c
+++ b/loader/cJSON.c
@@ -423,7 +423,6 @@ static char *print_string_ptr(const char *str, printbuffer *p) {
if ((unsigned char)*ptr > 31 && *ptr != '\"' && *ptr != '\\')
*ptr2++ = *ptr++;
else {
- *ptr2++ = '\\';
switch (token = *ptr++) {
case '\\':
*ptr2++ = '\\';
@@ -432,19 +431,19 @@ static char *print_string_ptr(const char *str, printbuffer *p) {
*ptr2++ = '\"';
break;
case '\b':
- *ptr2++ = 'b';
+ *ptr2++ = '\b';
break;
case '\f':
- *ptr2++ = 'f';
+ *ptr2++ = '\f';
break;
case '\n':
- *ptr2++ = 'n';
+ *ptr2++ = '\n';
break;
case '\r':
- *ptr2++ = 'r';
+ *ptr2++ = '\r';
break;
case '\t':
- *ptr2++ = 't';
+ *ptr2++ = '\t';
break;
default:
sprintf(ptr2, "u%04x", token);
diff --git a/loader/loader.c b/loader/loader.c
index c8e91531..1e74a6d9 100644
--- a/loader/loader.c
+++ b/loader/loader.c
@@ -1798,24 +1798,18 @@ static void loader_add_layer_property_meta(
}
-/**
- * Given a cJSON struct (json) of the top level JSON object from layer manifest
- * file, add entry to the layer_list.
- * Fill out the layer_properties in this list entry from the input cJSON object.
- *
- * \returns
- * void
- * layer_list has a new entry and initialized accordingly.
- * If the json input object does not have all the required fields no entry
- * is added to the list.
- */
-static void
-loader_add_layer_properties(const struct loader_instance *inst,
- struct loader_layer_list *layer_instance_list,
- cJSON *json, bool is_implicit, char *filename) {
- /* Fields in layer manifest file that are required:
- * (required) “file_format_version”
- * following are required in the "layer" object:
+static void loader_read_json_layer(
+ const struct loader_instance *inst,
+ struct loader_layer_list *layer_instance_list, cJSON *layer_node,
+ cJSON *item, cJSON *disable_environment, bool is_implicit, char *filename) {
+ char *temp;
+ char *name, *type, *library_path, *api_version;
+ char *implementation_version, *description;
+ cJSON *ext_item;
+ VkExtensionProperties ext_prop;
+
+ /*
+ * The following are required in the "layer" object:
* (required) "name"
* (required) "type"
* (required) “library_path”
@@ -1823,40 +1817,8 @@ loader_add_layer_properties(const struct loader_instance *inst,
* (required) “implementation_version”
* (required) “description”
* (required for implicit layers) “disable_environment”
- *
- * First get all required items and if any missing abort
*/
- cJSON *item, *layer_node, *ext_item;
- char *temp;
- char *name, *type, *library_path, *api_version;
- char *implementation_version, *description;
- cJSON *disable_environment = NULL;
- int i, j;
- VkExtensionProperties ext_prop;
- item = cJSON_GetObjectItem(json, "file_format_version");
- if (item == NULL) {
- return;
- }
- char *file_vers = cJSON_PrintUnformatted(item);
- loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
- "Found manifest file %s, version %s", filename, file_vers);
- if (strcmp(file_vers, "\"1.0.0\"") != 0)
- loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "Unexpected manifest file version (expected 1.0.0), may "
- "cause errors");
- loader_tls_heap_free(file_vers);
-
- layer_node = cJSON_GetObjectItem(json, "layer");
- if (layer_node == NULL) {
- loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "Can't find \"layer\" object in manifest JSON file, "
- "skipping this file");
- return;
- }
-
- // loop through all "layer" objects in the file
- do {
#define GET_JSON_OBJECT(node, var) \
{ \
var = cJSON_GetObjectItem(node, #var); \
@@ -1866,7 +1828,7 @@ loader_add_layer_properties(const struct loader_instance *inst,
"Didn't find required layer object %s in manifest " \
"JSON file, skipping this layer", \
#var); \
- continue; \
+ return; \
} \
}
#define GET_JSON_ITEM(node, var) \
@@ -1878,7 +1840,7 @@ loader_add_layer_properties(const struct loader_instance *inst,
"Didn't find required layer value %s in manifest JSON " \
"file, skipping this layer", \
#var); \
- continue; \
+ return; \
} \
temp = cJSON_Print(item); \
temp[strlen(temp) - 1] = '\0'; \
@@ -1886,103 +1848,91 @@ loader_add_layer_properties(const struct loader_instance *inst,
strcpy(var, &temp[1]); \
loader_tls_heap_free(temp); \
}
- GET_JSON_ITEM(layer_node, name)
- GET_JSON_ITEM(layer_node, type)
- GET_JSON_ITEM(layer_node, library_path)
- GET_JSON_ITEM(layer_node, api_version)
- GET_JSON_ITEM(layer_node, implementation_version)
- GET_JSON_ITEM(layer_node, description)
- if (is_implicit) {
- GET_JSON_OBJECT(layer_node, disable_environment)
- }
+ GET_JSON_ITEM(layer_node, name)
+ GET_JSON_ITEM(layer_node, type)
+ GET_JSON_ITEM(layer_node, library_path)
+ GET_JSON_ITEM(layer_node, api_version)
+ GET_JSON_ITEM(layer_node, implementation_version)
+ GET_JSON_ITEM(layer_node, description)
+ if (is_implicit) {
+ GET_JSON_OBJECT(layer_node, disable_environment)
+ }
#undef GET_JSON_ITEM
#undef GET_JSON_OBJECT
- // add list entry
- struct loader_layer_properties *props = NULL;
- if (!strcmp(type, "DEVICE")) {
- loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "Device layers are deprecated skipping this layer");
- layer_node = layer_node->next;
- continue;
-
- }
- if (!strcmp(type, "INSTANCE")) {
- if (layer_instance_list == NULL) {
- layer_node = layer_node->next;
- continue;
- }
- props = loader_get_next_layer_property(inst, layer_instance_list);
- props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT
- : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
- }
- if (!strcmp(type, "GLOBAL")) {
- loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
- "Global layers are treated the same as instance layers");
- if (layer_instance_list == NULL) {
- layer_node = layer_node->next;
- continue;
- }
- props = loader_get_next_layer_property(inst, layer_instance_list);
- props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT
- : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
- }
-
- if (props == NULL) {
+ // add list entry
+ struct loader_layer_properties *props = NULL;
+ if (!strcmp(type, "DEVICE")) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Device layers are deprecated skipping this layer");
+ layer_node = layer_node->next;
+ return;
+ }
+ // Allow either GLOBAL or INSTANCE type interchangeably to handle
+ // layers that must work with older loaders
+ if (!strcmp(type, "INSTANCE") || !strcmp(type, "GLOBAL")) {
+ if (layer_instance_list == NULL) {
layer_node = layer_node->next;
- continue;
+ return;
}
+ props = loader_get_next_layer_property(inst, layer_instance_list);
+ props->type = (is_implicit) ? VK_LAYER_TYPE_INSTANCE_IMPLICIT
+ : VK_LAYER_TYPE_INSTANCE_EXPLICIT;
+ }
- strncpy(props->info.layerName, name, sizeof(props->info.layerName));
- props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
+ if (props == NULL) {
+ layer_node = layer_node->next;
+ return;
+ }
- char *fullpath = props->lib_name;
- char *rel_base;
- if (loader_platform_is_path(library_path)) {
- // a relative or absolute path
- char *name_copy = loader_stack_alloc(strlen(filename) + 1);
- strcpy(name_copy, filename);
- rel_base = loader_platform_dirname(name_copy);
- loader_expand_path(library_path, rel_base, MAX_STRING_SIZE,
- fullpath);
- } else {
- // a filename which is assumed in a system directory
- loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH,
- MAX_STRING_SIZE, fullpath);
- }
- props->info.specVersion = loader_make_version(api_version);
- props->info.implementationVersion = atoi(implementation_version);
- strncpy((char *)props->info.description, description,
- sizeof(props->info.description));
- props->info.description[sizeof(props->info.description) - 1] = '\0';
- if (is_implicit) {
- if (!disable_environment || !disable_environment->child) {
- loader_log(
- inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "Didn't find required layer child value disable_environment"
- "in manifest JSON file, skipping this layer");
- layer_node = layer_node->next;
- continue;
- }
- strncpy(props->disable_env_var.name,
- disable_environment->child->string,
- sizeof(props->disable_env_var.name));
- props->disable_env_var
- .name[sizeof(props->disable_env_var.name) - 1] = '\0';
- strncpy(props->disable_env_var.value,
- disable_environment->child->valuestring,
- sizeof(props->disable_env_var.value));
- props->disable_env_var
- .value[sizeof(props->disable_env_var.value) - 1] = '\0';
+ strncpy(props->info.layerName, name, sizeof(props->info.layerName));
+ props->info.layerName[sizeof(props->info.layerName) - 1] = '\0';
+
+ char *fullpath = props->lib_name;
+ char *rel_base;
+ if (loader_platform_is_path(library_path)) {
+ // a relative or absolute path
+ char *name_copy = loader_stack_alloc(strlen(filename) + 1);
+ strcpy(name_copy, filename);
+ rel_base = loader_platform_dirname(name_copy);
+ loader_expand_path(library_path, rel_base, MAX_STRING_SIZE, fullpath);
+ } else {
+ // a filename which is assumed in a system directory
+ loader_get_fullpath(library_path, DEFAULT_VK_LAYERS_PATH,
+ MAX_STRING_SIZE, fullpath);
+ }
+ props->info.specVersion = loader_make_version(api_version);
+ props->info.implementationVersion = atoi(implementation_version);
+ strncpy((char *)props->info.description, description,
+ sizeof(props->info.description));
+ props->info.description[sizeof(props->info.description) - 1] = '\0';
+ if (is_implicit) {
+ if (!disable_environment || !disable_environment->child) {
+ loader_log(
+ inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Didn't find required layer child value disable_environment"
+ "in manifest JSON file, skipping this layer");
+ layer_node = layer_node->next;
+ return;
}
+ strncpy(props->disable_env_var.name, disable_environment->child->string,
+ sizeof(props->disable_env_var.name));
+ props->disable_env_var.name[sizeof(props->disable_env_var.name) - 1] =
+ '\0';
+ strncpy(props->disable_env_var.value,
+ disable_environment->child->valuestring,
+ sizeof(props->disable_env_var.value));
+ props->disable_env_var.value[sizeof(props->disable_env_var.value) - 1] =
+ '\0';
+ }
/**
- * Now get all optional items and objects and put in list:
- * functions
- * instance_extensions
- * device_extensions
- * enable_environment (implicit layers only)
- */
+* Now get all optional items and objects and put in list:
+* functions
+* instance_extensions
+* device_extensions
+* enable_environment (implicit layers only)
+*/
#define GET_JSON_OBJECT(node, var) \
{ var = cJSON_GetObjectItem(node, #var); }
#define GET_JSON_ITEM(node, var) \
@@ -1997,133 +1947,251 @@ loader_add_layer_properties(const struct loader_instance *inst,
} \
}
- cJSON *instance_extensions, *device_extensions, *functions,
- *enable_environment;
- cJSON *entrypoints;
- char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
- char **entry_array;
- vkGetInstanceProcAddr = NULL;
- vkGetDeviceProcAddr = NULL;
- spec_version = NULL;
- entrypoints = NULL;
- entry_array = NULL;
- /**
- * functions
- * vkGetInstanceProcAddr
- * vkGetDeviceProcAddr
- */
- GET_JSON_OBJECT(layer_node, functions)
- if (functions != NULL) {
- GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
- GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
- if (vkGetInstanceProcAddr != NULL)
- strncpy(props->functions.str_gipa, vkGetInstanceProcAddr,
- sizeof(props->functions.str_gipa));
- props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] =
- '\0';
- if (vkGetDeviceProcAddr != NULL)
- strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr,
- sizeof(props->functions.str_gdpa));
- props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] =
- '\0';
- }
- /**
- * instance_extensions
- * array of
- * name
- * spec_version
- */
- GET_JSON_OBJECT(layer_node, instance_extensions)
- if (instance_extensions != NULL) {
- int count = cJSON_GetArraySize(instance_extensions);
- for (i = 0; i < count; i++) {
- ext_item = cJSON_GetArrayItem(instance_extensions, i);
- GET_JSON_ITEM(ext_item, name)
- GET_JSON_ITEM(ext_item, spec_version)
- if (name != NULL) {
- strncpy(ext_prop.extensionName, name,
- sizeof(ext_prop.extensionName));
- ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
- '\0';
- }
- ext_prop.specVersion = atoi(spec_version);
- bool ext_unsupported =
- wsi_unsupported_instance_extension(&ext_prop);
- if (!ext_unsupported) {
- loader_add_to_ext_list(
- inst, &props->instance_extension_list, 1, &ext_prop);
- }
+ cJSON *instance_extensions, *device_extensions, *functions,
+ *enable_environment;
+ cJSON *entrypoints;
+ char *vkGetInstanceProcAddr, *vkGetDeviceProcAddr, *spec_version;
+ char **entry_array;
+ vkGetInstanceProcAddr = NULL;
+ vkGetDeviceProcAddr = NULL;
+ spec_version = NULL;
+ entrypoints = NULL;
+ entry_array = NULL;
+ int i, j;
+
+ /**
+ * functions
+ * vkGetInstanceProcAddr
+ * vkGetDeviceProcAddr
+ */
+ GET_JSON_OBJECT(layer_node, functions)
+ if (functions != NULL) {
+ GET_JSON_ITEM(functions, vkGetInstanceProcAddr)
+ GET_JSON_ITEM(functions, vkGetDeviceProcAddr)
+ if (vkGetInstanceProcAddr != NULL)
+ strncpy(props->functions.str_gipa, vkGetInstanceProcAddr,
+ sizeof(props->functions.str_gipa));
+ props->functions.str_gipa[sizeof(props->functions.str_gipa) - 1] = '\0';
+ if (vkGetDeviceProcAddr != NULL)
+ strncpy(props->functions.str_gdpa, vkGetDeviceProcAddr,
+ sizeof(props->functions.str_gdpa));
+ props->functions.str_gdpa[sizeof(props->functions.str_gdpa) - 1] = '\0';
+ }
+ /**
+ * instance_extensions
+ * array of
+ * name
+ * spec_version
+ */
+ GET_JSON_OBJECT(layer_node, instance_extensions)
+ if (instance_extensions != NULL) {
+ int count = cJSON_GetArraySize(instance_extensions);
+ for (i = 0; i < count; i++) {
+ ext_item = cJSON_GetArrayItem(instance_extensions, i);
+ GET_JSON_ITEM(ext_item, name)
+ GET_JSON_ITEM(ext_item, spec_version)
+ if (name != NULL) {
+ strncpy(ext_prop.extensionName, name,
+ sizeof(ext_prop.extensionName));
+ ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
+ '\0';
+ }
+ ext_prop.specVersion = atoi(spec_version);
+ bool ext_unsupported =
+ wsi_unsupported_instance_extension(&ext_prop);
+ if (!ext_unsupported) {
+ loader_add_to_ext_list(inst, &props->instance_extension_list, 1,
+ &ext_prop);
}
}
- /**
- * device_extensions
- * array of
- * name
- * spec_version
- * entrypoints
- */
- GET_JSON_OBJECT(layer_node, device_extensions)
- if (device_extensions != NULL) {
- int count = cJSON_GetArraySize(device_extensions);
- for (i = 0; i < count; i++) {
- ext_item = cJSON_GetArrayItem(device_extensions, i);
- GET_JSON_ITEM(ext_item, name)
- GET_JSON_ITEM(ext_item, spec_version)
- if (name != NULL) {
- strncpy(ext_prop.extensionName, name,
- sizeof(ext_prop.extensionName));
- ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
- '\0';
- }
- ext_prop.specVersion = atoi(spec_version);
- // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
- GET_JSON_OBJECT(ext_item, entrypoints)
- int entry_count;
- if (entrypoints == NULL) {
- loader_add_to_dev_ext_list(inst,
- &props->device_extension_list,
- &ext_prop, 0, NULL);
- continue;
- }
- entry_count = cJSON_GetArraySize(entrypoints);
- if (entry_count)
- entry_array = (char **)loader_stack_alloc(sizeof(char *) *
- entry_count);
- for (j = 0; j < entry_count; j++) {
- ext_item = cJSON_GetArrayItem(entrypoints, j);
- if (ext_item != NULL) {
- temp = cJSON_Print(ext_item);
- temp[strlen(temp) - 1] = '\0';
- entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
- strcpy(entry_array[j], &temp[1]);
- loader_tls_heap_free(temp);
- }
- }
+ }
+ /**
+ * device_extensions
+ * array of
+ * name
+ * spec_version
+ * entrypoints
+ */
+ GET_JSON_OBJECT(layer_node, device_extensions)
+ if (device_extensions != NULL) {
+ int count = cJSON_GetArraySize(device_extensions);
+ for (i = 0; i < count; i++) {
+ ext_item = cJSON_GetArrayItem(device_extensions, i);
+ GET_JSON_ITEM(ext_item, name)
+ GET_JSON_ITEM(ext_item, spec_version)
+ if (name != NULL) {
+ strncpy(ext_prop.extensionName, name,
+ sizeof(ext_prop.extensionName));
+ ext_prop.extensionName[sizeof(ext_prop.extensionName) - 1] =
+ '\0';
+ }
+ ext_prop.specVersion = atoi(spec_version);
+ // entrypoints = cJSON_GetObjectItem(ext_item, "entrypoints");
+ GET_JSON_OBJECT(ext_item, entrypoints)
+ int entry_count;
+ if (entrypoints == NULL) {
loader_add_to_dev_ext_list(inst, &props->device_extension_list,
- &ext_prop, entry_count, entry_array);
+ &ext_prop, 0, NULL);
+ continue;
}
- }
- if (is_implicit) {
- GET_JSON_OBJECT(layer_node, enable_environment)
-
- // enable_environment is optional
- if (enable_environment) {
- strncpy(props->enable_env_var.name,
- enable_environment->child->string,
- sizeof(props->enable_env_var.name));
- props->enable_env_var
- .name[sizeof(props->enable_env_var.name) - 1] = '\0';
- strncpy(props->enable_env_var.value,
- enable_environment->child->valuestring,
- sizeof(props->enable_env_var.value));
- props->enable_env_var
- .value[sizeof(props->enable_env_var.value) - 1] = '\0';
+ entry_count = cJSON_GetArraySize(entrypoints);
+ if (entry_count)
+ entry_array =
+ (char **)loader_stack_alloc(sizeof(char *) * entry_count);
+ for (j = 0; j < entry_count; j++) {
+ ext_item = cJSON_GetArrayItem(entrypoints, j);
+ if (ext_item != NULL) {
+ temp = cJSON_Print(ext_item);
+ temp[strlen(temp) - 1] = '\0';
+ entry_array[j] = loader_stack_alloc(strlen(temp) + 1);
+ strcpy(entry_array[j], &temp[1]);
+ loader_tls_heap_free(temp);
+ }
}
+ loader_add_to_dev_ext_list(inst, &props->device_extension_list,
+ &ext_prop, entry_count, entry_array);
+ }
+ }
+ if (is_implicit) {
+ GET_JSON_OBJECT(layer_node, enable_environment)
+
+ // enable_environment is optional
+ if (enable_environment) {
+ strncpy(props->enable_env_var.name,
+ enable_environment->child->string,
+ sizeof(props->enable_env_var.name));
+ props->enable_env_var.name[sizeof(props->enable_env_var.name) - 1] =
+ '\0';
+ strncpy(props->enable_env_var.value,
+ enable_environment->child->valuestring,
+ sizeof(props->enable_env_var.value));
+ props->enable_env_var
+ .value[sizeof(props->enable_env_var.value) - 1] = '\0';
}
+ }
#undef GET_JSON_ITEM
#undef GET_JSON_OBJECT
- layer_node = layer_node->next;
- } while (layer_node != NULL);
+}
+
+/**
+ * Given a cJSON struct (json) of the top level JSON object from layer manifest
+ * file, add entry to the layer_list. Fill out the layer_properties in this list
+ * entry from the input cJSON object.
+ *
+ * \returns
+ * void
+ * layer_list has a new entry and initialized accordingly.
+ * If the json input object does not have all the required fields no entry
+ * is added to the list.
+ */
+static void
+loader_add_layer_properties(const struct loader_instance *inst,
+ struct loader_layer_list *layer_instance_list,
+ cJSON *json, bool is_implicit, char *filename) {
+ /* Fields in layer manifest file that are required:
+ * (required) “file_format_version”
+ *
+ * If more than one "layer" object are to be used, use the "layers" array instead.
+ *
+ * First get all required items and if any missing abort
+ */
+
+ cJSON *item, *layers_node, *layer_node;
+ uint16_t file_major_vers = 0;
+ uint16_t file_minor_vers = 0;
+ uint16_t file_patch_vers = 0;
+ char *vers_tok;
+ cJSON *disable_environment = NULL;
+ item = cJSON_GetObjectItem(json, "file_format_version");
+ if (item == NULL) {
+ return;
+ }
+ char *file_vers = cJSON_PrintUnformatted(item);
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
+ "Found manifest file %s, version %s", filename, file_vers);
+ // Get the major/minor/and patch as integers for easier comparison
+ vers_tok = strtok(file_vers, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_major_vers = atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_minor_vers = atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_patch_vers = atoi(vers_tok);
+ }
+ }
+ }
+ if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "%s Unexpected manifest file version (expected 1.0.0 or "
+ "1.0.1), may cause errors",
+ filename);
+ }
+ loader_tls_heap_free(file_vers);
+ // If "layers" is present, read in the array of layer objects
+ layers_node = cJSON_GetObjectItem(json, "layers");
+ if (layers_node != NULL) {
+ int numItems = cJSON_GetArraySize(layers_node);
+ if (file_major_vers == 1 && file_minor_vers == 0 &&
+ file_patch_vers == 0) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "\"layers\" tag not officially added until file version "
+ "1.0.1, but %s is reporting version %s",
+ filename, file_vers);
+ }
+ for (int curLayer = 0; curLayer < numItems; curLayer++) {
+ layer_node = cJSON_GetArrayItem(layers_node, curLayer);
+ if (layer_node == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Can't find \"layers\" array element %d object in "
+ "manifest JSON file %s, skipping this file",
+ curLayer, filename);
+ return;
+ }
+ loader_read_json_layer(inst, layer_instance_list, layer_node, item,
+ disable_environment, is_implicit, filename);
+ }
+ } else {
+ // Otherwise, try to read in individual layers
+ layer_node = cJSON_GetObjectItem(json, "layer");
+ if (layer_node == NULL) {
+ loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
+ "Can't find \"layer\" object in manifest JSON file %s, "
+ "skipping this file",
+ filename);
+ return;
+ }
+ // Loop through all "layer" objects in the file to get a count of them
+ // first.
+ uint16_t layer_count = 0;
+ cJSON *tempNode = layer_node;
+ do {
+ tempNode = tempNode->next;
+ layer_count++;
+ } while (tempNode != NULL);
+ /*
+ * Throw a warning if we encounter multiple "layer" objects in file
+ * versions newer than 1.0.0. Having multiple objects with the same
+ * name at the same level is actually a JSON standard violation.
+ */
+ if (layer_count > 1 &&
+ (file_major_vers > 1 ||
+ !(file_minor_vers == 0 && file_patch_vers == 0))) {
+ loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ "Multiple \"layer\" nodes are deprecated starting in "
+ "file version \"1.0.1\". Please use \"layers\" : [] "
+ "array instead in %s.",
+ filename);
+ } else {
+ do {
+ loader_read_json_layer(inst, layer_instance_list, layer_node,
+ item, disable_environment, is_implicit,
+ filename);
+ layer_node = layer_node->next;
+ } while (layer_node != NULL);
+ }
+ }
return;
}
@@ -2382,6 +2450,10 @@ void loader_destroy_icd_lib_list() {}
void loader_icd_scan(const struct loader_instance *inst,
struct loader_icd_libs *icds) {
char *file_str;
+ uint16_t file_major_vers = 0;
+ uint16_t file_minor_vers = 0;
+ uint16_t file_patch_vers = 0;
+ char *vers_tok;
struct loader_manifest_files manifest_files;
loader_scanned_icd_init(inst, icds);
@@ -2408,11 +2480,24 @@ void loader_icd_scan(const struct loader_instance *inst,
return;
}
char *file_vers = cJSON_Print(item);
+ // Get the major/minor/and patch as integers for easier comparison
+ vers_tok = strtok(file_vers, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_major_vers = atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_minor_vers = atoi(vers_tok);
+ vers_tok = strtok(NULL, ".\"\n\r");
+ if (NULL != vers_tok) {
+ file_patch_vers = atoi(vers_tok);
+ }
+ }
+ }
loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
"Found manifest file %s, version %s", file_str, file_vers);
- if (strcmp(file_vers, "\"1.0.0\"") != 0)
+ if (file_major_vers != 1 || file_minor_vers != 0 || file_patch_vers > 1)
loader_log(inst, VK_DEBUG_REPORT_WARNING_BIT_EXT, 0,
- "Unexpected manifest file version (expected 1.0.0), may "
+ "Unexpected manifest file version (expected 1.0.0 or 1.0.1), may "
"cause errors");
loader_tls_heap_free(file_vers);
itemICD = cJSON_GetObjectItem(json, "ICD");
@@ -3279,7 +3364,7 @@ loader_create_device_chain(const struct loader_physical_device_tramp *pd,
loader_platform_get_proc_address(
lib_handle, layer_prop->functions.str_gdpa);
if (!fpGDPA) {
- loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
+ loader_log(inst, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, 0,
"Failed to find vkGetDeviceProcAddr in layer %s",
layer_prop->lib_name);
continue;
diff --git a/loader/loader.h b/loader/loader.h
index 95803c01..ecc945ed 100644
--- a/loader/loader.h
+++ b/loader/loader.h
@@ -30,8 +30,9 @@
#include <vulkan/vulkan.h>
#include "vk_loader_platform.h"
-
+#include "vk_loader_layer.h"
#include <vulkan/vk_layer.h>
+
#include <vulkan/vk_icd.h>
#include <assert.h>
diff --git a/loader/vk_loader_layer.h b/loader/vk_loader_layer.h
new file mode 100644
index 00000000..2207c029
--- /dev/null
+++ b/loader/vk_loader_layer.h
@@ -0,0 +1,32 @@
+/*
+*
+* Copyright (c) 2016 The Khronos Group Inc.
+* Copyright (c) 2016 Valve Corporation
+* Copyright (c) 2016 LunarG, Inc.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+* Author: Mark Lobodzinski <mark@lunarg.com>
+*
+*/
+#pragma once
+
+// Linked list node for tree of debug callback functions
+typedef struct VkLayerDbgFunctionNode_ {
+ VkDebugReportCallbackEXT msgCallback;
+ PFN_vkDebugReportCallbackEXT pfnMsgCallback;
+ VkFlags msgFlags;
+ void *pUserData;
+ struct VkLayerDbgFunctionNode_ *pNext;
+} VkLayerDbgFunctionNode;
+
diff --git a/loader/wsi.c b/loader/wsi.c
index 3182a589..c5f527fb 100644
--- a/loader/wsi.c
+++ b/loader/wsi.c
@@ -536,7 +536,7 @@ terminator_CreateWin32SurfaceKHR(VkInstance instance,
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_win32_surface extension not enabled. "
"vkCreateWin32SurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -644,7 +644,7 @@ terminator_CreateMirSurfaceKHR(VkInstance instance,
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_mir_surface extension not enabled. "
"vkCreateMirSurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -743,7 +743,8 @@ vkCreateWaylandSurfaceKHR(VkInstance instance,
* This is the instance chain terminator function
* for CreateWaylandSurfaceKHR
*/
-VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(
+VKAPI_ATTR VkResult VKAPI_CALL
+terminator_CreateWaylandSurfaceKHR(
VkInstance instance, const VkWaylandSurfaceCreateInfoKHR *pCreateInfo,
const VkAllocationCallbacks *pAllocator, VkSurfaceKHR *pSurface) {
// First, check to ensure the appropriate extension was enabled:
@@ -752,7 +753,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateWaylandSurfaceKHR(
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_wayland_surface extension not enabled. "
"vkCreateWaylandSurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -862,7 +863,7 @@ terminator_CreateXcbSurfaceKHR(VkInstance instance,
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_xcb_surface extension not enabled. "
"vkCreateXcbSurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -973,7 +974,7 @@ terminator_CreateXlibSurfaceKHR(VkInstance instance,
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_xlib_surface extension not enabled. "
"vkCreateXlibSurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -1080,7 +1081,7 @@ terminator_CreateAndroidSurfaceKHR(VkInstance instance, Window window,
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_display extension not enabled. "
"vkCreateAndroidSurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -1293,7 +1294,7 @@ terminator_CreateDisplayModeKHR(VkPhysicalDevice physicalDevice,
loader_log(ptr_instance, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_display extension not enabled. "
"vkCreateDisplayModeKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
// Next, if so, proceed with the implementation of this function:
@@ -1368,7 +1369,7 @@ VKAPI_ATTR VkResult VKAPI_CALL terminator_CreateDisplayPlaneSurfaceKHR(
loader_log(inst, VK_DEBUG_REPORT_ERROR_BIT_EXT, 0,
"VK_KHR_surface extension not enabled. "
"vkCreateDisplayPlaneSurfaceKHR not executed!\n");
- return VK_SUCCESS;
+ return VK_ERROR_EXTENSION_NOT_PRESENT;
}
pIcdSurface = loader_heap_alloc(inst, sizeof(VkIcdSurfaceDisplay),
diff --git a/spirv-tools_revision b/spirv-tools_revision
index 9a829b9c..fa8390ba 100644
--- a/spirv-tools_revision
+++ b/spirv-tools_revision
@@ -1 +1 @@
-469f0e8fd53b527ad410c46bf18eee327c9256a3
+0d512bbef58dfcdb1a6bcde7fe17fcc4a33a1aa7
diff --git a/update_external_sources.bat b/update_external_sources.bat
index b9ff00df..b9ff00df 100755..100644
--- a/update_external_sources.bat
+++ b/update_external_sources.bat
diff --git a/vk-layer-generate.py b/vk-layer-generate.py
index 4e39c561..a645f4b4 100755
--- a/vk-layer-generate.py
+++ b/vk-layer-generate.py
@@ -289,7 +289,7 @@ class Subcommand(object):
def _gen_create_msg_callback(self):
r_body = []
r_body.append('%s' % self.lineinfo.get())
- r_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(')
+ r_body.append('VKAPI_ATTR VkResult VKAPI_CALL CreateDebugReportCallbackEXT(')
r_body.append(' VkInstance instance,')
r_body.append(' const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,')
r_body.append(' const VkAllocationCallbacks* pAllocator,')
@@ -302,6 +302,7 @@ class Subcommand(object):
r_body.append(' if (VK_SUCCESS == result) {')
r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
r_body.append(' result = layer_create_msg_callback(my_data->report_data,')
+ r_body.append(' false,')
r_body.append(' pCreateInfo,')
r_body.append(' pAllocator,')
r_body.append(' pCallback);')
@@ -311,7 +312,7 @@ class Subcommand(object):
r_body.append(' VkResult result = instance_dispatch_table(instance)->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pCallback);')
r_body.append(' if (VK_SUCCESS == result) {')
r_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);')
- r_body.append(' result = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pCallback);')
+ r_body.append(' result = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pCallback);')
r_body.append(' }')
r_body.append(' return result;')
r_body.append('}')
@@ -320,7 +321,7 @@ class Subcommand(object):
def _gen_destroy_msg_callback(self):
r_body = []
r_body.append('%s' % self.lineinfo.get())
- r_body.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)')
+ r_body.append('VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance, VkDebugReportCallbackEXT msgCallback, const VkAllocationCallbacks *pAllocator)')
r_body.append('{')
# Switch to this code section for the new per-instance storage and debug callbacks
if self.layer_name in ['object_tracker', 'unique_objects']:
@@ -336,7 +337,7 @@ class Subcommand(object):
def _gen_debug_report_msg(self):
r_body = []
r_body.append('%s' % self.lineinfo.get())
- r_body.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg)')
+ r_body.append('VKAPI_ATTR void VKAPI_CALL DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object, size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg)')
r_body.append('{')
# Switch to this code section for the new per-instance storage and debug callbacks
if self.layer_name == 'object_tracker':
@@ -347,79 +348,74 @@ class Subcommand(object):
r_body.append('}')
return "\n".join(r_body)
- def _gen_layer_get_global_extension_props(self, layer="object_tracker"):
- ggep_body = []
- # generated layers do not provide any global extensions
- ggep_body.append('%s' % self.lineinfo.get())
-
- ggep_body.append('')
- if self.layer_name == 'object_tracker':
- ggep_body.append('static const VkExtensionProperties instance_extensions[] = {')
- ggep_body.append(' {')
- ggep_body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,')
- ggep_body.append(' VK_EXT_DEBUG_REPORT_SPEC_VERSION')
- ggep_body.append(' }')
- ggep_body.append('};')
- ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)')
- ggep_body.append('{')
- if self.layer_name == 'object_tracker':
- ggep_body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);')
- else:
- ggep_body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
- ggep_body.append('}')
- return "\n".join(ggep_body)
-
- def _gen_layer_get_global_layer_props(self, layer="object_tracker"):
- ggep_body = []
- layer_name = re.sub('(.)([A-Z][a-z]+)', r'\1_\2', layer)
- layer_name = re.sub('([a-z0-9])([A-Z])', r'\1_\2', layer_name).lower()
- ggep_body.append('%s' % self.lineinfo.get())
- ggep_body.append('static const VkLayerProperties globalLayerProps[] = {')
- ggep_body.append(' {')
- if self.layer_name in ['unique_objects']:
- ggep_body.append(' "VK_LAYER_GOOGLE_%s",' % layer)
- ggep_body.append(' VK_LAYER_API_VERSION, // specVersion')
- ggep_body.append(' 1, // implementationVersion')
- ggep_body.append(' "Google Validation Layer"')
- else:
- ggep_body.append(' "VK_LAYER_LUNARG_%s",' % layer)
- ggep_body.append(' VK_LAYER_API_VERSION, // specVersion')
- ggep_body.append(' 1, // implementationVersion')
- ggep_body.append(' "LunarG Validation Layer"')
- ggep_body.append(' }')
- ggep_body.append('};')
- ggep_body.append('')
- ggep_body.append('%s' % self.lineinfo.get())
- ggep_body.append('')
- ggep_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
- ggep_body.append('{')
- ggep_body.append(' return util_GetLayerProperties(ARRAY_SIZE(globalLayerProps), globalLayerProps, pCount, pProperties);')
- ggep_body.append('}')
- return "\n".join(ggep_body)
-
- def _gen_layer_get_physical_device_layer_props(self, layer="object_tracker"):
- gpdlp_body = []
- gpdlp_body.append('%s' % self.lineinfo.get())
- gpdlp_body.append('static const VkLayerProperties deviceLayerProps[] = {')
- gpdlp_body.append(' {')
- if self.layer_name in ['unique_objects']:
- gpdlp_body.append(' "VK_LAYER_GOOGLE_%s",' % layer)
- gpdlp_body.append(' VK_LAYER_API_VERSION, // specVersion')
- gpdlp_body.append(' 1, // implementationVersion')
- gpdlp_body.append(' "Google Validation Layer"')
- else:
- gpdlp_body.append(' "VK_LAYER_LUNARG_%s",' % layer)
- gpdlp_body.append(' VK_LAYER_API_VERSION, // specVersion')
- gpdlp_body.append(' 1, // implementationVersion')
- gpdlp_body.append(' "LunarG Validation Layer"')
- gpdlp_body.append(' }')
- gpdlp_body.append('};')
- gpdlp_body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
- gpdlp_body.append('{')
- gpdlp_body.append(' return util_GetLayerProperties(ARRAY_SIZE(deviceLayerProps), deviceLayerProps, pCount, pProperties);')
- gpdlp_body.append('}')
- gpdlp_body.append('')
- return "\n".join(gpdlp_body)
+ def _gen_layer_logging_workaround(self):
+ body = []
+ body.append('%s' % self.lineinfo.get())
+ body.append('// vk_layer_logging.h expects these to be defined')
+ body.append('')
+ body.append('VKAPI_ATTR VkResult VKAPI_CALL')
+ body.append('vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,')
+ body.append(' const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {')
+ body.append(' return %s::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,')
+ body.append(' VkDebugReportCallbackEXT msgCallback,')
+ body.append(' const VkAllocationCallbacks *pAllocator) {')
+ body.append(' %s::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VKAPI_ATTR void VKAPI_CALL')
+ body.append('vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,')
+ body.append(' size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {')
+ body.append(' %s::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);' % self.layer_name)
+ body.append('}')
+
+ return "\n".join(body)
+
+ def _gen_layer_interface_v0_functions(self):
+ body = []
+ body.append('%s' % self.lineinfo.get())
+ body.append('// loader-layer interface v0, just wrappers since there is only a layer')
+ body.append('')
+
+ body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)')
+ body.append('{')
+ body.append(' return %s::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
+ body.append('{')
+ body.append(' return %s::EnumerateInstanceLayerProperties(pCount, pProperties);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
+ body.append('{')
+ body.append(' // the layer command handles VK_NULL_HANDLE just fine internally')
+ body.append(' assert(physicalDevice == VK_NULL_HANDLE);')
+ body.append(' return %s::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName)')
+ body.append('{')
+ body.append(' return %s::GetDeviceProcAddr(dev, funcName);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName)')
+ body.append('{')
+ body.append(' return %s::GetInstanceProcAddr(instance, funcName);' % self.layer_name)
+ body.append('}')
+ body.append('')
+ body.append('VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,')
+ body.append(' const char *pLayerName, uint32_t *pCount,')
+ body.append(' VkExtensionProperties *pProperties)')
+ body.append('{')
+ body.append(' // the layer command handles VK_NULL_HANDLE just fine internally')
+ body.append(' assert(physicalDevice == VK_NULL_HANDLE);')
+ body.append(' return %s::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);' % self.layer_name)
+ body.append('}')
+
+ return "\n".join(body)
def _generate_dispatch_entrypoints(self, qual=""):
if qual:
@@ -428,8 +424,13 @@ class Subcommand(object):
funcs = []
intercepted = []
for proto in self.protos:
- if proto.name == "GetDeviceProcAddr" or proto.name == "GetInstanceProcAddr":
- continue
+ if proto.name in ["EnumerateInstanceExtensionProperties",
+ "EnumerateInstanceLayerProperties",
+ "EnumerateDeviceLayerProperties",
+ "GetDeviceProcAddr",
+ "GetInstanceProcAddr"]:
+ funcs.append(proto.c_func(attr="VKAPI") + ';')
+ intercepted.append(proto)
else:
intercept = self.generate_intercept(proto, qual)
if intercept is None:
@@ -442,58 +443,41 @@ class Subcommand(object):
intercept = self._gen_debug_report_msg()
elif 'CreateDevice' == proto.name:
funcs.append('/* CreateDevice HERE */')
- elif 'EnumerateInstanceExtensionProperties' == proto.name:
- intercept = self._gen_layer_get_global_extension_props(self.layer_name)
- elif 'EnumerateInstanceLayerProperties' == proto.name:
- intercept = self._gen_layer_get_global_layer_props(self.layer_name)
- elif 'EnumerateDeviceLayerProperties' == proto.name:
- intercept = self._gen_layer_get_physical_device_layer_props(self.layer_name)
if intercept is not None:
funcs.append(intercept)
if not "KHR" in proto.name:
intercepted.append(proto)
- prefix="vk"
- lookups = []
+ instance_lookups = []
+ device_lookups = []
for proto in intercepted:
- lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
- lookups.append(" return (PFN_vkVoidFunction) %s%s;" %
- (prefix, proto.name))
+ if proto_is_global(proto):
+ instance_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
+ instance_lookups.append(" return (PFN_vkVoidFunction) %s;" % (proto.name))
+ else:
+ device_lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
+ device_lookups.append(" return (PFN_vkVoidFunction) %s;" % (proto.name))
- # add customized layer_intercept_proc
+ # add customized intercept_core_device_command
body = []
body.append('%s' % self.lineinfo.get())
- body.append("static inline PFN_vkVoidFunction layer_intercept_proc(const char *name)")
+ body.append("static inline PFN_vkVoidFunction intercept_core_device_command(const char *name)")
body.append("{")
body.append(generate_get_proc_addr_check("name"))
body.append("")
body.append(" name += 2;")
- body.append(" %s" % "\n ".join(lookups))
+ body.append(" %s" % "\n ".join(device_lookups))
body.append("")
body.append(" return NULL;")
body.append("}")
- # add layer_intercept_instance_proc
- lookups = []
- for proto in self.protos:
- if not proto_is_global(proto):
- continue
-
- if not proto in intercepted:
- continue
- if proto.name == "CreateInstance":
- continue
- if proto.name == "CreateDevice":
- continue
- lookups.append("if (!strcmp(name, \"%s\"))" % proto.name)
- lookups.append(" return (PFN_vkVoidFunction) %s%s;" % (prefix, proto.name))
-
- body.append("static inline PFN_vkVoidFunction layer_intercept_instance_proc(const char *name)")
+ # add intercept_core_instance_command
+ body.append("static inline PFN_vkVoidFunction intercept_core_instance_command(const char *name)")
body.append("{")
body.append(generate_get_proc_addr_check("name"))
body.append("")
body.append(" name += 2;")
- body.append(" %s" % "\n ".join(lookups))
+ body.append(" %s" % "\n ".join(instance_lookups))
body.append("")
body.append(" return NULL;")
body.append("}")
@@ -509,86 +493,153 @@ class Subcommand(object):
exts.append(self._gen_debug_report_msg())
return "\n".join(exts)
+ def _generate_layer_introspection_function(self):
+ body = []
+ body.append('%s' % self.lineinfo.get())
+ if self.layer_name == 'object_tracker':
+ body.append('static const VkExtensionProperties instance_extensions[] = {')
+ body.append(' {')
+ body.append(' VK_EXT_DEBUG_REPORT_EXTENSION_NAME,')
+ body.append(' VK_EXT_DEBUG_REPORT_SPEC_VERSION')
+ body.append(' }')
+ body.append('};')
+ body.append('')
+
+ body.append('static const VkLayerProperties globalLayerProps = {')
+ body.append(' "VK_LAYER_LUNARG_%s",' % self.layer_name)
+ body.append(' VK_LAYER_API_VERSION, // specVersion')
+ body.append(' 1, // implementationVersion')
+ body.append(' "LunarG Validation Layer"')
+ body.append('};')
+ body.append('')
+ else:
+ body.append('static const VkLayerProperties globalLayerProps = {')
+ body.append(' "VK_LAYER_GOOGLE_%s",' % self.layer_name)
+ body.append(' VK_LAYER_API_VERSION, // specVersion')
+ body.append(' 1, // implementationVersion')
+ body.append(' "Google Validation Layer"')
+ body.append('};')
+ body.append('')
+
+ body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties* pProperties)')
+ body.append('{')
+ body.append(' return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);')
+ body.append('}')
+ body.append('')
+ body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties* pProperties)')
+ body.append('{')
+ body.append(' return util_GetLayerProperties(1, &globalLayerProps, pCount, pProperties);')
+ body.append('}')
+ body.append('')
+ body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties* pProperties)')
+ body.append('{')
+ body.append(' if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))')
+ if self.layer_name == 'object_tracker':
+ body.append(' return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);')
+ else:
+ body.append(' return util_GetExtensionProperties(0, NULL, pCount, pProperties);')
+ body.append('')
+ body.append(' return VK_ERROR_LAYER_NOT_PRESENT;')
+ body.append('}')
+ body.append('')
+ body.append('VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,')
+ body.append(' const char *pLayerName, uint32_t *pCount,')
+ body.append(' VkExtensionProperties *pProperties)')
+ body.append('{')
+ body.append(' if (pLayerName && !strcmp(pLayerName, globalLayerProps.layerName))')
+ body.append(' return util_GetExtensionProperties(0, nullptr, pCount, pProperties);')
+ body.append('')
+ body.append(' assert(physicalDevice);')
+ body.append(' VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, physicalDevice);' % self.layer_name)
+ body.append(' return pTable->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);')
+ body.append('}')
+
+ return "\n".join(body)
+
def _generate_layer_gpa_function(self, extensions=[], instance_extensions=[]):
func_body = []
#
# New style of GPA Functions for the new layer_data/layer_logging changes
#
if self.layer_name in ['object_tracker', 'unique_objects']:
- func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
+ for ext_enable, ext_list in extensions:
+ func_body.append('%s' % self.lineinfo.get())
+ func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkDevice dev)' % ext_enable)
+ func_body.append('{')
+ func_body.append(' if (dev) {')
+ func_body.append(' layer_data *my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);')
+ func_body.append(' if (!my_data->%s)' % ext_enable)
+ func_body.append(' return nullptr;')
+ func_body.append(' }\n')
+
+ for ext_name in ext_list:
+ func_body.append(' if (!strcmp("%s", name))\n'
+ ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (ext_name, ext_name[2:]))
+ func_body.append('\n return nullptr;')
+ func_body.append('}\n')
+
+ func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* funcName)\n"
"{\n"
" PFN_vkVoidFunction addr;\n"
- " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
- " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
- " }\n\n"
- " addr = layer_intercept_proc(funcName);\n"
+ " addr = intercept_core_device_command(funcName);\n"
" if (addr)\n"
" return addr;\n"
- " if (device == VK_NULL_HANDLE) {\n"
- " return NULL;\n"
- " }\n")
- if 0 != len(extensions):
- func_body.append('%s' % self.lineinfo.get())
- func_body.append(' layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);')
- for (ext_enable, ext_list) in extensions:
- extra_space = ""
- if 0 != len(ext_enable):
- func_body.append(' if (my_device_data->%s) {' % ext_enable)
- extra_space = " "
- for ext_name in ext_list:
- func_body.append(' %sif (!strcmp("%s", funcName))\n'
- ' %sreturn reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, extra_space, ext_name))
- if 0 != len(ext_enable):
- func_body.append(' }\n')
+ " assert(device);\n")
+ for ext_enable, _ in extensions:
+ func_body.append(' addr = intercept_%s_command(funcName, device);' % ext_enable)
+ func_body.append(' if (addr)\n'
+ ' return addr;')
func_body.append("\n if (get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr == NULL)\n"
" return NULL;\n"
" return get_dispatch_table(%s_device_table_map, device)->GetDeviceProcAddr(device, funcName);\n"
"}\n" % (self.layer_name, self.layer_name))
- func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
+
+ for ext_enable, ext_list in instance_extensions:
+ func_body.append('%s' % self.lineinfo.get())
+ func_body.append('static inline PFN_vkVoidFunction intercept_%s_command(const char *name, VkInstance instance)' % ext_enable)
+ func_body.append('{')
+ if ext_enable == 'msg_callback_get_proc_addr':
+ func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
+ " return debug_report_get_instance_proc_addr(my_data->report_data, name);")
+ else:
+ func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
+ func_body.append(' if (instanceExtMap.size() == 0 || !instanceExtMap[pTable].%s)' % ext_enable)
+ func_body.append(' return nullptr;\n')
+
+ for ext_name in ext_list:
+ if wsi_name(ext_name):
+ func_body.append('%s' % wsi_ifdef(ext_name))
+ func_body.append(' if (!strcmp("%s", name))\n'
+ ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (ext_name, ext_name[2:]))
+ if wsi_name(ext_name):
+ func_body.append('%s' % wsi_endif(ext_name))
+
+ func_body.append('\n return nullptr;')
+ func_body.append('}\n')
+
+ func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
"{\n"
" PFN_vkVoidFunction addr;\n"
- " if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
- " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
- " if (!strcmp(funcName, \"vkCreateInstance\"))\n"
- " return (PFN_vkVoidFunction) vkCreateInstance;\n"
- " if (!strcmp(funcName, \"vkCreateDevice\"))\n"
- " return (PFN_vkVoidFunction) vkCreateDevice;\n"
- " addr = layer_intercept_instance_proc(funcName);\n"
- " if (addr) {\n"
- " return addr;"
- " }\n"
- " if (instance == VK_NULL_HANDLE) {\n"
- " return NULL;\n"
+ " addr = intercept_core_instance_command(funcName);\n"
+ " if (!addr) {\n"
+ " addr = intercept_core_device_command(funcName);\n"
+ " }")
+
+ for ext_enable, _ in extensions:
+ func_body.append(" if (!addr) {\n"
+ " addr = intercept_%s_command(funcName, VkDevice(VK_NULL_HANDLE));\n"
+ " }" % ext_enable)
+
+ func_body.append(" if (addr) {\n"
+ " return addr;\n"
" }\n"
+ " assert(instance);\n"
)
- table_declared = False
- if 0 != len(instance_extensions):
- for (ext_enable, ext_list) in instance_extensions:
- extra_space = ""
- if 0 != len(ext_enable):
- if ext_enable == 'msg_callback_get_proc_addr':
- func_body.append(" layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);\n"
- " addr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);\n"
- " if (addr) {\n"
- " return addr;\n"
- " }\n")
- else:
- if table_declared == False:
- func_body.append(" VkLayerInstanceDispatchTable* pTable = get_dispatch_table(%s_instance_table_map, instance);" % self.layer_name)
- table_declared = True
- func_body.append(' if (instanceExtMap.size() != 0 && instanceExtMap[pTable].%s)' % ext_enable)
- func_body.append(' {')
- extra_space = " "
- for ext_name in ext_list:
- if wsi_name(ext_name):
- func_body.append('%s' % wsi_ifdef(ext_name))
- func_body.append(' %sif (!strcmp("%s", funcName))\n'
- ' return reinterpret_cast<PFN_vkVoidFunction>(%s);' % (extra_space, ext_name, ext_name))
- if wsi_name(ext_name):
- func_body.append('%s' % wsi_endif(ext_name))
- if 0 != len(ext_enable):
- func_body.append(' }\n')
+ for ext_enable, _ in instance_extensions:
+ func_body.append(' addr = intercept_%s_command(funcName, instance);' % ext_enable)
+ func_body.append(' if (addr)\n'
+ ' return addr;\n')
func_body.append(" if (get_dispatch_table(%s_instance_table_map, instance)->GetInstanceProcAddr == NULL) {\n"
" return NULL;\n"
@@ -598,20 +649,15 @@ class Subcommand(object):
return "\n".join(func_body)
else:
func_body.append('%s' % self.lineinfo.get())
- func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)\n"
+ func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char* funcName)\n"
"{\n"
" PFN_vkVoidFunction addr;\n")
func_body.append("\n"
" loader_platform_thread_once(&initOnce, init%s);\n\n"
- " if (!strcmp(\"vkGetDeviceProcAddr\", funcName)) {\n"
- " return (PFN_vkVoidFunction) vkGetDeviceProcAddr;\n"
- " }\n\n"
- " addr = layer_intercept_proc(funcName);\n"
+ " addr = intercept_core_device_command(funcName);\n"
" if (addr)\n"
" return addr;" % self.layer_name)
- func_body.append(" if (device == VK_NULL_HANDLE) {\n"
- " return NULL;\n"
- " }\n")
+ func_body.append(" assert(device);\n")
func_body.append('')
func_body.append(' VkLayerDispatchTable *pDisp = device_dispatch_table(device);')
if 0 != len(extensions):
@@ -634,24 +680,16 @@ class Subcommand(object):
" }\n"
"}\n")
func_body.append('%s' % self.lineinfo.get())
- func_body.append("VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
+ func_body.append("VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)\n"
"{\n"
" PFN_vkVoidFunction addr;\n"
- " if (!strcmp(funcName, \"vkGetInstanceProcAddr\"))\n"
- " return (PFN_vkVoidFunction) vkGetInstanceProcAddr;\n"
- " if (!strcmp(funcName, \"vkCreateInstance\"))\n"
- " return (PFN_vkVoidFunction) vkCreateInstance;\n"
- " if (!strcmp(funcName, \"vkCreateDevice\"))\n"
- " return (PFN_vkVoidFunction) vkCreateDevice;\n"
)
func_body.append(
" loader_platform_thread_once(&initOnce, init%s);\n\n"
- " addr = layer_intercept_instance_proc(funcName);\n"
+ " addr = intercept_core_instance_command(funcName);\n"
" if (addr)\n"
" return addr;" % self.layer_name)
- func_body.append(" if (instance == VK_NULL_HANDLE) {\n"
- " return NULL;\n"
- " }\n")
+ func_body.append(" assert(instance);\n")
func_body.append("")
func_body.append(" VkLayerInstanceDispatchTable* pTable = instance_dispatch_table(instance);\n")
if 0 != len(instance_extensions):
@@ -872,7 +910,7 @@ class ObjectTrackerSubcommand(Subcommand):
def generate_destroy_instance(self):
gedi_txt = []
gedi_txt.append('%s' % self.lineinfo.get())
- gedi_txt.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(')
+ gedi_txt.append('VKAPI_ATTR void VKAPI_CALL DestroyInstance(')
gedi_txt.append('VkInstance instance,')
gedi_txt.append('const VkAllocationCallbacks* pAllocator)')
gedi_txt.append('{')
@@ -959,7 +997,7 @@ class ObjectTrackerSubcommand(Subcommand):
def generate_destroy_device(self):
gedd_txt = []
gedd_txt.append('%s' % self.lineinfo.get())
- gedd_txt.append('VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(')
+ gedd_txt.append('VKAPI_ATTR void VKAPI_CALL DestroyDevice(')
gedd_txt.append('VkDevice device,')
gedd_txt.append('const VkAllocationCallbacks* pAllocator)')
gedd_txt.append('{')
@@ -1128,7 +1166,7 @@ class ObjectTrackerSubcommand(Subcommand):
"DestroySwapchainKHR",
"GetSwapchainImagesKHR"
]
- decl = proto.c_func(prefix="vk", attr="VKAPI")
+ decl = proto.c_func(attr="VKAPI")
param0_name = proto.params[0].name
using_line = ''
create_line = ''
@@ -1344,14 +1382,19 @@ class ObjectTrackerSubcommand(Subcommand):
print('Error: Undefined DisplayServer')
instance_extensions=[]
- body = [self.generate_maps(),
+ body = ["namespace %s {" % self.layer_name,
+ self.generate_maps(),
self.generate_procs(),
self.generate_destroy_instance(),
self.generate_destroy_device(),
- self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
+ self._generate_dispatch_entrypoints(),
self._generate_extensions(),
+ self._generate_layer_introspection_function(),
self._generate_layer_gpa_function(extensions,
- instance_extensions)]
+ instance_extensions),
+ "} // namespace %s" % self.layer_name,
+ self._gen_layer_logging_workaround(),
+ self._gen_layer_interface_v0_functions()]
return "\n\n".join(body)
class UniqueObjectsSubcommand(Subcommand):
@@ -1465,7 +1508,7 @@ class UniqueObjectsSubcommand(Subcommand):
post_call_txt = '' # code following call down chain such to wrap newly created ndos, or destroy local wrap struct
funcs = []
indent = ' ' # indent level for generated code
- decl = proto.c_func(prefix="vk", attr="VKAPI")
+ decl = proto.c_func(attr="VKAPI")
# A few API cases that are manual code
# TODO : Special case Create*Pipelines funcs to handle creating multiple unique objects
explicit_object_tracker_functions = ['GetSwapchainImagesKHR',
@@ -1649,9 +1692,13 @@ class UniqueObjectsSubcommand(Subcommand):
print('Error: Undefined DisplayServer')
instance_extensions=[]
- body = [self._generate_dispatch_entrypoints("VK_LAYER_EXPORT"),
+ body = ["namespace %s {" % self.layer_name,
+ self._generate_dispatch_entrypoints(),
+ self._generate_layer_introspection_function(),
self._generate_layer_gpa_function(extensions,
- instance_extensions)]
+ instance_extensions),
+ "} // namespace %s" % self.layer_name,
+ self._gen_layer_interface_v0_functions()]
return "\n\n".join(body)
def main():
diff --git a/vk-layer-introspect b/vk-layer-introspect
new file mode 100755
index 00000000..e64373e1
--- /dev/null
+++ b/vk-layer-introspect
@@ -0,0 +1,399 @@
+#!/usr/bin/env python3
+#
+# Copyright (c) 2016 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.
+
+import argparse
+import ctypes
+import json
+import os
+import platform
+import sys
+import xml.etree.ElementTree
+
+if platform.system() == "Windows":
+ VKAPI_DLL = ctypes.windll
+ VKAPI_FUNCTYPE = ctypes.WINFUNCTYPE
+else:
+ VKAPI_DLL = ctypes.cdll
+ VKAPI_FUNCTYPE = ctypes.CFUNCTYPE
+
+# Vulkan types
+
+VkInstance = ctypes.c_void_p
+VkPhysicalDevice = ctypes.c_void_p
+VkDevice = ctypes.c_void_p
+VkResult = ctypes.c_int
+
+
+class VkLayerProperties(ctypes.Structure):
+ _fields_ = [("c_layerName", ctypes.c_char * 256),
+ ("c_specVersion", ctypes.c_uint32),
+ ("c_implementationVersion", ctypes.c_uint32),
+ ("c_description", ctypes.c_char * 256)]
+
+ def layer_name(self):
+ return self.c_layerName.decode()
+
+ def spec_version(self):
+ return "%d.%d.%d" % (
+ self.c_specVersion >> 22,
+ (self.c_specVersion >> 12) & 0x3ff,
+ self.c_specVersion & 0xfff)
+
+ def implementation_version(self):
+ return str(self.c_implementationVersion)
+
+ def description(self):
+ return self.c_description.decode()
+
+ def __eq__(self, other):
+ return (self.c_layerName == other.c_layerName and
+ self.c_specVersion == other.c_specVersion and
+ self.c_implementationVersion == other.c_implementationVersion and
+ self.c_description == other.c_description)
+
+
+class VkExtensionProperties(ctypes.Structure):
+ _fields_ = [("c_extensionName", ctypes.c_char * 256),
+ ("c_specVersion", ctypes.c_uint32)]
+
+ def extension_name(self):
+ return self.c_extensionName.decode()
+
+ def spec_version(self):
+ return str(self.c_specVersion)
+
+# Vulkan commands
+
+PFN_vkVoidFunction = VKAPI_FUNCTYPE(None)
+PFN_vkEnumerateInstanceExtensionProperties = VKAPI_FUNCTYPE(
+ VkResult, ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(VkExtensionProperties))
+PFN_vkEnumerateDeviceExtensionProperties = VKAPI_FUNCTYPE(
+ VkResult, VkPhysicalDevice, ctypes.c_char_p, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(VkExtensionProperties))
+PFN_vkEnumerateInstanceLayerProperties = VKAPI_FUNCTYPE(
+ VkResult, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(VkLayerProperties))
+PFN_vkEnumerateDeviceLayerProperties = VKAPI_FUNCTYPE(
+ VkResult, VkPhysicalDevice, ctypes.POINTER(ctypes.c_uint32), ctypes.POINTER(VkLayerProperties))
+PFN_vkGetInstanceProcAddr = VKAPI_FUNCTYPE(
+ PFN_vkVoidFunction, VkInstance, ctypes.c_char_p)
+PFN_vkGetDeviceProcAddr = VKAPI_FUNCTYPE(
+ PFN_vkVoidFunction, VkDevice, ctypes.c_char_p)
+
+
+class Layer(object):
+
+ def __init__(self, *args):
+ self.props = args[0]
+ self.is_global = args[1]
+ self.instance_extensions = args[2]
+ self.device_extensions = args[3]
+ self.gipa_name = args[4]
+ self.gdpa_name = args[5]
+
+
+class LayerLibrary(object):
+
+ def __init__(self, path):
+ self.library = None
+ self.version = 0
+
+ self._load(path)
+ self._negotiate_version()
+
+ def introspect(self):
+ if self.version == 0:
+ layers = self._enumerate_layers_v0()
+ else:
+ raise RuntimeError("unsupported v%d library" % self.version)
+
+ return layers
+
+ def _load(self, path):
+ try:
+ abspath = os.path.abspath(path)
+ self.library = VKAPI_DLL.LoadLibrary(abspath)
+ except OSError:
+ raise RuntimeError("failed to load library")
+
+ def _unload(self):
+ # no clean way to unload
+ pass
+
+ def _negotiate_version(self):
+ # only v0
+ self.version = 0
+
+ def _enumerate_properties_errcheck_v0(self, result, func, args):
+ if isinstance(func, PFN_vkEnumerateInstanceLayerProperties):
+ func_name = "vkEnumerateInstanceLayerProperties"
+ elif isinstance(func, PFN_vkEnumerateDeviceLayerProperties):
+ func_name = "vkEnumerateDeviceLayerProperties"
+ elif isinstance(func, PFN_vkEnumerateInstanceExtensionProperties):
+ func_name = "vkEnumerateInstanceExtensionProperties"
+ elif isinstance(func, PFN_vkEnumerateDeviceExtensionProperties):
+ func_name = "vkEnumerateDeviceExtensionProperties"
+ else:
+ raise AssertionError("unexpected vkEnumerate*Properties call")
+
+ if result != 0:
+ raise RuntimeError(func_name + " failed with " + str(result))
+
+ # pProperties and pCount mismatch
+ if args[-1] and len(args[-1]) != args[-2].value:
+ raise RuntimeError("invalid pCount returned in " + func_name)
+
+ return args[-1]
+
+ def _enumerate_properties_prototype_v0(self, func_name):
+ prototypes = {
+ "vkEnumerateInstanceLayerProperties":
+ PFN_vkEnumerateInstanceLayerProperties,
+ "vkEnumerateDeviceLayerProperties":
+ PFN_vkEnumerateDeviceLayerProperties,
+ "vkEnumerateInstanceExtensionProperties":
+ PFN_vkEnumerateInstanceExtensionProperties,
+ "vkEnumerateDeviceExtensionProperties":
+ PFN_vkEnumerateDeviceExtensionProperties,
+ }
+ prototype = prototypes[func_name]
+
+ try:
+ proc = prototype((func_name, self.library))
+ except AttributeError:
+ raise RuntimeError(func_name + " is missing")
+
+ proc.errcheck = self._enumerate_properties_errcheck_v0
+
+ return proc
+
+ def _get_gipa_name_v0(self, layer_name, can_fallback):
+ names = [layer_name + "GetInstanceProcAddr"]
+ if can_fallback:
+ names.append("vkGetInstanceProcAddr")
+
+ for name in names:
+ try:
+ PFN_vkGetInstanceProcAddr((name, self.library))
+ return name
+ except AttributeError:
+ pass
+
+ raise RuntimeError(" or ".join(names) + " is missing")
+
+ def _get_gdpa_name_v0(self, layer_name, can_fallback):
+ names = [layer_name + "GetDeviceProcAddr"]
+ if can_fallback:
+ names.append("vkGetDeviceProcAddr")
+
+ for name in names:
+ try:
+ PFN_vkGetDeviceProcAddr((name, self.library))
+ return name
+ except AttributeError:
+ pass
+
+ raise RuntimeError(" or ".join(names) + " is missing")
+
+ def _enumerate_layers_v0(self):
+ tmp_count = ctypes.c_uint32()
+
+ # enumerate instance layers
+ enumerate_instance_layer_properties = self._enumerate_properties_prototype_v0(
+ "vkEnumerateInstanceLayerProperties")
+ enumerate_instance_layer_properties(tmp_count, None)
+ p_props = enumerate_instance_layer_properties(
+ tmp_count, (VkLayerProperties * tmp_count.value)())
+
+ # enumerate device layers
+ enumerate_device_layer_properties = self._enumerate_properties_prototype_v0(
+ "vkEnumerateDeviceLayerProperties")
+ enumerate_device_layer_properties(None, tmp_count, None)
+ dev_p_props = enumerate_device_layer_properties(
+ None, tmp_count, (VkLayerProperties * tmp_count.value)())
+
+ # there must not be device-only layers
+ for props in dev_p_props:
+ if props not in p_props:
+ raise RuntimeError(
+ "unexpected device-only layer " + props.layer_name())
+
+ layers = []
+ for props in p_props:
+ is_global = (props in dev_p_props)
+
+ # enumerate instance extensions
+ enumerate_instance_extension_properties = self._enumerate_properties_prototype_v0(
+ "vkEnumerateInstanceExtensionProperties")
+ enumerate_instance_extension_properties(
+ props.c_layerName, tmp_count, None)
+ instance_extensions = enumerate_instance_extension_properties(
+ props.c_layerName,
+ tmp_count,
+ (VkExtensionProperties * tmp_count.value)())
+
+ gipa_name = self._get_gipa_name_v0(
+ props.layer_name(),
+ len(p_props) == 1)
+
+ if is_global:
+ # enumerate device extensions
+ enumerate_device_extension_properties = self._enumerate_properties_prototype_v0(
+ "vkEnumerateDeviceExtensionProperties")
+ enumerate_device_extension_properties(
+ None, props.c_layerName, tmp_count, None)
+ device_extensions = enumerate_device_extension_properties(
+ None,
+ props.c_layerName,
+ tmp_count,
+ (VkExtensionProperties * tmp_count.value)())
+
+ gdpa_name = self._get_gdpa_name_v0(
+ props.layer_name(),
+ len(p_props) == 1)
+ else:
+ device_extensions = None
+ gdpa_name = None
+
+ layers.append(
+ Layer(props, is_global, instance_extensions, device_extensions, gipa_name, gdpa_name))
+
+ return layers
+
+
+def serialize_layers(layers, path, ext_cmds):
+ data = {}
+ data["file_format_version"] = '1.0.0'
+
+ for idx, layer in enumerate(layers):
+ layer_data = {}
+
+ layer_data["name"] = layer.props.layer_name()
+ layer_data["api_version"] = layer.props.spec_version()
+ layer_data[
+ "implementation_version"] = layer.props.implementation_version()
+ layer_data["description"] = layer.props.description()
+
+ layer_data["type"] = "GLOBAL" if layer.is_global else "INSTANCE"
+
+ # TODO more flexible
+ layer_data["library_path"] = os.path.join(".", os.path.basename(path))
+
+ funcs = {}
+ if layer.gipa_name != "vkGetInstanceProcAddr":
+ funcs["vkGetInstanceProcAddr"] = layer.gipa_name
+ if layer.is_global and layer.gdpa_name != "vkGetDeviceProcAddr":
+ funcs["vkGetDeviceProcAddr"] = layer.gdpa_name
+ if funcs:
+ layer_data["functions"] = funcs
+
+ if layer.instance_extensions:
+ exts = [{
+ "name": ext.extension_name(),
+ "spec_version": ext.spec_version(),
+ } for ext in layer.instance_extensions]
+ layer_data["instance_extensions"] = exts
+
+ if layer.device_extensions:
+ exts = []
+ for ext in layer.device_extensions:
+ try:
+ cmds = ext_cmds[ext.extension_name()]
+ except KeyError:
+ raise RuntimeError(
+ "unknown device extension " + ext.extension_name())
+ else:
+ ext_data = {}
+ ext_data["name"] = ext.extension_name()
+ ext_data["spec_version"] = ext.spec_version()
+ if cmds:
+ ext_data["entrypoints"] = cmds
+
+ exts.append(ext_data)
+
+ layer_data["device_extensions"] = exts
+
+ if idx > 0:
+ data["layer.%d" % idx] = layer_data
+ else:
+ data["layer"] = layer_data
+
+ return data
+
+
+def dump_json(data):
+ dump = json.dumps(data, indent=4, sort_keys=True)
+
+ # replace "layer.<idx>" by "layer"
+ lines = dump.split("\n")
+ for line in lines:
+ if line.startswith(" \"layer.") and line.endswith("\": {"):
+ line = " \"layer\": {"
+ print(line)
+
+
+def parse_vk_xml(path):
+ """Parse vk.xml to get commands added by extensions."""
+ tree = xml.etree.ElementTree.parse(path)
+ extensions = tree.find("extensions")
+
+ ext_cmds = {}
+ for ext in extensions.iter("extension"):
+ if ext.attrib["supported"] != "vulkan":
+ continue
+
+ cmds = []
+ for cmd in ext.iter("command"):
+ cmds.append(cmd.attrib["name"])
+
+ ext_cmds[ext.attrib["name"]] = cmds
+
+ return ext_cmds
+
+
+def add_custom_ext_cmds(ext_cmds):
+ """Add commands added by in-development extensions."""
+ # VK_LAYER_LUNARG_basic
+ ext_cmds["vkLayerBasicEXT"] = ["vkLayerBasicEXT"]
+
+
+def main():
+ default_vk_xml = sys.path[0] + "/vk.xml" if sys.path[0] else "vk.xml"
+
+ parser = argparse.ArgumentParser(description="Introspect a layer library.")
+ parser.add_argument(
+ "-x", dest="vk_xml", default=default_vk_xml, help="Path to vk.xml")
+ parser.add_argument(
+ "layer_libs", metavar="layer-lib", nargs="+", help="Path to a layer library")
+ args = parser.parse_args()
+
+ try:
+ ext_cmds = parse_vk_xml(args.vk_xml)
+ except Exception as e:
+ print("failed to parse %s: %s" % (args.vk_xml, e))
+ sys.exit(-1)
+
+ add_custom_ext_cmds(ext_cmds)
+
+ for path in args.layer_libs:
+ try:
+ ll = LayerLibrary(path)
+ layers = ll.introspect()
+ data = serialize_layers(layers, path, ext_cmds)
+ dump_json(data)
+ except RuntimeError as err:
+ print("skipping %s: %s" % (path, err))
+
+if __name__ == "__main__":
+ main()
diff --git a/vk.xml b/vk.xml
index 6aecf317..b179211f 100644
--- a/vk.xml
+++ b/vk.xml
@@ -3,17 +3,24 @@
<comment>
Copyright (c) 2015-2016 The Khronos Group Inc.
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
+Permission is hereby granted, free of charge, to any person obtaining a
+copy of this software and/or associated documentation files (the
+"Materials"), to deal in the Materials without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Materials, and to
+permit persons to whom the Materials are furnished to do so, subject to
+the following conditions:
- http://www.apache.org/licenses/LICENSE-2.0
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Materials.
- 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.
+THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
------------------------------------------------------------------------
@@ -94,7 +101,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<type category="define">// Vulkan 1.0 version number
#define <name>VK_API_VERSION_1_0</name> <type>VK_MAKE_VERSION</type>(1, 0, 0)</type> <!-- The patch version here should never be set to anything other than 0 -->
<type category="define">// Version of this file
-#define <name>VK_HEADER_VERSION</name> 12</type>
+#define <name>VK_HEADER_VERSION</name> 13</type>
<type category="define">
#define <name>VK_DEFINE_HANDLE</name>(object) typedef struct object##_T* object;</type>
@@ -498,7 +505,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<member len="enabledExtensionCount,null-terminated">const <type>char</type>* const* <name>ppEnabledExtensionNames</name></member>
<member optional="true">const <type>VkPhysicalDeviceFeatures</type>* <name>pEnabledFeatures</name></member>
<validity>
- <usage>Any given element of pname:ppEnabledLayerNames must: be the name of a layer present on the system, exactly matching a string returned in the sname:VkLayerProperties structure by fname:vkEnumerateDeviceLayerProperties</usage>
+ <usage>pname:ppEnabledLayerNames must: either be sname:NULL or contain the same sequence of layer names that was enabled when creating the parent instance</usage>
<usage>Any given element of pname:ppEnabledExtensionNames must: be the name of an extension present on the system, exactly matching a string returned in the sname:VkExtensionProperties structure by fname:vkEnumerateDeviceExtensionProperties</usage>
<usage>If an extension listed in pname:ppEnabledExtensionNames is provided as part of a layer, then both the layer and extension must: be enabled to enable that extension</usage>
<usage>The pname:queueFamilyIndex member of any given element of pname:pQueueCreateInfos must: be unique within pname:pQueueCreateInfos</usage>
@@ -1919,7 +1926,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<member optional="true"><type>uint32_t</type> <name>signalSemaphoreCount</name></member>
<member len="signalSemaphoreCount">const <type>VkSemaphore</type>* <name>pSignalSemaphores</name></member>
<validity>
- <usage>Any given element of pname:pSignalSemaphores must: currently be unsignalled</usage>
+ <usage>Any given element of pname:pSignalSemaphores must: currently be unsignaled</usage>
<usage>Any given element of pname:pCommandBuffers must: either have been recorded with the ename:VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, or not currently be executing on the device</usage>
<usage>Any given element of pname:pCommandBuffers must: be in the executable state</usage>
<usage>If any given element of pname:pCommandBuffers contains commands that execute secondary command buffers, those secondary command buffers must: have been recorded with the ename:VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT, or not currently be executing on the device</usage>
@@ -2088,7 +2095,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<member optional="true"><type>VkSwapchainKHR</type> <name>oldSwapchain</name></member> <!-- Existing swap chain to replace, if any -->
<validity>
<usage>pname:surface must: be a surface that is supported by the device as determined using fname:vkGetPhysicalDeviceSurfaceSupportKHR</usage>
- <usage>The native window referred to by pname:surface mustnot: already be associated with a swapchain other than pname:oldSwapchain, or with a non-{apiname} graphics API surface</usage>
+ <usage>The native window referred to by pname:surface mustnot: already be associated with a swapchain other than pname:oldSwapchain, or with a non-Vulkan graphics API surface</usage>
<usage>pname:minImageCount must: be greater than or equal to the value returned in the pname:minImageCount member of the sname:VkSurfaceCapabilitiesKHR structure returned by fname:vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface</usage>
<usage>pname:minImageCount must: be less than or equal to the value returned in the pname:maxImageCount member of the sname:VkSurfaceCapabilitiesKHR structure returned by fname:vkGetPhysicalDeviceSurfaceCapabilitiesKHR for the surface if the returned pname:maxImageCount is not zero</usage>
<usage>pname:imageFormat and pname:imageColorspace must: match the pname:format and pname:colorSpace members, respectively, of one of the sname:VkSurfaceFormatKHR structures returned by fname:vkGetPhysicalDeviceSurfaceFormatsKHR for the surface</usage>
@@ -2650,7 +2657,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<enum value="1" name="VK_NOT_READY" comment="A fence or query has not yet completed"/>
<enum value="2" name="VK_TIMEOUT" comment="A wait operation has not completed in the specified time"/>
<enum value="3" name="VK_EVENT_SET" comment="An event is signaled"/>
- <enum value="4" name="VK_EVENT_RESET" comment="An event is unsignalled"/>
+ <enum value="4" name="VK_EVENT_RESET" comment="An event is unsignaled"/>
<enum value="5" name="VK_INCOMPLETE" comment="A return array was too small for the result"/>
<!-- Error codes (negative values) -->
<enum value="-1" name="VK_ERROR_OUT_OF_HOST_MEMORY" comment="A host memory allocation has failed"/>
@@ -2887,7 +2894,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<enum value="3" name="VK_PRESENT_MODE_FIFO_RELAXED_KHR"/>
</enums>
<enums name="VkColorSpaceKHR" type="enum">
- <enum value="0" name="VK_COLORSPACE_SRGB_NONLINEAR_KHR"/>
+ <enum value="0" name="VK_COLOR_SPACE_SRGB_NONLINEAR_KHR"/>
</enums>
<enums name="VkDisplayPlaneAlphaFlagBitsKHR" type="bitmask">
<enum bitpos="0" name="VK_DISPLAY_PLANE_ALPHA_OPAQUE_BIT_KHR"/>
@@ -3065,7 +3072,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
<param optional="true" len="pPropertyCount"><type>VkExtensionProperties</type>* <name>pProperties</name></param>
<validity>
- <usage>If pname:pLayerName is not `NULL`, it must: be the name of an instance layer returned by flink:vkEnumerateInstanceLayerProperties</usage>
+ <usage>If pname:pLayerName is not `NULL`, it must: be the name of a layer returned by flink:vkEnumerateInstanceLayerProperties</usage>
</validity>
</command>
<command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY">
@@ -3081,7 +3088,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<param optional="false,true"><type>uint32_t</type>* <name>pPropertyCount</name></param>
<param optional="true" len="pPropertyCount"><type>VkExtensionProperties</type>* <name>pProperties</name></param>
<validity>
- <usage>If pname:pLayerName is not `NULL`, it must: be the name of a device layer returned by flink:vkEnumerateDeviceLayerProperties</usage>
+ <usage>If pname:pLayerName is not `NULL`, it must: be the name of a layer returned by flink:vkEnumerateDeviceLayerProperties</usage>
</validity>
</command>
<command>
@@ -3102,7 +3109,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<param len="submitCount" externsync="pSubmits[].pWaitSemaphores[],pSubmits[].pSignalSemaphores[]">const <type>VkSubmitInfo</type>* <name>pSubmits</name></param>
<param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
<validity>
- <usage>If pname:fence is not sname:VK_NULL_HANDLE, pname:fence must: be unsignalled</usage>
+ <usage>If pname:fence is not sname:VK_NULL_HANDLE, pname:fence must: be unsignaled</usage>
<usage>If pname:fence is not sname:VK_NULL_HANDLE, pname:fence mustnot: be associated with any other queue command that has not yet completed execution on that queue</usage>
</validity>
</command>
@@ -3258,7 +3265,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<param len="bindInfoCount" externsync="pBindInfo[].pWaitSemaphores[],pBindInfo[].pSignalSemaphores[],pBindInfo[].pBufferBinds[].buffer,pBindInfo[].pImageOpaqueBinds[].image,pBindInfo[].pImageBinds[].image">const <type>VkBindSparseInfo</type>* <name>pBindInfo</name></param>
<param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
<validity>
- <usage>pname:fence must: be unsignalled</usage>
+ <usage>pname:fence must: be unsignaled</usage>
<usage>pname:fence mustnot: be associated with any other queue command that has not yet completed execution on that queue</usage>
</validity>
</command>
@@ -4592,7 +4599,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<usage>pname:queueFamilyIndex must: be less than pname:pQueueFamilyPropertyCount returned by fname:vkGetPhysicalDeviceQueueFamilyProperties for the given pname:physicalDevice</usage>
</validity>
</command>
- <command successcodes="VK_SUCCESS,VK_INCOMPLETE" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
+ <command successcodes="VK_SUCCESS" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_SURFACE_LOST_KHR">
<proto><type>VkResult</type> <name>vkGetPhysicalDeviceSurfaceCapabilitiesKHR</name></proto>
<param><type>VkPhysicalDevice</type> <name>physicalDevice</name></param>
<param><type>VkSurfaceKHR</type> <name>surface</name></param>
@@ -4646,8 +4653,8 @@ maintained in the master branch of the Khronos Vulkan Github project.
<param optional="true" externsync="true"><type>VkFence</type> <name>fence</name></param>
<param><type>uint32_t</type>* <name>pImageIndex</name></param>
<validity>
- <usage>If pname:semaphore is not sname:VK_NULL_HANDLE it must: be unsignalled</usage>
- <usage>If pname:fence is not sname:VK_NULL_HANDLE it must: be unsignalled and mustnot: be associated with any other queue command that has not yet completed execution on that queue</usage>
+ <usage>If pname:semaphore is not sname:VK_NULL_HANDLE it must: be unsignaled</usage>
+ <usage>If pname:fence is not sname:VK_NULL_HANDLE it must: be unsignaled and mustnot: be associated with any other queue command that has not yet completed execution on that queue</usage>
</validity>
</command>
<command successcodes="VK_SUCCESS,VK_SUBOPTIMAL_KHR" errorcodes="VK_ERROR_OUT_OF_HOST_MEMORY,VK_ERROR_OUT_OF_DEVICE_MEMORY,VK_ERROR_DEVICE_LOST,VK_ERROR_OUT_OF_DATE_KHR,VK_ERROR_SURFACE_LOST_KHR">
@@ -4754,7 +4761,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<usage>pname:instance must: be a valid sname:VkInstance handle</usage>
<usage>pname:flags must: be a combination of one or more of sname:VkDebugReportFlagBitsEXT</usage>
<usage>pname:objType must: be one of sname:VkDebugReportObjectTypeEXT, ename:VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT if pname:object is `NULL`</usage>
- <usage>pname:object may: be a {apiname} object</usage>
+ <usage>pname:object may: be a Vulkan object</usage>
<usage>pname:pLayerPrefix must: be a `NULL` terminated string.</usage>
<usage>pname:pMsg must: be a `NULL` terminated string.</usage>
</validity>
@@ -5036,6 +5043,7 @@ maintained in the master branch of the Khronos Vulkan Github project.
<enum value="&quot;VK_KHR_surface&quot;" name="VK_KHR_SURFACE_EXTENSION_NAME"/>
<enum offset="0" dir="-" extends="VkResult" name="VK_ERROR_SURFACE_LOST_KHR"/>
<enum offset="1" dir="-" extends="VkResult" name="VK_ERROR_NATIVE_WINDOW_IN_USE_KHR"/>
+ <enum value="VK_COLOR_SPACE_SRGB_NONLINEAR_KHR" name="VK_COLORSPACE_SRGB_NONLINEAR_KHR"/>
<command name="vkDestroySurfaceKHR"/>
<command name="vkGetPhysicalDeviceSurfaceSupportKHR"/>
<command name="vkGetPhysicalDeviceSurfaceCapabilitiesKHR"/>
diff --git a/vk_helper.py b/vk_helper.py
index ab99f638..dc49b0fb 100755
--- a/vk_helper.py
+++ b/vk_helper.py
@@ -1563,7 +1563,7 @@ class StructWrapperGen:
# If struct has sType or ptr members, generate safe type
def _hasSafeStruct(self, s):
- exceptions = ['VkPhysicalDeviceFeatures', 'VkPipelineColorBlendStateCreateInfo', 'VkDebugMarkerMarkerInfoEXT']
+ exceptions = ['VkPhysicalDeviceFeatures']
if s in exceptions:
return False
if 'sType' == self.struct_dict[s][0]['name']:
@@ -1713,23 +1713,29 @@ class StructWrapperGen:
destruct_txt += ' if (%s)\n' % (m_name)
destruct_txt += ' delete[] %s;\n' % (m_name)
elif self.struct_dict[s][m]['array']:
- # Init array ptr to NULL
- init_list += '\n\t%s(NULL),' % (m_name)
- init_func_txt += ' %s = NULL;\n' % (m_name)
- array_element = 'pInStruct->%s[i]' % (m_name)
- if is_type(self.struct_dict[s][m]['type'], 'struct') and self._hasSafeStruct(self.struct_dict[s][m]['type']):
- array_element = '%s(&pInStruct->%s[i])' % (self._getSafeStructName(self.struct_dict[s][m]['type']), m_name)
- construct_txt += ' if (%s && pInStruct->%s) {\n' % (self.struct_dict[s][m]['array_size'], m_name)
- construct_txt += ' %s = new %s[%s];\n' % (m_name, m_type, self.struct_dict[s][m]['array_size'])
- destruct_txt += ' if (%s)\n' % (m_name)
- destruct_txt += ' delete[] %s;\n' % (m_name)
- construct_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size'])
- if 'safe_' in m_type:
- construct_txt += ' %s[i].initialize(&pInStruct->%s[i]);\n' % (m_name, m_name)
+ if not self.struct_dict[s][m]['dyn_array']:
+ # Handle static array case
+ construct_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size'])
+ construct_txt += ' %s[i] = pInStruct->%s[i];\n' % (m_name, m_name)
+ construct_txt += ' }\n'
else:
- construct_txt += ' %s[i] = %s;\n' % (m_name, array_element)
- construct_txt += ' }\n'
- construct_txt += ' }\n'
+ # Init array ptr to NULL
+ init_list += '\n\t%s(NULL),' % (m_name)
+ init_func_txt += ' %s = NULL;\n' % (m_name)
+ array_element = 'pInStruct->%s[i]' % (m_name)
+ if is_type(self.struct_dict[s][m]['type'], 'struct') and self._hasSafeStruct(self.struct_dict[s][m]['type']):
+ array_element = '%s(&pInStruct->%s[i])' % (self._getSafeStructName(self.struct_dict[s][m]['type']), m_name)
+ construct_txt += ' if (%s && pInStruct->%s) {\n' % (self.struct_dict[s][m]['array_size'], m_name)
+ construct_txt += ' %s = new %s[%s];\n' % (m_name, m_type, self.struct_dict[s][m]['array_size'])
+ destruct_txt += ' if (%s)\n' % (m_name)
+ destruct_txt += ' delete[] %s;\n' % (m_name)
+ construct_txt += ' for (uint32_t i=0; i<%s; ++i) {\n' % (self.struct_dict[s][m]['array_size'])
+ if 'safe_' in m_type:
+ construct_txt += ' %s[i].initialize(&pInStruct->%s[i]);\n' % (m_name, m_name)
+ else:
+ construct_txt += ' %s[i] = %s;\n' % (m_name, array_element)
+ construct_txt += ' }\n'
+ construct_txt += ' }\n'
elif self.struct_dict[s][m]['ptr']:
construct_txt += ' if (pInStruct->%s)\n' % (m_name)
construct_txt += ' %s = new %s(pInStruct->%s);\n' % (m_name, m_type, m_name)
diff --git a/vulkan.py b/vulkan.py
index a623f4ab..a623f4ab 100755..100644
--- a/vulkan.py
+++ b/vulkan.py
diff --git a/windowsRuntimeInstaller/ConfigLayersAndVulkanDLL.ps1 b/windowsRuntimeInstaller/ConfigLayersAndVulkanDLL.ps1
index 6291bea6..341df5f9 100644
--- a/windowsRuntimeInstaller/ConfigLayersAndVulkanDLL.ps1
+++ b/windowsRuntimeInstaller/ConfigLayersAndVulkanDLL.ps1
@@ -29,28 +29,26 @@
# - Set the layer registry entries to point to the layer json files
# in the Vulkan SDK associated with the most recent vulkan*dll.
#
-# This script takes the following parameters:
+# This script can be called with the following two parameters:
# $majorabi : a single string number specifying the major abi version.
# $ossize : an integer indicating if the target is a 64 (64) or 32 (32) bit OS.
#
+# majorabi and ossize are either prepended to this script or specificied as args
Param(
- [string]$majorabi,
- [int]$ossize
+ [string]$majorabiarg,
+ [int]$ossizearg
)
+if ($majorabi -eq $null) {
+ $majorabi=$majorabiarg
+}
+if ($ossize -eq $null) {
+ $ossize=$ossizearg
+}
-# Start logging
-$log=$Env:Temp+"\VulkanRT"
-New-Item -ItemType Directory -Force -Path $log | Out-Null
-$logascii=$log+"\ConfigLayersAndVulkanDLL.log"
-$log=$log+"\ConfigLayersAndVulkanDLL16.log"
-echo "ConfigLayersAndVulkanDLL.ps1 $majorabi $ossize" >$log
-(Get-Date).ToString() >>$log
-
-$vulkandll = "vulkan-"+$majorabi+".dll"
-$windrive = $env:SYSTEMDRIVE
-$winfolder = $env:SYSTEMROOT
-$script:VulkanDllList=@()
+function WriteToLog ($x) {
+ echo $x | Out-File -encoding ascii -append -filepath $script:log
+}
function notNumeric ($x) {
try {
@@ -61,6 +59,34 @@ function notNumeric ($x) {
}
}
+function setScriptReturnValue($rvalue) {
+ if ($script:scriptReturnValue -eq 0) {
+ $script:scriptReturnValue = $rvalue
+ }
+}
+
+# Clear any pre-existing errors and set default return value
+$Error.Clear();
+$script:scriptReturnValue=0
+
+# Start logging
+$script:log=$Env:Temp+"\ConfigLayersAndVulkanDLL.log"
+Remove-Item $script:log
+
+# Ignore errors related to log file
+$Error.Clear();
+
+WriteToLog "ConfigLayersAndVulkanDLL.ps1 called with inputs of : $majorabi $ossize"
+$startTime=Get-Date
+WriteToLog "Start time : $startTime"
+WriteToLog "Poweshell Version information:"
+WriteToLog $PsVersionTable
+
+$vulkandll = "vulkan-"+$majorabi+".dll"
+$windrive = $env:SYSTEMDRIVE
+$winfolder = $env:SYSTEMROOT
+$script:VulkanDllList=@()
+
# The name of the versioned vulkan dll file is one of the following:
#
# vulkan-<majorabi>-<major>-<minor>-<patch>-<buildno>-<prerelease>-<prebuildno>
@@ -96,7 +122,7 @@ function notNumeric ($x) {
function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
{
- echo "UpdateVulkanSysFolder $dir $writeSdkName" >>$log
+ WriteToLog "UpdateVulkanSysFolder $dir $writeSdkName"
# Push the current path on the stack and go to $dir
Push-Location -Path $dir
@@ -108,25 +134,37 @@ function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
# Find all vulkan dll files in this directory
dir -name vulkan-$majorabi-*.dll |
ForEach-Object {
- echo "File $_" >>$log
+ WriteToLog "File $_"
if ($_ -match "=" -or
$_ -match "@" -or
$_ -match " " -or
- ($_.Split('-').count -lt 6) -or
- ($_.Split('-').count -gt 8))
+ ($_.Split('-').count -lt 6) -or
+ ($_.Split('-').count -gt 8) -or
+ !$?)
{
# If a file name contains "=", "@", or " ", or it contains less then 5 dashes or more than
# 7 dashes, it wasn't installed by the Vulkan Run Time.
# Note that we need to use return inside of ForEach-Object is to continue with iteration.
- echo "Rejected $_ - bad format" >>$log
+ WriteToLog "Ignoring $_ - bad format"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
# If the corresponding vulkaninfo is not present, it wasn't installed by the Vulkan Run Time
$vulkaninfo=$_ -replace ".dll",".exe"
$vulkaninfo=$vulkaninfo -replace "vulkan","vulkaninfo"
- if (-not (Test-Path $vulkaninfo)) {
- echo "Rejected $_ - vulkaninfo not present" >>$log
+ if (-not (Test-Path $vulkaninfo) -or
+ !$?) {
+ WriteToLog "Rejected $_ - $vulkaninfo not present"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
@@ -171,28 +209,62 @@ function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
$prebuildno="z"*10
}
}
- echo "Version $majorOrig $minorOrig $patchOrig $buildnoOrig $prereleaseOrig $prebuildnoOrig" >>$log
+ WriteToLog "Version $majorOrig $minorOrig $patchOrig $buildnoOrig $prereleaseOrig $prebuildnoOrig"
+ if (!$?) {
+ WriteToLog "Ignoring version $majorOrig $minorOrig $patchOrig $buildnoOrig $prereleaseOrig $prebuildnoOrig"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
+ return
+ }
# Make sure fields that are supposed to be numbers are numbers
if (notNumeric($major)) {
- echo "Rejected $_ - bad major" >>$log
+ WriteToLog "Ignoring $_ - bad major"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
if (notNumeric($minor)) {
- echo "Rejected $_ - bad minor" >>$log
+ WriteToLog "Ignoring $_ - bad minor"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
if (notNumeric($patch)) {
- echo "Rejected $_ - bad patch" >>$log
+ WriteToLog "Ignoring $_ - bad patch"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
if (notNumeric($buildno)) {
- echo "Rejected $_ - bad buildno" >>$log
+ WriteToLog "Ignoring $_ - bad buildno"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
if (notNumeric($prebuildno)) {
if ($prebuildno -ne "z"*10) {
- echo "Rejected $_ - bad prebuildno" >>$log
+ WriteToLog "Ignoring $_ - bad prebuildno"
+
+ # Not a real error, so just clear it for now.
+ $Error.Clear();
+
+ # NOTE: Inside a ForEach-Object block, the 'return' call behaves like a 'continue' for a For loop
return
}
}
@@ -205,8 +277,12 @@ function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
$prebuildno = $prebuildno.padleft(10,'0')
# Add a new element to the $VulkanDllList array
- echo "Adding $_ to Vulkan dll list " >>$log
+ WriteToLog "Adding $_ to Vulkan dll list "
$script:VulkanDllList+="$major=$minor=$patch=$buildno=$prebuildno=$prerelease= $_ @$majorOrig@$minorOrig@$patchOrig@$buildnoOrig@$prereleaseOrig@$prebuildnoOrig@"
+ if (!$?) {
+ WriteToLog "Error: UpdateVulkanSysFolder adding DLL $_ to list"
+ setScriptReturnValue(10)
+ }
}
# If $VulkanDllList contains at least one element, there's at least one vulkan*.dll file.
@@ -216,20 +292,32 @@ function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
# Sort the list. The most recent vulkan-*.dll will be in the last element of the list.
[array]::sort($script:VulkanDllList)
+ if (!$?) {
+ WriteToLog "Error: UpdateVulkanSysFolder sorting DLL list"
+ setScriptReturnValue(20)
+ }
# Put the name of the most recent vulkan-*.dll in $mrVulkanDLL.
# The most recent vulkanDLL is the second word in the last element of the
# sorted $VulkanDllList. Copy it to $vulkandll.
$mrVulkanDll=$script:VulkanDllList[-1].Split(' ')[1]
- echo "copy $mrVulkanDll $vulkandll" >>$log
- copy $mrVulkanDll $vulkandll
+ WriteToLog "Copying $mrVulkanDll $vulkandll"
+ Copy-Item $mrVulkanDll $vulkandll -force
+ if (!$?) {
+ WriteToLog "Error: UpdateVulkanSysFolder encountered error during copy $mrVulkanDll $vulkandll"
+ setScriptReturnValue(30)
+ }
# Copy the most recent version of vulkaninfo-<abimajor>-*.exe to vulkaninfo.exe.
# We create the source file name for the copy from $mrVulkanDll.
$mrVulkaninfo=$mrVulkanDll -replace ".dll",".exe"
$mrVulkaninfo=$mrVulkaninfo -replace "vulkan","vulkaninfo"
- echo "copy $mrVulkaninfo vulkaninfo.exe" >>$log
- copy $mrVulkaninfo vulkaninfo.exe
+ WriteToLog "Copying $mrVulkaninfo vulkaninfo.exe"
+ Copy-Item $mrVulkaninfo vulkaninfo.exe -force
+ if (!$?) {
+ WriteToLog "Error: UpdateVulkanSysFolder encountered error during copy $mrVulkaninfo vulkaninfo.exe"
+ setScriptReturnValue(40)
+ }
# Create the name used in the registry for the SDK associated with $mrVulkanDll.
$major=$script:VulkanDllList[-1].Split('@')[1]
@@ -246,11 +334,20 @@ function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
if ($prebuildno -ne "") {
$sdktempname=$sdktempname + "." + $prebuildno
}
- echo "sdkname = $sdktempname" >>$log
+
+ WriteToLog "sdkname = $sdktempname"
+ if (!$?) {
+ WriteToLog "Error: UpdateVulkanSysFolder encountered error generating SDK name"
+ setScriptReturnValue(50)
+ }
}
# Return to our previous folder
Pop-Location
+ if (!$?) {
+ WriteToLog "Error: UpdateVulkanSysFolder popping location"
+ setScriptReturnValue(60)
+ }
# Only update the overall script-scope SDK name if we're told to
if ($writeSdkName -ne 0) {
@@ -263,42 +360,64 @@ function UpdateVulkanSysFolder([string]$dir, [int]$writeSdkName)
# We only care about SYSWOW64 if we're targeting a 64-bit OS
if ($ossize -eq 64) {
# Update the SYSWOW64 Vulkan DLLS/EXEs
- echo "Calling UpdateVulkanSysFolder $winfolder\SYSWOW64 0" >>$log
+ WriteToLog "Calling UpdateVulkanSysFolder $winfolder\SYSWOW64 0"
UpdateVulkanSysFolder $winfolder\SYSWOW64 0
+ if (!$?) {
+ WriteToLog "Error: Calling UpdateVulkanSysFolder for 64-bit OS"
+ setScriptReturnValue(70)
+ }
}
# Update the SYSTEM32 Vulkan DLLS/EXEs
-echo "Calling UpdateVulkanSysFolder $winfolder\SYSTEM32 1" >>$log
+WriteToLog "Calling UpdateVulkanSysFolder $winfolder\SYSTEM32 1"
UpdateVulkanSysFolder $winfolder\SYSTEM32 1
+if (!$?) {
+ WriteToLog "Error: Calling UpdateVulkanSysFolder for all OS"
+ setScriptReturnValue(80)
+}
# Create an array of vulkan sdk install dirs
-echo "Creating array of of Vulkan SDK Install dirs" >>$log
+WriteToLog "Creating array of of Vulkan SDK Install dirs"
$mrVulkanDllInstallDir=""
$VulkanSdkDirs=@()
-Get-ChildItem -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall |
- ForEach-Object {
- $regkey=$_ -replace ".*\\",""
- if ($_ -match "\\VulkanSDK") {
- # Get the install path from UninstallString
- $tmp=Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$regkey -Name UninstallString
- $tmp=$tmp -replace "\\Uninstall.exe.*",""
- $tmp=$tmp -replace ".*=.",""
- echo "Adding $tmp to VulkanSDKDirs" >>$log
- $VulkanSdkDirs+=$tmp
- if ($regkey -eq $script:sdkname) {
- # Save away the sdk install dir for the the most recent vulkandll
- echo "Setting mrVulkanDllInstallDir to $tmp" >>$log
- $mrVulkanDllInstallDir=$tmp
- }
- }
+$installSDKRegs = @(Get-ChildItem -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall)
+if ($installSDKRegs -ne $null) {
+ ForEach ($curSDKReg in $installSDKRegs) {
+ if ($curSDKReg -ne $null) {
+ $regkey=$curSDKReg -replace ".*\\",""
+ if ($regkey -match "VulkanSDK") {
+ # Get the install path from UninstallString
+ $tmp=Get-ItemProperty -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$regkey -Name UninstallString
+ if (!$? -or $tmp -eq $null) {
+ WriteToLog "Error: Get-ItemProperty failed for Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$regkey"
+ $Error.Clear();
+ continue;
+ }
+ $tmp=$tmp -replace "\\Uninstall.exe.*",""
+ $tmp=$tmp -replace ".*=.",""
+ WriteToLog "Adding $tmp to VulkanSDKDirs"
+ $VulkanSdkDirs+=$tmp
+ if ($regkey -eq $script:sdkname) {
+ # Save away the sdk install dir for the the most recent vulkandll
+ WriteToLog "Setting mrVulkanDllInstallDir to $tmp"
+ $mrVulkanDllInstallDir=$tmp
+ }
+ }
+ }
}
+}
+if (!$?) {
+ WriteToLog "Error: Failed creating array of of Vulkan SDK Install dirs"
+ setScriptReturnValue(90)
+}
# Search list of sdk install dirs for an sdk compatible with $script:sdkname.
# We go backwards through VulkanDllList to generate SDK names, because we want the most recent SDK.
-if ($mrVulkanDllInstallDir -eq "") {
- echo "Searching VulkanDllList" >>$log
+
+if ($mrVulkanDllInstallDir -eq "" -and $script:VulkanDllList.Length -gt 0) {
+ WriteToLog "Searching VulkanDllList"
ForEach ($idx in ($script:VulkanDllList.Length-1)..0) {
$tmp=$script:VulkanDllList[$idx]
$vulkanDllMajor=$script:VulkanDllList[$idx].Split('@')[1]
@@ -314,8 +433,13 @@ if ($mrVulkanDllInstallDir -eq "") {
if ($vulkanDllPrebuildno) {
$regEntry=$regEntry+"."+$vulkanDllPrebuildno
}
- echo "Comparing $regEntry" >>$log
+ WriteToLog "Comparing $regEntry"
$rval=Get-ItemProperty -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$regEntry -ErrorAction SilentlyContinue
+ if (!$? -or $rval -eq $null) {
+ WriteToLog "Ignoring $regEntry - corresponding SDK registry entry does not exist"
+ $Error.Clear();
+ continue
+ }
$instDir=$rval
$instDir=$instDir -replace "\\Uninstall.exe.*",""
$instDir=$instDir -replace ".*=.",""
@@ -326,12 +450,16 @@ if ($mrVulkanDllInstallDir -eq "") {
$reMinor=$rval.Split('.')[1]
$rePatch=$rval.Split('.')[2]
if ($reMajor+$reMinor+$rePatch -eq $vulkanDllMajor+$vulkanDllMinor+$vulkanDllPatch) {
- echo "Setting mrVulkanDllInstallDir to $instDir" >>$log
+ WriteToLog "Setting mrVulkanDllInstallDir to $instDir"
$mrVulkanDllInstallDir=$instDir
break
}
}
}
+ if (!$?) {
+ WriteToLog "Failed searching VulkanDLLList"
+ $Error.Clear();
+ }
}
# Add C:\Vulkan\SDK\0.9.3 to list of SDK install dirs.
@@ -349,239 +477,142 @@ $VulkanSdkDirs+="$windrive\VulkanSDK\0.9.3"
# Note that we remove only those entries created by Vulkan SDKs. If other
# layers were installed that are not from an SDK, we don't mess with them.
-echo "Removing old layer registry values from HKLM\SOFTWARE\Khronos\Vulkan\ExplicitLayers" >>$log
-Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ExplicitLayers | Select-Object -ExpandProperty Property |
- ForEach-Object {
- $regval=$_
- ForEach ($sdkdir in $VulkanSdkDirs) {
- if ($regval -like "$sdkdir\*.json") {
- Remove-ItemProperty -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -name $regval
- echo "Removed registry value $regval" >>$log
- }
- }
- }
+WriteToLog "Removing old layer registry values from HKLM\SOFTWARE\Khronos\Vulkan\ExplicitLayers"
+$regkeys = @(Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\Vulkan\ExplicitLayers | Select-Object -ExpandProperty Property)
+if ($regkeys -ne $null) {
+ ForEach ($regval in $regkeys) {
+ if ($regval -ne $null) {
+ ForEach ($sdkdir in $VulkanSdkDirs) {
+ if ($regval -like "$sdkdir\*.json") {
+ Remove-ItemProperty -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -name $regval
+ if (!$?) {
+ WriteToLog "Error: Remove-ItemProperty failed for -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -name $regval"
+ } else {
+ WriteToLog "Removed registry value $regval"
+ }
+ }
+ }
+ }
+ }
+}
+
+if (!$?) {
+ WriteToLog "Error: Failed Removing old layer registry values from HKLM\SOFTWARE\Khronos\Vulkan\ExplicitLayers"
+ setScriptReturnValue(100)
+}
+
# Remove 32-bit layer registry value if we're targeting a 64-bit OS
if ($ossize -eq 64) {
- Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers | Select-Object -ExpandProperty Property |
- ForEach-Object {
- $regval=$_
- ForEach ($sdkdir in $VulkanSdkDirs) {
- if ($regval -like "$sdkdir\*.json") {
- Remove-ItemProperty -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers -name $regval
- echo "Removed WOW6432Node registry value $regval" >>$log
+ $regkeys = @(Get-Item -Path Registry::HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers | Select-Object -ExpandProperty Property)
+ if ($regkeys -ne $null) {
+ ForEach ($regval in $regkeys) {
+ if ($regval -ne $null) {
+ ForEach ($sdkdir in $VulkanSdkDirs) {
+ if ($regval -like "$sdkdir\*.json") {
+ Remove-ItemProperty -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers -name $regval
+ if (!$?) {
+ WriteToLog "Error: Remove-ItemProperty failed for -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers -name $regval"
+ } else {
+ WriteToLog "Removed WOW6432Node registry value $regval"
+ }
+ }
}
- }
+ }
}
+ }
+
+ if (!$?) {
+ WriteToLog "Error: Failed Removing old layer registry values from HKLM\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers"
+ setScriptReturnValue(110)
+ }
}
# Create layer registry values associated with Vulkan SDK from which $mrVulkanDll is from
-echo "Creating new layer registry values" >>$log
+WriteToLog "Creating new layer registry values"
if ($mrVulkanDllInstallDir -ne "") {
# Create registry keys if they don't exist
if (-not (Test-Path -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers)) {
- echo "Creating new registry key HKLM\SOFTWARE\Khronos\Vulkan\ExplicitLayers" >>$log
+ WriteToLog "Creating new registry key HKLM\SOFTWARE\Khronos\Vulkan\ExplicitLayers"
New-Item -Force -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers | out-null
+ if (!$?) {
+ WriteToLog "Error: Failed creating HKLM\SOFTWARE\Khronos\Vulkan\ExplicitLayers"
+ setScriptReturnValue(120)
+ }
}
if ($ossize -eq 64) {
if (-not (Test-Path -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers)) {
- echo "Creating new registry key HKLM\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers" >>$log
+ WriteToLog "Creating new registry key HKLM\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers"
New-Item -Force -ErrorAction SilentlyContinue -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers | out-null
- }
+ if (!$?) {
+ WriteToLog "Error: Failed creating HKLM\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers"
+ setScriptReturnValue(130)
+ }
+ }
}
if ($ossize -eq 64) {
-
# Create registry values in normal registry location for 64-bit items on a 64-bit OS
Get-ChildItem $mrVulkanDllInstallDir\Bin -Filter VkLayer*json |
ForEach-Object {
- echo "Creating registry value $mrVulkanDllInstallDir\Bin\$_" >>$log
+ WriteToLog "Creating registry value $mrVulkanDllInstallDir\Bin\$_"
New-ItemProperty -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -Name $mrVulkanDllInstallDir\Bin\$_ -PropertyType DWord -Value 0 | out-null
+ if (!$?) {
+ WriteToLog "Error: Failed creating $mrVulkanDllInstallDir\Bin\$_"
+ setScriptReturnValue(140)
+ }
+ }
+ if (!$?) {
+ WriteToLog "Error: Failed Get-ChildItem $mrVulkanDllInstallDir\Bin | ForEach-Object "
+ setScriptReturnValue(150)
}
# Create registry values for the WOW6432Node registry location for 32-bit items on a 64-bit OS
Get-ChildItem $mrVulkanDllInstallDir\Bin32 -Filter VkLayer*json |
ForEach-Object {
- echo "Creating WOW6432Node registry value $mrVulkanDllInstallDir\Bin32\$_" >>$log
+ WriteToLog "Creating WOW6432Node registry value $mrVulkanDllInstallDir\Bin32\$_"
New-ItemProperty -Path HKLM:\SOFTWARE\WOW6432Node\Khronos\Vulkan\ExplicitLayers -Name $mrVulkanDllInstallDir\Bin32\$_ -PropertyType DWord -Value 0 | out-null
+ if (!$?) {
+ WriteToLog "Error: Failed creating $mrVulkanDllInstallDir\Bin32\$_"
+ setScriptReturnValue(160)
+ }
+ }
+ if (!$?) {
+ WriteToLog "Error: Failed Get-ChildItem $mrVulkanDllInstallDir\Bin32 | ForEach-Object "
+ setScriptReturnValue(170)
}
-
} else {
-
# Create registry values in normal registry location for 32-bit items on a 32-bit OS
Get-ChildItem $mrVulkanDllInstallDir\Bin32 -Filter VkLayer*json |
ForEach-Object {
- echo "Creating registry value $mrVulkanDllInstallDir\Bin\$_" >>$log
+ WriteToLog "Creating registry value $mrVulkanDllInstallDir\Bin\$_"
New-ItemProperty -Path HKLM:\SOFTWARE\Khronos\Vulkan\ExplicitLayers -Name $mrVulkanDllInstallDir\Bin32\$_ -PropertyType DWord -Value 0 | out-null
- }
-
+ if (!$?) {
+ WriteToLog "Error: Failed creating $mrVulkanDllInstallDir\Bin\$_"
+ setScriptReturnValue(180)
+ }
+ }
+ if (!$?) {
+ WriteToLog "Error: Failed Get-ChildItem $mrVulkanDllInstallDir\Bin32 | ForEach-Object "
+ setScriptReturnValue(190)
+ }
}
}
+# Debug - for testing handling of script failure in installer
+#setScriptReturnValue(200)
+
# Final log output
-echo "ConfigLayersAndVulkanDLL.ps1 completed" >>$log
-(Get-Date).ToString() >>$log
-
-# Convert logfile to ascii
-cat $log | out-File -encoding ascii -filepath $logascii
-remove-item $log
-
-
-
-# SIG # Begin signature block
-# MIIcZgYJKoZIhvcNAQcCoIIcVzCCHFMCAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
-# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
-# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUQ4I+TKoMwtXHArekRd5/bX04
-# sreggheVMIIFHjCCBAagAwIBAgIQDmYEpPtQ2iBY4vC2AGq6uzANBgkqhkiG9w0B
-# AQsFADByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYD
-# VQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFz
-# c3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMB4XDTE1MDQzMDAwMDAwMFoXDTE2MDcw
-# NjEyMDAwMFowZTELMAkGA1UEBhMCVVMxETAPBgNVBAgTCENvbG9yYWRvMRUwEwYD
-# VQQHEwxGb3J0IENvbGxpbnMxFTATBgNVBAoTDEx1bmFyRywgSW5jLjEVMBMGA1UE
-# AxMMTHVuYXJHLCBJbmMuMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
-# jaLJm/Joxsn/IeopiGY3XPeSZeIhjSjSlQUkDyIyDGcBG7CvfiSsXIw3EgdGkjQg
-# yBcW5YsPz9bPGPUjo5go7CwZaRkhW7/LmSkAlx0UAv8EMLuJrAZ3jBNZvpPPqfWd
-# zgi/Rkm2gWQ6eSKouy7IjcLk+EwkeBbB+UBnYfMp0BfCPzR3mPgGAJH6efAmEaqQ
-# FBCrX97joYgDqp3v8u42jALLl/Ict/GNMHLxP+QWagIHIICCRgS6s02OsildLF6R
-# nqJOOG/43f2qUD4Cab65kzlI+0+uQyOl1UlxNxp0XareghGTqECsYA03j64Esxyo
-# 2xrNbV2LJm9crTX6QthxywIDAQABo4IBuzCCAbcwHwYDVR0jBBgwFoAUWsS5eyoK
-# o6XqcQPAYPkt9mV1DlgwHQYDVR0OBBYEFOSdVsqodGWApfCjHtAcn8sAzLBGMA4G
-# A1UdDwEB/wQEAwIHgDATBgNVHSUEDDAKBggrBgEFBQcDAzB3BgNVHR8EcDBuMDWg
-# M6Axhi9odHRwOi8vY3JsMy5kaWdpY2VydC5jb20vc2hhMi1hc3N1cmVkLWNzLWcx
-# LmNybDA1oDOgMYYvaHR0cDovL2NybDQuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJl
-# ZC1jcy1nMS5jcmwwQgYDVR0gBDswOTA3BglghkgBhv1sAwEwKjAoBggrBgEFBQcC
-# ARYcaHR0cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCBhAYIKwYBBQUHAQEEeDB2
-# MCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdpY2VydC5jb20wTgYIKwYBBQUH
-# MAKGQmh0dHA6Ly9jYWNlcnRzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydFNIQTJBc3N1
-# cmVkSURDb2RlU2lnbmluZ0NBLmNydDAMBgNVHRMBAf8EAjAAMA0GCSqGSIb3DQEB
-# CwUAA4IBAQCIt1S8zfvzMQEVmdAssjrwqBaq78xhtGPLjkNF06EvtWoV6VMLI/A6
-# 45KoULsaXeYuszLxNI+OT/b4HfD0e2LxImaTDZRmCLeIs+2pMLSlWDSV4okm8Vk2
-# rObLBlgiI1x0PiMa1le9D832COWM4EJcH7pxM+9JfiHYMLlZbcfNEVgv6Dhhl4MG
-# mOTMTl7vQNNQaJ1coNVf9m5Bez1DV9Iu2Cgd8BHp1oLVCQCHjVv0Ifj48RIPi4SQ
-# khzalrnrf+L/BWRDhpLnxYasazdV5WfrMHurPuBvYUiLQNkU9SqKgRk9XrzDAfMe
-# gPbGybMr0kqtbE/A/cDcTVnvRuTZnhXSMIIFMDCCBBigAwIBAgIQBAkYG1/Vu2Z1
-# U0O1b5VQCDANBgkqhkiG9w0BAQsFADBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMM
-# RGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQD
-# ExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMTMxMDIyMTIwMDAwWhcN
-# MjgxMDIyMTIwMDAwWjByMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQg
-# SW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2Vy
-# dCBTSEEyIEFzc3VyZWQgSUQgQ29kZSBTaWduaW5nIENBMIIBIjANBgkqhkiG9w0B
-# AQEFAAOCAQ8AMIIBCgKCAQEA+NOzHH8OEa9ndwfTCzFJGc/Q+0WZsTrbRPV/5aid
-# 2zLXcep2nQUut4/6kkPApfmJ1DcZ17aq8JyGpdglrA55KDp+6dFn08b7KSfH03sj
-# lOSRI5aQd4L5oYQjZhJUM1B0sSgmuyRpwsJS8hRniolF1C2ho+mILCCVrhxKhwjf
-# DPXiTWAYvqrEsq5wMWYzcT6scKKrzn/pfMuSoeU7MRzP6vIK5Fe7SrXpdOYr/mzL
-# fnQ5Ng2Q7+S1TqSp6moKq4TzrGdOtcT3jNEgJSPrCGQ+UpbB8g8S9MWOD8Gi6CxR
-# 93O8vYWxYoNzQYIH5DiLanMg0A9kczyen6Yzqf0Z3yWT0QIDAQABo4IBzTCCAckw
-# EgYDVR0TAQH/BAgwBgEB/wIBADAOBgNVHQ8BAf8EBAMCAYYwEwYDVR0lBAwwCgYI
-# KwYBBQUHAwMweQYIKwYBBQUHAQEEbTBrMCQGCCsGAQUFBzABhhhodHRwOi8vb2Nz
-# cC5kaWdpY2VydC5jb20wQwYIKwYBBQUHMAKGN2h0dHA6Ly9jYWNlcnRzLmRpZ2lj
-# ZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRFJvb3RDQS5jcnQwgYEGA1UdHwR6MHgw
-# OqA4oDaGNGh0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJ
-# RFJvb3RDQS5jcmwwOqA4oDaGNGh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdp
-# Q2VydEFzc3VyZWRJRFJvb3RDQS5jcmwwTwYDVR0gBEgwRjA4BgpghkgBhv1sAAIE
-# MCowKAYIKwYBBQUHAgEWHGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwCgYI
-# YIZIAYb9bAMwHQYDVR0OBBYEFFrEuXsqCqOl6nEDwGD5LfZldQ5YMB8GA1UdIwQY
-# MBaAFEXroq/0ksuCMS1Ri6enIZ3zbcgPMA0GCSqGSIb3DQEBCwUAA4IBAQA+7A1a
-# JLPzItEVyCx8JSl2qB1dHC06GsTvMGHXfgtg/cM9D8Svi/3vKt8gVTew4fbRknUP
-# UbRupY5a4l4kgU4QpO4/cY5jDhNLrddfRHnzNhQGivecRk5c/5CxGwcOkRX7uq+1
-# UcKNJK4kxscnKqEpKBo6cSgCPC6Ro8AlEeKcFEehemhor5unXCBc2XGxDI+7qPjF
-# Emifz0DLQESlE/DmZAwlCEIysjaKJAL+L3J+HNdJRZboWR3p+nRka7LrZkPas7CM
-# 1ekN3fYBIM6ZMWM9CBoYs4GbT8aTEAb8B4H6i9r5gkn3Ym6hU/oSlBiFLpKR6mhs
-# RDKyZqHnGKSaZFHvMIIGajCCBVKgAwIBAgIQAwGaAjr/WLFr1tXq5hfwZjANBgkq
-# hkiG9w0BAQUFADBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5j
-# MRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBB
-# c3N1cmVkIElEIENBLTEwHhcNMTQxMDIyMDAwMDAwWhcNMjQxMDIyMDAwMDAwWjBH
-# MQswCQYDVQQGEwJVUzERMA8GA1UEChMIRGlnaUNlcnQxJTAjBgNVBAMTHERpZ2lD
-# ZXJ0IFRpbWVzdGFtcCBSZXNwb25kZXIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-# ggEKAoIBAQCjZF38fLPggjXg4PbGKuZJdTvMbuBTqZ8fZFnmfGt/a4ydVfiS457V
-# WmNbAklQ2YPOb2bu3cuF6V+l+dSHdIhEOxnJ5fWRn8YUOawk6qhLLJGJzF4o9GS2
-# ULf1ErNzlgpno75hn67z/RJ4dQ6mWxT9RSOOhkRVfRiGBYxVh3lIRvfKDo2n3k5f
-# 4qi2LVkCYYhhchhoubh87ubnNC8xd4EwH7s2AY3vJ+P3mvBMMWSN4+v6GYeofs/s
-# jAw2W3rBerh4x8kGLkYQyI3oBGDbvHN0+k7Y/qpA8bLOcEaD6dpAoVk62RUJV5lW
-# MJPzyWHM0AjMa+xiQpGsAsDvpPCJEY93AgMBAAGjggM1MIIDMTAOBgNVHQ8BAf8E
-# BAMCB4AwDAYDVR0TAQH/BAIwADAWBgNVHSUBAf8EDDAKBggrBgEFBQcDCDCCAb8G
-# A1UdIASCAbYwggGyMIIBoQYJYIZIAYb9bAcBMIIBkjAoBggrBgEFBQcCARYcaHR0
-# cHM6Ly93d3cuZGlnaWNlcnQuY29tL0NQUzCCAWQGCCsGAQUFBwICMIIBVh6CAVIA
-# QQBuAHkAIAB1AHMAZQAgAG8AZgAgAHQAaABpAHMAIABDAGUAcgB0AGkAZgBpAGMA
-# YQB0AGUAIABjAG8AbgBzAHQAaQB0AHUAdABlAHMAIABhAGMAYwBlAHAAdABhAG4A
-# YwBlACAAbwBmACAAdABoAGUAIABEAGkAZwBpAEMAZQByAHQAIABDAFAALwBDAFAA
-# UwAgAGEAbgBkACAAdABoAGUAIABSAGUAbAB5AGkAbgBnACAAUABhAHIAdAB5ACAA
-# QQBnAHIAZQBlAG0AZQBuAHQAIAB3AGgAaQBjAGgAIABsAGkAbQBpAHQAIABsAGkA
-# YQBiAGkAbABpAHQAeQAgAGEAbgBkACAAYQByAGUAIABpAG4AYwBvAHIAcABvAHIA
-# YQB0AGUAZAAgAGgAZQByAGUAaQBuACAAYgB5ACAAcgBlAGYAZQByAGUAbgBjAGUA
-# LjALBglghkgBhv1sAxUwHwYDVR0jBBgwFoAUFQASKxOYspkH7R7for5XDStnAs0w
-# HQYDVR0OBBYEFGFaTSS2STKdSip5GoNL9B6Jwcp9MH0GA1UdHwR2MHQwOKA2oDSG
-# Mmh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEFzc3VyZWRJRENBLTEu
-# Y3JsMDigNqA0hjJodHRwOi8vY3JsNC5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1
-# cmVkSURDQS0xLmNybDB3BggrBgEFBQcBAQRrMGkwJAYIKwYBBQUHMAGGGGh0dHA6
-# Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBBBggrBgEFBQcwAoY1aHR0cDovL2NhY2VydHMu
-# ZGlnaWNlcnQuY29tL0RpZ2lDZXJ0QXNzdXJlZElEQ0EtMS5jcnQwDQYJKoZIhvcN
-# AQEFBQADggEBAJ0lfhszTbImgVybhs4jIA+Ah+WI//+x1GosMe06FxlxF82pG7xa
-# FjkAneNshORaQPveBgGMN/qbsZ0kfv4gpFetW7easGAm6mlXIV00Lx9xsIOUGQVr
-# NZAQoHuXx/Y/5+IRQaa9YtnwJz04HShvOlIJ8OxwYtNiS7Dgc6aSwNOOMdgv420X
-# Ewbu5AO2FKvzj0OncZ0h3RTKFV2SQdr5D4HRmXQNJsQOfxu19aDxxncGKBXp2JPl
-# VRbwuwqrHNtcSCdmyKOLChzlldquxC5ZoGHd2vNtomHpigtt7BIYvfdVVEADkitr
-# wlHCCkivsNRu4PQUCjob4489yq9qjXvc2EQwggbNMIIFtaADAgECAhAG/fkDlgOt
-# 6gAK6z8nu7obMA0GCSqGSIb3DQEBBQUAMGUxCzAJBgNVBAYTAlVTMRUwEwYDVQQK
-# EwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xJDAiBgNV
-# BAMTG0RpZ2lDZXJ0IEFzc3VyZWQgSUQgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBa
-# Fw0yMTExMTAwMDAwMDBaMGIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2Vy
-# dCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xITAfBgNVBAMTGERpZ2lD
-# ZXJ0IEFzc3VyZWQgSUQgQ0EtMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-# ggEBAOiCLZn5ysJClaWAc0Bw0p5WVFypxNJBBo/JM/xNRZFcgZ/tLJz4FlnfnrUk
-# FcKYubR3SdyJxArar8tea+2tsHEx6886QAxGTZPsi3o2CAOrDDT+GEmC/sfHMUiA
-# fB6iD5IOUMnGh+s2P9gww/+m9/uizW9zI/6sVgWQ8DIhFonGcIj5BZd9o8dD3QLo
-# Oz3tsUGj7T++25VIxO4es/K8DCuZ0MZdEkKB4YNugnM/JksUkK5ZZgrEjb7Szgau
-# rYRvSISbT0C58Uzyr5j79s5AXVz2qPEvr+yJIvJrGGWxwXOt1/HYzx4KdFxCuGh+
-# t9V3CidWfA9ipD8yFGCV/QcEogkCAwEAAaOCA3owggN2MA4GA1UdDwEB/wQEAwIB
-# hjA7BgNVHSUENDAyBggrBgEFBQcDAQYIKwYBBQUHAwIGCCsGAQUFBwMDBggrBgEF
-# BQcDBAYIKwYBBQUHAwgwggHSBgNVHSAEggHJMIIBxTCCAbQGCmCGSAGG/WwAAQQw
-# ggGkMDoGCCsGAQUFBwIBFi5odHRwOi8vd3d3LmRpZ2ljZXJ0LmNvbS9zc2wtY3Bz
-# LXJlcG9zaXRvcnkuaHRtMIIBZAYIKwYBBQUHAgIwggFWHoIBUgBBAG4AeQAgAHUA
-# cwBlACAAbwBmACAAdABoAGkAcwAgAEMAZQByAHQAaQBmAGkAYwBhAHQAZQAgAGMA
-# bwBuAHMAdABpAHQAdQB0AGUAcwAgAGEAYwBjAGUAcAB0AGEAbgBjAGUAIABvAGYA
-# IAB0AGgAZQAgAEQAaQBnAGkAQwBlAHIAdAAgAEMAUAAvAEMAUABTACAAYQBuAGQA
-# IAB0AGgAZQAgAFIAZQBsAHkAaQBuAGcAIABQAGEAcgB0AHkAIABBAGcAcgBlAGUA
-# bQBlAG4AdAAgAHcAaABpAGMAaAAgAGwAaQBtAGkAdAAgAGwAaQBhAGIAaQBsAGkA
-# dAB5ACAAYQBuAGQAIABhAHIAZQAgAGkAbgBjAG8AcgBwAG8AcgBhAHQAZQBkACAA
-# aABlAHIAZQBpAG4AIABiAHkAIAByAGUAZgBlAHIAZQBuAGMAZQAuMAsGCWCGSAGG
-# /WwDFTASBgNVHRMBAf8ECDAGAQH/AgEAMHkGCCsGAQUFBwEBBG0wazAkBggrBgEF
-# BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEMGCCsGAQUFBzAChjdodHRw
-# Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0Eu
-# Y3J0MIGBBgNVHR8EejB4MDqgOKA2hjRodHRwOi8vY3JsMy5kaWdpY2VydC5jb20v
-# RGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMDqgOKA2hjRodHRwOi8vY3JsNC5k
-# aWdpY2VydC5jb20vRGlnaUNlcnRBc3N1cmVkSURSb290Q0EuY3JsMB0GA1UdDgQW
-# BBQVABIrE5iymQftHt+ivlcNK2cCzTAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
-# pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEARlA+ybcoJKc4HbZbKa9Sz1LpMUer
-# Vlx71Q0LQbPv7HUfdDjyslxhopyVw1Dkgrkj0bo6hnKtOHisdV0XFzRyR4WUVtHr
-# uzaEd8wkpfMEGVWp5+Pnq2LN+4stkMLA0rWUvV5PsQXSDj0aqRRbpoYxYqioM+Sb
-# OafE9c4deHaUJXPkKqvPnHZL7V/CSxbkS3BMAIke/MV5vEwSV/5f4R68Al2o/vsH
-# OE8Nxl2RuQ9nRc3Wg+3nkg2NsWmMT/tZ4CMP0qquAHzunEIOz5HXJ7cW7g/DvXwK
-# oO4sCFWFIrjrGBpN/CohrUkxg0eVd3HcsRtLSxwQnHcUwZ1PL1qVCCkQJjGCBDsw
-# ggQ3AgEBMIGGMHIxCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMx
-# GTAXBgNVBAsTEHd3dy5kaWdpY2VydC5jb20xMTAvBgNVBAMTKERpZ2lDZXJ0IFNI
-# QTIgQXNzdXJlZCBJRCBDb2RlIFNpZ25pbmcgQ0ECEA5mBKT7UNogWOLwtgBqursw
-# CQYFKw4DAhoFAKB4MBgGCisGAQQBgjcCAQwxCjAIoAKAAKECgAAwGQYJKoZIhvcN
-# AQkDMQwGCisGAQQBgjcCAQQwHAYKKwYBBAGCNwIBCzEOMAwGCisGAQQBgjcCARUw
-# IwYJKoZIhvcNAQkEMRYEFAoOC46C6ArmxtlmLsUTidSbkN3rMA0GCSqGSIb3DQEB
-# AQUABIIBADXG8YUKEPQHyMUpBvGWwb5VeZ8oWPyiSSE649GXu5tHDn+N2lhDPngR
-# Cksh4FpF56hP4RgTzH/Nmxf2D4kZUzPCrs2Il1S+U0ZoFpoAwrN8dbnvw2Wvf7ns
-# LZHXKG9eIaMYx6r/nn+VV8qvL/25fZ8oNyIFCYy4FYRLmla5g1+Vmtg6anHj89c+
-# EMSIwR8BR5UlAagfhfKJQHYMz4xkdqMrR6ZDsMHvYjbOg3MILrrdgomH2R5JKAHK
-# IaD3EqM+Tgu8LH1MMt/hIf4RS/lgqT12qM88J64dyhquaM1BUzw5dnwb+h3aAF2O
-# ZJ4IhONECJbJf8wVT8rTUA+6uUm/Y6ihggIPMIICCwYJKoZIhvcNAQkGMYIB/DCC
-# AfgCAQEwdjBiMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkw
-# FwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSEwHwYDVQQDExhEaWdpQ2VydCBBc3N1
-# cmVkIElEIENBLTECEAMBmgI6/1ixa9bV6uYX8GYwCQYFKw4DAhoFAKBdMBgGCSqG
-# SIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTE2MDQwNzIxNTM0
-# OFowIwYJKoZIhvcNAQkEMRYEFERKj5qmhGjIIeKV/myZFhJ/EUO7MA0GCSqGSIb3
-# DQEBAQUABIIBAJYQytkxzpn/UVwVJ0tsompGzVKSEgjuqAiI2jA0LiQwWM9iBHpG
-# 8ijDH6Dh+Fqa1JSsynyFixF26SuHeDoY/LX14HhRPDEkBa70qt9h9gc/73f9AzUy
-# eSbxwRhlF/UAyk0E3fbK1of431HxfvcdhnvCIDW8orfiG5v7gS0Mub4C70TlMXTp
-# b6XT1orYqnih9j4EVCYWZwv+EsOADRHW7o1RvIC2gI2dzmAkMSEjehk3we6u8KXI
-# xkggPOXy5O8TFgFdjvKU6XaoTTCklKWFIQIRG9r5m//Qj3jwzwN/03gLPphi6zze
-# 8fAJmClDyH+kHivSSfFnFUB7elvajTvasQE=
-# SIG # End signature block
+WriteToLog "ConfigLayersAndVulkanDLL.ps1 completed, return status is $script:scriptReturnValue"
+$endTime=Get-Date
+WriteToLog "End time: $endTime"
+
+# Since InstallerRT.nsi runs this script by piping it to powershell.exe, the exit status
+# doesn't seem to be available. So we put in it a file where InstallRT.nsi can retrieve it.
+$statusfile=$Env:Temp+"\ConfigLayersAndVulkanDLL.stat"
+echo $script:scriptReturnValue | Out-File -encoding ascii -filepath $statusfile
+
+exit $script:scriptReturnValue
diff --git a/windowsRuntimeInstaller/InstallerRT.nsi b/windowsRuntimeInstaller/InstallerRT.nsi
index 6b1771f4..0bfd47fb 100644
--- a/windowsRuntimeInstaller/InstallerRT.nsi
+++ b/windowsRuntimeInstaller/InstallerRT.nsi
@@ -86,10 +86,6 @@ Var IDir
# Install count
Var IC
-# Error code from powershell script
-Var PsErr
-
-
#############################################
# StrRep - string replace
@@ -232,16 +228,92 @@ VIAddVersionKey "LegalCopyright" ""
VIAddVersionKey "FileDescription" "Vulkan Runtime Installer"
!endif
+
+# Function to run ConfigLayersAndVulkanDll ps script.
+# Return value is in $0 - 0 is success, all else is failure.
+!macro ConfigLayersAndVulkanDLL un
+Function ${un}ConfigLayersAndVulkanDLL
+
+ ${If} ${RunningX64}
+ Strcpy $1 64
+ ${Else}
+ Strcpy $1 32
+ ${Endif}
+
+ # Create the script, the first two lines are the majorabi and ossize.
+ nsExec::ExecToStack 'cmd /k echo $$majorabi=${VERSION_ABI_MAJOR} >"$TEMP\VulkanRT\VulkanRT.ps1"'
+ nsExec::ExecToStack 'cmd /k echo $$ossize=$1 >>"$TEMP\VulkanRT\VulkanRT.ps1"'
+ nsExec::ExecToStack 'cmd /k type ConfigLayersAndVulkanDLL.ps1 >>"$TEMP\VulkanRT\VulkanRT.ps1"'
+
+ # Exectute the script by piping it to powershell.exe. This gets around possible OS
+ # security restrictions on running powershell scripts.
+ nsExec::ExecToStack 'cmd /k type "$TEMP\VulkanRT\VulkanRT.ps1" | powershell -NoProfile -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -Command -'
+ Delete "$TEMP\VulkanRT\ConfigLayersAndVulkanDLL1.${un}log"
+ Rename "$TEMP\ConfigLayersAndVulkanDLL.log" "$TEMP\VulkanRT\ConfigLayersAndVulkanDLL1.${un}log"
+ pop $0
+
+ # If it failed, try again, with a full path to powershell.exe
+ ${If} $0 != 0
+ nsExec::ExecToStack 'cmd /k type "$TEMP\VulkanRT\VulkanRT.ps1" | "$WINDIR\System32\WindowsPowerShell\v1.0\powershell" -NoProfile -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -Command -'
+ pop $0
+ Delete "$TEMP\VulkanRT\ConfigLayersAndVulkanDLL2.${un}log"
+ Rename "$TEMP\ConfigLayersAndVulkanDLL.log" "$TEMP\VulkanRT\ConfigLayersAndVulkanDLL2.${un}log"
+ ${Endif}
+
+ # Read the return value of the script and put it in $0, stripping trailing newline
+ FileOpen $1 "$TEMP\ConfigLayersAndVulkanDLL.stat" r
+ ${If} $1 != ""
+ FileRead $1 $2
+ FileClose $1
+ ${StrRep} $3 $2 "$\n" ""
+ ${StrRep} $0 $3 "$\r" ""
+ ${Else}
+ # error
+ StrCpy $0 -1
+ ${Endif}
+
+ # Cleanup
+ Delete "$TEMP\ConfigLayersAndVulkanDLL.stat"
+ Delete "$TEMP\VulkanRT\VulkanRT.ps1"
+
+ # Ignore errors. If something went wrong, the return value will indicate it.
+ ClearErrors
+
+FunctionEnd
+!macroend
+!insertmacro ConfigLayersAndVulkanDLL ""
+!insertmacro ConfigLayersAndVulkanDLL "un."
+
+
+# Function to run diagnostics if ConfigLayersAndVulkanDll ps script failed.
+# On entry $0, contains the return value from ConfigLayersAndVulkanDll.ps1. It shouldn't be changed.
+!macro DiagConfigLayersAndVulkanDLL un
+Function ${un}DiagConfigLayersAndVulkanDLL
+ LogText "ConfigLayersAndVulkanDLL.ps1 rval is $0"
+ nsExec::ExecToStack 'powershell -NoProfile -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -Command Write-Output Diagnostic0 | Out-File -encoding ascii -filePath "$TEMP\VulkanRT\Diagnostic0.${un}log"'
+ pop $1
+ LogText "ps cmd rval is $1"
+ nsExec::ExecToStack 'cmd /k echo %PATH% >"$TEMP\VulkanRT\Diagnostic1.${un}log"'
+ pop $1
+ LogText "cmd1 rval is $1"
+ nsExec::ExecToStack 'cmd /k dir "$WINDIR\System32\WindowsPowerShell\v1.0" >"$TEMP\VulkanRT\Diagnostic2.${un}log"'
+ pop $1
+ LogText "cmd2 rval is $1"
+
+ # Ignore errors
+ ClearErrors
+
+FunctionEnd
+!macroend
+!insertmacro DiagConfigLayersAndVulkanDLL ""
+!insertmacro DiagConfigLayersAndVulkanDLL "un."
+
# Start default section
Section
# Turn on logging
LogSet on
- # Remove contents of temp dir
- SetOutPath "$TEMP\VulkanRT"
- RmDir /R "$TEMP\VulkanRT"
-
# If running on a 64-bit OS machine, disable registry re-direct since we're running as a 32-bit executable.
${If} ${RunningX64}
@@ -251,6 +323,7 @@ Section
${Endif}
# Create our temp directory, with minimal permissions
+ RmDir /R "$TEMP\VulkanRT"
SetOutPath "$TEMP\VulkanRT"
AccessControl::DisableFileInheritance $TEMP\VulkanRT
AccessControl::SetFileOwner $TEMP\VulkanRT "Administrators"
@@ -415,17 +488,6 @@ Section
StrCpy $1 40
Call CheckForError
- # Run the ConfigLayersAndVulkanDLL.ps1 script to copy the most recent version of
- # vulkan-<abimajor>-*.dll to vulkan-<abimajor>.dll, and to set up layer registry
- # entries to use layers from the corresponding SDK
- nsExec::ExecToStack 'powershell -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -ExecutionPolicy RemoteSigned -File ConfigLayersAndVulkanDLL.ps1 ${VERSION_ABI_MAJOR} 64'
- pop $PsErr
- ${If} $PsErr != 0
- SetErrors
- ${EndIf}
- StrCpy $1 45
- Call CheckForError
-
# Else, running on a 32-bit OS machine
${Else}
@@ -443,58 +505,42 @@ Section
StrCpy $1 55
Call CheckForError
- # Run the ConfigLayersAndVulkanDLL.ps1 script to copy the most recent version of
- # vulkan-<abimajor>-*.dll to vulkan-<abimajor>.dll, and to set up layer registry
- # entries to use layers from the corresponding SDK
- nsExec::ExecToStack 'powershell -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -ExecutionPolicy RemoteSigned -File ConfigLayersAndVulkanDLL.ps1 ${VERSION_ABI_MAJOR} 32'
- pop $PsErr
- ${If} $PsErr != 0
- SetErrors
- ${EndIf}
- StrCpy $1 60
- Call CheckForError
-
${Endif}
- # We are done using ConfigLayersAndVulkanDLL.ps1, delete it. It will be re-installed
- # by the uninstaller when it needs to be run again during uninstall.
- Delete ConfigLayersAndVulkanDLL.ps1
+ # Run the ConfigLayersAndVulkanDLL.ps1 script to copy the most recent version of
+ # vulkan-<abimajor>-*.dll to vulkan-<abimajor>.dll, and to set up layer registry
+ # entries to use layers from the corresponding SDK
+ SetOutPath "$INSTDIR"
+ Call ConfigLayersAndVulkanDLL
+ ${If} $0 != 0
+ SetOutPath "$INSTDIR"
+ Call DiagConfigLayersAndVulkanDLL
- # Possibly install MSVC 2013 redistributables
- ClearErrors
- ${If} ${RunningX64}
- ReadRegDword $1 HKLM "SOFTWARE\WOW6432Node\Microsoft\DevDiv\vc\Servicing\12.0\RuntimeMinimum" "Install"
- ${If} ${Errors}
- StrCpy $1 0
- ClearErrors
- ${Endif}
- ${Else}
- StrCpy $1 1
- ${Endif}
- ReadRegDword $2 HKLM "SOFTWARE\Microsoft\DevDiv\vc\Servicing\12.0\RuntimeMinimum" "Install"
- ${If} ${Errors}
- StrCpy $2 0
- ClearErrors
- ${Endif}
- IntOp $3 $1 + $2
- ${If} $3 <= 1
- # If either x86 or x64 redistributables are not present, install redistributables.
- # We install both resdistributables because we have found that the x86 redist
- # will uninstall the x64 redist if the x64 redistrib is an old version. Amazing, isn't it?
- SetOutPath "$TEMP\VulkanRT"
+ # The Powershell script failed, and we don't know why.
+ # Simply configure system to use our loader and vulkaninfo.
+ MessageBox MB_OK "Warning!$\n$\nPowershell script called by VulkanRT Installer failed with error $0. Is Powershell installed on your system?$\n$\nWill configure system with Vulkan $FileVersion." /SD IDOK
${If} ${RunningX64}
- File vcredist_x64.exe
- ExecWait '"$TEMP\VulkanRT\vcredist_x64.exe" /quiet /norestart'
+ Delete $WINDIR\SysWow64\vulkan-${VERSION_ABI_MAJOR}.dll
+ Delete $WINDIR\SysWow64\vulkaninfo.exe
+ CopyFiles /SILENT $WINDIR\SysWow64\vulkan-$FileVersion.dll $WINDIR\SysWow64\vulkan-${VERSION_ABI_MAJOR}.dll
+ CopyFiles /SILENT $WINDIR\SysWow64\vulkaninfo-$FileVersion.exe $WINDIR\SysWow64\vulkaninfo.exe
${Endif}
- File vcredist_x86.exe
- ExecWait '"$TEMP\VulkanRT\vcredist_x86.exe" /quiet /norestart'
+ Delete $WINDIR\System32\vulkan-${VERSION_ABI_MAJOR}.dll
+ Delete $WINDIR\System32\vulkaninfo.exe
+ CopyFiles /SILENT $WINDIR\System32\vulkan-$FileVersion.dll $WINDIR\System32\vulkan-${VERSION_ABI_MAJOR}.dll
+ CopyFiles /SILENT $WINDIR\System32\vulkaninfo-$FileVersion.exe $WINDIR\System32\vulkaninfo.exe
+ ClearErrors
${Endif}
- StrCpy $1 65
+ StrCpy $1 60
Call CheckForError
+ # We are done using ConfigLayersAndVulkanDLL.ps1, delete it. It will be re-installed
+ # by the uninstaller when it needs to be run again during uninstall.
+ Delete ConfigLayersAndVulkanDLL.ps1
+
# Finish logging and move log file to TEMP dir
LogSet off
- Rename "$INSTDIR\install.log" "$TEMP\VulkanRT\Install.log"
+ Rename "$INSTDIR\install.log" "$TEMP\VulkanRT\installer.log"
SectionEnd
@@ -502,12 +548,9 @@ SectionEnd
!ifdef UNINSTALLER
Section "uninstall"
- # Remove contents of temp dir
- SetOutPath "$TEMP\VulkanRT"
- RmDir /R "$TEMP\VulkanRT"
-
# Turn on logging
- StrCpy $INSTDIR $TEMP\VulkanRT
+ SetOutPath "$TEMP\VulkanRT"
+ StrCpy $INSTDIR "$TEMP\VulkanRT"
LogSet on
# If running on a 64-bit OS machine, disable registry re-direct since we're running as a 32-bit executable.
@@ -522,7 +565,7 @@ Section "uninstall"
ReadRegStr $0 HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}${PRODUCTVERSION}" "InstallDir"
StrCpy $IDir $0
- StrCpy $1 70
+ StrCpy $1 65
Call un.CheckForError
SetOutPath "$IDir"
@@ -544,6 +587,8 @@ Section "uninstall"
Delete /REBOOTOK "$IDir\Instance_$IC\Uninstall${PRODUCTNAME}.exe"
Rmdir /REBOOTOK "$IDir\Instance_$IC"
${Endif}
+ StrCpy $1 70
+ Call un.CheckForError
# Modify registry for Programs and Features
@@ -560,6 +605,8 @@ Section "uninstall"
IntOp $IC $IC - 1
DeleteRegKey HKLM "Software\Microsoft\Windows\CurrentVersion\Uninstall\${PRODUCTNAME}${PRODUCTVERSION}"
${EndIf}
+ StrCpy $1 75
+ Call un.CheckForError
# Install the ConfigLayersAndVulkanDLL.ps1 so we can run it.
@@ -581,12 +628,6 @@ Section "uninstall"
Delete /REBOOTOK $WINDIR\System32\vulkan-${VERSION_ABI_MAJOR}.dll
Delete /REBOOTOK $WINDIR\System32\vulkan-$FileVersion.dll
- # Run the ConfigLayersAndVulkanDLL.ps1 script to:
- # Copy the most recent version of vulkan-<abimajor>-*.dll to vulkan-<abimajor>.dll
- # Copy the most recent version of vulkaninfo-<abimajor>-*.exe to vulkaninfo.exe
- # Set up layer registry entries to use layers from the corresponding SDK
- nsExec::ExecToStack 'powershell -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -ExecutionPolicy RemoteSigned -File "$IDir\ConfigLayersAndVulkanDLL.ps1" ${VERSION_ABI_MAJOR} 64'
-
# Else, running on a 32-bit OS machine
${Else}
@@ -598,13 +639,30 @@ Section "uninstall"
Delete /REBOOTOK $WINDIR\System32\vulkan-${VERSION_ABI_MAJOR}.dll
Delete /REBOOTOK $WINDIR\System32\vulkan-$FileVersion.dll
- # Run the ConfigLayersAndVulkanDLL.ps1 script to:
- # Copy the most recent version of vulkan-<abimajor>-*.dll to vulkan-<abimajor>.dll
- # Copy the most recent version of vulkaninfo-<abimajor>-*.exe to vulkaninfo.exe
- # Set up layer registry entries to use layers from the corresponding SDK
- nsExec::ExecToStack 'powershell -NoLogo -NonInteractive -WindowStyle Hidden -inputformat none -ExecutionPolicy RemoteSigned -File "$IDir\ConfigLayersAndVulkanDLL.ps1" ${VERSION_ABI_MAJOR} 32'
-
${EndIf}
+ StrCpy $1 80
+ Call un.CheckForError
+
+ # Run the ConfigLayersAndVulkanDLL.ps1 script to copy the most recent version of
+ # vulkan-<abimajor>-*.dll to vulkan-<abimajor>.dll, and to set up layer registry
+ # entries to use layers from the corresponding SDK
+ SetOutPath "$IDir"
+ Call un.ConfigLayersAndVulkanDLL
+ ${If} $0 != 0
+ SetOutPath "$IDir"
+ Call un.DiagConfigLayersAndVulkanDLL
+ MessageBox MB_OK "Warning!$\n$\nPowershell script called by VulkanRT Uninstaller failed with error $0. Is Powershell installed on your system?$\n$\nVulkan $FileVersion has been uninstalled from your system." /SD IDOK
+ ${If} ${RunningX64}
+ Delete $WINDIR\SysWow64\vulkan-${VERSION_ABI_MAJOR}.dll
+ Delete $WINDIR\SysWow64\vulkaninfo.exe
+ ${Endif}
+ Delete $WINDIR\System32\vulkan-${VERSION_ABI_MAJOR}.dll
+ Delete $WINDIR\System32\vulkaninfo.exe
+ ClearErrors
+ ${Else}
+ StrCpy $1 85
+ ${Endif}
+ Call un.CheckForError
# If Ref Count is zero, uninstall everything
${If} $IC <= 0
@@ -622,7 +680,7 @@ Section "uninstall"
Delete /REBOOTOK "$IDir\vulkaninfo32.exe"
${EndIf}
- StrCpy $1 75
+ StrCpy $1 90
Call un.CheckForError
# Need to do a SetOutPath to something outside of install dir,
@@ -650,12 +708,12 @@ Section "uninstall"
${Endif}
- StrCpy $1 80
+ StrCpy $1 95
Call un.CheckForError
- # Finish logging and move log file to TEMP dir
+ # Finish logging
LogSet off
- Rename "$INSTDIR\install.log" "$INSTDIR\Uninstall.log"
+ Rename "$INSTDIR\install.log" "$TEMP\VulkanRT\uninstaller.log"
SectionEnd
!endif
@@ -699,19 +757,18 @@ Function CheckForError
# Finish logging and move log file to TEMP dir
LogSet off
- Rename "$INSTDIR\install.log" "$TEMP\VulkanRT\install.log"
+ Rename "$INSTDIR\install.log" "$TEMP\VulkanRT\installer.log"
# Copy the uninstaller to a temp folder of our own creation so we can completely
# delete the old contents.
SetOutPath "$TEMP\VulkanRT"
CopyFiles "$INSTDIR\Uninstall${PRODUCTNAME}.exe" "$TEMP\VulkanRT"
- # No uninstall using the version in the temporary folder.
+ # Do uninstall using the version in the temporary folder.
ExecWait '"$TEMP\VulkanRT\Uninstall${PRODUCTNAME}.exe" /S _?=$INSTDIR'
# Delete the copy of the uninstaller we ran
Delete /REBOOTOK "$TEMP\VulkanRT\Uninstall${PRODUCTNAME}.exe"
- RmDir /R /REBOOTOK "$TEMP\VulkanRT"
# Set an error message to output
SetErrorLevel $1
@@ -721,7 +778,7 @@ Function CheckForError
FunctionEnd
# Check for errors during uninstall. If we hit an error, don't attempt
-# to do anything. Just set a non-zero return code and quit.
+# to do anything. Just set a non-zero return code and continue.
Function un.CheckForError
${If} ${Errors}
# IHV's using this install may want no message box.
@@ -730,11 +787,5 @@ Function un.CheckForError
# Set an error message to output
SetErrorLevel $1
- # Finish logging and move log file to TEMP dir
- LogSet off
- Delete "$TEMP\VulkanRT\Uninstall.log"
- Rename "$INSTDIR\install.log" "$TEMP\VulkanRT\Uninstall.log"
-
- Quit
${EndIf}
FunctionEnd
diff --git a/windowsRuntimeInstaller/vcredist_x64.exe b/windowsRuntimeInstaller/vcredist_x64.exe
deleted file mode 100644
index 54736409..00000000
--- a/windowsRuntimeInstaller/vcredist_x64.exe
+++ /dev/null
Binary files differ
diff --git a/windowsRuntimeInstaller/vcredist_x86.exe b/windowsRuntimeInstaller/vcredist_x86.exe
deleted file mode 100644
index b7955781..00000000
--- a/windowsRuntimeInstaller/vcredist_x86.exe
+++ /dev/null
Binary files differ