blob: bf851750b1c593b611f33ca3fef5e7065e1688f4 [file] [log] [blame]
Mark Lobodzinski183746f2020-07-21 11:48:18 -06001/* Copyright (c) 2020 The Khronos Group Inc.
2 * Copyright (c) 2020 Valve Corporation
3 * Copyright (c) 2020 LunarG, Inc.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Author: Mark Lobodzinski <mark@lunarg.com>
John Zulaufa7624e22020-08-31 16:46:41 -060018 * Author: John Zulauf <jzulauf@lunarg.com>
Mark Lobodzinski183746f2020-07-21 11:48:18 -060019 */
20
21#include "layer_options.h"
22
23// Set the local disable flag for the appropriate VALIDATION_CHECK_DISABLE enum
24void SetValidationDisable(CHECK_DISABLED &disable_data, const ValidationCheckDisables disable_id) {
25 switch (disable_id) {
26 case VALIDATION_CHECK_DISABLE_COMMAND_BUFFER_STATE:
27 disable_data[command_buffer_state] = true;
28 break;
29 case VALIDATION_CHECK_DISABLE_OBJECT_IN_USE:
30 disable_data[object_in_use] = true;
31 break;
32 case VALIDATION_CHECK_DISABLE_IDLE_DESCRIPTOR_SET:
33 disable_data[idle_descriptor_set] = true;
34 break;
35 case VALIDATION_CHECK_DISABLE_PUSH_CONSTANT_RANGE:
36 disable_data[push_constant_range] = true;
37 break;
38 case VALIDATION_CHECK_DISABLE_QUERY_VALIDATION:
39 disable_data[query_validation] = true;
40 break;
41 case VALIDATION_CHECK_DISABLE_IMAGE_LAYOUT_VALIDATION:
42 disable_data[image_layout_validation] = true;
43 break;
44 default:
45 assert(true);
46 }
47}
48
49// Set the local disable flag for a single VK_VALIDATION_FEATURE_DISABLE_* flag
50void SetValidationFeatureDisable(CHECK_DISABLED &disable_data, const VkValidationFeatureDisableEXT feature_disable) {
51 switch (feature_disable) {
52 case VK_VALIDATION_FEATURE_DISABLE_SHADERS_EXT:
53 disable_data[shader_validation] = true;
54 break;
55 case VK_VALIDATION_FEATURE_DISABLE_THREAD_SAFETY_EXT:
56 disable_data[thread_safety] = true;
57 break;
58 case VK_VALIDATION_FEATURE_DISABLE_API_PARAMETERS_EXT:
59 disable_data[stateless_checks] = true;
60 break;
61 case VK_VALIDATION_FEATURE_DISABLE_OBJECT_LIFETIMES_EXT:
62 disable_data[object_tracking] = true;
63 break;
64 case VK_VALIDATION_FEATURE_DISABLE_CORE_CHECKS_EXT:
65 disable_data[core_checks] = true;
66 break;
67 case VK_VALIDATION_FEATURE_DISABLE_UNIQUE_HANDLES_EXT:
68 disable_data[handle_wrapping] = true;
69 break;
70 case VK_VALIDATION_FEATURE_DISABLE_ALL_EXT:
71 // Set all disabled flags to true
72 std::fill(disable_data.begin(), disable_data.end(), true);
73 break;
74 default:
75 break;
76 }
77}
78
79// Set the local enable flag for the appropriate VALIDATION_CHECK_ENABLE enum
80void SetValidationEnable(CHECK_ENABLED &enable_data, const ValidationCheckEnables enable_id) {
81 switch (enable_id) {
82 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ARM:
83 enable_data[vendor_specific_arm] = true;
84 break;
85 case VALIDATION_CHECK_ENABLE_VENDOR_SPECIFIC_ALL:
86 enable_data[vendor_specific_arm] = true;
87 break;
88 default:
89 assert(true);
90 }
91}
92
93// Set the local enable flag for a single VK_VALIDATION_FEATURE_ENABLE_* flag
94void SetValidationFeatureEnable(CHECK_ENABLED &enable_data, const VkValidationFeatureEnableEXT feature_enable) {
95 switch (feature_enable) {
96 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_EXT:
97 enable_data[gpu_validation] = true;
98 break;
99 case VK_VALIDATION_FEATURE_ENABLE_GPU_ASSISTED_RESERVE_BINDING_SLOT_EXT:
100 enable_data[gpu_validation_reserve_binding_slot] = true;
101 break;
102 case VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT:
103 enable_data[best_practices] = true;
104 break;
105 case VK_VALIDATION_FEATURE_ENABLE_DEBUG_PRINTF_EXT:
106 enable_data[debug_printf] = true;
John Zulaufa7624e22020-08-31 16:46:41 -0600107 break;
108 case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT:
109 enable_data[sync_validation] = true;
110 break;
Mark Lobodzinski183746f2020-07-21 11:48:18 -0600111 default:
112 break;
113 }
114}
115
116void SetValidationFeatureEnable2(CHECK_ENABLED &enable_data, const VkValidationFeatureEnable feature_enable) {
117 switch (feature_enable) {
118 case VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION:
119 enable_data[sync_validation] = true;
120 break;
121 default:
122 break;
123 }
124}
125
126// Set the local disable flag for settings specified through the VK_EXT_validation_flags extension
127void SetValidationFlags(CHECK_DISABLED &disables, const VkValidationFlagsEXT *val_flags_struct) {
128 for (uint32_t i = 0; i < val_flags_struct->disabledValidationCheckCount; ++i) {
129 switch (val_flags_struct->pDisabledValidationChecks[i]) {
130 case VK_VALIDATION_CHECK_SHADERS_EXT:
131 disables[shader_validation] = true;
132 break;
133 case VK_VALIDATION_CHECK_ALL_EXT:
134 // Set all disabled flags to true
135 disables[shader_validation] = true;
136 break;
137 default:
138 break;
139 }
140 }
141}
142
143// Process Validation Features flags specified through the ValidationFeature extension
144void SetValidationFeatures(CHECK_DISABLED &disable_data, CHECK_ENABLED &enable_data,
145 const VkValidationFeaturesEXT *val_features_struct) {
146 for (uint32_t i = 0; i < val_features_struct->disabledValidationFeatureCount; ++i) {
147 SetValidationFeatureDisable(disable_data, val_features_struct->pDisabledValidationFeatures[i]);
148 }
149 for (uint32_t i = 0; i < val_features_struct->enabledValidationFeatureCount; ++i) {
150 SetValidationFeatureEnable(enable_data, val_features_struct->pEnabledValidationFeatures[i]);
151 }
152}
153
154std::string GetNextToken(std::string *token_list, const std::string &delimiter, size_t *pos) {
155 std::string token;
156 *pos = token_list->find(delimiter);
157 if (*pos != std::string::npos) {
158 token = token_list->substr(0, *pos);
159 } else {
160 *pos = token_list->length() - delimiter.length();
161 token = *token_list;
162 }
163 token_list->erase(0, *pos + delimiter.length());
164 return token;
165}
166
167// Given a string representation of a list of enable enum values, call the appropriate setter function
168void SetLocalEnableSetting(std::string list_of_enables, std::string delimiter, CHECK_ENABLED &enables) {
169 size_t pos = 0;
170 std::string token;
171 while (list_of_enables.length() != 0) {
172 token = GetNextToken(&list_of_enables, delimiter, &pos);
173 if (token.find("VK_VALIDATION_FEATURE_ENABLE_") != std::string::npos) {
174 auto result = VkValFeatureEnableLookup.find(token);
175 if (result != VkValFeatureEnableLookup.end()) {
176 SetValidationFeatureEnable(enables, result->second);
177 } else {
178 auto result2 = VkValFeatureEnableLookup2.find(token);
179 if (result2 != VkValFeatureEnableLookup2.end()) {
180 SetValidationFeatureEnable2(enables, result2->second);
181 }
182 }
183 } else if (token.find("VALIDATION_CHECK_ENABLE_") != std::string::npos) {
184 auto result = ValidationEnableLookup.find(token);
185 if (result != ValidationEnableLookup.end()) {
186 SetValidationEnable(enables, result->second);
187 }
188 }
189 }
190}
191
192// Given a string representation of a list of disable enum values, call the appropriate setter function
193void SetLocalDisableSetting(std::string list_of_disables, std::string delimiter, CHECK_DISABLED &disables) {
194 size_t pos = 0;
195 std::string token;
196 while (list_of_disables.length() != 0) {
197 token = GetNextToken(&list_of_disables, delimiter, &pos);
198 if (token.find("VK_VALIDATION_FEATURE_DISABLE_") != std::string::npos) {
199 auto result = VkValFeatureDisableLookup.find(token);
200 if (result != VkValFeatureDisableLookup.end()) {
201 SetValidationFeatureDisable(disables, result->second);
202 }
203 } else if (token.find("VALIDATION_CHECK_DISABLE_") != std::string::npos) {
204 auto result = ValidationDisableLookup.find(token);
205 if (result != ValidationDisableLookup.end()) {
206 SetValidationDisable(disables, result->second);
207 }
208 }
209 }
210}
211
212uint32_t TokenToUint(std::string &token) {
213 uint32_t int_id = 0;
214 if ((token.find("0x") == 0) || token.find("0X") == 0) { // Handle hex format
215 int_id = std::strtoul(token.c_str(), nullptr, 16);
216 } else {
217 int_id = std::strtoul(token.c_str(), nullptr, 10); // Decimal format
218 }
219 return int_id;
220}
221
222void CreateFilterMessageIdList(std::string raw_id_list, std::string delimiter, std::vector<uint32_t> &filter_list) {
223 size_t pos = 0;
224 std::string token;
225 while (raw_id_list.length() != 0) {
226 token = GetNextToken(&raw_id_list, delimiter, &pos);
227 uint32_t int_id = TokenToUint(token);
228 if (int_id == 0) {
229 size_t id_hash = XXH32(token.c_str(), strlen(token.c_str()), 8); // String
230 if (id_hash != 0) {
231 int_id = static_cast<uint32_t>(id_hash);
232 }
233 }
234 if ((int_id != 0) && (std::find(filter_list.begin(), filter_list.end(), int_id)) == filter_list.end()) {
235 filter_list.push_back(int_id);
236 }
237 }
238}
239
240void SetCustomStypeInfo(std::string raw_id_list, std::string delimiter) {
241 size_t pos = 0;
242 std::string token;
243 // List format is a list of integer pairs
244 while (raw_id_list.length() != 0) {
245 token = GetNextToken(&raw_id_list, delimiter, &pos);
246 uint32_t stype_id = TokenToUint(token);
247 token = GetNextToken(&raw_id_list, delimiter, &pos);
248 uint32_t struct_size_in_bytes = TokenToUint(token);
249 if ((stype_id != 0) && (struct_size_in_bytes != 0)) {
250 bool found = false;
251 // Prevent duplicate entries
252 for (auto item : custom_stype_info) {
253 if (item.first == stype_id) {
254 found = true;
255 break;
256 }
257 }
258 if (!found) custom_stype_info.push_back(std::make_pair(stype_id, struct_size_in_bytes));
259 }
260 }
261}
262
263uint32_t SetMessageDuplicateLimit(std::string &config_message_limit, std::string &env_message_limit) {
264 uint32_t limit = 0;
265 auto GetNum = [](std::string &source_string) {
266 uint32_t limit = 0;
267 int radix = ((source_string.find("0x") == 0) ? 16 : 10);
268 limit = std::strtoul(source_string.c_str(), nullptr, radix);
269 return limit;
270 };
271 // ENV var takes precedence over settings file
272 limit = GetNum(env_message_limit);
273 if (limit == 0) {
274 limit = GetNum(config_message_limit);
275 }
276 return limit;
277}
278
279const VkLayerSettingsEXT *FindSettingsInChain(const void *next) {
280 const VkBaseOutStructure *current = reinterpret_cast<const VkBaseOutStructure *>(next);
281 const VkLayerSettingsEXT *found = nullptr;
282 while (current) {
283 if (static_cast<VkStructureType>(VK_STRUCTURE_TYPE_INSTANCE_LAYER_SETTINGS_EXT) == current->sType) {
284 found = reinterpret_cast<const VkLayerSettingsEXT *>(current);
285 current = nullptr;
286 } else {
287 current = current->pNext;
288 }
289 }
290 return found;
291}
292
293// Process enables and disables set though the vk_layer_settings.txt config file or through an environment variable
294void ProcessConfigAndEnvSettings(ConfigAndEnvSettings *settings_data) {
295 const auto layer_settings_ext = FindSettingsInChain(settings_data->pnext_chain);
296 if (layer_settings_ext) {
297 for (uint32_t i = 0; i < layer_settings_ext->settingCount; i++) {
298 auto cur_setting = layer_settings_ext->pSettings[i];
299 std::string name(cur_setting.name);
300 if (name == "enables") {
301 std::string data(cur_setting.data.arrayString.pCharArray);
302 SetLocalEnableSetting(data, ",", settings_data->enables);
303 } else if (name == "disables") {
304 std::string data(cur_setting.data.arrayString.pCharArray);
305 SetLocalDisableSetting(data, ",", settings_data->disables);
306 } else if (name == "message_id_filter") {
307 std::string data(cur_setting.data.arrayString.pCharArray);
308 CreateFilterMessageIdList(data, ",", settings_data->message_filter_list);
309 } else if (name == "duplicate_message_limit") {
310 *settings_data->duplicate_message_limit = cur_setting.data.value32;
311 } else if (name == "custom_stype_list") {
312 if (cur_setting.type == VK_LAYER_SETTING_VALUE_TYPE_STRING_ARRAY_EXT) {
313 std::string data(cur_setting.data.arrayString.pCharArray);
314 SetCustomStypeInfo(data, ",");
315 } else if (cur_setting.type == VK_LAYER_SETTING_VALUE_TYPE_UINT32_ARRAY_EXT) {
316 for (uint32_t j = 0; j < cur_setting.data.arrayInt32.count / 2; j++) {
317 auto stype_id = cur_setting.data.arrayInt32.pInt32Array[j * 2];
318 auto struct_size = cur_setting.data.arrayInt32.pInt32Array[(j * 2) + 1];
319 bool found = false;
320 // Prevent duplicate entries
321 for (auto item : custom_stype_info) {
322 if (item.first == stype_id) {
323 found = true;
324 break;
325 }
326 }
327 if (!found) custom_stype_info.push_back(std::make_pair(stype_id, struct_size));
328 }
329 }
330 }
331 }
332 }
333 const auto *validation_features_ext = lvl_find_in_chain<VkValidationFeaturesEXT>(settings_data->pnext_chain);
334 if (validation_features_ext) {
335 SetValidationFeatures(settings_data->disables, settings_data->enables, validation_features_ext);
336 }
337 const auto *validation_flags_ext = lvl_find_in_chain<VkValidationFlagsEXT>(settings_data->pnext_chain);
338 if (validation_flags_ext) {
339 SetValidationFlags(settings_data->disables, validation_flags_ext);
340 }
341
342 std::string enable_key(settings_data->layer_description);
343 std::string disable_key(settings_data->layer_description);
344 std::string stypes_key(settings_data->layer_description);
345 std::string filter_msg_key(settings_data->layer_description);
346 std::string message_limit(settings_data->layer_description);
347 enable_key.append(".enables");
348 disable_key.append(".disables");
349 stypes_key.append(".custom_stype_list");
350 filter_msg_key.append(".message_id_filter");
351 message_limit.append(".duplicate_message_limit");
352 std::string list_of_config_enables = getLayerOption(enable_key.c_str());
353 std::string list_of_env_enables = GetLayerEnvVar("VK_LAYER_ENABLES");
354 std::string list_of_config_disables = getLayerOption(disable_key.c_str());
355 std::string list_of_env_disables = GetLayerEnvVar("VK_LAYER_DISABLES");
356 std::string list_of_config_filter_ids = getLayerOption(filter_msg_key.c_str());
357 std::string list_of_env_filter_ids = GetLayerEnvVar("VK_LAYER_MESSAGE_ID_FILTER");
358 std::string list_of_config_stypes = getLayerOption(stypes_key.c_str());
359 std::string list_of_env_stypes = GetLayerEnvVar("VK_LAYER_CUSTOM_STYPE_LIST");
360 std::string config_message_limit = getLayerOption(message_limit.c_str());
361 std::string env_message_limit = GetLayerEnvVar("VK_LAYER_DUPLICATE_MESSAGE_LIMIT");
362
363#if defined(_WIN32)
364 std::string env_delimiter = ";";
365#else
366 std::string env_delimiter = ":";
367#endif
368 // Process layer enables and disable settings
369 SetLocalEnableSetting(list_of_config_enables, ",", settings_data->enables);
370 SetLocalEnableSetting(list_of_env_enables, env_delimiter, settings_data->enables);
371 SetLocalDisableSetting(list_of_config_disables, ",", settings_data->disables);
372 SetLocalDisableSetting(list_of_env_disables, env_delimiter, settings_data->disables);
373 // Process message filter ID list
374 CreateFilterMessageIdList(list_of_config_filter_ids, ",", settings_data->message_filter_list);
375 CreateFilterMessageIdList(list_of_env_filter_ids, env_delimiter, settings_data->message_filter_list);
376 // Process custom stype struct list
377 SetCustomStypeInfo(list_of_config_stypes, ",");
378 SetCustomStypeInfo(list_of_env_stypes, env_delimiter);
379 // Process message limit
380 uint32_t config_limit_setting = SetMessageDuplicateLimit(config_message_limit, env_message_limit);
381 if (config_limit_setting != 0) {
382 *settings_data->duplicate_message_limit = config_limit_setting;
383 }
384}