blob: 5084d5a1ef74a0e2a20a840a28fda88659c27859 [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"
31
Dustin Graves8ffbbf62016-07-22 13:19:46 -060032#include "parameter_name.h"
33
Dustin Gravesb83fc2d2016-05-04 12:56:08 -060034namespace parameter_validation {
35
Dustin Gravesf233e502016-05-05 13:44:21 -060036enum ErrorCode {
37 NONE, // Used for INFO & other non-error messages
38 INVALID_USAGE, // The value of a parameter is not consistent
39 // with the valid usage criteria defined in
40 // the Vulkan specification.
41 INVALID_STRUCT_STYPE, // The sType field of a Vulkan structure does
42 // not contain the value expected for a structure
43 // of that type.
44 INVALID_STRUCT_PNEXT, // The pNext field of a Vulkan structure references
45 // a value that is not compatible with a structure of
46 // that type or is not NULL when a structure of that
47 // type has no compatible pNext values.
48 REQUIRED_PARAMETER, // A required parameter was specified as 0 or NULL.
49 RESERVED_PARAMETER, // A parameter reserved for future use was not
50 // specified as 0 or NULL.
51 UNRECOGNIZED_VALUE, // A Vulkan enumeration, VkFlags, or VkBool32 parameter
52 // contains a value that is not recognized as valid for
53 // that type.
Mark Lobodzinski4dc6cb02016-06-28 11:23:08 -060054 DEVICE_LIMIT, // A specified parameter exceeds the limits returned
55 // by the physical device
56 DEVICE_FEATURE, // Use of a requested feature is not supported by
57 // the device
Dustin Gravesf233e502016-05-05 13:44:21 -060058 FAILURE_RETURN_CODE, // A Vulkan return code indicating a failure condition
59 // was encountered.
60};
61
Dustin Graves58c2f662016-03-08 17:48:20 -070062struct GenericHeader {
63 VkStructureType sType;
64 const void *pNext;
65};
Dustin Graves58c2f662016-03-08 17:48:20 -070066
Dustin Graves29148ff2016-03-23 19:44:00 -060067// Layer name string to be logged with validation messages.
Dustin Gravesb83fc2d2016-05-04 12:56:08 -060068const char LayerName[] = "ParameterValidation";
Dustin Graves29148ff2016-03-23 19:44:00 -060069
Mark Lobodzinskiaf00fa82016-08-09 10:44:38 -060070// Enables for display-related instance extensions
71struct instance_extension_enables {
72 bool wsi_enabled;
73 bool xlib_enabled;
74 bool xcb_enabled;
75 bool wayland_enabled;
76 bool mir_enabled;
77 bool android_enabled;
78 bool win32_enabled;
79};
80
Dustin Graves29148ff2016-03-23 19:44:00 -060081// String returned by string_VkStructureType for an unrecognized type.
Dustin Graves58c2f662016-03-08 17:48:20 -070082const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
83
Dustin Gravesca7aa7c2016-03-25 15:13:28 -060084// String returned by string_VkResult for an unrecognized type.
85const std::string UnsupportedResultString = "Unhandled VkResult";
86
Dustin Graves29148ff2016-03-23 19:44:00 -060087// The base value used when computing the offset for an enumeration token value that is added by an extension.
88// When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
89// See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
90const uint32_t ExtEnumBaseValue = 1000000000;
91
92template <typename T> bool is_extension_added_token(T value) {
93 return (std::abs(static_cast<int32_t>(value)) >= ExtEnumBaseValue);
94}
95
96// VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE token is a special case that was converted from a core token to an
97// extension added token. Its original value was intentionally preserved after the conversion, so it does not use
98// the base value that other extension added tokens use, and it does not fall within the enum's begin/end range.
99template <> bool is_extension_added_token(VkSamplerAddressMode value) {
100 bool result = (std::abs(static_cast<int32_t>(value)) >= ExtEnumBaseValue);
101 return (result || (value == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));
102}
103
Dustin Graves1e92cd72016-02-09 14:00:18 -0700104/**
Dustin Gravesf8032f22016-05-11 18:31:44 -0600105* Validate a minimum value.
106*
107* Verify that the specified value is greater than the specified lower bound.
108*
109* @param report_data debug_report_data object for routing validation messages.
110* @param api_name Name of API call being validated.
111* @param parameter_name Name of parameter being validated.
112* @param value Value to validate.
113* @param lower_bound Lower bound value to use for validation.
114* @return Boolean value indicating that the call should be skipped.
115*/
116template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600117bool ValidateGreaterThan(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name, T value,
118 T lower_bound) {
Dustin Gravesf8032f22016-05-11 18:31:44 -0600119 bool skip_call = false;
120
121 if (value <= lower_bound) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600122 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, LayerName,
123 "%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 -0600124 }
125
126 return skip_call;
127}
128
129/**
Dustin Graves1e92cd72016-02-09 14:00:18 -0700130 * Validate a required pointer.
131 *
Dustin Graves58c2f662016-03-08 17:48:20 -0700132 * Verify that a required pointer is not NULL.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700133 *
134 * @param report_data debug_report_data object for routing validation messages.
135 * @param apiName Name of API call being validated.
136 * @param parameterName Name of parameter being validated.
137 * @param value Pointer to validate.
138 * @return Boolean value indicating that the call should be skipped.
139 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600140static bool validate_required_pointer(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
Dustin Graves080069b2016-04-05 13:48:15 -0600141 const void *value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600142 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700143
144 if (value == NULL) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600145
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600146 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 -0600147 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
148 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700149 }
150
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600151 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700152}
153
154/**
155 * Validate array count and pointer to array.
156 *
Dustin Graves58d114b2016-03-08 14:42:59 -0700157 * Verify that required count and array parameters are not 0 or NULL. If the
158 * count parameter is not optional, verify that it is not 0. If the array
159 * parameter is NULL, and it is not optional, verify that count is 0.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700160 *
161 * @param report_data debug_report_data object for routing validation messages.
162 * @param apiName Name of API call being validated.
163 * @param countName Name of count parameter.
164 * @param arrayName Name of array parameter.
165 * @param count Number of elements in the array.
166 * @param array Array to validate.
167 * @param countRequired The 'count' parameter may not be 0 when true.
168 * @param arrayRequired The 'array' parameter may not be NULL when true.
169 * @return Boolean value indicating that the call should be skipped.
170 */
171template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600172bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
173 const ParameterName &arrayName, T count, const void *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600174 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700175
176 // Count parameters not tagged as optional cannot be 0
Józef Kucia20bb8fb2016-09-23 12:45:04 +0200177 if (countRequired && (count == 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600178 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 -0600179 REQUIRED_PARAMETER, LayerName, "%s: parameter %s must be greater than 0", apiName,
180 countName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700181 }
182
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600183 // Array parameters not tagged as optional cannot be NULL, unless the count is 0
Dustin Graves080069b2016-04-05 13:48:15 -0600184 if ((array == NULL) && arrayRequired && (count != 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600185 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 -0600186 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
187 arrayName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600188 }
189
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600190 return skip_call;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600191}
192
193/**
194* Validate pointer to array count and pointer to array.
195*
196* Verify that required count and array parameters are not NULL. If count
197* is not NULL and its value is not optional, verify that it is not 0. If the
198* array parameter is NULL, and it is not optional, verify that count is 0.
199* The array parameter will typically be optional for this case (where count is
200* a pointer), allowing the caller to retrieve the available count.
201*
202* @param report_data debug_report_data object for routing validation messages.
203* @param apiName Name of API call being validated.
204* @param countName Name of count parameter.
205* @param arrayName Name of array parameter.
206* @param count Pointer to the number of elements in the array.
207* @param array Array to validate.
208* @param countPtrRequired The 'count' parameter may not be NULL when true.
209* @param countValueRequired The '*count' value may not be 0 when true.
210* @param arrayRequired The 'array' parameter may not be NULL when true.
211* @return Boolean value indicating that the call should be skipped.
212*/
213template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600214bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
215 const ParameterName &arrayName, const T *count, const void *array, bool countPtrRequired,
216 bool countValueRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600217 bool skip_call = false;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600218
219 if (count == NULL) {
220 if (countPtrRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600221 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 -0600222 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
223 countName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600224 }
225 }
226 else {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600227 skip_call |= validate_array(report_data, apiName, countName, arrayName, (*count), array, countValueRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700228 }
229
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600230 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700231}
232
233/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600234 * Validate a pointer to a Vulkan structure.
235 *
236 * Verify that a required pointer to a structure is not NULL. If the pointer is
237 * not NULL, verify that each structure's sType field is set to the correct
238 * VkStructureType value.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700239 *
240 * @param report_data debug_report_data object for routing validation messages.
241 * @param apiName Name of API call being validated.
242 * @param parameterName Name of struct parameter being validated.
243 * @param sTypeName Name of expected VkStructureType value.
244 * @param value Pointer to the struct to validate.
245 * @param sType VkStructureType for structure validation.
246 * @param required The parameter may not be NULL when true.
247 * @return Boolean value indicating that the call should be skipped.
248 */
249template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600250bool validate_struct_type(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
251 const char *sTypeName, const T *value, VkStructureType sType, bool required) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600252 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700253
254 if (value == NULL) {
Dustin Graves080069b2016-04-05 13:48:15 -0600255 if (required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600256 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
257 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
258 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700259 }
260 } else if (value->sType != sType) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600261 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
262 INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s->sType must be %s", apiName,
263 parameterName.get_name().c_str(), sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700264 }
265
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600266 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700267}
268
269/**
270 * Validate an array of Vulkan structures.
271 *
272 * Verify that required count and array parameters are not NULL. If count
273 * is not NULL and its value is not optional, verify that it is not 0.
274 * If the array contains 1 or more structures, verify that each structure's
275 * sType field is set to the correct VkStructureType value.
276 *
277 * @param report_data debug_report_data object for routing validation messages.
278 * @param apiName Name of API call being validated.
279 * @param countName Name of count parameter.
280 * @param arrayName Name of array parameter.
281 * @param sTypeName Name of expected VkStructureType value.
282 * @param count Pointer to the number of elements in the array.
283 * @param array Array to validate.
284 * @param sType VkStructureType for structure validation.
285 * @param countPtrRequired The 'count' parameter may not be NULL when true.
286 * @param countValueRequired The '*count' value may not be 0 when true.
287 * @param arrayRequired The 'array' parameter may not be NULL when true.
288 * @return Boolean value indicating that the call should be skipped.
289 */
290template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600291bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
292 const ParameterName &arrayName, const char *sTypeName, const uint32_t *count, const T *array,
293 VkStructureType sType, bool countPtrRequired, bool countValueRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600294 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700295
296 if (count == NULL) {
Dustin Graves080069b2016-04-05 13:48:15 -0600297 if (countPtrRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600298 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 -0600299 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
300 countName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700301 }
302 } else {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600303 skip_call |= validate_struct_type_array(report_data, apiName, countName, arrayName, sTypeName, (*count), array, sType,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600304 countValueRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700305 }
306
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600307 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700308}
309
310/**
311 * Validate an array of Vulkan structures
312 *
313 * Verify that required count and array parameters are not 0 or NULL. If
314 * the array contains 1 or more structures, verify that each structure's
315 * sType field is set to the correct VkStructureType value.
316 *
317 * @param report_data debug_report_data object for routing validation messages.
318 * @param apiName Name of API call being validated.
319 * @param countName Name of count parameter.
320 * @param arrayName Name of array parameter.
321 * @param sTypeName Name of expected VkStructureType value.
322 * @param count Number of elements in the array.
323 * @param array Array to validate.
324 * @param sType VkStructureType for structure validation.
325 * @param countRequired The 'count' parameter may not be 0 when true.
326 * @param arrayRequired The 'array' parameter may not be NULL when true.
327 * @return Boolean value indicating that the call should be skipped.
328 */
329template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600330bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
331 const ParameterName &arrayName, const char *sTypeName, uint32_t count, const T *array,
332 VkStructureType sType, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600333 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700334
335 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600336 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700337 } else {
338 // Verify that all structs in the array have the correct type
339 for (uint32_t i = 0; i < count; ++i) {
340 if (array[i].sType != sType) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600341 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 -0600342 __LINE__, INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s[%d].sType must be %s", apiName,
343 arrayName.get_name().c_str(), i, sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700344 }
345 }
346 }
347
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600348 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700349}
350
Dustin Graves58d114b2016-03-08 14:42:59 -0700351/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600352* Validate a Vulkan handle.
353*
354* Verify that the specified handle is not VK_NULL_HANDLE.
355*
356* @param report_data debug_report_data object for routing validation messages.
357* @param api_name Name of API call being validated.
358* @param parameter_name Name of struct parameter being validated.
359* @param value Handle to validate.
360* @return Boolean value indicating that the call should be skipped.
361*/
362template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600363bool 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 -0600364 bool skip_call = false;
365
366 if (value == VK_NULL_HANDLE) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600367 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
368 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as VK_NULL_HANDLE", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600369 parameter_name.get_name().c_str());
Dustin Graves20fd66f2016-04-18 18:33:21 -0600370 }
371
372 return skip_call;
373}
374
375/**
376* Validate an array of Vulkan handles.
377*
378* Verify that required count and array parameters are not NULL. If count
379* is not NULL and its value is not optional, verify that it is not 0.
380* If the array contains 1 or more handles, verify that no handle is set to
381* VK_NULL_HANDLE.
382*
383* @note This function is only intended to validate arrays of handles when none
384* of the handles are allowed to be VK_NULL_HANDLE. For arrays of handles
385* that are allowed to contain VK_NULL_HANDLE, use validate_array() instead.
386*
387* @param report_data debug_report_data object for routing validation messages.
388* @param api_name Name of API call being validated.
389* @param count_name Name of count parameter.
390* @param array_name Name of array parameter.
391* @param count Number of elements in the array.
392* @param array Array to validate.
393* @param count_required The 'count' parameter may not be 0 when true.
394* @param array_required The 'array' parameter may not be NULL when true.
395* @return Boolean value indicating that the call should be skipped.
396*/
397template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600398bool validate_handle_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
399 const ParameterName &array_name, uint32_t count, const T *array, bool count_required,
400 bool array_required) {
Dustin Graves20fd66f2016-04-18 18:33:21 -0600401 bool skip_call = false;
402
403 if ((count == 0) || (array == NULL)) {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600404 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 -0600405 } else {
406 // Verify that no handles in the array are VK_NULL_HANDLE
407 for (uint32_t i = 0; i < count; ++i) {
408 if (array[i] == VK_NULL_HANDLE) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600409 skip_call |=
410 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
411 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as VK_NULL_HANDLE", api_name,
412 array_name.get_name().c_str(), i);
Dustin Graves20fd66f2016-04-18 18:33:21 -0600413 }
414 }
415 }
416
417 return skip_call;
418}
419
420/**
Dustin Graves58d114b2016-03-08 14:42:59 -0700421 * Validate string array count and content.
422 *
423 * Verify that required count and array parameters are not 0 or NULL. If the
424 * count parameter is not optional, verify that it is not 0. If the array
425 * parameter is NULL, and it is not optional, verify that count is 0. If the
426 * array parameter is not NULL, verify that none of the strings are NULL.
427 *
428 * @param report_data debug_report_data object for routing validation messages.
429 * @param apiName Name of API call being validated.
430 * @param countName Name of count parameter.
431 * @param arrayName Name of array parameter.
432 * @param count Number of strings in the array.
433 * @param array Array of strings to validate.
434 * @param countRequired The 'count' parameter may not be 0 when true.
435 * @param arrayRequired The 'array' parameter may not be NULL when true.
436 * @return Boolean value indicating that the call should be skipped.
437 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600438static bool validate_string_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
439 const ParameterName &arrayName, uint32_t count, const char *const *array, bool countRequired,
440 bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600441 bool skip_call = false;
Dustin Graves58d114b2016-03-08 14:42:59 -0700442
443 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600444 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves58d114b2016-03-08 14:42:59 -0700445 } else {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600446 // Verify that strings in the array are not NULL
Dustin Graves58d114b2016-03-08 14:42:59 -0700447 for (uint32_t i = 0; i < count; ++i) {
448 if (array[i] == NULL) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600449 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 -0600450 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as NULL",
451 apiName, arrayName.get_name().c_str(), i);
Dustin Graves58d114b2016-03-08 14:42:59 -0700452 }
453 }
454 }
455
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600456 return skip_call;
Dustin Graves58d114b2016-03-08 14:42:59 -0700457}
458
Dustin Graves58c2f662016-03-08 17:48:20 -0700459/**
460 * Validate a structure's pNext member.
461 *
462 * Verify that the specified pNext value points to the head of a list of
463 * allowed extension structures. If no extension structures are allowed,
464 * verify that pNext is null.
465 *
466 * @param report_data debug_report_data object for routing validation messages.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600467 * @param api_name Name of API call being validated.
468 * @param parameter_name Name of parameter being validated.
469 * @param allowed_struct_names Names of allowed structs.
Dustin Graves58c2f662016-03-08 17:48:20 -0700470 * @param next Pointer to validate.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600471 * @param allowed_type_count Total number of allowed structure types.
472 * @param allowed_types Array of strcuture types allowed for pNext.
473 * @param header_version Version of header defining the pNext validation rules.
Dustin Graves58c2f662016-03-08 17:48:20 -0700474 * @return Boolean value indicating that the call should be skipped.
475 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600476static bool validate_struct_pnext(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600477 const char *allowed_struct_names, const void *next, size_t allowed_type_count,
478 const VkStructureType *allowed_types, uint32_t header_version) {
479 bool skip_call = false;
480 const char disclaimer[] = "This warning is based on the Valid Usage documentation for version %d of the Vulkan header. It "
481 "is possible that you are using a struct from a private extension or an extension that was added "
482 "to a later version of the Vulkan header, in which case your use of %s is perfectly valid but "
483 "is not guaranteed to work correctly with validation enabled";
Dustin Graves58c2f662016-03-08 17:48:20 -0700484
485 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
497 while (current != NULL) {
498 if (std::find(start, end, current->sType) == end) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600499 std::string type_name = string_VkStructureType(current->sType);
Dustin Graves58c2f662016-03-08 17:48:20 -0700500
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600501 if (type_name == UnsupportedStructureTypeString) {
502 std::string message = "%s: %s chain includes a structure with unexpected VkStructureType (%d); Allowed "
503 "structures are [%s]. ";
504 message += disclaimer;
505 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
506 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600507 parameter_name.get_name().c_str(), current->sType, allowed_struct_names,
508 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700509 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600510 std::string message =
511 "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures are [%s]. ";
512 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600513 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
514 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
515 parameter_name.get_name().c_str(), type_name.c_str(), allowed_struct_names,
516 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700517 }
518 }
519
520 current = reinterpret_cast<const GenericHeader *>(current->pNext);
521 }
522 }
523 }
524
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600525 return skip_call;
Dustin Graves58c2f662016-03-08 17:48:20 -0700526}
527
Dustin Graves29148ff2016-03-23 19:44:00 -0600528/**
529* Validate a VkBool32 value.
530*
531* Generate a warning if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
532*
533* @param report_data debug_report_data object for routing validation messages.
534* @param apiName Name of API call being validated.
535* @param parameterName Name of parameter being validated.
536* @param value Boolean value to validate.
537* @return Boolean value indicating that the call should be skipped.
538*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600539static bool validate_bool32(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
540 VkBool32 value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600541 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600542
543 if ((value != VK_TRUE) && (value != VK_FALSE)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600544 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 -0600545 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE", apiName,
546 parameterName.get_name().c_str(), value);
Dustin Graves29148ff2016-03-23 19:44:00 -0600547 }
548
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600549 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600550}
551
552/**
553* Validate a Vulkan enumeration value.
554*
555* Generate a warning if an enumeration token value does not fall within the core enumeration
556* begin and end token values, and was not added to the enumeration by an extension. Extension
557* provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
558* with 1,000,000,000 as the base token value.
559*
560* @note This function does not expect to process enumerations defining bitmask flag bits.
561*
562* @param report_data debug_report_data object for routing validation messages.
563* @param apiName Name of API call being validated.
564* @param parameterName Name of parameter being validated.
565* @param enumName Name of the enumeration being validated.
566* @param begin The begin range value for the enumeration.
567* @param end The end range value for the enumeration.
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600568* @param value Enumeration value to validate.
Dustin Graves29148ff2016-03-23 19:44:00 -0600569* @return Boolean value indicating that the call should be skipped.
570*/
571template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600572bool validate_ranged_enum(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
573 const char *enumName, T begin, T end, T value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600574 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600575
576 if (((value < begin) || (value > end)) && !is_extension_added_token(value)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600577 skip_call |=
Dustin Gravesf233e502016-05-05 13:44:21 -0600578 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
579 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s (%d) does not fall within the begin..end range of the core %s "
580 "enumeration tokens and is not an extension added token",
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600581 apiName, parameterName.get_name().c_str(), value, enumName);
Dustin Graves29148ff2016-03-23 19:44:00 -0600582 }
583
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600584 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600585}
586
587/**
588* Validate an array of Vulkan enumeration value.
589*
590* Process all enumeration token values in the specified array and generate a warning if a value
591* does not fall within the core enumeration begin and end token values, and was not added to
592* the enumeration by an extension. Extension provided enumerations use the equation specified
593* in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
594*
595* @note This function does not expect to process enumerations defining bitmask flag bits.
596*
597* @param report_data debug_report_data object for routing validation messages.
598* @param apiName Name of API call being validated.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600599* @param countName Name of count parameter.
600* @param arrayName Name of array parameter.
Dustin Graves29148ff2016-03-23 19:44:00 -0600601* @param enumName Name of the enumeration being validated.
602* @param begin The begin range value for the enumeration.
603* @param end The end range value for the enumeration.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600604* @param count Number of enumeration values in the array.
605* @param array Array of enumeration values to validate.
606* @param countRequired The 'count' parameter may not be 0 when true.
607* @param arrayRequired The 'array' parameter may not be NULL when true.
Dustin Graves29148ff2016-03-23 19:44:00 -0600608* @return Boolean value indicating that the call should be skipped.
609*/
610template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600611static bool validate_ranged_enum_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
612 const ParameterName &arrayName, const char *enumName, T begin, T end, uint32_t count,
613 const T *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600614 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600615
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600616 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600617 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600618 } else {
619 for (uint32_t i = 0; i < count; ++i) {
620 if (((array[i] < begin) || (array[i] > end)) && !is_extension_added_token(array[i])) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600621 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 -0600622 __LINE__, UNRECOGNIZED_VALUE, LayerName,
623 "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
624 "enumeration tokens and is not an extension added token",
625 apiName, arrayName.get_name().c_str(), i, array[i], enumName);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600626 }
Dustin Graves29148ff2016-03-23 19:44:00 -0600627 }
628 }
629
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600630 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600631}
632
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600633/**
Dustin Graves78df8512016-04-28 17:58:59 -0600634* Verify that a reserved VkFlags value is zero.
635*
636* Verify that the specified value is zero, to check VkFlags values that are reserved for
637* future use.
638*
639* @param report_data debug_report_data object for routing validation messages.
640* @param api_name Name of API call being validated.
641* @param parameter_name Name of parameter being validated.
642* @param value Value to validate.
643* @return Boolean value indicating that the call should be skipped.
644*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600645static bool validate_reserved_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600646 VkFlags value) {
647 bool skip_call = false;
648
649 if (value != 0) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600650 skip_call |=
651 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
652 RESERVED_PARAMETER, LayerName, "%s: parameter %s must be 0", api_name, parameter_name.get_name().c_str());
Dustin Graves78df8512016-04-28 17:58:59 -0600653 }
654
655 return skip_call;
656}
657
658/**
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600659* Validate a Vulkan bitmask value.
660*
661* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
662* for that type.
663*
664* @param report_data debug_report_data object for routing validation messages.
665* @param api_name Name of API call being validated.
666* @param parameter_name Name of parameter being validated.
667* @param flag_bits_name Name of the VkFlags type being validated.
668* @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated.
669* @param value VkFlags value to validate.
670* @param flags_required The 'value' parameter may not be 0 when true.
671* @return Boolean value indicating that the call should be skipped.
672*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600673static bool validate_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600674 const char *flag_bits_name, VkFlags all_flags, VkFlags value, bool flags_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600675 bool skip_call = false;
676
677 if (value == 0) {
678 if (flags_required) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600679 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 -0600680 REQUIRED_PARAMETER, LayerName, "%s: value of %s must not be 0", api_name,
681 parameter_name.get_name().c_str());
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600682 }
683 } else if ((value & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600684 skip_call |=
685 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
686 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s contains flag bits that are not recognized members of %s",
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600687 api_name, parameter_name.get_name().c_str(), flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600688 }
689
690 return skip_call;
691}
692
693/**
694* Validate an array of Vulkan bitmask values.
695*
696* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
697* for that type.
698*
699* @param report_data debug_report_data object for routing validation messages.
700* @param api_name Name of API call being validated.
701* @param count_name Name of parameter being validated.
702* @param array_name Name of parameter being validated.
703* @param flag_bits_name Name of the VkFlags type being validated.
704* @param all_flags A bitmask combining all valid flag bits for the VkFlags type being validated.
705* @param count Number of VkFlags values in the array.
706* @param array Array of VkFlags value to validate.
707* @param count_required The 'count' parameter may not be 0 when true.
708* @param array_required The 'array' parameter may not be NULL when true.
709* @return Boolean value indicating that the call should be skipped.
710*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600711static bool validate_flags_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
712 const ParameterName &array_name, const char *flag_bits_name, VkFlags all_flags, uint32_t count,
Dustin Graves78df8512016-04-28 17:58:59 -0600713 const VkFlags *array, bool count_required, bool array_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600714 bool skip_call = false;
715
716 if ((count == 0) || (array == NULL)) {
717 skip_call |= validate_array(report_data, api_name, count_name, array_name, count, array, count_required, array_required);
718 } else {
719 // Verify that all VkFlags values in the array
720 for (uint32_t i = 0; i < count; ++i) {
Dustin Graves78df8512016-04-28 17:58:59 -0600721 if (array[i] == 0) {
722 // Current XML registry logic for validity generation uses the array parameter's optional tag to determine if
723 // elements in the array are allowed be 0
724 if (array_required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600725 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
726 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: value of %s[%d] must not be 0", api_name,
727 array_name.get_name().c_str(), i);
Dustin Graves78df8512016-04-28 17:58:59 -0600728 }
729 } else if ((array[i] & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600730 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
731 __LINE__, UNRECOGNIZED_VALUE, LayerName,
732 "%s: value of %s[%d] contains flag bits that are not recognized members of %s", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600733 array_name.get_name().c_str(), i, flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600734 }
735 }
736 }
737
738 return skip_call;
739}
740
741/**
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600742* Get VkResult code description.
743*
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600744* Returns a string describing the specified VkResult code. The description is based on the language in the Vulkan API
745* specification.
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600746*
747* @param value VkResult code to process.
748* @return String describing the specified VkResult code.
749*/
750static std::string get_result_description(VkResult result) {
751 // clang-format off
752 switch (result) {
753 case VK_SUCCESS: return "a command completed successfully";
754 case VK_NOT_READY: return "a fence or query has not yet completed";
755 case VK_TIMEOUT: return "a wait operation has not completed in the specified time";
756 case VK_EVENT_SET: return "an event is signaled";
757 case VK_EVENT_RESET: return "an event is unsignalled";
758 case VK_INCOMPLETE: return "a return array was too small for the result";
759 case VK_ERROR_OUT_OF_HOST_MEMORY: return "a host memory allocation has failed";
760 case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "a device memory allocation has failed";
Dustin Graves2adca842016-05-16 18:35:55 -0600761 case VK_ERROR_INITIALIZATION_FAILED: return "initialization of an object has failed";
762 case VK_ERROR_DEVICE_LOST: return "the logical device has been lost";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600763 case VK_ERROR_MEMORY_MAP_FAILED: return "mapping of a memory object has failed";
764 case VK_ERROR_LAYER_NOT_PRESENT: return "the specified layer does not exist";
765 case VK_ERROR_EXTENSION_NOT_PRESENT: return "the specified extension does not exist";
766 case VK_ERROR_FEATURE_NOT_PRESENT: return "the requested feature is not available on this device";
767 case VK_ERROR_INCOMPATIBLE_DRIVER: return "a Vulkan driver could not be found";
768 case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects of the type have already been created";
769 case VK_ERROR_FORMAT_NOT_SUPPORTED: return "the requested format is not supported on this device";
770 case VK_ERROR_SURFACE_LOST_KHR: return "a surface is no longer available";
771 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "the requested window is already connected to another "
772 "VkSurfaceKHR object, or some other non-Vulkan surface object";
773 case VK_SUBOPTIMAL_KHR: return "an image became available, and the swapchain no longer "
774 "matches the surface properties exactly, but can still be used to "
775 "present to the surface successfully.";
776 case VK_ERROR_OUT_OF_DATE_KHR: return "a surface has changed in such a way that it is no "
777 "longer compatible with the swapchain";
778 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "the display used by a swapchain does not use the same "
779 "presentable image layout, or is incompatible in a way that prevents "
780 "sharing an image";
781 case VK_ERROR_VALIDATION_FAILED_EXT: return "API validation has detected an invalid use of the API";
782 case VK_ERROR_INVALID_SHADER_NV: return "one or more shaders failed to compile or link";
Eric Engestrombcbb0fd2016-04-02 22:06:13 +0100783 default: return "an error has occurred";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600784 };
785 // clang-format on
786}
787
788/**
789* Validate return code.
790*
791* Print a message describing the reason for failure when an error code is returned.
792*
793* @param report_data debug_report_data object for routing validation messages.
794* @param apiName Name of API call being validated.
795* @param value VkResult value to validate.
796*/
797static void validate_result(debug_report_data *report_data, const char *apiName, VkResult result) {
798 if (result < 0) {
799 std::string resultName = string_VkResult(result);
800
801 if (resultName == UnsupportedResultString) {
802 // Unrecognized result code
Dustin Gravesf233e502016-05-05 13:44:21 -0600803 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
804 FAILURE_RETURN_CODE, LayerName, "%s: returned a result code indicating that an error has occurred", apiName);
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600805 } else {
806 std::string resultDesc = get_result_description(result);
Dustin Gravesf233e502016-05-05 13:44:21 -0600807 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
808 FAILURE_RETURN_CODE, LayerName, "%s: returned %s, indicating that %s", apiName, resultName.c_str(),
809 resultDesc.c_str());
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600810 }
811 }
812}
813
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600814} // namespace parameter_validation
815
Mark Lobodzinski739391a2016-03-17 15:08:18 -0600816#endif // PARAMETER_VALIDATION_UTILS_H