blob: 744f40df3d017af918fe9359e7cd271a06af925d [file] [log] [blame]
Dustin Graves1e92cd72016-02-09 14:00:18 -07001/* Copyright (c) 2015-2016 The Khronos Group Inc.
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 * Copyright (C) 2015-2016 Google Inc.
5 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06006 * 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
Dustin Graves1e92cd72016-02-09 14:00:18 -07009 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060010 * http://www.apache.org/licenses/LICENSE-2.0
Dustin Graves1e92cd72016-02-09 14:00:18 -070011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * 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.
Dustin Graves1e92cd72016-02-09 14:00:18 -070017 *
18 * Author: Dustin Graves <dustin@lunarg.com>
19 */
20
Mark Lobodzinski739391a2016-03-17 15:08:18 -060021#ifndef PARAMETER_VALIDATION_UTILS_H
22#define PARAMETER_VALIDATION_UTILS_H
Dustin Graves1e92cd72016-02-09 14:00:18 -070023
Dustin Graves58c2f662016-03-08 17:48:20 -070024#include <algorithm>
Dustin Graves29148ff2016-03-23 19:44:00 -060025#include <cstdlib>
Dustin Graves58c2f662016-03-08 17:48:20 -070026#include <string>
27
Dustin Graves1e92cd72016-02-09 14:00:18 -070028#include "vulkan/vulkan.h"
Dustin Graves58c2f662016-03-08 17:48:20 -070029#include "vk_enum_string_helper.h"
Dustin Graves1e92cd72016-02-09 14:00:18 -070030#include "vk_layer_logging.h"
Karl Schultza9ef1e52016-10-06 17:53:48 -060031#include "vk_validation_error_messages.h"
Dustin Graves1e92cd72016-02-09 14:00:18 -070032
Dustin Graves8ffbbf62016-07-22 13:19:46 -060033#include "parameter_name.h"
34
Dustin Gravesb83fc2d2016-05-04 12:56:08 -060035namespace parameter_validation {
36
Dustin Gravesf233e502016-05-05 13:44:21 -060037enum ErrorCode {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070038 NONE, // Used for INFO & other non-error messages
39 INVALID_USAGE, // The value of a parameter is not consistent
40 // with the valid usage criteria defined in
41 // the Vulkan specification.
42 INVALID_STRUCT_STYPE, // The sType field of a Vulkan structure does
43 // not contain the value expected for a structure
44 // of that type.
45 INVALID_STRUCT_PNEXT, // The pNext field of a Vulkan structure references
46 // a value that is not compatible with a structure of
47 // that type or is not NULL when a structure of that
48 // type has no compatible pNext values.
49 REQUIRED_PARAMETER, // A required parameter was specified as 0 or NULL.
50 RESERVED_PARAMETER, // A parameter reserved for future use was not
51 // specified as 0 or NULL.
52 UNRECOGNIZED_VALUE, // A Vulkan enumeration, VkFlags, or VkBool32 parameter
53 // contains a value that is not recognized as valid for
54 // that type.
55 DEVICE_LIMIT, // A specified parameter exceeds the limits returned
56 // by the physical device
57 DEVICE_FEATURE, // Use of a requested feature is not supported by
58 // the device
59 FAILURE_RETURN_CODE, // A Vulkan return code indicating a failure condition
60 // was encountered.
61 EXTENSION_NOT_ENABLED, // An extension entrypoint was called, but the required
62 // extension was not enabled at CreateInstance or
63 // CreateDevice time.
Dustin Gravesf233e502016-05-05 13:44:21 -060064};
65
Dustin Graves58c2f662016-03-08 17:48:20 -070066struct GenericHeader {
67 VkStructureType sType;
68 const void *pNext;
69};
Dustin Graves58c2f662016-03-08 17:48:20 -070070
Dustin Graves29148ff2016-03-23 19:44:00 -060071// Layer name string to be logged with validation messages.
Dustin Gravesb83fc2d2016-05-04 12:56:08 -060072const char LayerName[] = "ParameterValidation";
Dustin Graves29148ff2016-03-23 19:44:00 -060073
74// String returned by string_VkStructureType for an unrecognized type.
Dustin Graves58c2f662016-03-08 17:48:20 -070075const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
76
Dustin Gravesca7aa7c2016-03-25 15:13:28 -060077// String returned by string_VkResult for an unrecognized type.
78const std::string UnsupportedResultString = "Unhandled VkResult";
79
Dustin Graves29148ff2016-03-23 19:44:00 -060080// The base value used when computing the offset for an enumeration token value that is added by an extension.
81// When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
82// See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
83const uint32_t ExtEnumBaseValue = 1000000000;
84
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070085template <typename T>
86bool is_extension_added_token(T value) {
Jamie Madill6069c822016-12-15 09:35:36 -050087 return (static_cast<uint32_t>(std::abs(static_cast<int32_t>(value))) >= ExtEnumBaseValue);
Dustin Graves29148ff2016-03-23 19:44:00 -060088}
89
90// VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE token is a special case that was converted from a core token to an
91// extension added token. Its original value was intentionally preserved after the conversion, so it does not use
92// the base value that other extension added tokens use, and it does not fall within the enum's begin/end range.
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070093template <>
94bool is_extension_added_token(VkSamplerAddressMode value) {
Jamie Madill6069c822016-12-15 09:35:36 -050095 bool result = (static_cast<uint32_t>(std::abs(static_cast<int32_t>(value))) >= ExtEnumBaseValue);
Dustin Graves29148ff2016-03-23 19:44:00 -060096 return (result || (value == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));
97}
98
Dustin Graves1e92cd72016-02-09 14:00:18 -070099/**
Dustin Gravesf8032f22016-05-11 18:31:44 -0600100* Validate a minimum value.
101*
102* Verify that the specified value is greater than the specified lower bound.
103*
104* @param report_data debug_report_data object for routing validation messages.
105* @param api_name Name of API call being validated.
106* @param parameter_name Name of parameter being validated.
107* @param value Value to validate.
108* @param lower_bound Lower bound value to use for validation.
109* @return Boolean value indicating that the call should be skipped.
110*/
111template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600112bool ValidateGreaterThan(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name, T value,
113 T lower_bound) {
Dustin Gravesf8032f22016-05-11 18:31:44 -0600114 bool skip_call = false;
115
116 if (value <= lower_bound) {
Mark Lobodzinskieb9e73f2017-04-13 10:06:48 -0600117 skip_call |=
118 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 1, LayerName,
119 "%s: parameter %s must be greater than %d", api_name, parameter_name.get_name().c_str(), lower_bound);
Dustin Gravesf8032f22016-05-11 18:31:44 -0600120 }
121
122 return skip_call;
123}
124
125/**
Dustin Graves1e92cd72016-02-09 14:00:18 -0700126 * Validate a required pointer.
127 *
Dustin Graves58c2f662016-03-08 17:48:20 -0700128 * Verify that a required pointer is not NULL.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700129 *
130 * @param report_data debug_report_data object for routing validation messages.
131 * @param apiName Name of API call being validated.
132 * @param parameterName Name of parameter being validated.
133 * @param value Pointer to validate.
134 * @return Boolean value indicating that the call should be skipped.
135 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600136static bool validate_required_pointer(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
Dustin Graves080069b2016-04-05 13:48:15 -0600137 const void *value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600138 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700139
140 if (value == NULL) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600141 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600142 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
143 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700144 }
145
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600146 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700147}
148
149/**
150 * Validate array count and pointer to array.
151 *
Dustin Graves58d114b2016-03-08 14:42:59 -0700152 * Verify that required count and array parameters are not 0 or NULL. If the
153 * count parameter is not optional, verify that it is not 0. If the array
154 * parameter is NULL, and it is not optional, verify that count is 0.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700155 *
156 * @param report_data debug_report_data object for routing validation messages.
157 * @param apiName Name of API call being validated.
158 * @param countName Name of count parameter.
159 * @param arrayName Name of array parameter.
160 * @param count Number of elements in the array.
161 * @param array Array to validate.
162 * @param countRequired The 'count' parameter may not be 0 when true.
163 * @param arrayRequired The 'array' parameter may not be NULL when true.
164 * @return Boolean value indicating that the call should be skipped.
165 */
166template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600167bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
168 const ParameterName &arrayName, T count, const void *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600169 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700170
171 // Count parameters not tagged as optional cannot be 0
Józef Kucia20bb8fb2016-09-23 12:45:04 +0200172 if (countRequired && (count == 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600173 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700174 REQUIRED_PARAMETER, LayerName, "%s: parameter %s must be greater than 0", apiName,
175 countName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700176 }
177
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600178 // Array parameters not tagged as optional cannot be NULL, unless the count is 0
Dustin Graves080069b2016-04-05 13:48:15 -0600179 if ((array == NULL) && arrayRequired && (count != 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600180 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700181 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
182 arrayName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600183 }
184
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600185 return skip_call;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600186}
187
188/**
189* Validate pointer to array count and pointer to array.
190*
191* Verify that required count and array parameters are not NULL. If count
192* is not NULL and its value is not optional, verify that it is not 0. If the
193* array parameter is NULL, and it is not optional, verify that count is 0.
194* The array parameter will typically be optional for this case (where count is
195* a pointer), allowing the caller to retrieve the available count.
196*
197* @param report_data debug_report_data object for routing validation messages.
198* @param apiName Name of API call being validated.
199* @param countName Name of count parameter.
200* @param arrayName Name of array parameter.
201* @param count Pointer to the number of elements in the array.
202* @param array Array to validate.
203* @param countPtrRequired The 'count' parameter may not be NULL when true.
204* @param countValueRequired The '*count' value may not be 0 when true.
205* @param arrayRequired The 'array' parameter may not be NULL when true.
206* @return Boolean value indicating that the call should be skipped.
207*/
208template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600209bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
210 const ParameterName &arrayName, const T *count, const void *array, bool countPtrRequired,
211 bool countValueRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600212 bool skip_call = false;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600213
214 if (count == NULL) {
215 if (countPtrRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600216 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600217 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
218 countName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600219 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700220 } else {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600221 skip_call |= validate_array(report_data, apiName, countName, arrayName, (*count), array, countValueRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700222 }
223
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600224 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700225}
226
227/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600228 * Validate a pointer to a Vulkan structure.
229 *
230 * Verify that a required pointer to a structure is not NULL. If the pointer is
231 * not NULL, verify that each structure's sType field is set to the correct
232 * VkStructureType value.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700233 *
234 * @param report_data debug_report_data object for routing validation messages.
235 * @param apiName Name of API call being validated.
236 * @param parameterName Name of struct parameter being validated.
237 * @param sTypeName Name of expected VkStructureType value.
238 * @param value Pointer to the struct to validate.
239 * @param sType VkStructureType for structure validation.
240 * @param required The parameter may not be NULL when true.
241 * @return Boolean value indicating that the call should be skipped.
242 */
243template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600244bool validate_struct_type(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
245 const char *sTypeName, const T *value, VkStructureType sType, bool required) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600246 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700247
248 if (value == NULL) {
Dustin Graves080069b2016-04-05 13:48:15 -0600249 if (required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600250 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
251 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
252 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700253 }
254 } else if (value->sType != sType) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600255 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
256 INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s->sType must be %s", apiName,
257 parameterName.get_name().c_str(), sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700258 }
259
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600260 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700261}
262
263/**
Dustin Graves1e92cd72016-02-09 14:00:18 -0700264 * Validate an array of Vulkan structures
265 *
266 * Verify that required count and array parameters are not 0 or NULL. If
267 * the array contains 1 or more structures, verify that each structure's
268 * sType field is set to the correct VkStructureType value.
269 *
270 * @param report_data debug_report_data object for routing validation messages.
271 * @param apiName Name of API call being validated.
272 * @param countName Name of count parameter.
273 * @param arrayName Name of array parameter.
274 * @param sTypeName Name of expected VkStructureType value.
275 * @param count Number of elements in the array.
276 * @param array Array to validate.
277 * @param sType VkStructureType for structure validation.
278 * @param countRequired The 'count' parameter may not be 0 when true.
279 * @param arrayRequired The 'array' parameter may not be NULL when true.
280 * @return Boolean value indicating that the call should be skipped.
281 */
282template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600283bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
284 const ParameterName &arrayName, const char *sTypeName, uint32_t count, const T *array,
285 VkStructureType sType, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600286 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700287
288 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600289 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700290 } else {
291 // Verify that all structs in the array have the correct type
292 for (uint32_t i = 0; i < count; ++i) {
293 if (array[i].sType != sType) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600294 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600295 __LINE__, INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s[%d].sType must be %s", apiName,
296 arrayName.get_name().c_str(), i, sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700297 }
298 }
299 }
300
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600301 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700302}
303
Dustin Graves58d114b2016-03-08 14:42:59 -0700304/**
Mark Young39389872017-01-19 21:10:49 -0700305 * Validate an array of Vulkan structures.
306 *
307 * Verify that required count and array parameters are not NULL. If count
308 * is not NULL and its value is not optional, verify that it is not 0.
309 * If the array contains 1 or more structures, verify that each structure's
310 * sType field is set to the correct VkStructureType value.
311 *
312 * @param report_data debug_report_data object for routing validation messages.
313 * @param apiName Name of API call being validated.
314 * @param countName Name of count parameter.
315 * @param arrayName Name of array parameter.
316 * @param sTypeName Name of expected VkStructureType value.
317 * @param count Pointer to the number of elements in the array.
318 * @param array Array to validate.
319 * @param sType VkStructureType for structure validation.
320 * @param countPtrRequired The 'count' parameter may not be NULL when true.
321 * @param countValueRequired The '*count' value may not be 0 when true.
322 * @param arrayRequired The 'array' parameter may not be NULL when true.
323 * @return Boolean value indicating that the call should be skipped.
324 */
325template <typename T>
326bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
327 const ParameterName &arrayName, const char *sTypeName, uint32_t *count, const T *array,
328 VkStructureType sType, bool countPtrRequired, bool countValueRequired, bool arrayRequired) {
329 bool skip_call = false;
330
331 if (count == NULL) {
332 if (countPtrRequired) {
333 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
334 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
335 countName.get_name().c_str());
336 }
337 } else {
338 skip_call |= validate_struct_type_array(report_data, apiName, countName, arrayName, sTypeName, (*count), array, sType,
339 countValueRequired, arrayRequired);
340 }
341
342 return skip_call;
343}
344
345/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600346* Validate a Vulkan handle.
347*
348* Verify that the specified handle is not VK_NULL_HANDLE.
349*
350* @param report_data debug_report_data object for routing validation messages.
351* @param api_name Name of API call being validated.
352* @param parameter_name Name of struct parameter being validated.
353* @param value Handle to validate.
354* @return Boolean value indicating that the call should be skipped.
355*/
356template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600357bool validate_required_handle(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name, T value) {
Dustin Graves20fd66f2016-04-18 18:33:21 -0600358 bool skip_call = false;
359
360 if (value == VK_NULL_HANDLE) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600361 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
362 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as VK_NULL_HANDLE", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600363 parameter_name.get_name().c_str());
Dustin Graves20fd66f2016-04-18 18:33:21 -0600364 }
365
366 return skip_call;
367}
368
369/**
370* Validate an array of Vulkan handles.
371*
372* Verify that required count and array parameters are not NULL. If count
373* is not NULL and its value is not optional, verify that it is not 0.
374* If the array contains 1 or more handles, verify that no handle is set to
375* VK_NULL_HANDLE.
376*
377* @note This function is only intended to validate arrays of handles when none
378* of the handles are allowed to be VK_NULL_HANDLE. For arrays of handles
379* that are allowed to contain VK_NULL_HANDLE, use validate_array() instead.
380*
381* @param report_data debug_report_data object for routing validation messages.
382* @param api_name Name of API call being validated.
383* @param count_name Name of count parameter.
384* @param array_name Name of array parameter.
385* @param count Number of elements in the array.
386* @param array Array to validate.
387* @param count_required The 'count' parameter may not be 0 when true.
388* @param array_required The 'array' parameter may not be NULL when true.
389* @return Boolean value indicating that the call should be skipped.
390*/
391template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600392bool validate_handle_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
393 const ParameterName &array_name, uint32_t count, const T *array, bool count_required,
394 bool array_required) {
Dustin Graves20fd66f2016-04-18 18:33:21 -0600395 bool skip_call = false;
396
397 if ((count == 0) || (array == NULL)) {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600398 skip_call |= validate_array(report_data, api_name, count_name, array_name, count, array, count_required, array_required);
Dustin Graves20fd66f2016-04-18 18:33:21 -0600399 } else {
400 // Verify that no handles in the array are VK_NULL_HANDLE
401 for (uint32_t i = 0; i < count; ++i) {
402 if (array[i] == VK_NULL_HANDLE) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600403 skip_call |=
404 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
405 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as VK_NULL_HANDLE", api_name,
406 array_name.get_name().c_str(), i);
Dustin Graves20fd66f2016-04-18 18:33:21 -0600407 }
408 }
409 }
410
411 return skip_call;
412}
413
414/**
Dustin Graves58d114b2016-03-08 14:42:59 -0700415 * Validate string array count and content.
416 *
417 * Verify that required count and array parameters are not 0 or NULL. If the
418 * count parameter is not optional, verify that it is not 0. If the array
419 * parameter is NULL, and it is not optional, verify that count is 0. If the
420 * array parameter is not NULL, verify that none of the strings are NULL.
421 *
422 * @param report_data debug_report_data object for routing validation messages.
423 * @param apiName Name of API call being validated.
424 * @param countName Name of count parameter.
425 * @param arrayName Name of array parameter.
426 * @param count Number of strings in the array.
427 * @param array Array of strings to validate.
428 * @param countRequired The 'count' parameter may not be 0 when true.
429 * @param arrayRequired The 'array' parameter may not be NULL when true.
430 * @return Boolean value indicating that the call should be skipped.
431 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600432static bool validate_string_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
433 const ParameterName &arrayName, uint32_t count, const char *const *array, bool countRequired,
434 bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600435 bool skip_call = false;
Dustin Graves58d114b2016-03-08 14:42:59 -0700436
437 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600438 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves58d114b2016-03-08 14:42:59 -0700439 } else {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600440 // Verify that strings in the array are not NULL
Dustin Graves58d114b2016-03-08 14:42:59 -0700441 for (uint32_t i = 0; i < count; ++i) {
442 if (array[i] == NULL) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600443 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600444 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as NULL",
445 apiName, arrayName.get_name().c_str(), i);
Dustin Graves58d114b2016-03-08 14:42:59 -0700446 }
447 }
448 }
449
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600450 return skip_call;
Dustin Graves58d114b2016-03-08 14:42:59 -0700451}
452
Dustin Graves58c2f662016-03-08 17:48:20 -0700453/**
454 * Validate a structure's pNext member.
455 *
456 * Verify that the specified pNext value points to the head of a list of
457 * allowed extension structures. If no extension structures are allowed,
458 * verify that pNext is null.
459 *
460 * @param report_data debug_report_data object for routing validation messages.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600461 * @param api_name Name of API call being validated.
462 * @param parameter_name Name of parameter being validated.
463 * @param allowed_struct_names Names of allowed structs.
Dustin Graves58c2f662016-03-08 17:48:20 -0700464 * @param next Pointer to validate.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600465 * @param allowed_type_count Total number of allowed structure types.
466 * @param allowed_types Array of strcuture types allowed for pNext.
467 * @param header_version Version of header defining the pNext validation rules.
Dustin Graves58c2f662016-03-08 17:48:20 -0700468 * @return Boolean value indicating that the call should be skipped.
469 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600470static bool validate_struct_pnext(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600471 const char *allowed_struct_names, const void *next, size_t allowed_type_count,
472 const VkStructureType *allowed_types, uint32_t header_version) {
473 bool skip_call = false;
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600474 std::unordered_set<const void *> cycle_check;
475 std::unordered_set<VkStructureType, std::hash<int>> unique_stype_check;
476
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700477 const char disclaimer[] =
478 "This warning is based on the Valid Usage documentation for version %d of the Vulkan header. It "
479 "is possible that you are using a struct from a private extension or an extension that was added "
480 "to a later version of the Vulkan header, in which case your use of %s is perfectly valid but "
481 "is not guaranteed to work correctly with validation enabled";
Dustin Graves58c2f662016-03-08 17:48:20 -0700482
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600483 // TODO: The valid pNext structure types are not recursive. Each structure has its own list of valid sTypes for pNext.
484 // Codegen a map of vectors containing the allowable pNext types for each struct and use that here -- also simplifies parms.
Dustin Graves58c2f662016-03-08 17:48:20 -0700485 if (next != NULL) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600486 if (allowed_type_count == 0) {
487 std::string message = "%s: value of %s must be NULL. ";
488 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600489 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
490 INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name, parameter_name.get_name().c_str(),
491 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700492 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600493 const VkStructureType *start = allowed_types;
494 const VkStructureType *end = allowed_types + allowed_type_count;
Dustin Graves58c2f662016-03-08 17:48:20 -0700495 const GenericHeader *current = reinterpret_cast<const GenericHeader *>(next);
496
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600497 cycle_check.insert(next);
Dustin Graves58c2f662016-03-08 17:48:20 -0700498
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600499
500 while (current != NULL) {
501 if (cycle_check.find(current->pNext) != cycle_check.end()) {
502 std::string message = "%s: %s chain contains a cycle -- pNext pointer " PRIx64 " is repeated.";
503 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
504 __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
505 parameter_name.get_name().c_str(), reinterpret_cast<uint64_t>(next));
506 break;
507 } else {
508 cycle_check.insert(current->pNext);
509 }
510
511 std::string type_name = string_VkStructureType(current->sType);
512 if (unique_stype_check.find(current->sType) != unique_stype_check.end()) {
513 std::string message = "%s: %s chain contains duplicate structure types: %s appears multiple times.";
514 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
515 __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
516 parameter_name.get_name().c_str(), type_name.c_str());
517 } else {
518 unique_stype_check.insert(current->sType);
519 }
520
521 if (std::find(start, end, current->sType) == end) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600522 if (type_name == UnsupportedStructureTypeString) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700523 std::string message =
524 "%s: %s chain includes a structure with unexpected VkStructureType (%d); Allowed "
525 "structures are [%s]. ";
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600526 message += disclaimer;
527 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
528 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600529 parameter_name.get_name().c_str(), current->sType, allowed_struct_names,
530 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700531 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600532 std::string message =
533 "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures are [%s]. ";
534 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600535 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
536 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
537 parameter_name.get_name().c_str(), type_name.c_str(), allowed_struct_names,
538 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700539 }
540 }
Dustin Graves58c2f662016-03-08 17:48:20 -0700541 current = reinterpret_cast<const GenericHeader *>(current->pNext);
542 }
543 }
544 }
545
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600546 return skip_call;
Dustin Graves58c2f662016-03-08 17:48:20 -0700547}
548
Dustin Graves29148ff2016-03-23 19:44:00 -0600549/**
550* Validate a VkBool32 value.
551*
552* Generate a warning if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
553*
554* @param report_data debug_report_data object for routing validation messages.
555* @param apiName Name of API call being validated.
556* @param parameterName Name of parameter being validated.
557* @param value Boolean value to validate.
558* @return Boolean value indicating that the call should be skipped.
559*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600560static bool validate_bool32(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
561 VkBool32 value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600562 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600563
564 if ((value != VK_TRUE) && (value != VK_FALSE)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600565 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600566 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE", apiName,
567 parameterName.get_name().c_str(), value);
Dustin Graves29148ff2016-03-23 19:44:00 -0600568 }
569
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600570 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600571}
572
573/**
574* Validate a Vulkan enumeration value.
575*
576* Generate a warning if an enumeration token value does not fall within the core enumeration
577* begin and end token values, and was not added to the enumeration by an extension. Extension
578* provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
579* with 1,000,000,000 as the base token value.
580*
581* @note This function does not expect to process enumerations defining bitmask flag bits.
582*
583* @param report_data debug_report_data object for routing validation messages.
584* @param apiName Name of API call being validated.
585* @param parameterName Name of parameter being validated.
586* @param enumName Name of the enumeration being validated.
587* @param begin The begin range value for the enumeration.
588* @param end The end range value for the enumeration.
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600589* @param value Enumeration value to validate.
Dustin Graves29148ff2016-03-23 19:44:00 -0600590* @return Boolean value indicating that the call should be skipped.
591*/
592template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600593bool validate_ranged_enum(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
594 const char *enumName, T begin, T end, T value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600595 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600596
597 if (((value < begin) || (value > end)) && !is_extension_added_token(value)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700598 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
599 UNRECOGNIZED_VALUE, LayerName,
600 "%s: value of %s (%d) does not fall within the begin..end range of the core %s "
601 "enumeration tokens and is not an extension added token",
602 apiName, parameterName.get_name().c_str(), value, enumName);
Dustin Graves29148ff2016-03-23 19:44:00 -0600603 }
604
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600605 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600606}
607
608/**
609* Validate an array of Vulkan enumeration value.
610*
611* Process all enumeration token values in the specified array and generate a warning if a value
612* does not fall within the core enumeration begin and end token values, and was not added to
613* the enumeration by an extension. Extension provided enumerations use the equation specified
614* in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
615*
616* @note This function does not expect to process enumerations defining bitmask flag bits.
617*
618* @param report_data debug_report_data object for routing validation messages.
619* @param apiName Name of API call being validated.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600620* @param countName Name of count parameter.
621* @param arrayName Name of array parameter.
Dustin Graves29148ff2016-03-23 19:44:00 -0600622* @param enumName Name of the enumeration being validated.
623* @param begin The begin range value for the enumeration.
624* @param end The end range value for the enumeration.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600625* @param count Number of enumeration values in the array.
626* @param array Array of enumeration values to validate.
627* @param countRequired The 'count' parameter may not be 0 when true.
628* @param arrayRequired The 'array' parameter may not be NULL when true.
Dustin Graves29148ff2016-03-23 19:44:00 -0600629* @return Boolean value indicating that the call should be skipped.
630*/
631template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600632static bool validate_ranged_enum_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
633 const ParameterName &arrayName, const char *enumName, T begin, T end, uint32_t count,
634 const T *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600635 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600636
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600637 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600638 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600639 } else {
640 for (uint32_t i = 0; i < count; ++i) {
641 if (((array[i] < begin) || (array[i] > end)) && !is_extension_added_token(array[i])) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600642 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600643 __LINE__, UNRECOGNIZED_VALUE, LayerName,
644 "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
645 "enumeration tokens and is not an extension added token",
646 apiName, arrayName.get_name().c_str(), i, array[i], enumName);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600647 }
Dustin Graves29148ff2016-03-23 19:44:00 -0600648 }
649 }
650
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600651 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600652}
653
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600654/**
Dustin Graves78df8512016-04-28 17:58:59 -0600655* Verify that a reserved VkFlags value is zero.
656*
657* Verify that the specified value is zero, to check VkFlags values that are reserved for
658* future use.
659*
660* @param report_data debug_report_data object for routing validation messages.
661* @param api_name Name of API call being validated.
662* @param parameter_name Name of parameter being validated.
663* @param value Value to validate.
664* @return Boolean value indicating that the call should be skipped.
665*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600666static bool validate_reserved_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600667 VkFlags value) {
668 bool skip_call = false;
669
670 if (value != 0) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600671 skip_call |=
672 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
673 RESERVED_PARAMETER, LayerName, "%s: parameter %s must be 0", api_name, parameter_name.get_name().c_str());
Dustin Graves78df8512016-04-28 17:58:59 -0600674 }
675
676 return skip_call;
677}
678
679/**
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600680* Validate a Vulkan bitmask value.
681*
682* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
683* for that type.
684*
685* @param report_data debug_report_data object for routing validation messages.
686* @param api_name Name of API call being validated.
687* @param parameter_name Name of parameter being validated.
688* @param flag_bits_name Name of the VkFlags type being validated.
689* @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated.
690* @param value VkFlags value to validate.
691* @param flags_required The 'value' parameter may not be 0 when true.
692* @return Boolean value indicating that the call should be skipped.
693*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600694static bool validate_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600695 const char *flag_bits_name, VkFlags all_flags, VkFlags value, bool flags_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600696 bool skip_call = false;
697
698 if (value == 0) {
699 if (flags_required) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600700 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600701 REQUIRED_PARAMETER, LayerName, "%s: value of %s must not be 0", api_name,
702 parameter_name.get_name().c_str());
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600703 }
704 } else if ((value & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600705 skip_call |=
706 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
707 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s contains flag bits that are not recognized members of %s",
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600708 api_name, parameter_name.get_name().c_str(), flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600709 }
710
711 return skip_call;
712}
713
714/**
715* Validate an array of Vulkan bitmask values.
716*
717* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
718* for that type.
719*
720* @param report_data debug_report_data object for routing validation messages.
721* @param api_name Name of API call being validated.
722* @param count_name Name of parameter being validated.
723* @param array_name Name of parameter being validated.
724* @param flag_bits_name Name of the VkFlags type being validated.
725* @param all_flags A bitmask combining all valid flag bits for the VkFlags type being validated.
726* @param count Number of VkFlags values in the array.
727* @param array Array of VkFlags value to validate.
728* @param count_required The 'count' parameter may not be 0 when true.
729* @param array_required The 'array' parameter may not be NULL when true.
730* @return Boolean value indicating that the call should be skipped.
731*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600732static bool validate_flags_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
733 const ParameterName &array_name, const char *flag_bits_name, VkFlags all_flags, uint32_t count,
Dustin Graves78df8512016-04-28 17:58:59 -0600734 const VkFlags *array, bool count_required, bool array_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600735 bool skip_call = false;
736
737 if ((count == 0) || (array == NULL)) {
738 skip_call |= validate_array(report_data, api_name, count_name, array_name, count, array, count_required, array_required);
739 } else {
740 // Verify that all VkFlags values in the array
741 for (uint32_t i = 0; i < count; ++i) {
Dustin Graves78df8512016-04-28 17:58:59 -0600742 if (array[i] == 0) {
743 // Current XML registry logic for validity generation uses the array parameter's optional tag to determine if
744 // elements in the array are allowed be 0
745 if (array_required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600746 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
747 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: value of %s[%d] must not be 0", api_name,
748 array_name.get_name().c_str(), i);
Dustin Graves78df8512016-04-28 17:58:59 -0600749 }
750 } else if ((array[i] & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600751 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
752 __LINE__, UNRECOGNIZED_VALUE, LayerName,
753 "%s: value of %s[%d] contains flag bits that are not recognized members of %s", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600754 array_name.get_name().c_str(), i, flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600755 }
756 }
757 }
758
759 return skip_call;
760}
761
762/**
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600763* Get VkResult code description.
764*
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600765* Returns a string describing the specified VkResult code. The description is based on the language in the Vulkan API
766* specification.
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600767*
768* @param value VkResult code to process.
769* @return String describing the specified VkResult code.
770*/
771static std::string get_result_description(VkResult result) {
772 // clang-format off
773 switch (result) {
774 case VK_SUCCESS: return "a command completed successfully";
775 case VK_NOT_READY: return "a fence or query has not yet completed";
776 case VK_TIMEOUT: return "a wait operation has not completed in the specified time";
777 case VK_EVENT_SET: return "an event is signaled";
778 case VK_EVENT_RESET: return "an event is unsignalled";
779 case VK_INCOMPLETE: return "a return array was too small for the result";
780 case VK_ERROR_OUT_OF_HOST_MEMORY: return "a host memory allocation has failed";
781 case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "a device memory allocation has failed";
Dustin Graves2adca842016-05-16 18:35:55 -0600782 case VK_ERROR_INITIALIZATION_FAILED: return "initialization of an object has failed";
783 case VK_ERROR_DEVICE_LOST: return "the logical device has been lost";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600784 case VK_ERROR_MEMORY_MAP_FAILED: return "mapping of a memory object has failed";
785 case VK_ERROR_LAYER_NOT_PRESENT: return "the specified layer does not exist";
786 case VK_ERROR_EXTENSION_NOT_PRESENT: return "the specified extension does not exist";
787 case VK_ERROR_FEATURE_NOT_PRESENT: return "the requested feature is not available on this device";
788 case VK_ERROR_INCOMPATIBLE_DRIVER: return "a Vulkan driver could not be found";
789 case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects of the type have already been created";
790 case VK_ERROR_FORMAT_NOT_SUPPORTED: return "the requested format is not supported on this device";
791 case VK_ERROR_SURFACE_LOST_KHR: return "a surface is no longer available";
792 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "the requested window is already connected to another "
793 "VkSurfaceKHR object, or some other non-Vulkan surface object";
794 case VK_SUBOPTIMAL_KHR: return "an image became available, and the swapchain no longer "
795 "matches the surface properties exactly, but can still be used to "
796 "present to the surface successfully.";
797 case VK_ERROR_OUT_OF_DATE_KHR: return "a surface has changed in such a way that it is no "
798 "longer compatible with the swapchain";
799 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "the display used by a swapchain does not use the same "
800 "presentable image layout, or is incompatible in a way that prevents "
801 "sharing an image";
802 case VK_ERROR_VALIDATION_FAILED_EXT: return "API validation has detected an invalid use of the API";
803 case VK_ERROR_INVALID_SHADER_NV: return "one or more shaders failed to compile or link";
Eric Engestrombcbb0fd2016-04-02 22:06:13 +0100804 default: return "an error has occurred";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600805 };
806 // clang-format on
807}
808
809/**
810* Validate return code.
811*
812* Print a message describing the reason for failure when an error code is returned.
813*
814* @param report_data debug_report_data object for routing validation messages.
815* @param apiName Name of API call being validated.
Mark Lobodzinskib42e51b2017-05-09 13:49:59 -0600816* @param ignore vector of VkResult return codes to be ignored
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600817* @param value VkResult value to validate.
818*/
Mark Lobodzinskib42e51b2017-05-09 13:49:59 -0600819static void validate_result(debug_report_data *report_data, const char *apiName, std::vector<VkResult> const &ignore,
820 VkResult result) {
Chris Forbesf1f4e382016-10-13 14:44:03 +1300821 if (result < 0 && result != VK_ERROR_VALIDATION_FAILED_EXT) {
Mark Lobodzinskib42e51b2017-05-09 13:49:59 -0600822 if (std::find(ignore.begin(), ignore.end(), result) != ignore.end()) {
823 return;
824 }
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600825 std::string resultName = string_VkResult(result);
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600826 if (resultName == UnsupportedResultString) {
827 // Unrecognized result code
Dustin Gravesf233e502016-05-05 13:44:21 -0600828 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
829 FAILURE_RETURN_CODE, LayerName, "%s: returned a result code indicating that an error has occurred", apiName);
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600830 } else {
831 std::string resultDesc = get_result_description(result);
Dustin Gravesf233e502016-05-05 13:44:21 -0600832 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
833 FAILURE_RETURN_CODE, LayerName, "%s: returned %s, indicating that %s", apiName, resultName.c_str(),
834 resultDesc.c_str());
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600835 }
836 }
837}
838
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700839} // namespace parameter_validation
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600840
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700841#endif // PARAMETER_VALIDATION_UTILS_H