blob: f556731a7fafac50ff88acfb641fc9ec21151765 [file] [log] [blame]
/* Copyright (c) 2020-2026 The Khronos Group Inc.
* Copyright (c) 2020-2026 Valve Corporation
* Copyright (c) 2020-2026 LunarG, Inc.
* Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
*
* 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.
*/
#include "layer_options.h"
#include <vulkan/vulkan_core.h>
#include "chassis/validation_object.h"
#include "containers/span.h"
#include "error_message/log_message_type.h"
#include "error_message/logging.h"
#include "error_message/error_location.h"
#include "generated/error_location_helper.h"
#include "utils/hash_util.h"
#include <cstring>
#include <string>
#include <vector>
#include <vulkan/layer/vk_layer_settings.hpp>
#include "gpuav/core/gpuav_settings.h"
#include "sync/sync_settings.h"
#include "vk_layer_config.h"
// Include new / delete overrides if using mimalloc. This needs to be include exactly once in a file that is
// part of the VVL but not the layer utils library.
#if defined(USE_MIMALLOC) && defined(_WIN64)
#include "mimalloc-new-delete.h"
#endif
const auto &VkValFeatureDisableLookup() {
static const vvl::unordered_map<std::string, VkValidationFeatureDisableEXT> vk_val_feature_disable_lookup = {
{"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT", VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT},
{"VK_VALIDATION_FEATURE_DISABLE_ALL_EXT", VK_VALIDATION_FEATURE_DISABLE_ALL_EXT},
};
return vk_val_feature_disable_lookup;
}
const auto &VkValFeatureEnableLookup() {
static const vvl::unordered_map<std::string, VkValidationFeatureEnableEXT> vk_val_feature_enable_lookup = {
{"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT},
{"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT",
VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT},
{"VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT", VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT},
{"VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT", VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT},
{"VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT",
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT},
};
return vk_val_feature_enable_lookup;
}
const auto &ValidationDisableLookup() {
static const vvl::unordered_map<std::string, ValidationCheckDisables> validation_disable_lookup = {
{"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE},
{"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", VALIDATION_CHECK_DISABLE_OBJECT_IN_USE},
{"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", VALIDATION_CHECK_DISABLE_QUERY_VALIDATION},
{"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION},
};
return validation_disable_lookup;
}
const auto &ValidationEnableLookup() {
static const vvl::unordered_map<std::string, ValidationCheckEnables> validation_enable_lookup = {
{"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ARM", VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ARM},
{"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD", VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD},
{"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_IMG", VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_IMG},
{"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA", VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA},
{"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ALL", VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ALL},
};
return validation_enable_lookup;
}
// This should mirror the 'DisableFlags' enumerated type
const std::vector<std::string> &GetDisableFlagNameHelper() {
static const std::vector<std::string> disable_flag_name_helper = {
"VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE", // command_buffer_state,
"VALIDATION_CHECK_DISABLE_OBJECT_IN_USE", // object_in_use,
"VALIDATION_CHECK_DISABLE_QUERY_VALIDATION", // query_validation,
"VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION", // image_layout_validation,
"VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT", // object_tracking,
"VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT", // core_checks,
"VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT", // thread_safety,
"VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT", // stateless_checks,
"VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT", // handle_wrapping,
"VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT", // shader_validation,
"VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHING_EXT", // shader_validation_caching
};
return disable_flag_name_helper;
}
const std::vector<std::string> &GetEnableFlagNameHelper() {
// This should mirror the 'EnableFlags' enumerated type
static const std::vector<std::string> enable_flag_name_helper = {
"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT", // gpu_validation,
"VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT", // gpu_validation_reserve_binding_slot,
"VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT", // best_practices,
"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ARM", // vendor_specific_arm,
"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD", // vendor_specific_amd,
"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_IMG", // vendor_specific_img,
"VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA", // vendor_specific_nvidia,
"VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT", // debug_printf,
"VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT", // sync_validation,
"VK_VALIDATION_LEGACY_DETECTION", // legacy_detection,
};
return enable_flag_name_helper;
}
// To enable "my_setting",
// Set env var VK_LAYER_MY_SETTING to 1
//
// The ["VK_LAYER_" + toUpper(key)] logic is don in vk_layer_setting (VUL)
//
// To quickly be able to find the env var corresponding to a setting,
// the following `const char*` holding setting names match their corresponding environment variable
// Corresponding to VkValidationFeatureEnableEXT
// ---
const char *VK_LAYER_ENABLES = "enables";
const char *VK_LAYER_VALIDATE_BEST_PRACTICES = "validate_best_practices";
const char *VK_LAYER_VALIDATE_BEST_PRACTICES_ARM = "validate_best_practices_arm";
const char *VK_LAYER_VALIDATE_BEST_PRACTICES_AMD = "validate_best_practices_amd";
const char *VK_LAYER_VALIDATE_BEST_PRACTICES_IMG = "validate_best_practices_img";
const char *VK_LAYER_VALIDATE_BEST_PRACTICES_NVIDIA = "validate_best_practices_nvidia";
const char *VK_LAYER_VALIDATE_SYNC = "validate_sync";
// Corresponding to VkValidationFeatureDisableEXT
// ---
const char *VK_LAYER_DISABLES = "disables";
const char *VK_LAYER_CHECK_SHADERS = "check_shaders";
const char *VK_LAYER_THREAD_SAFETY = "thread_safety";
const char *VK_LAYER_STATELESS_PARAM = "stateless_param";
const char *VK_LAYER_LEGACY_DETECTION = "legacy_detection";
const char *VK_LAYER_OBJECT_LIFETIME = "object_lifetime";
const char *VK_LAYER_VALIDATE_CORE = "validate_core";
const char *VK_LAYER_UNIQUE_HANDLES = "unique_handles";
const char *VK_LAYER_CHECK_SHADERS_CACHING = "check_shaders_caching";
// Additional checks exposed in vkconfig, but not in VkValidationFeatureDisableEXT
// ---
const char *VK_LAYER_CHECK_COMMAND_BUFFER = "check_command_buffer";
const char *VK_LAYER_CHECK_OBJECT_IN_USE = "check_object_in_use";
const char *VK_LAYER_CHECK_QUERY = "check_query";
const char *VK_LAYER_CHECK_IMAGE_LAYOUT = "check_image_layout";
// Options related to debug reporting
// ---
const char *VK_LAYER_MESSAGE_ID_FILTER = "message_id_filter";
const char *VK_LAYER_CUSTOM_STYPE_LIST = "custom_stype_list";
const char *VK_LAYER_ENABLE_MESSAGE_LIMIT = "enable_message_limit";
const char *VK_LAYER_DUPLICATE_MESSAGE_LIMIT = "duplicate_message_limit";
// Global settings
// ---
const char *VK_LAYER_FINE_GRAINED_LOCKING = "fine_grained_locking";
// Debug settings used for internal development
const char *VK_LAYER_DEBUG_DISABLE_SPIRV_VAL = "debug_disable_spirv_val";
// DebugPrintf (which is now part of GPU-AV internally)
// ---
// Quick, single setting to turn on DebugPrintf
const char *VK_LAYER_PRINTF_ONLY_PRESET = "printf_only_preset";
// Was added a new way to set things without having to use VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT
const char *VK_LAYER_PRINTF_ENABLE = "printf_enable";
const char *VK_LAYER_PRINTF_TO_STDOUT = "printf_to_stdout";
const char *VK_LAYER_PRINTF_VERBOSE = "printf_verbose";
const char *VK_LAYER_PRINTF_BUFFER_SIZE = "printf_buffer_size";
// GPU-AV
// ---
const char *VK_LAYER_GPUAV_ENABLE = "gpuav_enable";
const char *VK_LAYER_GPUAV_SAFE_MODE = "gpuav_safe_mode";
const char *VK_LAYER_GPUAV_SHADER_INSTRUMENTATION = "gpuav_shader_instrumentation";
const char *VK_LAYER_GPUAV_DESCRIPTOR_CHECKS = "gpuav_descriptor_checks";
const char *VK_LAYER_GPUAV_BUFFER_ADDRESS_OOB = "gpuav_buffer_address_oob";
const char *VK_LAYER_GPUAV_VALIDATE_RAY_QUERY = "gpuav_validate_ray_query";
const char *VK_LAYER_GPUAV_MESH_SHADING = "gpuav_mesh_shading";
const char *VK_LAYER_GPUAV_POST_PROCESS_DESCRIPTOR_INDEXING = "gpuav_post_process_descriptor_indexing";
const char *VK_LAYER_GPUAV_VERTEX_ATTRIBUTE_FETCH_OOB = "gpuav_vertex_attribute_fetch_oob";
const char *VK_LAYER_GPUAV_SHADER_SANITIZER = "gpuav_shader_sanitizer";
const char *VK_LAYER_GPUAV_MAX_INDICES_COUNT = "gpuav_max_indices_count";
const char *VK_LAYER_GPUAV_SELECT_INSTRUMENTED_SHADERS = "gpuav_select_instrumented_shaders";
const char *VK_LAYER_GPUAV_SHADERS_TO_INSTRUMENT = "gpuav_shaders_to_instrument";
const char *VK_LAYER_GPUAV_BUFFERS_VALIDATION = "gpuav_buffers_validation";
const char *VK_LAYER_GPUAV_INDIRECT_DRAWS_BUFFERS = "gpuav_indirect_draws_buffers";
const char *VK_LAYER_GPUAV_INDIRECT_DISPATCHES_BUFFERS = "gpuav_indirect_dispatches_buffers";
const char *VK_LAYER_GPUAV_INDIRECT_TRACE_RAYS_BUFFERS = "gpuav_indirect_trace_rays_buffers";
const char *VK_LAYER_GPUAV_BUFFER_COPIES = "gpuav_buffer_copies";
const char *VK_LAYER_GPUAV_COPY_MEMORY_INDIRECT = "gpuav_copy_memory_indirect";
const char *VK_LAYER_GPUAV_INDEX_BUFFERS = "gpuav_index_buffers";
const char *VK_LAYER_GPUAV_ACCELERATION_STRUCTURES_BUILDS = "gpuav_acceleration_structures_builds";
// A temporary workaround until we get proper Descriptor Buffer support
const char *VK_LAYER_GPUAV_DESCRIPTOR_BUFFER_OVERRIDE = "gpuav_descriptor_buffer_override";
const char *VK_LAYER_GPUAV_FORCE_ON_ROBUSTNESS = "gpuav_force_on_robustness";
const char *VK_LAYER_GPUAV_DEBUG_DISABLE_ALL = "gpuav_debug_disable_all";
const char *VK_LAYER_GPUAV_DEBUG_VALIDATE_INSTRUMENTED_SHADERS = "gpuav_debug_validate_instrumented_shaders";
const char *VK_LAYER_GPUAV_DEBUG_DUMP_INSTRUMENTED_SHADERS = "gpuav_debug_dump_instrumented_shaders";
const char *VK_LAYER_GPUAV_DEBUG_MAX_INSTRUMENTATIONS_COUNT = "gpuav_debug_max_instrumentations_count";
const char *VK_LAYER_GPUAV_DEBUG_PRINT_INSTRUMENTATION_INFO = "gpuav_debug_print_instrumentation_info";
// SyncVal
// ---
const char *VK_LAYER_SYNCVAL_SUBMIT_TIME_VALIDATION = "syncval_submit_time_validation";
const char *VK_LAYER_SYNCVAL_SHADER_ACCESSES_HEURISTIC = "syncval_shader_accesses_heuristic";
const char *VK_LAYER_SYNCVAL_LOAD_OP_AFTER_STORE_OP_VALIDATION = "syncval_load_op_after_store_op_validation";
const char *VK_LAYER_SYNCVAL_MESSAGE_EXTRA_PROPERTIES = "syncval_message_extra_properties";
// Message Formatting
// ---
const char *VK_LAYER_MESSAGE_FORMAT_JSON = "message_format_json";
const char *VK_LAYER_MESSAGE_FORMAT_DISPLAY_APPLICATION_NAME = "message_format_display_application_name";
// Until post 1.3.290 SDK release, these were not possible to set via environment variables
const char *VK_LAYER_LOG_FILENAME = "log_filename";
const char *VK_LAYER_DEBUG_ACTION = "debug_action";
const char *VK_LAYER_REPORT_FLAGS = "report_flags";
// Don't need any setting helper when using self vvl and don't want unused function warnings
#if !defined(BUILD_SELF_VVL)
// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
void SetValidationDisable(ValidationDisabled &disable_data, const ValidationCheckDisables disable_id) {
switch (disable_id) {
case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
disable_data[command_buffer_state] = true;
break;
case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
disable_data[object_in_use] = true;
break;
case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
disable_data[query_validation] = true;
break;
case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
disable_data[image_layout_validation] = true;
break;
default:
assert(false);
}
}
// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
void SetValidationFeatureDisable(ValidationDisabled &disable_data, const VkValidationFeatureDisableEXT feature_disable) {
switch (feature_disable) {
case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
disable_data[shader_validation] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
disable_data[thread_safety] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
disable_data[stateless_checks] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
disable_data[object_tracking] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
disable_data[core_checks] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
disable_data[handle_wrapping] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT:
disable_data[shader_validation_caching] = true;
break;
case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
// Set all disabled flags to true
std::fill(disable_data.begin(), disable_data.end(), true);
break;
default:
break;
}
}
// Set the local enable flag for the appropriate VALIDATION_CHECK_ENABLE enum
void SetValidationEnable(ValidationEnabled &enable_data, const ValidationCheckEnables enable_id) {
switch (enable_id) {
case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ARM:
enable_data[vendor_specific_arm] = true;
break;
case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD:
enable_data[vendor_specific_amd] = true;
break;
case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_IMG:
enable_data[vendor_specific_img] = true;
break;
case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA:
enable_data[vendor_specific_nvidia] = true;
break;
case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ALL:
enable_data[vendor_specific_arm] = true;
enable_data[vendor_specific_amd] = true;
enable_data[vendor_specific_img] = true;
enable_data[vendor_specific_nvidia] = true;
break;
default:
assert(false);
}
}
// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
void SetValidationFeatureEnable(ValidationEnabled &enable_data, const VkValidationFeatureEnableEXT feature_enable) {
switch (feature_enable) {
case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
enable_data[gpu_validation] = true;
break;
case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
enable_data[gpu_validation_reserve_binding_slot] = true;
break;
case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT:
enable_data[best_practices] = true;
break;
case VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT:
enable_data[debug_printf_validation] = true;
break;
case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT:
enable_data[sync_validation] = true;
break;
default:
break;
}
}
// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
void SetValidationFlags(ValidationDisabled &disabled, const VkValidationFlagsEXT *val_flags_struct) {
for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
switch (val_flags_struct->pDisabledValidationChecks[i]) {
case VK_VALIDATION_CHECK_SHADERS_EXT:
disabled[shader_validation] = true;
break;
case VK_VALIDATION_CHECK_ALL_EXT:
// Set all disabled flags to true
disabled[shader_validation] = true;
break;
default:
break;
}
}
}
// Process Validation Features flags specified through the ValidationFeature extension
void SetValidationFeatures(ValidationDisabled &disable_data, ValidationEnabled &enable_data,
const VkValidationFeaturesEXT *val_features_struct) {
for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
}
for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
}
}
std::string GetNextToken(std::string *token_list, const std::string &delimiter, size_t *pos) {
std::string token;
*pos = token_list->find(delimiter);
if (*pos != std::string::npos) {
token = token_list->substr(0, *pos);
} else {
*pos = token_list->length() - delimiter.length();
token = *token_list;
}
token_list->erase(0, *pos + delimiter.length());
// Remove quotes from quoted strings
if ((token.length() > 0) && (token[0] == '\"')) {
token.erase(token.begin());
if ((token.length() > 0) && (token[token.length() - 1] == '\"')) {
token.erase(--token.end());
}
}
return token;
}
// Given a string representation of a list of enable enum values, call the appropriate setter function
bool SetLocalEnableSetting(std::string list_of_enabled, const std::string& delimiter, ValidationEnabled& enabled) {
bool used = false;
size_t pos = 0;
std::string token;
while (list_of_enabled.length() != 0) {
token = GetNextToken(&list_of_enabled, delimiter, &pos);
if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
auto result = VkValFeatureEnableLookup().find(token);
if (result != VkValFeatureEnableLookup().end()) {
used = true;
SetValidationFeatureEnable(enabled, result->second);
}
} else if (token.find("VALIDATION_CHECK_ENABLE_") != std::string::npos) {
auto result = ValidationEnableLookup().find(token);
if (result != ValidationEnableLookup().end()) {
used = true;
SetValidationEnable(enabled, result->second);
}
}
}
return used;
}
// Given a string representation of a list of disable enum values, call the appropriate setter function
bool SetLocalDisableSetting(std::string list_of_disabled, const std::string& delimiter, ValidationDisabled& disabled) {
bool used = false;
size_t pos = 0;
std::string token;
while (list_of_disabled.length() != 0) {
token = GetNextToken(&list_of_disabled, delimiter, &pos);
if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
auto result = VkValFeatureDisableLookup().find(token);
if (result != VkValFeatureDisableLookup().end()) {
SetValidationFeatureDisable(disabled, result->second);
used = true;
}
} else if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
auto result = ValidationDisableLookup().find(token);
if (result != ValidationDisableLookup().end()) {
SetValidationDisable(disabled, result->second);
used = true;
}
}
}
return used;
}
uint32_t TokenToUint(std::string &token) {
uint32_t int_id = 0;
if ((token.find("0x") == 0) || token.find("0X") == 0) { // Handle hex format
int_id = static_cast<uint32_t>(std::strtoul(token.c_str(), nullptr, 16));
} else {
int_id = static_cast<uint32_t>(std::strtoul(token.c_str(), nullptr, 10)); // Decimal format
}
return int_id;
}
void CreateFilterMessageIdList(std::string raw_id_list, const std::string &delimiter, vvl::unordered_set<uint32_t> &filter_list) {
size_t pos = 0;
std::string token;
while (raw_id_list.length() != 0) {
token = GetNextToken(&raw_id_list, delimiter, &pos);
uint32_t int_id = TokenToUint(token);
if (int_id == 0) {
const uint32_t id_hash = hash_util::VuidHash(token);
if (id_hash != 0) {
int_id = id_hash;
}
}
if ((int_id != 0) && filter_list.find(int_id) == filter_list.end()) {
filter_list.insert(int_id);
}
}
}
// Because VkLayerSettingsCreateInfoEXT/VkLayerSettingEXT are passed in and used before everything else, need to do the stateless
// validation here as a special exception
//
// We want to use the DebugReport object to print VU error messages in here, but we need to parse the settings in
// VkLayerSettingsCreateInfoEXT in order to configure the DebugReport object. Therefor we just settle with printf in here. These are
// very unlikely things to hit validation layers messages (as everything after will likely crumble) so should be ok.
//
// Returns if valid
static bool ValidateLayerSettingsCreateInfo(const VkLayerSettingsCreateInfoEXT *layer_settings) {
bool valid = true;
if (!layer_settings) return valid;
const Location loc(vvl::Func::vkCreateInstance, vvl::Field::pCreateInfo);
const Location create_info_loc = loc.pNext(vvl::Struct::VkLayerSettingsCreateInfoEXT);
std::ostringstream ss;
if (layer_settings->pSettings) {
for (const auto [i, setting] : vvl::enumerate(layer_settings->pSettings, layer_settings->settingCount)) {
const Location setting_loc = create_info_loc.dot(vvl::Field::pSettings, i);
if (setting.valueCount > 0 && !setting.pValues) {
ss << "[ VUID-VkLayerSettingEXT-valueCount-10070 ] " << setting_loc.dot(vvl::Field::pValues).Message()
<< " is NULL";
printf("Validation Layer Error: %s\n", ss.str().c_str());
valid = false;
}
if (!setting.pLayerName) {
ss << "[ VUID-VkLayerSettingEXT-pLayerName-parameter ] " << setting_loc.dot(vvl::Field::pLayerName).Message()
<< " is NULL";
printf("Validation Layer Error: %s\n", ss.str().c_str());
valid = false;
}
if (!setting.pSettingName) {
ss << "[ VUID-VkLayerSettingEXT-pSettingName-parameter ] " << setting_loc.dot(vvl::Field::pSettingName).Message()
<< " is NULL";
printf("Validation Layer Error: %s\n", ss.str().c_str());
valid = false;
}
// Can assume no new VkLayerSettingTypeEXT will be added
const uint32_t casted_type = (uint32_t)setting.type;
const uint32_t last_setting_type = (uint32_t)VK_LAYER_SETTING_TYPE_STRING_EXT;
if (casted_type > last_setting_type) {
ss << "[ VUID-VkLayerSettingEXT-type-parameter ] " << setting_loc.dot(vvl::Field::type).Message() << " is "
<< casted_type << " which is not a valid VkLayerSettingTypeEXT enum value";
printf("Validation Layer Error: %s\n", ss.str().c_str());
valid = false;
}
}
} else if (layer_settings->settingCount > 0) {
ss << "[ VUID-VkLayerSettingsCreateInfoEXT-pSettings-parameter ] " << create_info_loc.dot(vvl::Field::pSettings).Message()
<< " is NULL";
printf("Validation Layer Error: %s\n", ss.str().c_str());
valid = false;
}
return valid;
}
static void SetValidationSetting(VkuLayerSettingSet layer_setting_set, ValidationDisabled &disable_data,
const DisableFlags feature_disable, const char *setting) {
if (vkuHasLayerSetting(layer_setting_set, setting)) {
bool enabled = true;
vkuGetLayerSettingValue(layer_setting_set, setting, enabled);
disable_data[feature_disable] = !enabled;
}
}
static void SetValidationSetting(VkuLayerSettingSet layer_setting_set, ValidationEnabled &enable_data,
const EnableFlags feature_enable, const char *setting) {
if (vkuHasLayerSetting(layer_setting_set, setting)) {
bool enabled = true;
vkuGetLayerSettingValue(layer_setting_set, setting, enabled);
enable_data[feature_enable] = enabled;
}
}
static std::string Merge(const std::vector<std::string> &strings) {
std::string result;
for (std::size_t i = 0, n = strings.size(); i < n; ++i) {
if (!result.empty()) {
result += ",";
}
result += strings[i];
}
return result;
}
// If log_filename is NULL or stdout, return stdout, otherwise try to open log_filename
// as a filename. If successful, return file handle, otherwise stdout
FILE *GetLayerLogOutput(const char *log_filename, std::vector<std::string> &setting_warnings) {
FILE *log_output = NULL;
if (!log_filename || !strcmp("stdout", log_filename)) {
log_output = stdout;
} else {
log_output = fopen(log_filename, "w");
if (log_output == NULL) {
if (log_filename) {
setting_warnings.emplace_back("log_filename (" + std::string(log_filename) +
") could not be opened, falling back to stdout instead.");
}
log_output = stdout;
}
}
return log_output;
}
// Definitions for Debug Actions
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,
};
using VkLayerDbgActionFlags = VkFlags;
static void ProcessDebugReportSettings(ConfigAndEnvSettings *settings_data, VkuLayerSettingSet &layer_setting_set,
std::vector<std::string> &setting_warnings) {
DebugReport *debug_report = settings_data->debug_report;
// Message ID Filtering
std::vector<std::string> message_id_filter;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_MESSAGE_ID_FILTER)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_MESSAGE_ID_FILTER, message_id_filter);
}
const std::string string_message_id_filter = Merge(message_id_filter);
CreateFilterMessageIdList(string_message_id_filter, ",", debug_report->filter_message_ids);
// Duplicate message limit
bool enable_message_limit = true; // default in JSON
uint32_t duplicate_message_limit = 10; // default in JSON
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_ENABLE_MESSAGE_LIMIT)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_ENABLE_MESSAGE_LIMIT, enable_message_limit);
}
if (enable_message_limit) {
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_DUPLICATE_MESSAGE_LIMIT)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_DUPLICATE_MESSAGE_LIMIT, duplicate_message_limit);
}
} else {
duplicate_message_limit = 0;
}
debug_report->duplicate_message_limit = duplicate_message_limit;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_MESSAGE_FORMAT_JSON)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_MESSAGE_FORMAT_JSON, debug_report->message_format_settings.json);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_MESSAGE_FORMAT_DISPLAY_APPLICATION_NAME)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_MESSAGE_FORMAT_DISPLAY_APPLICATION_NAME,
debug_report->message_format_settings.display_application_name);
}
std::string log_filename = "stdout"; // Default
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_LOG_FILENAME)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_LOG_FILENAME, log_filename);
}
const bool is_stdout = log_filename.compare("stdout") == 0;
// Default
std::vector<std::string> debug_actions_list = {"VK_DBG_LAYER_ACTION_DEFAULT", "VK_DBG_LAYER_ACTION_LOG_MSG"};
#ifdef WIN32
// For Windows, enable message logging AND OutputDebugString
debug_actions_list.push_back("VK_DBG_LAYER_ACTION_DEBUG_OUTPUT");
#endif // WIN32
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_DEBUG_ACTION)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_DEBUG_ACTION, debug_actions_list);
}
VkLayerDbgActionFlags debug_action = 0;
const vvl::unordered_map<std::string, VkFlags> debug_actions_option = {
{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},
{std::string("VK_DBG_LAYER_ACTION_DEBUG_OUTPUT"), VK_DBG_LAYER_ACTION_DEBUG_OUTPUT},
{std::string("VK_DBG_LAYER_ACTION_DEFAULT"), VK_DBG_LAYER_ACTION_DEFAULT}};
for (const auto &element : debug_actions_list) {
auto enum_value = debug_actions_option.find(element);
if (enum_value != debug_actions_option.end()) {
debug_action |= enum_value->second;
} else {
if (element.find(',') != std::string::npos) {
setting_warnings.emplace_back("\"" + element +
"\" was not a valid option for VK_LAYER_DEBUG_ACTION (ignoring).\nIf using "
"VkLayerSettings, each string needs to be its own VkLayerSettingEXT::pValues.");
} else {
setting_warnings.emplace_back(
"\"" + element +
"\" was not a valid option for VK_LAYER_DEBUG_ACTION (ignoring).\nValid options are "
"[VK_DBG_LAYER_ACTION_IGNORE, VK_DBG_LAYER_ACTION_CALLBACK, VK_DBG_LAYER_ACTION_LOG_MSG, "
"VK_DBG_LAYER_ACTION_BREAK, VK_DBG_LAYER_ACTION_DEBUG_OUTPUT, VK_DBG_LAYER_ACTION_DEFAULT]");
}
}
}
std::vector<std::string> report_flags_list = {"error", "warn"}; // Default
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_REPORT_FLAGS)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_REPORT_FLAGS, report_flags_list);
}
VkLayerDbgActionFlags report_flags = 0;
const vvl::unordered_map<std::string, VkFlags> report_flags_options = {{std::string("warn"), kWarningBit},
{std::string("info"), kInformationBit},
{std::string("perf"), kPerformanceWarningBit},
{std::string("error"), kErrorBit},
{std::string("verbose"), kVerboseBit}};
for (const auto &element : report_flags_list) {
auto enum_value = report_flags_options.find(element);
if (enum_value != report_flags_options.end()) {
report_flags |= enum_value->second;
} else {
if (element.find(',') != std::string::npos) {
setting_warnings.emplace_back("\"" + element +
"\" was not a valid option for VK_LAYER_REPORT_FLAGS (ignoring)\nIf using "
"VkLayerSettings, each string needs to be its own VkLayerSettingEXT::pValues.");
} else {
setting_warnings.emplace_back("\"" + element +
"\" was not a valid option for VK_LAYER_REPORT_FLAGS (ignoring)\nValid options are "
"[error, warn, info, perf, verbose].");
}
}
}
// Before creating the debug callback, see if other settings interfere
if (settings_data->gpuav_settings->debug_printf_enabled) {
if (settings_data->gpuav_settings->debug_printf_to_stdout && (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)) {
if (is_stdout) {
setting_warnings.emplace_back(
"The debug callback is already logging to stdout, but " + std::string(VK_LAYER_PRINTF_TO_STDOUT) +
" is also enabled. DebugPrintf will skip the debug callback in favor of a direct stdout write.");
} else {
setting_warnings.emplace_back("The logging to " + log_filename + " will not contain any DebugPrintf info because " +
std::string(VK_LAYER_PRINTF_TO_STDOUT) + " is enabled.");
}
}
if (!settings_data->gpuav_settings->debug_printf_to_stdout && ((report_flags & kInformationBit) == 0)) {
// Normally it is a lot of spam to use kInformationBit, but if only using DebugPrintf, it should be minimal information
// printed
setting_warnings.emplace_back(
"DebugPrintf logs to the Information message severity, enabling Information level logging otherwise the message "
"will not be seen.");
report_flags |= kInformationBit;
}
}
if (settings_data->enabled[legacy_detection] && ((report_flags & kWarningBit) == 0)) {
setting_warnings.emplace_back(
"Legacy Detection logs to the Warning message severity, enabling Warning level logging otherwise the message "
"will not be seen.");
report_flags |= kWarningBit;
}
// Flag as default if these settings are not from a vk_layer_settings.txt file
const bool default_layer_callback = (debug_action & VK_DBG_LAYER_ACTION_DEFAULT) != 0;
VkDebugUtilsMessengerCreateInfoEXT dbg_create_info = vku::InitStructHelper();
dbg_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
if (report_flags & kErrorBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
}
if (report_flags & kWarningBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
}
if (report_flags & kPerformanceWarningBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT;
dbg_create_info.messageType |= VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
}
if (report_flags & kInformationBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT;
}
if (report_flags & kVerboseBit) {
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT;
}
settings_data->global_settings->only_report_errors = report_flags == kErrorBit;
VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_LOG_MSG) {
FILE *log_output = GetLayerLogOutput(log_filename.c_str(), setting_warnings);
if (log_output != stdout) {
// This particular warning is designed to show the user where the debug callback is going (which is important to know!),
// so it makes no sense to put the warning in the callback location. For this one only we attempt to print to the
// everywhere else possible
const std::string tmp = "Validation Layer Info - Logging validation error to " + log_filename + "\n";
const char *cstr = tmp.c_str();
printf("%s", cstr);
#ifdef VK_USE_PLATFORM_WIN32_KHR
OutputDebugString(cstr);
#endif
#ifdef VK_USE_PLATFORM_ANDROID_KHR
__android_log_print(ANDROID_LOG_INFO, "VALIDATION", "%s", cstr);
#endif
}
dbg_create_info.pfnUserCallback = MessengerLogCallback;
dbg_create_info.pUserData = (void *)log_output;
LayerCreateMessengerCallback(debug_report, default_layer_callback, &dbg_create_info, &messenger);
} else if (!is_stdout) {
setting_warnings.emplace_back("The log_filename was set to " + log_filename +
" but VK_DBG_LAYER_ACTION_LOG_MSG was not set, so it won't be sent to the file.");
}
#ifdef VK_USE_PLATFORM_WIN32_KHR
messenger = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
dbg_create_info.pfnUserCallback = MessengerWin32DebugOutputMsg;
dbg_create_info.pUserData = nullptr;
LayerCreateMessengerCallback(debug_report, default_layer_callback, &dbg_create_info, &messenger);
}
#endif
messenger = VK_NULL_HANDLE;
if (debug_action & VK_DBG_LAYER_ACTION_BREAK) {
dbg_create_info.pfnUserCallback = MessengerBreakCallback;
dbg_create_info.pUserData = nullptr;
LayerCreateMessengerCallback(debug_report, default_layer_callback, &dbg_create_info, &messenger);
}
}
// Set as deprecated for the first time in the 1.4.335 SDK release
static std::string GetDeprecatedEnabledDisabledWarning(const std::vector<std::string>& enabled,
const std::vector<std::string>& disabled) {
std::ostringstream ss;
ss << "Application is using deprecated";
if (!enabled.empty()) {
ss << " \"enables\" (VK_LAYER_ENABLES)";
if (!disabled.empty()) {
ss << " and";
}
}
if (!disabled.empty()) {
ss << " \"disables\" (VK_LAYER_DISABLES)";
}
ss << " layer settings.\nDeprecated settings and new settings cannot be mixed, and deprecated ones take precedence. Consider "
"only using the new settings:\n";
// We tried to have a more clever way to do this, but was hitting strange compiler issues...
// This for loop will NEVER grow, these are the only deprecated settings we have because they are baked into the Vulkan Spec
for (const std::string& deprecated_string : enabled) {
if (deprecated_string == "VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT | New: \"" << VK_LAYER_GPUAV_ENABLE
<< "\" (VK_LAYER_GPUAV_ENABLE=1)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT | New: \"" << VK_LAYER_VALIDATE_BEST_PRACTICES
<< "\" (VK_LAYER_VALIDATE_BEST_PRACTICES=1)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT | New: \"" << VK_LAYER_PRINTF_ENABLE
<< "\" (VK_LAYER_PRINTF_ENABLE=1)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT | New: \"" << VK_LAYER_VALIDATE_SYNC
<< "\" (VK_LAYER_VALIDATE_SYNC=1)\n";
}
}
for (const std::string& deprecated_string : disabled) {
if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT | New: \"" << VK_LAYER_CHECK_SHADERS
<< "\" (VK_LAYER_CHECK_SHADERS=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT | New: \"" << VK_LAYER_THREAD_SAFETY
<< "\" (VK_LAYER_THREAD_SAFETY=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT | New: \"" << VK_LAYER_STATELESS_PARAM
<< "\" (VK_LAYER_STATELESS_PARAM=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT | New: \"" << VK_LAYER_OBJECT_LIFETIME
<< "\" (VK_LAYER_OBJECT_LIFETIME=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT | New: \"" << VK_LAYER_VALIDATE_CORE
<< "\" (VK_LAYER_VALIDATE_CORE=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT | New: \"" << VK_LAYER_UNIQUE_HANDLES
<< "\" (VK_LAYER_UNIQUE_HANDLES=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT | New: \""
<< VK_LAYER_CHECK_SHADERS_CACHING << "\" (VK_LAYER_CHECK_SHADERS_CACHING=0)\n";
} else if (deprecated_string == "VK_VALIDATION_FEATURE_DISABLE_ALL_EXT") {
ss << " Deprecated: VK_VALIDATION_FEATURE_DISABLE_ALL_EXT | Currently has no replacement, disabling the layer has the "
"same effects.\n";
}
}
return ss.str();
}
static const char *GetDefaultPrefix() {
#ifdef __ANDROID__
return "vvl";
#else
return "LAYER";
#endif
}
#endif // !defined(BUILD_SELF_VVL)
// Global list of sType,size identifiers
std::vector<std::pair<uint32_t, uint32_t>> &GetCustomStypeInfo() {
static std::vector<std::pair<uint32_t, uint32_t>> custom_stype_info{};
return custom_stype_info;
}
#if !defined(BUILD_SELF_VVL)
// Generated, put here to mimic where it would have been if manually written
// Can't move up to top of file until we generate the VK_LAYER_* names as well
#include "layer_options_validation.h"
#endif
// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
void ProcessConfigAndEnvSettings(ConfigAndEnvSettings *settings_data) {
// When compiling a build for self validation, ProcessConfigAndEnvSettings immediately returns,
// so that the layer always defaults to the standard validation options we want,
// and does not try to process option coming from the VVL we are debugging
#if defined(BUILD_SELF_VVL)
// Setup default messenger callback to stdout and just error validation messages
FILE *log_output = stdout;
VkDebugUtilsMessengerEXT messenger = VK_NULL_HANDLE;
VkDebugUtilsMessengerCreateInfoEXT dbg_create_info = vku::InitStructHelper();
dbg_create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT | VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT;
dbg_create_info.messageSeverity |= VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
dbg_create_info.pfnUserCallback = MessengerLogCallback;
dbg_create_info.pUserData = (void *)log_output;
LayerCreateMessengerCallback(settings_data->debug_report, true, &dbg_create_info, &messenger);
#ifdef WIN32
messenger = VK_NULL_HANDLE;
dbg_create_info.pfnUserCallback = MessengerWin32DebugOutputMsg;
dbg_create_info.pUserData = nullptr;
LayerCreateMessengerCallback(settings_data->debug_report, true, &dbg_create_info, &messenger);
#endif // WIN32
return;
#else
// We need to send all warnings through the DebugCallback (printf will go into the void and likely is not seen for people), but
// we also need to get settings setup before creating the DebugCallback. This is the only spot that needs this, so we create a
// temp list of strings here and shove them through DebugCallback right after we call it. This function should not be a
// bottleneck so some extra string building should be ok here.
std::vector<std::string> setting_warnings;
// If not cleared, garbage has been seen in some Android run effecting the error message
GetCustomStypeInfo().clear();
VkuLayerSettingSet layer_setting_set = VK_NULL_HANDLE;
auto layer_setting_create_info = vkuFindLayerSettingsCreateInfo(settings_data->create_info);
if (!ValidateLayerSettingsCreateInfo(layer_setting_create_info)) {
return; // nullptr will crash things
}
vkuCreateLayerSettingSet(OBJECT_LAYER_NAME, layer_setting_create_info, nullptr, nullptr, &layer_setting_set);
vkuSetLayerSettingCompatibilityNamespace(layer_setting_set, GetDefaultPrefix());
if (layer_setting_create_info) {
ValidateLayerSettingsProvided(*layer_setting_create_info, setting_warnings);
}
// Read legacy "enables" flags for backward compatibility
std::vector<std::string> enabled;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_ENABLES)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_ENABLES, enabled);
}
const std::string string_enabled = Merge(enabled);
const bool used_enabled = SetLocalEnableSetting(string_enabled, ",", settings_data->enabled);
// Read legacy "disables" flags for backward compatibility
std::vector<std::string> disabled;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_DISABLES)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_DISABLES, disabled);
}
const std::string string_disabled = Merge(disabled);
const bool used_disabled = SetLocalDisableSetting(string_disabled, ",", settings_data->disabled);
// Check if actually used, or will give bogus warning if the user set VK_LAYER_ENABLES to some garbage setting
if (used_enabled || used_disabled) {
setting_warnings.emplace_back(GetDeprecatedEnabledDisabledWarning(enabled, disabled));
}
GlobalSettings &global_settings = *settings_data->global_settings;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_FINE_GRAINED_LOCKING)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_FINE_GRAINED_LOCKING, global_settings.fine_grained_locking);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_DEBUG_DISABLE_SPIRV_VAL)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_DEBUG_DISABLE_SPIRV_VAL, global_settings.debug_disable_spirv_val);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_CUSTOM_STYPE_LIST)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_CUSTOM_STYPE_LIST, GetCustomStypeInfo());
}
GpuAVSettings &gpuav_settings = *settings_data->gpuav_settings;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_SAFE_MODE)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_SAFE_MODE, gpuav_settings.safe_mode);
}
bool shader_instrumentation_enabled = true;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_SHADER_INSTRUMENTATION)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_SHADER_INSTRUMENTATION, shader_instrumentation_enabled);
}
if (!shader_instrumentation_enabled) {
gpuav_settings.DisableShaderInstrumentationAndOptions();
} else {
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DESCRIPTOR_CHECKS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DESCRIPTOR_CHECKS,
gpuav_settings.shader_instrumentation.descriptor_checks);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_POST_PROCESS_DESCRIPTOR_INDEXING)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_POST_PROCESS_DESCRIPTOR_INDEXING,
gpuav_settings.shader_instrumentation.post_process_descriptor_indexing);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_MESH_SHADING)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_MESH_SHADING,
gpuav_settings.shader_instrumentation.mesh_shading);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_VERTEX_ATTRIBUTE_FETCH_OOB)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_VERTEX_ATTRIBUTE_FETCH_OOB,
gpuav_settings.shader_instrumentation.vertex_attribute_fetch_oob);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_BUFFER_ADDRESS_OOB)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_BUFFER_ADDRESS_OOB,
gpuav_settings.shader_instrumentation.buffer_device_address);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_VALIDATE_RAY_QUERY)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_VALIDATE_RAY_QUERY,
gpuav_settings.shader_instrumentation.ray_query);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_SHADER_SANITIZER)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_SHADER_SANITIZER,
gpuav_settings.shader_instrumentation.sanitizer);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_MAX_INDICES_COUNT)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_MAX_INDICES_COUNT, gpuav_settings.invalid_index_command);
// Hard limit is set by the fact we have kActionId_Mask used... which is also arbitrary
// ... we don't need 64k slots for the kErrorLoggerId_Mask, so could increase 64k if really wanted
// (If we update, please update the SetMaxIndicesCountAtTheLimit test)
if (gpuav_settings.invalid_index_command >= 65535) {
setting_warnings.emplace_back(
"VK_LAYER_GPUAV_MAX_INDICES_COUNT (gpuav_max_indices_count) is being set to 65534, the max value supported "
"currently.");
gpuav_settings.invalid_index_command = 65534;
}
gpuav_settings.indices_buffer_count = gpuav_settings.invalid_index_command + 1;
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_SELECT_INSTRUMENTED_SHADERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_SELECT_INSTRUMENTED_SHADERS,
gpuav_settings.select_instrumented_shaders);
}
if (gpuav_settings.select_instrumented_shaders) {
std::vector<std::string> shaders_to_instrument;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_SHADERS_TO_INSTRUMENT)) {
vkuGetLayerSettingValues(layer_setting_set, VK_LAYER_GPUAV_SHADERS_TO_INSTRUMENT, shaders_to_instrument);
}
gpuav_settings.SetShaderSelectionRegexes(std::move(shaders_to_instrument));
}
// No need to enable shader instrumentation options is no instrumentation is done
if (!gpuav_settings.IsShaderInstrumentationEnabled()) {
gpuav_settings.DisableShaderInstrumentationAndOptions();
}
}
bool buffers_validation_enabled = true;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_BUFFERS_VALIDATION)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_BUFFERS_VALIDATION, buffers_validation_enabled);
}
if (!buffers_validation_enabled) {
gpuav_settings.SetBufferValidationEnabled(false);
} else {
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_INDIRECT_DRAWS_BUFFERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_INDIRECT_DRAWS_BUFFERS,
gpuav_settings.validate_indirect_draws_buffers);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_INDIRECT_DISPATCHES_BUFFERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_INDIRECT_DISPATCHES_BUFFERS,
gpuav_settings.validate_indirect_dispatches_buffers);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_INDIRECT_TRACE_RAYS_BUFFERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_INDIRECT_TRACE_RAYS_BUFFERS,
gpuav_settings.validate_indirect_trace_rays_buffers);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_BUFFER_COPIES)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_BUFFER_COPIES, gpuav_settings.validate_buffer_copies);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_COPY_MEMORY_INDIRECT)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_COPY_MEMORY_INDIRECT,
gpuav_settings.validate_copy_memory_indirect);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_INDEX_BUFFERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_INDEX_BUFFERS, gpuav_settings.validate_index_buffers);
}
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_ACCELERATION_STRUCTURES_BUILDS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_ACCELERATION_STRUCTURES_BUILDS,
gpuav_settings.validate_acceleration_structures_builds);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DESCRIPTOR_BUFFER_OVERRIDE)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DESCRIPTOR_BUFFER_OVERRIDE,
gpuav_settings.descriptor_buffer_override);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_FORCE_ON_ROBUSTNESS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_FORCE_ON_ROBUSTNESS, gpuav_settings.force_on_robustness);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DEBUG_VALIDATE_INSTRUMENTED_SHADERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DEBUG_VALIDATE_INSTRUMENTED_SHADERS,
gpuav_settings.debug_validate_instrumented_shaders);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DEBUG_DUMP_INSTRUMENTED_SHADERS)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DEBUG_DUMP_INSTRUMENTED_SHADERS,
gpuav_settings.debug_dump_instrumented_shaders);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DEBUG_MAX_INSTRUMENTATIONS_COUNT)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DEBUG_MAX_INSTRUMENTATIONS_COUNT,
gpuav_settings.debug_max_instrumentations_count);
}
// Debug Printf - (which we bundle into GPU-AV internally)
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_PRINTF_ENABLE)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_PRINTF_ENABLE, gpuav_settings.debug_printf_enabled);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DEBUG_PRINT_INSTRUMENTATION_INFO)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DEBUG_PRINT_INSTRUMENTATION_INFO,
gpuav_settings.debug_print_instrumentation_info);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_PRINTF_TO_STDOUT)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_PRINTF_TO_STDOUT, gpuav_settings.debug_printf_to_stdout);
}
// This option was published when DebugPrintf came out, leave to not break people's flow
// Deprecated right after the 1.3.280 SDK release
if (!GetEnvironment("DEBUG_PRINTF_TO_STDOUT").empty()) {
setting_warnings.emplace_back("DEBUG_PRINTF_TO_STDOUT was set, this is deprecated, please use VK_LAYER_PRINTF_TO_STDOUT");
gpuav_settings.debug_printf_to_stdout = true;
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_PRINTF_VERBOSE)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_PRINTF_VERBOSE, gpuav_settings.debug_printf_verbose);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_PRINTF_BUFFER_SIZE)) {
const uint32_t default_buffer_size = gpuav_settings.debug_printf_buffer_size;
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_PRINTF_BUFFER_SIZE, gpuav_settings.debug_printf_buffer_size);
if (gpuav_settings.debug_printf_buffer_size == 0) {
gpuav_settings.debug_printf_buffer_size = default_buffer_size;
setting_warnings.emplace_back(std::string(VK_LAYER_PRINTF_BUFFER_SIZE) +
" was set to zero, which is invalid, setting to the default of " +
std::to_string(default_buffer_size));
}
}
SyncValSettings &syncval_settings = *settings_data->syncval_settings;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_SYNCVAL_SUBMIT_TIME_VALIDATION)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_SYNCVAL_SUBMIT_TIME_VALIDATION,
syncval_settings.submit_time_validation);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_SYNCVAL_SHADER_ACCESSES_HEURISTIC)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_SYNCVAL_SHADER_ACCESSES_HEURISTIC,
syncval_settings.shader_accesses_heuristic);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_SYNCVAL_LOAD_OP_AFTER_STORE_OP_VALIDATION)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_SYNCVAL_LOAD_OP_AFTER_STORE_OP_VALIDATION,
syncval_settings.load_op_after_store_op_validation);
}
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_SYNCVAL_MESSAGE_EXTRA_PROPERTIES)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_SYNCVAL_MESSAGE_EXTRA_PROPERTIES,
syncval_settings.message_extra_properties);
}
const char *REMOVED_VK_LAYER_SYNCVAL_MESSAGE_EXTRA_PROPERTIES_PRETTY_PRINT = "syncval_message_extra_properties_pretty_print";
if (vkuHasLayerSetting(layer_setting_set, REMOVED_VK_LAYER_SYNCVAL_MESSAGE_EXTRA_PROPERTIES_PRETTY_PRINT)) {
setting_warnings.emplace_back(std::string(REMOVED_VK_LAYER_SYNCVAL_MESSAGE_EXTRA_PROPERTIES_PRETTY_PRINT) +
" was removed. The main purpose of the extra properties section is to filter syncval error "
"messages. The priority is to have a fixed and easy-to-parse layout.");
}
const auto *validation_features_ext = vku::FindStructInPNextChain<VkValidationFeaturesEXT>(settings_data->create_info);
if (validation_features_ext) {
SetValidationFeatures(settings_data->disabled, settings_data->enabled, validation_features_ext);
}
const auto *validation_flags_ext = vku::FindStructInPNextChain<VkValidationFlagsEXT>(settings_data->create_info);
if (validation_flags_ext) {
SetValidationFlags(settings_data->disabled, validation_flags_ext);
}
const bool use_fine_grained_settings = disabled.empty() && enabled.empty();
// Only read the legacy enables flags when used, not their replacement.
// Avoid Android C.I. performance regression from reading Android env variables
if (use_fine_grained_settings) {
SetValidationSetting(layer_setting_set, settings_data->enabled, best_practices, VK_LAYER_VALIDATE_BEST_PRACTICES);
SetValidationSetting(layer_setting_set, settings_data->enabled, vendor_specific_arm, VK_LAYER_VALIDATE_BEST_PRACTICES_ARM);
SetValidationSetting(layer_setting_set, settings_data->enabled, vendor_specific_amd, VK_LAYER_VALIDATE_BEST_PRACTICES_AMD);
SetValidationSetting(layer_setting_set, settings_data->enabled, vendor_specific_img, VK_LAYER_VALIDATE_BEST_PRACTICES_IMG);
SetValidationSetting(layer_setting_set, settings_data->enabled, vendor_specific_nvidia,
VK_LAYER_VALIDATE_BEST_PRACTICES_NVIDIA);
SetValidationSetting(layer_setting_set, settings_data->enabled, sync_validation, VK_LAYER_VALIDATE_SYNC);
SetValidationSetting(layer_setting_set, settings_data->enabled, legacy_detection, VK_LAYER_LEGACY_DETECTION);
}
// Only read the legacy disables flags when used, not their replacement.
// Avoid Android C.I. performance regression from reading Android env variables
if (use_fine_grained_settings) {
SetValidationSetting(layer_setting_set, settings_data->disabled, stateless_checks, VK_LAYER_STATELESS_PARAM);
SetValidationSetting(layer_setting_set, settings_data->disabled, thread_safety, VK_LAYER_THREAD_SAFETY);
SetValidationSetting(layer_setting_set, settings_data->disabled, core_checks, VK_LAYER_VALIDATE_CORE);
SetValidationSetting(layer_setting_set, settings_data->disabled, command_buffer_state, VK_LAYER_CHECK_COMMAND_BUFFER);
SetValidationSetting(layer_setting_set, settings_data->disabled, object_in_use, VK_LAYER_CHECK_OBJECT_IN_USE);
SetValidationSetting(layer_setting_set, settings_data->disabled, query_validation, VK_LAYER_CHECK_QUERY);
SetValidationSetting(layer_setting_set, settings_data->disabled, image_layout_validation, VK_LAYER_CHECK_IMAGE_LAYOUT);
SetValidationSetting(layer_setting_set, settings_data->disabled, handle_wrapping, VK_LAYER_UNIQUE_HANDLES);
SetValidationSetting(layer_setting_set, settings_data->disabled, object_tracking, VK_LAYER_OBJECT_LIFETIME);
SetValidationSetting(layer_setting_set, settings_data->disabled, shader_validation, VK_LAYER_CHECK_SHADERS);
SetValidationSetting(layer_setting_set, settings_data->disabled, shader_validation_caching, VK_LAYER_CHECK_SHADERS_CACHING);
}
// This is the "original" way to use DebugPrintf before you could use it with GPU-AV
// In this case, we want to emulate supporting only for DebugPrintf with GPU-AV disabled
if (settings_data->enabled[debug_printf_validation]) {
gpuav_settings.debug_printf_enabled = true;
} else if (gpuav_settings.debug_printf_enabled) {
// enabled the new way, but chassis uses this to create Validation Object
settings_data->enabled[debug_printf_validation] = true;
}
// New way to override everything to make it easy to use DebugPrintf when VkConfig isn't available
bool printf_only_preset = false;
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_PRINTF_ONLY_PRESET)) {
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_PRINTF_ONLY_PRESET, printf_only_preset);
if (printf_only_preset) {
gpuav_settings.SetOnlyDebugPrintf();
// chassis uses this to create Validation Object
settings_data->enabled[debug_printf_validation] = true;
settings_data->enabled[gpu_validation] = false;
// Tried to use VK_VALIDATION_FEATURE_DISABLE_ALL_EXT but when running on Android
// (--gtest_filter="NegativeGpuAVDebugPrintf.BasicLayerSettingsPrintfPreset:NegativeWsi.UseDestroyedSwapchain")
// Was getting asserts in VulkanTypedHandle::Cast() Simple fix was to just not disable
// VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT
SetValidationFeatureDisable(settings_data->disabled, VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT);
SetValidationFeatureDisable(settings_data->disabled, VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT);
SetValidationFeatureDisable(settings_data->disabled, VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT);
SetValidationFeatureDisable(settings_data->disabled, VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT);
SetValidationFeatureDisable(settings_data->disabled, VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT);
SetValidationFeatureDisable(settings_data->disabled, VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT);
setting_warnings.emplace_back(
"Disabling as much of normal validation as possible so that only DebugPrintf will be running.");
}
}
// This is the "new" way to enable GPU-AV
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_ENABLE)) {
bool gpuav_enable = false;
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_ENABLE, gpuav_enable);
if (printf_only_preset) {
setting_warnings.emplace_back(std::string(VK_LAYER_PRINTF_ONLY_PRESET) + " was set, so ignoring " + std::string(VK_LAYER_GPUAV_ENABLE) + ".");
} else if (gpuav_enable) {
// enabled the new way, but chassis uses this to create Validation Object
settings_data->enabled[gpu_validation] = true;
}
}
// After checking the various ways to enable both DebugPrintf and GPU-AV, disable non-DebugPrintf portion if not used
if (settings_data->enabled[debug_printf_validation] && !settings_data->enabled[gpu_validation]) {
gpuav_settings.SetOnlyDebugPrintf();
}
// if app is setting VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT, we can use this to disable it for debugging
if (vkuHasLayerSetting(layer_setting_set, VK_LAYER_GPUAV_DEBUG_DISABLE_ALL)) {
bool disable_gpuav = false;
vkuGetLayerSettingValue(layer_setting_set, VK_LAYER_GPUAV_DEBUG_DISABLE_ALL, disable_gpuav);
if (disable_gpuav) {
settings_data->enabled[gpu_validation] = false;
}
}
if (settings_data->enabled[gpu_validation] && !settings_data->disabled[core_checks]) {
setting_warnings.emplace_back(
"Both GPU Assisted Validation and Normal Core Check Validation are enabled, this is not recommend as it will be very "
"slow. Once all "
"errors in Core Check are solved, please disable, then only use GPU-AV for best performance.");
}
// Set at the end once we decide what settings are actually on
if (settings_data->disabled[shader_validation] || settings_data->disabled[core_checks]) {
// only is used for core validation checks
global_settings.spirv_const_fold = false;
// sync val relies on the information from spirv::Module being parsed and stored
if (!settings_data->enabled[sync_validation]) {
// GPU-AV/DebugPrintf relies on spirv::Module to hold the original SPIR-V
if (!settings_data->enabled[gpu_validation] && !settings_data->enabled[debug_printf_validation]) {
global_settings.spirv_store = false;
} else if (settings_data->disabled[shader_validation]) {
setting_warnings.emplace_back(
"Shader Validation was explicitly turned off, but the SPIR-V still needs to be stored, but not validated, in "
"order for GPU-AV/DebugPrintf to get information from the original SPIR-V.");
}
} else if (settings_data->disabled[shader_validation]) {
setting_warnings.emplace_back(
"Shader Validation was explicitly turned off, but the SPIR-V still needs to be parsed/stored, but not validated, "
"in order for Sync Validation to get read/write information out the SPIR-V.");
}
}
// Last as previous settings are needed so we can make sure they line up with the DebugReport settings
ProcessDebugReportSettings(settings_data, layer_setting_set, setting_warnings);
// Grab application name here while we have access to it and know if to save it or not
if (settings_data->debug_report->message_format_settings.display_application_name) {
const VkApplicationInfo *app_info = settings_data->create_info->pApplicationInfo;
settings_data->debug_report->message_format_settings.application_name =
(app_info && app_info->pApplicationName) ? app_info->pApplicationName : "";
}
for (const auto &warning : setting_warnings) {
Location loc(vvl::Func::vkCreateInstance);
settings_data->debug_report->LogMessage(kWarningBit, "VALIDATION-SETTINGS", {}, loc, warning);
}
vkuDestroyLayerSettingSet(layer_setting_set, nullptr);
#endif // !BUILD_SELF_VVL
}