blob: 14ade034ea52bca4ad5eb5e34424c9e4b87ccfb6 [file] [log] [blame]
Jeremy Gebben50edce62022-01-03 14:54:40 -07001/* Copyright (c) 2020-2022 The Khronos Group Inc.
2 * Copyright (c) 2020-2022 Valve Corporation
3 * Copyright (c) 2020-2022 LunarG, Inc.
Nadav Geva41c12a22021-05-21 13:14:05 -04004 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
Mark Lobodzinski183746f2020-07-21 11:48:18 -06005 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * Author: Mark Lobodzinski <mark@lunarg.com>
John Zulaufa7624e22020-08-31 16:46:41 -060019 * Author: John Zulauf <jzulauf@lunarg.com>
Nadav Geva41c12a22021-05-21 13:14:05 -040020 * Author: Nadav Geva <nadav.geva@amd.com>
Mark Lobodzinski183746f2020-07-21 11:48:18 -060021 */
22
23#include "layer_options.h"
24
25// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
26void SetValidationDisable(CHECK_DISABLED &disable_data, const ValidationCheckDisables disable_id) {
27 switch (disable_id) {
28 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
29 disable_data[command_buffer_state] = true;
30 break;
31 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
32 disable_data[object_in_use] = true;
33 break;
Mark Lobodzinski183746f2020-07-21 11:48:18 -060034 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
35 disable_data[query_validation] = true;
36 break;
37 case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
38 disable_data[image_layout_validation] = true;
39 break;
40 default:
41 assert(true);
42 }
43}
44
45// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
46void SetValidationFeatureDisable(CHECK_DISABLED &disable_data, const VkValidationFeatureDisableEXT feature_disable) {
47 switch (feature_disable) {
48 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
49 disable_data[shader_validation] = true;
50 break;
51 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
52 disable_data[thread_safety] = true;
53 break;
54 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
55 disable_data[stateless_checks] = true;
56 break;
57 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
58 disable_data[object_tracking] = true;
59 break;
60 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
61 disable_data[core_checks] = true;
62 break;
63 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
64 disable_data[handle_wrapping] = true;
65 break;
Tony-LunarG55a3fc22021-05-11 13:32:45 -060066 case VK_VALIDATION_FEATURE_DISABLE_SHADER_VALIDATION_CACHE_EXT:
67 disable_data[shader_validation_caching] = true;
68 break;
Mark Lobodzinski183746f2020-07-21 11:48:18 -060069 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
70 // Set all disabled flags to true
71 std::fill(disable_data.begin(), disable_data.end(), true);
72 break;
73 default:
74 break;
75 }
76}
77
78// Set the local enable flag for the appropriate VALIDATION_CHECK_ENABLE enum
79void SetValidationEnable(CHECK_ENABLED &enable_data, const ValidationCheckEnables enable_id) {
80 switch (enable_id) {
81 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ARM:
82 enable_data[vendor_specific_arm] = true;
83 break;
Nadav Geva41c12a22021-05-21 13:14:05 -040084 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_AMD:
85 enable_data[vendor_specific_amd] = true;
86 break;
LawG475463092022-02-22 10:45:54 +000087 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_IMG:
88 enable_data[vendor_specific_img] = true;
89 break;
Rodrigo Locattic779cb32022-02-25 19:26:31 -030090 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_NVIDIA:
91 enable_data[vendor_specific_nvidia] = true;
92 break;
Mark Lobodzinski183746f2020-07-21 11:48:18 -060093 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ALL:
94 enable_data[vendor_specific_arm] = true;
Nadav Geva41c12a22021-05-21 13:14:05 -040095 enable_data[vendor_specific_amd] = true;
LawG475463092022-02-22 10:45:54 +000096 enable_data[vendor_specific_img] = true;
Rodrigo Locattic779cb32022-02-25 19:26:31 -030097 enable_data[vendor_specific_nvidia] = true;
Mark Lobodzinski183746f2020-07-21 11:48:18 -060098 break;
John Zulauf78cb2082022-04-20 16:37:48 -060099 case VALIDATION_CHECK_ENABLE_SYNCHRONIZATION_VALIDATION_QUEUE_SUBMIT:
100 enable_data[sync_validation_queue_submit] = true;
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600101 default:
102 assert(true);
103 }
104}
105
106// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
107void SetValidationFeatureEnable(CHECK_ENABLED &enable_data, const VkValidationFeatureEnableEXT feature_enable) {
108 switch (feature_enable) {
109 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
110 enable_data[gpu_validation] = true;
111 break;
112 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
113 enable_data[gpu_validation_reserve_binding_slot] = true;
114 break;
115 case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT:
116 enable_data[best_practices] = true;
117 break;
118 case VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT:
119 enable_data[debug_printf] = true;
John Zulaufa7624e22020-08-31 16:46:41 -0600120 break;
121 case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT:
122 enable_data[sync_validation] = true;
123 break;
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600124 default:
125 break;
126 }
127}
128
129void SetValidationFeatureEnable2(CHECK_ENABLED &enable_data, const VkValidationFeatureEnable feature_enable) {
130 switch (feature_enable) {
131 case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION:
132 enable_data[sync_validation] = true;
133 break;
134 default:
135 break;
136 }
137}
138
139// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
140void SetValidationFlags(CHECK_DISABLED &disables, const VkValidationFlagsEXT *val_flags_struct) {
141 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
142 switch (val_flags_struct->pDisabledValidationChecks[i]) {
143 case VK_VALIDATION_CHECK_SHADERS_EXT:
144 disables[shader_validation] = true;
145 break;
146 case VK_VALIDATION_CHECK_ALL_EXT:
147 // Set all disabled flags to true
148 disables[shader_validation] = true;
149 break;
150 default:
151 break;
152 }
153 }
154}
155
156// Process Validation Features flags specified through the ValidationFeature extension
157void SetValidationFeatures(CHECK_DISABLED &disable_data, CHECK_ENABLED &enable_data,
158 const VkValidationFeaturesEXT *val_features_struct) {
159 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
160 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
161 }
162 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
163 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
164 }
165}
166
167std::string GetNextToken(std::string *token_list, const std::string &delimiter, size_t *pos) {
168 std::string token;
169 *pos = token_list->find(delimiter);
170 if (*pos != std::string::npos) {
171 token = token_list->substr(0, *pos);
172 } else {
173 *pos = token_list->length() - delimiter.length();
174 token = *token_list;
175 }
176 token_list->erase(0, *pos + delimiter.length());
Mark Lobodzinskiab4df2f2020-12-16 11:18:32 -0700177
178 // Remove quotes from quoted strings
179 if ((token.length() > 0) && (token[0] == '\"')) {
180 token.erase(token.begin());
181 if ((token.length() > 0) && (token[token.length() - 1] == '\"')) {
182 token.erase(--token.end());
183 }
184 }
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600185 return token;
186}
187
188// Given a string representation of a list of enable enum values, call the appropriate setter function
189void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED &enables) {
190 size_t pos = 0;
191 std::string token;
192 while (list_of_enables.length() != 0) {
193 token = GetNextToken(&list_of_enables, delimiter, &pos);
194 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
195 auto result = VkValFeatureEnableLookup.find(token);
196 if (result != VkValFeatureEnableLookup.end()) {
197 SetValidationFeatureEnable(enables, result->second);
198 } else {
199 auto result2 = VkValFeatureEnableLookup2.find(token);
200 if (result2 != VkValFeatureEnableLookup2.end()) {
201 SetValidationFeatureEnable2(enables, result2->second);
202 }
203 }
204 } else if (token.find("VALIDATION_CHECK_ENABLE_") != std::string::npos) {
205 auto result = ValidationEnableLookup.find(token);
206 if (result != ValidationEnableLookup.end()) {
207 SetValidationEnable(enables, result->second);
208 }
209 }
210 }
211}
212
213// Given a string representation of a list of disable enum values, call the appropriate setter function
214void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED &disables) {
215 size_t pos = 0;
216 std::string token;
217 while (list_of_disables.length() != 0) {
218 token = GetNextToken(&list_of_disables, delimiter, &pos);
219 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
220 auto result = VkValFeatureDisableLookup.find(token);
221 if (result != VkValFeatureDisableLookup.end()) {
222 SetValidationFeatureDisable(disables, result->second);
223 }
224 } else if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
225 auto result = ValidationDisableLookup.find(token);
226 if (result != ValidationDisableLookup.end()) {
227 SetValidationDisable(disables, result->second);
228 }
229 }
230 }
231}
232
233uint32_t TokenToUint(std::string &token) {
234 uint32_t int_id = 0;
235 if ((token.find("0x") == 0) || token.find("0X") == 0) { // Handle hex format
Mark Young0ec6b062020-11-19 15:32:17 -0700236 int_id = static_cast<uint32_t>(std::strtoul(token.c_str(), nullptr, 16));
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600237 } else {
Mark Young0ec6b062020-11-19 15:32:17 -0700238 int_id = static_cast<uint32_t>(std::strtoul(token.c_str(), nullptr, 10)); // Decimal format
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600239 }
240 return int_id;
241}
242
243void CreateFilterMessageIdList(std::string raw_id_list, std::string delimiter, std::vector<uint32_t> &filter_list) {
244 size_t pos = 0;
245 std::string token;
246 while (raw_id_list.length() != 0) {
247 token = GetNextToken(&raw_id_list, delimiter, &pos);
248 uint32_t int_id = TokenToUint(token);
249 if (int_id == 0) {
250 size_t id_hash = XXH32(token.c_str(), strlen(token.c_str()), 8); // String
251 if (id_hash != 0) {
252 int_id = static_cast<uint32_t>(id_hash);
253 }
254 }
255 if ((int_id != 0) && (std::find(filter_list.begin(), filter_list.end(), int_id)) == filter_list.end()) {
256 filter_list.push_back(int_id);
257 }
258 }
259}
260
261void SetCustomStypeInfo(std::string raw_id_list, std::string delimiter) {
262 size_t pos = 0;
263 std::string token;
264 // List format is a list of integer pairs
265 while (raw_id_list.length() != 0) {
266 token = GetNextToken(&raw_id_list, delimiter, &pos);
267 uint32_t stype_id = TokenToUint(token);
268 token = GetNextToken(&raw_id_list, delimiter, &pos);
269 uint32_t struct_size_in_bytes = TokenToUint(token);
270 if ((stype_id != 0) && (struct_size_in_bytes != 0)) {
271 bool found = false;
272 // Prevent duplicate entries
John Zulauf79f06582021-02-27 18:38:39 -0700273 for (const auto &item : custom_stype_info) {
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600274 if (item.first == stype_id) {
275 found = true;
276 break;
277 }
278 }
279 if (!found) custom_stype_info.push_back(std::make_pair(stype_id, struct_size_in_bytes));
280 }
281 }
282}
283
284uint32_t SetMessageDuplicateLimit(std::string &config_message_limit, std::string &env_message_limit) {
285 uint32_t limit = 0;
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700286 auto get_num = [](std::string &source_string) {
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600287 uint32_t limit = 0;
288 int radix = ((source_string.find("0x") == 0) ? 16 : 10);
Mark Young0ec6b062020-11-19 15:32:17 -0700289 limit = static_cast<uint32_t>(std::strtoul(source_string.c_str(), nullptr, radix));
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600290 return limit;
291 };
292 // ENV var takes precedence over settings file
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700293 limit = get_num(env_message_limit);
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600294 if (limit == 0) {
Nathaniel Cesarioce9b4812020-12-17 08:55:28 -0700295 limit = get_num(config_message_limit);
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600296 }
297 return limit;
298}
299
300const VkLayerSettingsEXT *FindSettingsInChain(const void *next) {
301 const VkBaseOutStructure *current = reinterpret_cast<const VkBaseOutStructure *>(next);
302 const VkLayerSettingsEXT *found = nullptr;
303 while (current) {
Artem Bolgar82d08362021-06-03 13:11:13 -0700304 if (VK_STRUCTURE_TYPE_INSTANCE_LAYER_SETTINGS_EXT == static_cast<uint32_t>(current->sType)) {
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600305 found = reinterpret_cast<const VkLayerSettingsEXT *>(current);
306 current = nullptr;
307 } else {
308 current = current->pNext;
309 }
310 }
311 return found;
312}
313
Jeremy Gebben50edce62022-01-03 14:54:40 -0700314static bool SetBool(std::string &config_string, std::string &env_string, bool default_val) {
315 bool result = default_val;
316
317 std::string setting;
318 if (!env_string.empty()) {
319 setting = env_string;
320 } else if (!config_string.empty()) {
321 setting = config_string;
322 }
323 if (!setting.empty()) {
324 transform(setting.begin(), setting.end(), setting.begin(), ::tolower);
325 if (setting == "true") {
326 result = true;
327 } else {
328 result = std::atoi(setting.c_str()) != 0;
329 }
330 }
331 return result;
332}
333
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600334// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
335void ProcessConfigAndEnvSettings(ConfigAndEnvSettings *settings_data) {
336 const auto layer_settings_ext = FindSettingsInChain(settings_data->pnext_chain);
337 if (layer_settings_ext) {
338 for (uint32_t i = 0; i < layer_settings_ext->settingCount; i++) {
339 auto cur_setting = layer_settings_ext->pSettings[i];
340 std::string name(cur_setting.name);
341 if (name == "enables") {
342 std::string data(cur_setting.data.arrayString.pCharArray);
343 SetLocalEnableSetting(data, ",", settings_data->enables);
344 } else if (name == "disables") {
345 std::string data(cur_setting.data.arrayString.pCharArray);
346 SetLocalDisableSetting(data, ",", settings_data->disables);
347 } else if (name == "message_id_filter") {
348 std::string data(cur_setting.data.arrayString.pCharArray);
349 CreateFilterMessageIdList(data, ",", settings_data->message_filter_list);
350 } else if (name == "duplicate_message_limit") {
351 *settings_data->duplicate_message_limit = cur_setting.data.value32;
352 } else if (name == "custom_stype_list") {
353 if (cur_setting.type == VK_LAYER_SETTING_VALUE_TYPE_STRING_ARRAY_EXT) {
354 std::string data(cur_setting.data.arrayString.pCharArray);
355 SetCustomStypeInfo(data, ",");
356 } else if (cur_setting.type == VK_LAYER_SETTING_VALUE_TYPE_UINT32_ARRAY_EXT) {
357 for (uint32_t j = 0; j < cur_setting.data.arrayInt32.count / 2; j++) {
358 auto stype_id = cur_setting.data.arrayInt32.pInt32Array[j * 2];
359 auto struct_size = cur_setting.data.arrayInt32.pInt32Array[(j * 2) + 1];
360 bool found = false;
361 // Prevent duplicate entries
John Zulauf79f06582021-02-27 18:38:39 -0700362 for (const auto &item : custom_stype_info) {
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600363 if (item.first == stype_id) {
364 found = true;
365 break;
366 }
367 }
368 if (!found) custom_stype_info.push_back(std::make_pair(stype_id, struct_size));
369 }
370 }
371 }
372 }
373 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700374 const auto *validation_features_ext = LvlFindInChain<VkValidationFeaturesEXT>(settings_data->pnext_chain);
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600375 if (validation_features_ext) {
376 SetValidationFeatures(settings_data->disables, settings_data->enables, validation_features_ext);
377 }
Mark Lobodzinski1f887d32020-12-30 15:31:33 -0700378 const auto *validation_flags_ext = LvlFindInChain<VkValidationFlagsEXT>(settings_data->pnext_chain);
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600379 if (validation_flags_ext) {
380 SetValidationFlags(settings_data->disables, validation_flags_ext);
381 }
382
383 std::string enable_key(settings_data->layer_description);
384 std::string disable_key(settings_data->layer_description);
385 std::string stypes_key(settings_data->layer_description);
386 std::string filter_msg_key(settings_data->layer_description);
387 std::string message_limit(settings_data->layer_description);
Jeremy Gebben50edce62022-01-03 14:54:40 -0700388 std::string fine_grained_locking(settings_data->layer_description);
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600389 enable_key.append(".enables");
390 disable_key.append(".disables");
391 stypes_key.append(".custom_stype_list");
392 filter_msg_key.append(".message_id_filter");
393 message_limit.append(".duplicate_message_limit");
Jeremy Gebben50edce62022-01-03 14:54:40 -0700394 fine_grained_locking.append(".fine_grained_locking");
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600395 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
Jeremy Gebben427d3972022-07-14 13:48:08 -0600396 std::string list_of_env_enables = GetEnvironment("VK_LAYER_ENABLES");
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600397 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
Jeremy Gebben427d3972022-07-14 13:48:08 -0600398 std::string list_of_env_disables = GetEnvironment("VK_LAYER_DISABLES");
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600399 std::string list_of_config_filter_ids = getLayerOption(filter_msg_key.c_str());
Jeremy Gebben427d3972022-07-14 13:48:08 -0600400 std::string list_of_env_filter_ids = GetEnvironment("VK_LAYER_MESSAGE_ID_FILTER");
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600401 std::string list_of_config_stypes = getLayerOption(stypes_key.c_str());
Jeremy Gebben427d3972022-07-14 13:48:08 -0600402 std::string list_of_env_stypes = GetEnvironment("VK_LAYER_CUSTOM_STYPE_LIST");
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600403 std::string config_message_limit = getLayerOption(message_limit.c_str());
Jeremy Gebben427d3972022-07-14 13:48:08 -0600404 std::string env_message_limit = GetEnvironment("VK_LAYER_DUPLICATE_MESSAGE_LIMIT");
Jeremy Gebben50edce62022-01-03 14:54:40 -0700405 std::string config_fine_grained_locking = getLayerOption(fine_grained_locking.c_str());
Jeremy Gebben427d3972022-07-14 13:48:08 -0600406 std::string env_fine_grained_locking = GetEnvironment("VK_LAYER_FINE_GRAINED_LOCKING");
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600407
408#if defined(_WIN32)
409 std::string env_delimiter = ";";
410#else
411 std::string env_delimiter = ":";
412#endif
413 // Process layer enables and disable settings
414 SetLocalEnableSetting(list_of_config_enables, ",", settings_data->enables);
415 SetLocalEnableSetting(list_of_env_enables, env_delimiter, settings_data->enables);
416 SetLocalDisableSetting(list_of_config_disables, ",", settings_data->disables);
417 SetLocalDisableSetting(list_of_env_disables, env_delimiter, settings_data->disables);
418 // Process message filter ID list
419 CreateFilterMessageIdList(list_of_config_filter_ids, ",", settings_data->message_filter_list);
420 CreateFilterMessageIdList(list_of_env_filter_ids, env_delimiter, settings_data->message_filter_list);
421 // Process custom stype struct list
422 SetCustomStypeInfo(list_of_config_stypes, ",");
423 SetCustomStypeInfo(list_of_env_stypes, env_delimiter);
424 // Process message limit
425 uint32_t config_limit_setting = SetMessageDuplicateLimit(config_message_limit, env_message_limit);
426 if (config_limit_setting != 0) {
427 *settings_data->duplicate_message_limit = config_limit_setting;
428 }
Jeremy Gebbenc872f3a2022-05-02 09:35:15 -0600429 *settings_data->fine_grained_locking = SetBool(config_fine_grained_locking, env_fine_grained_locking, true);
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600430}