blob: 368c5107a39231a03a163dceb2eec2a4a88af855 [file] [log] [blame]
Dustin Gravesc87f31e2016-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 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials
11 * are furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included
14 * in all copies or substantial portions of the Materials.
15 *
16 * The Materials are Confidential Information as defined by the Khronos
17 * Membership Agreement until designated non-confidential by Khronos, at which
18 * point this condition clause shall be removed.
19 *
20 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
21 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
23 *
24 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
25 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
26 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
27 * USE OR OTHER DEALINGS IN THE MATERIALS
28 *
29 * Author: Dustin Graves <dustin@lunarg.com>
30 */
31
Mark Lobodzinski1c333572016-03-17 15:08:18 -060032#ifndef PARAMETER_VALIDATION_UTILS_H
33#define PARAMETER_VALIDATION_UTILS_H
Dustin Gravesc87f31e2016-02-09 14:00:18 -070034
Dustin Graves2949a5a2016-03-08 17:48:20 -070035#include <algorithm>
Dustin Gravesc3fc3d82016-03-23 19:44:00 -060036#include <cstdlib>
Dustin Graves2949a5a2016-03-08 17:48:20 -070037#include <string>
38
Dustin Gravesc87f31e2016-02-09 14:00:18 -070039#include "vulkan/vulkan.h"
Dustin Graves2949a5a2016-03-08 17:48:20 -070040#include "vk_enum_string_helper.h"
Dustin Gravesc87f31e2016-02-09 14:00:18 -070041#include "vk_layer_logging.h"
42
Dustin Graves2949a5a2016-03-08 17:48:20 -070043namespace {
44struct GenericHeader {
45 VkStructureType sType;
46 const void *pNext;
47};
48}
49
Dustin Gravesc3fc3d82016-03-23 19:44:00 -060050// Layer name string to be logged with validation messages.
51const char ParameterValidationName[] = "ParameterValidation";
52
53// String returned by string_VkStructureType for an unrecognized type.
Dustin Graves2949a5a2016-03-08 17:48:20 -070054const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
55
Dustin Gravese78276b2016-03-25 15:13:28 -060056// String returned by string_VkResult for an unrecognized type.
57const std::string UnsupportedResultString = "Unhandled VkResult";
58
Dustin Gravesc3fc3d82016-03-23 19:44:00 -060059// The base value used when computing the offset for an enumeration token value that is added by an extension.
60// When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
61// See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
62const uint32_t ExtEnumBaseValue = 1000000000;
63
64template <typename T> bool is_extension_added_token(T value) {
65 return (std::abs(static_cast<int32_t>(value)) >= ExtEnumBaseValue);
66}
67
68// VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE token is a special case that was converted from a core token to an
69// extension added token. Its original value was intentionally preserved after the conversion, so it does not use
70// the base value that other extension added tokens use, and it does not fall within the enum's begin/end range.
71template <> bool is_extension_added_token(VkSamplerAddressMode value) {
72 bool result = (std::abs(static_cast<int32_t>(value)) >= ExtEnumBaseValue);
73 return (result || (value == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));
74}
75
Dustin Gravesc87f31e2016-02-09 14:00:18 -070076/**
77 * Validate a required pointer.
78 *
Dustin Graves2949a5a2016-03-08 17:48:20 -070079 * Verify that a required pointer is not NULL.
Dustin Gravesc87f31e2016-02-09 14:00:18 -070080 *
81 * @param report_data debug_report_data object for routing validation messages.
82 * @param apiName Name of API call being validated.
83 * @param parameterName Name of parameter being validated.
84 * @param value Pointer to validate.
85 * @return Boolean value indicating that the call should be skipped.
86 */
Dustin Gravesbb849942016-04-05 13:48:15 -060087static bool validate_required_pointer(debug_report_data *report_data, const char *apiName, const char *parameterName,
88 const void *value) {
89 bool skipCall = false;
Dustin Gravesc87f31e2016-02-09 14:00:18 -070090
91 if (value == NULL) {
Dustin Gravesc3fc3d82016-03-23 19:44:00 -060092 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
93 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, parameterName);
Jon Ashburn491a3cd2016-03-08 17:48:44 -070094 }
Dustin Gravesc87f31e2016-02-09 14:00:18 -070095
96 return skipCall;
97}
98
99/**
100 * Validate pointer to array count and pointer to array.
101 *
102 * Verify that required count and array parameters are not NULL. If count
Dustin Gravesaf0d6dc2016-03-02 18:23:29 -0700103 * is not NULL and its value is not optional, verify that it is not 0. If the
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700104 * array parameter is NULL, and it is not optional, verify that count is 0.
105 * The array parameter will typically be optional for this case (where count is
106 * a pointer), allowing the caller to retrieve the available count.
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700107 *
108 * @param report_data debug_report_data object for routing validation messages.
109 * @param apiName Name of API call being validated.
110 * @param countName Name of count parameter.
111 * @param arrayName Name of array parameter.
112 * @param count Pointer to the number of elements in the array.
113 * @param array Array to validate.
114 * @param countPtrRequired The 'count' parameter may not be NULL when true.
115 * @param countValueRequired The '*count' value may not be 0 when true.
116 * @param arrayRequired The 'array' parameter may not be NULL when true.
117 * @return Boolean value indicating that the call should be skipped.
118 */
119template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600120bool validate_array(debug_report_data *report_data, const char *apiName, const char *countName, const char *arrayName,
121 const T *count, const void *array, bool countPtrRequired, bool countValueRequired, bool arrayRequired) {
122 bool skipCall = false;
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700123
124 if (count == NULL) {
Dustin Gravesbb849942016-04-05 13:48:15 -0600125 if (countPtrRequired) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700126 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600127 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, countName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700128 }
129 } else {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700130 skipCall |= validate_array(report_data, apiName, countName, arrayName, (*count), array, countValueRequired, arrayRequired);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700131 }
132
133 return skipCall;
134}
135
136/**
137 * Validate array count and pointer to array.
138 *
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700139 * Verify that required count and array parameters are not 0 or NULL. If the
140 * count parameter is not optional, verify that it is not 0. If the array
141 * parameter is NULL, and it is not optional, verify that count is 0.
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700142 *
143 * @param report_data debug_report_data object for routing validation messages.
144 * @param apiName Name of API call being validated.
145 * @param countName Name of count parameter.
146 * @param arrayName Name of array parameter.
147 * @param count Number of elements in the array.
148 * @param array Array to validate.
149 * @param countRequired The 'count' parameter may not be 0 when true.
150 * @param arrayRequired The 'array' parameter may not be NULL when true.
151 * @return Boolean value indicating that the call should be skipped.
152 */
153template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600154bool validate_array(debug_report_data *report_data, const char *apiName, const char *countName, const char *arrayName, T count,
155 const void *array, bool countRequired, bool arrayRequired) {
156 bool skipCall = false;
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700157
158 // Count parameters not tagged as optional cannot be 0
Dustin Gravesbb849942016-04-05 13:48:15 -0600159 if ((count == 0) && countRequired) {
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600160 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
161 ParameterValidationName, "%s: value of %s must be greater than 0", apiName, countName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700162 }
163
164 // Array parameters not tagged as optional cannot be NULL,
165 // unless the count is 0
Dustin Gravesbb849942016-04-05 13:48:15 -0600166 if ((array == NULL) && arrayRequired && (count != 0)) {
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600167 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
168 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, arrayName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700169 }
170
171 return skipCall;
172}
173
174/**
175 * Validate an Vulkan structure type.
176 *
177 * @param report_data debug_report_data object for routing validation messages.
178 * @param apiName Name of API call being validated.
179 * @param parameterName Name of struct parameter being validated.
180 * @param sTypeName Name of expected VkStructureType value.
181 * @param value Pointer to the struct to validate.
182 * @param sType VkStructureType for structure validation.
183 * @param required The parameter may not be NULL when true.
184 * @return Boolean value indicating that the call should be skipped.
185 */
186template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600187bool validate_struct_type(debug_report_data *report_data, const char *apiName, const char *parameterName, const char *sTypeName,
188 const T *value, VkStructureType sType, bool required) {
189 bool skipCall = false;
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700190
191 if (value == NULL) {
Dustin Gravesbb849942016-04-05 13:48:15 -0600192 if (required) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700193 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600194 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, parameterName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700195 }
196 } else if (value->sType != sType) {
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600197 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
198 ParameterValidationName, "%s: parameter %s->sType must be %s", apiName, parameterName, sTypeName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700199 }
200
201 return skipCall;
202}
203
204/**
205 * Validate an array of Vulkan structures.
206 *
207 * Verify that required count and array parameters are not NULL. If count
208 * is not NULL and its value is not optional, verify that it is not 0.
209 * If the array contains 1 or more structures, verify that each structure's
210 * sType field is set to the correct VkStructureType value.
211 *
212 * @param report_data debug_report_data object for routing validation messages.
213 * @param apiName Name of API call being validated.
214 * @param countName Name of count parameter.
215 * @param arrayName Name of array parameter.
216 * @param sTypeName Name of expected VkStructureType value.
217 * @param count Pointer to the number of elements in the array.
218 * @param array Array to validate.
219 * @param sType VkStructureType for structure validation.
220 * @param countPtrRequired The 'count' parameter may not be NULL when true.
221 * @param countValueRequired The '*count' value may not be 0 when true.
222 * @param arrayRequired The 'array' parameter may not be NULL when true.
223 * @return Boolean value indicating that the call should be skipped.
224 */
225template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600226bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const char *countName, const char *arrayName,
227 const char *sTypeName, const uint32_t *count, const T *array, VkStructureType sType,
228 bool countPtrRequired, bool countValueRequired, bool arrayRequired) {
229 bool skipCall = false;
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700230
231 if (count == NULL) {
Dustin Gravesbb849942016-04-05 13:48:15 -0600232 if (countPtrRequired) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700233 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600234 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, countName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700235 }
236 } else {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700237 skipCall |= validate_struct_type_array(report_data, apiName, countName, arrayName, sTypeName, (*count), array, sType,
238 countValueRequired, arrayRequired);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700239 }
240
241 return skipCall;
242}
243
244/**
245 * Validate an array of Vulkan structures
246 *
247 * Verify that required count and array parameters are not 0 or NULL. If
248 * the array contains 1 or more structures, verify that each structure's
249 * sType field is set to the correct VkStructureType value.
250 *
251 * @param report_data debug_report_data object for routing validation messages.
252 * @param apiName Name of API call being validated.
253 * @param countName Name of count parameter.
254 * @param arrayName Name of array parameter.
255 * @param sTypeName Name of expected VkStructureType value.
256 * @param count Number of elements in the array.
257 * @param array Array to validate.
258 * @param sType VkStructureType for structure validation.
259 * @param countRequired The 'count' parameter may not be 0 when true.
260 * @param arrayRequired The 'array' parameter may not be NULL when true.
261 * @return Boolean value indicating that the call should be skipped.
262 */
263template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600264bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const char *countName, const char *arrayName,
265 const char *sTypeName, uint32_t count, const T *array, VkStructureType sType, bool countRequired,
266 bool arrayRequired) {
267 bool skipCall = false;
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700268
269 if ((count == 0) || (array == NULL)) {
270 // Count parameters not tagged as optional cannot be 0
Dustin Gravesbb849942016-04-05 13:48:15 -0600271 if ((count == 0) && countRequired) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700272 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600273 ParameterValidationName, "%s: parameter %s must be greater than 0", apiName, countName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700274 }
275
276 // Array parameters not tagged as optional cannot be NULL,
277 // unless the count is 0
Dustin Gravesbb849942016-04-05 13:48:15 -0600278 if ((array == NULL) && arrayRequired && (count != 0)) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700279 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600280 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, arrayName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700281 }
282 } else {
283 // Verify that all structs in the array have the correct type
284 for (uint32_t i = 0; i < count; ++i) {
285 if (array[i].sType != sType) {
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600286 skipCall |=
287 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
288 ParameterValidationName, "%s: parameter %s[%d].sType must be %s", apiName, arrayName, i, sTypeName);
Dustin Gravesc87f31e2016-02-09 14:00:18 -0700289 }
290 }
291 }
292
293 return skipCall;
294}
295
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700296/**
297 * Validate string array count and content.
298 *
299 * Verify that required count and array parameters are not 0 or NULL. If the
300 * count parameter is not optional, verify that it is not 0. If the array
301 * parameter is NULL, and it is not optional, verify that count is 0. If the
302 * array parameter is not NULL, verify that none of the strings are NULL.
303 *
304 * @param report_data debug_report_data object for routing validation messages.
305 * @param apiName Name of API call being validated.
306 * @param countName Name of count parameter.
307 * @param arrayName Name of array parameter.
308 * @param count Number of strings in the array.
309 * @param array Array of strings to validate.
310 * @param countRequired The 'count' parameter may not be 0 when true.
311 * @param arrayRequired The 'array' parameter may not be NULL when true.
312 * @return Boolean value indicating that the call should be skipped.
313 */
Dustin Gravesbb849942016-04-05 13:48:15 -0600314static bool validate_string_array(debug_report_data *report_data, const char *apiName, const char *countName, const char *arrayName,
315 uint32_t count, const char *const *array, bool countRequired, bool arrayRequired) {
316 bool skipCall = false;
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700317
318 if ((count == 0) || (array == NULL)) {
319 // Count parameters not tagged as optional cannot be 0
Dustin Gravesbb849942016-04-05 13:48:15 -0600320 if ((count == 0) && countRequired) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700321 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600322 ParameterValidationName, "%s: parameter %s must be greater than 0", apiName, countName);
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700323 }
324
325 // Array parameters not tagged as optional cannot be NULL,
326 // unless the count is 0
Dustin Gravesbb849942016-04-05 13:48:15 -0600327 if ((array == NULL) && arrayRequired && (count != 0)) {
Jon Ashburn491a3cd2016-03-08 17:48:44 -0700328 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600329 ParameterValidationName, "%s: required parameter %s specified as NULL", apiName, arrayName);
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700330 }
331 } else {
332 // Verify that strings in the array not NULL
333 for (uint32_t i = 0; i < count; ++i) {
334 if (array[i] == NULL) {
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600335 skipCall |=
336 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
337 ParameterValidationName, "%s: required parameter %s[%d] specified as NULL", apiName, arrayName, i);
Dustin Gravesc3fbcf82016-03-08 14:42:59 -0700338 }
339 }
340 }
341
342 return skipCall;
343}
344
Dustin Graves2949a5a2016-03-08 17:48:20 -0700345/**
346 * Validate a structure's pNext member.
347 *
348 * Verify that the specified pNext value points to the head of a list of
349 * allowed extension structures. If no extension structures are allowed,
350 * verify that pNext is null.
351 *
352 * @param report_data debug_report_data object for routing validation messages.
353 * @param apiName Name of API call being validated.
354 * @param parameterName Name of parameter being validated.
355 * @param allowedStructNames Names of allowed structs.
356 * @param next Pointer to validate.
357 * @param allowedTypeCount total number of allowed structure types.
358 * @param allowedTypes array of strcuture types allowed for pNext.
359 * @return Boolean value indicating that the call should be skipped.
360 */
Dustin Gravesbb849942016-04-05 13:48:15 -0600361static bool validate_struct_pnext(debug_report_data *report_data, const char *apiName, const char *parameterName,
362 const char *allowedStructNames, const void *next, size_t allowedTypeCount,
363 const VkStructureType *allowedTypes) {
364 bool skipCall = false;
Dustin Graves2949a5a2016-03-08 17:48:20 -0700365
366 if (next != NULL) {
367 if (allowedTypeCount == 0) {
368 skipCall |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600369 ParameterValidationName, "%s: value of %s must be NULL", apiName, parameterName);
Dustin Graves2949a5a2016-03-08 17:48:20 -0700370 } else {
371 const VkStructureType *start = allowedTypes;
372 const VkStructureType *end = allowedTypes + allowedTypeCount;
373 const GenericHeader *current = reinterpret_cast<const GenericHeader *>(next);
374
375 while (current != NULL) {
376 if (std::find(start, end, current->sType) == end) {
377 std::string typeName = string_VkStructureType(current->sType);
378
379 if (typeName == UnsupportedStructureTypeString) {
380 skipCall |= log_msg(
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600381 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
382 ParameterValidationName,
Dustin Graves2949a5a2016-03-08 17:48:20 -0700383 "%s: %s chain includes a structure with unexpected VkStructureType (%d); Allowed structures are [%s]",
384 apiName, parameterName, current->sType, allowedStructNames);
385 } else {
386 skipCall |= log_msg(
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600387 report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
388 ParameterValidationName,
Dustin Graves2949a5a2016-03-08 17:48:20 -0700389 "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures are [%s]",
390 apiName, parameterName, typeName.c_str(), allowedStructNames);
391 }
392 }
393
394 current = reinterpret_cast<const GenericHeader *>(current->pNext);
395 }
396 }
397 }
398
399 return skipCall;
400}
401
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600402/**
403* Validate a VkBool32 value.
404*
405* Generate a warning if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
406*
407* @param report_data debug_report_data object for routing validation messages.
408* @param apiName Name of API call being validated.
409* @param parameterName Name of parameter being validated.
410* @param value Boolean value to validate.
411* @return Boolean value indicating that the call should be skipped.
412*/
Dustin Gravesbb849942016-04-05 13:48:15 -0600413static bool validate_bool32(debug_report_data *report_data, const char *apiName, const char *parameterName, VkBool32 value) {
414 bool skipCall = false;
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600415
416 if ((value != VK_TRUE) && (value != VK_FALSE)) {
417 skipCall |=
418 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
419 ParameterValidationName, "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE", apiName, parameterName, value);
420 }
421
422 return skipCall;
423}
424
425/**
426* Validate a Vulkan enumeration value.
427*
428* Generate a warning if an enumeration token value does not fall within the core enumeration
429* begin and end token values, and was not added to the enumeration by an extension. Extension
430* provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
431* with 1,000,000,000 as the base token value.
432*
433* @note This function does not expect to process enumerations defining bitmask flag bits.
434*
435* @param report_data debug_report_data object for routing validation messages.
436* @param apiName Name of API call being validated.
437* @param parameterName Name of parameter being validated.
438* @param enumName Name of the enumeration being validated.
439* @param begin The begin range value for the enumeration.
440* @param end The end range value for the enumeration.
441* @param value Boolean value to validate.
442* @return Boolean value indicating that the call should be skipped.
443*/
444template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600445bool validate_ranged_enum(debug_report_data *report_data, const char *apiName, const char *parameterName, const char *enumName,
446 T begin, T end, T value) {
447 bool skipCall = false;
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600448
449 if (((value < begin) || (value > end)) && !is_extension_added_token(value)) {
450 skipCall |=
451 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
452 ParameterValidationName, "%s: value of %s (%d) does not fall within the begin..end range of the core %s "
453 "enumeration tokens and is not an extension added token",
454 apiName, parameterName, value, enumName);
455 }
456
457 return skipCall;
458}
459
460/**
461* Validate an array of Vulkan enumeration value.
462*
463* Process all enumeration token values in the specified array and generate a warning if a value
464* does not fall within the core enumeration begin and end token values, and was not added to
465* the enumeration by an extension. Extension provided enumerations use the equation specified
466* in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
467*
468* @note This function does not expect to process enumerations defining bitmask flag bits.
469*
470* @param report_data debug_report_data object for routing validation messages.
471* @param apiName Name of API call being validated.
472* @param parameterName Name of parameter being validated.
473* @param enumName Name of the enumeration being validated.
474* @param begin The begin range value for the enumeration.
475* @param end The end range value for the enumeration.
476* @param value Boolean value to validate.
477* @return Boolean value indicating that the call should be skipped.
478*/
479template <typename T>
Dustin Gravesbb849942016-04-05 13:48:15 -0600480static bool validate_ranged_enum_array(debug_report_data *report_data, const char *apiName, const char *parameterName,
481 const char *enumName, T begin, T end, uint32_t count, const T *pValues) {
482 bool skipCall = false;
Dustin Gravesc3fc3d82016-03-23 19:44:00 -0600483
484 for (uint32_t i = 0; i < count; ++i) {
485 if (((pValues[i] < begin) || (pValues[i] > end)) && !is_extension_added_token(pValues[i])) {
486 skipCall |=
487 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
488 ParameterValidationName, "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
489 "enumeration tokens and is not an extension added token",
490 apiName, parameterName, i, pValues[i], enumName);
491 }
492 }
493
494 return skipCall;
495}
496
Dustin Gravese78276b2016-03-25 15:13:28 -0600497/**
498* Get VkResult code description.
499*
500* Returns a string describing the specified VkResult code. The description is based on the language in the Vulkan API specification.
501*
502* @param value VkResult code to process.
503* @return String describing the specified VkResult code.
504*/
505static std::string get_result_description(VkResult result) {
506 // clang-format off
507 switch (result) {
508 case VK_SUCCESS: return "a command completed successfully";
509 case VK_NOT_READY: return "a fence or query has not yet completed";
510 case VK_TIMEOUT: return "a wait operation has not completed in the specified time";
511 case VK_EVENT_SET: return "an event is signaled";
512 case VK_EVENT_RESET: return "an event is unsignalled";
513 case VK_INCOMPLETE: return "a return array was too small for the result";
514 case VK_ERROR_OUT_OF_HOST_MEMORY: return "a host memory allocation has failed";
515 case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "a device memory allocation has failed";
516 case VK_ERROR_INITIALIZATION_FAILED: return "the logical device has been lost";
517 case VK_ERROR_DEVICE_LOST: return "initialization of an object has failed";
518 case VK_ERROR_MEMORY_MAP_FAILED: return "mapping of a memory object has failed";
519 case VK_ERROR_LAYER_NOT_PRESENT: return "the specified layer does not exist";
520 case VK_ERROR_EXTENSION_NOT_PRESENT: return "the specified extension does not exist";
521 case VK_ERROR_FEATURE_NOT_PRESENT: return "the requested feature is not available on this device";
522 case VK_ERROR_INCOMPATIBLE_DRIVER: return "a Vulkan driver could not be found";
523 case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects of the type have already been created";
524 case VK_ERROR_FORMAT_NOT_SUPPORTED: return "the requested format is not supported on this device";
525 case VK_ERROR_SURFACE_LOST_KHR: return "a surface is no longer available";
526 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "the requested window is already connected to another "
527 "VkSurfaceKHR object, or some other non-Vulkan surface object";
528 case VK_SUBOPTIMAL_KHR: return "an image became available, and the swapchain no longer "
529 "matches the surface properties exactly, but can still be used to "
530 "present to the surface successfully.";
531 case VK_ERROR_OUT_OF_DATE_KHR: return "a surface has changed in such a way that it is no "
532 "longer compatible with the swapchain";
533 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "the display used by a swapchain does not use the same "
534 "presentable image layout, or is incompatible in a way that prevents "
535 "sharing an image";
536 case VK_ERROR_VALIDATION_FAILED_EXT: return "API validation has detected an invalid use of the API";
537 case VK_ERROR_INVALID_SHADER_NV: return "one or more shaders failed to compile or link";
Eric Engestrom81264dd2016-04-02 22:06:13 +0100538 default: return "an error has occurred";
Dustin Gravese78276b2016-03-25 15:13:28 -0600539 };
540 // clang-format on
541}
542
543/**
544* Validate return code.
545*
546* Print a message describing the reason for failure when an error code is returned.
547*
548* @param report_data debug_report_data object for routing validation messages.
549* @param apiName Name of API call being validated.
550* @param value VkResult value to validate.
551*/
552static void validate_result(debug_report_data *report_data, const char *apiName, VkResult result) {
553 if (result < 0) {
554 std::string resultName = string_VkResult(result);
555
556 if (resultName == UnsupportedResultString) {
557 // Unrecognized result code
558 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
Eric Engestrom81264dd2016-04-02 22:06:13 +0100559 ParameterValidationName, "%s: returned a result code indicating that an error has occurred", apiName);
Dustin Gravese78276b2016-03-25 15:13:28 -0600560 } else {
561 std::string resultDesc = get_result_description(result);
562 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
563 ParameterValidationName, "%s: returned %s, indicating that %s", apiName, resultName.c_str(), resultDesc.c_str());
564 }
565 }
566}
567
Mark Lobodzinski1c333572016-03-17 15:08:18 -0600568#endif // PARAMETER_VALIDATION_UTILS_H