blob: 9e9996438bc04e8125925262b8d05316ce24f647 [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 {
38 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.
Mark Lobodzinski4dc6cb02016-06-28 11:23:08 -060055 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
Dustin Gravesf233e502016-05-05 13:44:21 -060059 FAILURE_RETURN_CODE, // A Vulkan return code indicating a failure condition
60 // was encountered.
Chris Forbes9a083b92016-11-02 16:58:15 +130061 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
Mark Lobodzinskiaf00fa82016-08-09 10:44:38 -060074// Enables for display-related instance extensions
75struct instance_extension_enables {
Chris Forbesd017eff2016-11-02 17:36:42 +130076 bool surface_enabled;
Mark Lobodzinskiaf00fa82016-08-09 10:44:38 -060077 bool xlib_enabled;
78 bool xcb_enabled;
79 bool wayland_enabled;
80 bool mir_enabled;
81 bool android_enabled;
82 bool win32_enabled;
Chris Forbes2e47f432016-11-03 10:18:18 +130083 bool display_enabled;
Mark Lobodzinskiaf00fa82016-08-09 10:44:38 -060084};
85
Dustin Graves29148ff2016-03-23 19:44:00 -060086// String returned by string_VkStructureType for an unrecognized type.
Dustin Graves58c2f662016-03-08 17:48:20 -070087const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
88
Dustin Gravesca7aa7c2016-03-25 15:13:28 -060089// String returned by string_VkResult for an unrecognized type.
90const std::string UnsupportedResultString = "Unhandled VkResult";
91
Dustin Graves29148ff2016-03-23 19:44:00 -060092// The base value used when computing the offset for an enumeration token value that is added by an extension.
93// When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
94// See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
95const uint32_t ExtEnumBaseValue = 1000000000;
96
97template <typename T> bool is_extension_added_token(T value) {
98 return (std::abs(static_cast<int32_t>(value)) >= ExtEnumBaseValue);
99}
100
101// VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE token is a special case that was converted from a core token to an
102// extension added token. Its original value was intentionally preserved after the conversion, so it does not use
103// the base value that other extension added tokens use, and it does not fall within the enum's begin/end range.
104template <> bool is_extension_added_token(VkSamplerAddressMode value) {
105 bool result = (std::abs(static_cast<int32_t>(value)) >= ExtEnumBaseValue);
106 return (result || (value == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));
107}
108
Dustin Graves1e92cd72016-02-09 14:00:18 -0700109/**
Dustin Gravesf8032f22016-05-11 18:31:44 -0600110* Validate a minimum value.
111*
112* Verify that the specified value is greater than the specified lower bound.
113*
114* @param report_data debug_report_data object for routing validation messages.
115* @param api_name Name of API call being validated.
116* @param parameter_name Name of parameter being validated.
117* @param value Value to validate.
118* @param lower_bound Lower bound value to use for validation.
119* @return Boolean value indicating that the call should be skipped.
120*/
121template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600122bool ValidateGreaterThan(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name, T value,
123 T lower_bound) {
Dustin Gravesf8032f22016-05-11 18:31:44 -0600124 bool skip_call = false;
125
126 if (value <= lower_bound) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600127 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, LayerName,
128 "%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 -0600129 }
130
131 return skip_call;
132}
133
134/**
Dustin Graves1e92cd72016-02-09 14:00:18 -0700135 * Validate a required pointer.
136 *
Dustin Graves58c2f662016-03-08 17:48:20 -0700137 * Verify that a required pointer is not NULL.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700138 *
139 * @param report_data debug_report_data object for routing validation messages.
140 * @param apiName Name of API call being validated.
141 * @param parameterName Name of parameter being validated.
142 * @param value Pointer to validate.
143 * @return Boolean value indicating that the call should be skipped.
144 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600145static bool validate_required_pointer(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
Dustin Graves080069b2016-04-05 13:48:15 -0600146 const void *value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600147 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700148
149 if (value == NULL) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600150
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600151 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 -0600152 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
153 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700154 }
155
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600156 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700157}
158
159/**
160 * Validate array count and pointer to array.
161 *
Dustin Graves58d114b2016-03-08 14:42:59 -0700162 * Verify that required count and array parameters are not 0 or NULL. If the
163 * count parameter is not optional, verify that it is not 0. If the array
164 * parameter is NULL, and it is not optional, verify that count is 0.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700165 *
166 * @param report_data debug_report_data object for routing validation messages.
167 * @param apiName Name of API call being validated.
168 * @param countName Name of count parameter.
169 * @param arrayName Name of array parameter.
170 * @param count Number of elements in the array.
171 * @param array Array to validate.
172 * @param countRequired The 'count' parameter may not be 0 when true.
173 * @param arrayRequired The 'array' parameter may not be NULL when true.
174 * @return Boolean value indicating that the call should be skipped.
175 */
176template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600177bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
178 const ParameterName &arrayName, T count, const void *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600179 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700180
181 // Count parameters not tagged as optional cannot be 0
Józef Kucia20bb8fb2016-09-23 12:45:04 +0200182 if (countRequired && (count == 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600183 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 -0600184 REQUIRED_PARAMETER, LayerName, "%s: parameter %s must be greater than 0", apiName,
185 countName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700186 }
187
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600188 // Array parameters not tagged as optional cannot be NULL, unless the count is 0
Dustin Graves080069b2016-04-05 13:48:15 -0600189 if ((array == NULL) && arrayRequired && (count != 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600190 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 -0600191 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
192 arrayName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600193 }
194
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600195 return skip_call;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600196}
197
198/**
199* Validate pointer to array count and pointer to array.
200*
201* Verify that required count and array parameters are not NULL. If count
202* is not NULL and its value is not optional, verify that it is not 0. If the
203* array parameter is NULL, and it is not optional, verify that count is 0.
204* The array parameter will typically be optional for this case (where count is
205* a pointer), allowing the caller to retrieve the available count.
206*
207* @param report_data debug_report_data object for routing validation messages.
208* @param apiName Name of API call being validated.
209* @param countName Name of count parameter.
210* @param arrayName Name of array parameter.
211* @param count Pointer to the number of elements in the array.
212* @param array Array to validate.
213* @param countPtrRequired The 'count' parameter may not be NULL when true.
214* @param countValueRequired The '*count' value may not be 0 when true.
215* @param arrayRequired The 'array' parameter may not be NULL when true.
216* @return Boolean value indicating that the call should be skipped.
217*/
218template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600219bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
220 const ParameterName &arrayName, const T *count, const void *array, bool countPtrRequired,
221 bool countValueRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600222 bool skip_call = false;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600223
224 if (count == NULL) {
225 if (countPtrRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600226 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 -0600227 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
228 countName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600229 }
230 }
231 else {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600232 skip_call |= validate_array(report_data, apiName, countName, arrayName, (*count), array, countValueRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700233 }
234
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600235 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700236}
237
238/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600239 * Validate a pointer to a Vulkan structure.
240 *
241 * Verify that a required pointer to a structure is not NULL. If the pointer is
242 * not NULL, verify that each structure's sType field is set to the correct
243 * VkStructureType value.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700244 *
245 * @param report_data debug_report_data object for routing validation messages.
246 * @param apiName Name of API call being validated.
247 * @param parameterName Name of struct parameter being validated.
248 * @param sTypeName Name of expected VkStructureType value.
249 * @param value Pointer to the struct to validate.
250 * @param sType VkStructureType for structure validation.
251 * @param required The parameter may not be NULL when true.
252 * @return Boolean value indicating that the call should be skipped.
253 */
254template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600255bool validate_struct_type(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
256 const char *sTypeName, const T *value, VkStructureType sType, bool required) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600257 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700258
259 if (value == NULL) {
Dustin Graves080069b2016-04-05 13:48:15 -0600260 if (required) {
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 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
263 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700264 }
265 } else if (value->sType != sType) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600266 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
267 INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s->sType must be %s", apiName,
268 parameterName.get_name().c_str(), sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700269 }
270
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600271 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700272}
273
274/**
275 * Validate an array of Vulkan structures.
276 *
277 * Verify that required count and array parameters are not NULL. If count
278 * is not NULL and its value is not optional, verify that it is not 0.
279 * If the array contains 1 or more structures, verify that each structure's
280 * sType field is set to the correct VkStructureType value.
281 *
282 * @param report_data debug_report_data object for routing validation messages.
283 * @param apiName Name of API call being validated.
284 * @param countName Name of count parameter.
285 * @param arrayName Name of array parameter.
286 * @param sTypeName Name of expected VkStructureType value.
287 * @param count Pointer to the number of elements in the array.
288 * @param array Array to validate.
289 * @param sType VkStructureType for structure validation.
290 * @param countPtrRequired The 'count' parameter may not be NULL when true.
291 * @param countValueRequired The '*count' value may not be 0 when true.
292 * @param arrayRequired The 'array' parameter may not be NULL when true.
293 * @return Boolean value indicating that the call should be skipped.
294 */
295template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600296bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
297 const ParameterName &arrayName, const char *sTypeName, const uint32_t *count, const T *array,
298 VkStructureType sType, bool countPtrRequired, bool countValueRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600299 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700300
301 if (count == NULL) {
Dustin Graves080069b2016-04-05 13:48:15 -0600302 if (countPtrRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600303 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 -0600304 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
305 countName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700306 }
307 } else {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600308 skip_call |= validate_struct_type_array(report_data, apiName, countName, arrayName, sTypeName, (*count), array, sType,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600309 countValueRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700310 }
311
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600312 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700313}
314
315/**
316 * Validate an array of Vulkan structures
317 *
318 * Verify that required count and array parameters are not 0 or NULL. If
319 * the array contains 1 or more structures, verify that each structure's
320 * sType field is set to the correct VkStructureType value.
321 *
322 * @param report_data debug_report_data object for routing validation messages.
323 * @param apiName Name of API call being validated.
324 * @param countName Name of count parameter.
325 * @param arrayName Name of array parameter.
326 * @param sTypeName Name of expected VkStructureType value.
327 * @param count Number of elements in the array.
328 * @param array Array to validate.
329 * @param sType VkStructureType for structure validation.
330 * @param countRequired The 'count' parameter may not be 0 when true.
331 * @param arrayRequired The 'array' parameter may not be NULL when true.
332 * @return Boolean value indicating that the call should be skipped.
333 */
334template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600335bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
336 const ParameterName &arrayName, const char *sTypeName, uint32_t count, const T *array,
337 VkStructureType sType, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600338 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700339
340 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600341 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700342 } else {
343 // Verify that all structs in the array have the correct type
344 for (uint32_t i = 0; i < count; ++i) {
345 if (array[i].sType != sType) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600346 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 -0600347 __LINE__, INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s[%d].sType must be %s", apiName,
348 arrayName.get_name().c_str(), i, sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700349 }
350 }
351 }
352
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600353 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700354}
355
Dustin Graves58d114b2016-03-08 14:42:59 -0700356/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600357* Validate a Vulkan handle.
358*
359* Verify that the specified handle is not VK_NULL_HANDLE.
360*
361* @param report_data debug_report_data object for routing validation messages.
362* @param api_name Name of API call being validated.
363* @param parameter_name Name of struct parameter being validated.
364* @param value Handle to validate.
365* @return Boolean value indicating that the call should be skipped.
366*/
367template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600368bool 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 -0600369 bool skip_call = false;
370
371 if (value == VK_NULL_HANDLE) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600372 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
373 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as VK_NULL_HANDLE", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600374 parameter_name.get_name().c_str());
Dustin Graves20fd66f2016-04-18 18:33:21 -0600375 }
376
377 return skip_call;
378}
379
380/**
381* Validate an array of Vulkan handles.
382*
383* Verify that required count and array parameters are not NULL. If count
384* is not NULL and its value is not optional, verify that it is not 0.
385* If the array contains 1 or more handles, verify that no handle is set to
386* VK_NULL_HANDLE.
387*
388* @note This function is only intended to validate arrays of handles when none
389* of the handles are allowed to be VK_NULL_HANDLE. For arrays of handles
390* that are allowed to contain VK_NULL_HANDLE, use validate_array() instead.
391*
392* @param report_data debug_report_data object for routing validation messages.
393* @param api_name Name of API call being validated.
394* @param count_name Name of count parameter.
395* @param array_name Name of array parameter.
396* @param count Number of elements in the array.
397* @param array Array to validate.
398* @param count_required The 'count' parameter may not be 0 when true.
399* @param array_required The 'array' parameter may not be NULL when true.
400* @return Boolean value indicating that the call should be skipped.
401*/
402template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600403bool validate_handle_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
404 const ParameterName &array_name, uint32_t count, const T *array, bool count_required,
405 bool array_required) {
Dustin Graves20fd66f2016-04-18 18:33:21 -0600406 bool skip_call = false;
407
408 if ((count == 0) || (array == NULL)) {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600409 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 -0600410 } else {
411 // Verify that no handles in the array are VK_NULL_HANDLE
412 for (uint32_t i = 0; i < count; ++i) {
413 if (array[i] == VK_NULL_HANDLE) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600414 skip_call |=
415 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
416 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as VK_NULL_HANDLE", api_name,
417 array_name.get_name().c_str(), i);
Dustin Graves20fd66f2016-04-18 18:33:21 -0600418 }
419 }
420 }
421
422 return skip_call;
423}
424
425/**
Dustin Graves58d114b2016-03-08 14:42:59 -0700426 * Validate string array count and content.
427 *
428 * Verify that required count and array parameters are not 0 or NULL. If the
429 * count parameter is not optional, verify that it is not 0. If the array
430 * parameter is NULL, and it is not optional, verify that count is 0. If the
431 * array parameter is not NULL, verify that none of the strings are NULL.
432 *
433 * @param report_data debug_report_data object for routing validation messages.
434 * @param apiName Name of API call being validated.
435 * @param countName Name of count parameter.
436 * @param arrayName Name of array parameter.
437 * @param count Number of strings in the array.
438 * @param array Array of strings to validate.
439 * @param countRequired The 'count' parameter may not be 0 when true.
440 * @param arrayRequired The 'array' parameter may not be NULL when true.
441 * @return Boolean value indicating that the call should be skipped.
442 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600443static bool validate_string_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
444 const ParameterName &arrayName, uint32_t count, const char *const *array, bool countRequired,
445 bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600446 bool skip_call = false;
Dustin Graves58d114b2016-03-08 14:42:59 -0700447
448 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600449 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves58d114b2016-03-08 14:42:59 -0700450 } else {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600451 // Verify that strings in the array are not NULL
Dustin Graves58d114b2016-03-08 14:42:59 -0700452 for (uint32_t i = 0; i < count; ++i) {
453 if (array[i] == NULL) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600454 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 -0600455 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as NULL",
456 apiName, arrayName.get_name().c_str(), i);
Dustin Graves58d114b2016-03-08 14:42:59 -0700457 }
458 }
459 }
460
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600461 return skip_call;
Dustin Graves58d114b2016-03-08 14:42:59 -0700462}
463
Dustin Graves58c2f662016-03-08 17:48:20 -0700464/**
465 * Validate a structure's pNext member.
466 *
467 * Verify that the specified pNext value points to the head of a list of
468 * allowed extension structures. If no extension structures are allowed,
469 * verify that pNext is null.
470 *
471 * @param report_data debug_report_data object for routing validation messages.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600472 * @param api_name Name of API call being validated.
473 * @param parameter_name Name of parameter being validated.
474 * @param allowed_struct_names Names of allowed structs.
Dustin Graves58c2f662016-03-08 17:48:20 -0700475 * @param next Pointer to validate.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600476 * @param allowed_type_count Total number of allowed structure types.
477 * @param allowed_types Array of strcuture types allowed for pNext.
478 * @param header_version Version of header defining the pNext validation rules.
Dustin Graves58c2f662016-03-08 17:48:20 -0700479 * @return Boolean value indicating that the call should be skipped.
480 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600481static bool validate_struct_pnext(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600482 const char *allowed_struct_names, const void *next, size_t allowed_type_count,
483 const VkStructureType *allowed_types, uint32_t header_version) {
484 bool skip_call = false;
485 const char disclaimer[] = "This warning is based on the Valid Usage documentation for version %d of the Vulkan header. It "
486 "is possible that you are using a struct from a private extension or an extension that was added "
487 "to a later version of the Vulkan header, in which case your use of %s is perfectly valid but "
488 "is not guaranteed to work correctly with validation enabled";
Dustin Graves58c2f662016-03-08 17:48:20 -0700489
490 if (next != NULL) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600491 if (allowed_type_count == 0) {
492 std::string message = "%s: value of %s must be NULL. ";
493 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600494 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
495 INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name, parameter_name.get_name().c_str(),
496 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700497 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600498 const VkStructureType *start = allowed_types;
499 const VkStructureType *end = allowed_types + allowed_type_count;
Dustin Graves58c2f662016-03-08 17:48:20 -0700500 const GenericHeader *current = reinterpret_cast<const GenericHeader *>(next);
501
502 while (current != NULL) {
503 if (std::find(start, end, current->sType) == end) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600504 std::string type_name = string_VkStructureType(current->sType);
Dustin Graves58c2f662016-03-08 17:48:20 -0700505
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600506 if (type_name == UnsupportedStructureTypeString) {
507 std::string message = "%s: %s chain includes a structure with unexpected VkStructureType (%d); Allowed "
508 "structures are [%s]. ";
509 message += disclaimer;
510 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
511 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600512 parameter_name.get_name().c_str(), current->sType, allowed_struct_names,
513 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700514 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600515 std::string message =
516 "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures are [%s]. ";
517 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600518 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
519 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
520 parameter_name.get_name().c_str(), type_name.c_str(), allowed_struct_names,
521 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700522 }
523 }
524
525 current = reinterpret_cast<const GenericHeader *>(current->pNext);
526 }
527 }
528 }
529
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600530 return skip_call;
Dustin Graves58c2f662016-03-08 17:48:20 -0700531}
532
Dustin Graves29148ff2016-03-23 19:44:00 -0600533/**
534* Validate a VkBool32 value.
535*
536* Generate a warning if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
537*
538* @param report_data debug_report_data object for routing validation messages.
539* @param apiName Name of API call being validated.
540* @param parameterName Name of parameter being validated.
541* @param value Boolean value to validate.
542* @return Boolean value indicating that the call should be skipped.
543*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600544static bool validate_bool32(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
545 VkBool32 value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600546 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600547
548 if ((value != VK_TRUE) && (value != VK_FALSE)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600549 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 -0600550 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE", apiName,
551 parameterName.get_name().c_str(), value);
Dustin Graves29148ff2016-03-23 19:44:00 -0600552 }
553
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600554 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600555}
556
557/**
558* Validate a Vulkan enumeration value.
559*
560* Generate a warning if an enumeration token value does not fall within the core enumeration
561* begin and end token values, and was not added to the enumeration by an extension. Extension
562* provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
563* with 1,000,000,000 as the base token value.
564*
565* @note This function does not expect to process enumerations defining bitmask flag bits.
566*
567* @param report_data debug_report_data object for routing validation messages.
568* @param apiName Name of API call being validated.
569* @param parameterName Name of parameter being validated.
570* @param enumName Name of the enumeration being validated.
571* @param begin The begin range value for the enumeration.
572* @param end The end range value for the enumeration.
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600573* @param value Enumeration value to validate.
Dustin Graves29148ff2016-03-23 19:44:00 -0600574* @return Boolean value indicating that the call should be skipped.
575*/
576template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600577bool validate_ranged_enum(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
578 const char *enumName, T begin, T end, T value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600579 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600580
581 if (((value < begin) || (value > end)) && !is_extension_added_token(value)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600582 skip_call |=
Dustin Gravesf233e502016-05-05 13:44:21 -0600583 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
584 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s (%d) does not fall within the begin..end range of the core %s "
585 "enumeration tokens and is not an extension added token",
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600586 apiName, parameterName.get_name().c_str(), value, enumName);
Dustin Graves29148ff2016-03-23 19:44:00 -0600587 }
588
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600589 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600590}
591
592/**
593* Validate an array of Vulkan enumeration value.
594*
595* Process all enumeration token values in the specified array and generate a warning if a value
596* does not fall within the core enumeration begin and end token values, and was not added to
597* the enumeration by an extension. Extension provided enumerations use the equation specified
598* in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
599*
600* @note This function does not expect to process enumerations defining bitmask flag bits.
601*
602* @param report_data debug_report_data object for routing validation messages.
603* @param apiName Name of API call being validated.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600604* @param countName Name of count parameter.
605* @param arrayName Name of array parameter.
Dustin Graves29148ff2016-03-23 19:44:00 -0600606* @param enumName Name of the enumeration being validated.
607* @param begin The begin range value for the enumeration.
608* @param end The end range value for the enumeration.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600609* @param count Number of enumeration values in the array.
610* @param array Array of enumeration values to validate.
611* @param countRequired The 'count' parameter may not be 0 when true.
612* @param arrayRequired The 'array' parameter may not be NULL when true.
Dustin Graves29148ff2016-03-23 19:44:00 -0600613* @return Boolean value indicating that the call should be skipped.
614*/
615template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600616static bool validate_ranged_enum_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
617 const ParameterName &arrayName, const char *enumName, T begin, T end, uint32_t count,
618 const T *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600619 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600620
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600621 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600622 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600623 } else {
624 for (uint32_t i = 0; i < count; ++i) {
625 if (((array[i] < begin) || (array[i] > end)) && !is_extension_added_token(array[i])) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600626 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 -0600627 __LINE__, UNRECOGNIZED_VALUE, LayerName,
628 "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
629 "enumeration tokens and is not an extension added token",
630 apiName, arrayName.get_name().c_str(), i, array[i], enumName);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600631 }
Dustin Graves29148ff2016-03-23 19:44:00 -0600632 }
633 }
634
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600635 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600636}
637
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600638/**
Dustin Graves78df8512016-04-28 17:58:59 -0600639* Verify that a reserved VkFlags value is zero.
640*
641* Verify that the specified value is zero, to check VkFlags values that are reserved for
642* future use.
643*
644* @param report_data debug_report_data object for routing validation messages.
645* @param api_name Name of API call being validated.
646* @param parameter_name Name of parameter being validated.
647* @param value Value to validate.
648* @return Boolean value indicating that the call should be skipped.
649*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600650static bool validate_reserved_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600651 VkFlags value) {
652 bool skip_call = false;
653
654 if (value != 0) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600655 skip_call |=
656 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
657 RESERVED_PARAMETER, LayerName, "%s: parameter %s must be 0", api_name, parameter_name.get_name().c_str());
Dustin Graves78df8512016-04-28 17:58:59 -0600658 }
659
660 return skip_call;
661}
662
663/**
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600664* Validate a Vulkan bitmask value.
665*
666* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
667* for that type.
668*
669* @param report_data debug_report_data object for routing validation messages.
670* @param api_name Name of API call being validated.
671* @param parameter_name Name of parameter being validated.
672* @param flag_bits_name Name of the VkFlags type being validated.
673* @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated.
674* @param value VkFlags value to validate.
675* @param flags_required The 'value' parameter may not be 0 when true.
676* @return Boolean value indicating that the call should be skipped.
677*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600678static bool validate_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600679 const char *flag_bits_name, VkFlags all_flags, VkFlags value, bool flags_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600680 bool skip_call = false;
681
682 if (value == 0) {
683 if (flags_required) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600684 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 -0600685 REQUIRED_PARAMETER, LayerName, "%s: value of %s must not be 0", api_name,
686 parameter_name.get_name().c_str());
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600687 }
688 } else if ((value & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600689 skip_call |=
690 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
691 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s contains flag bits that are not recognized members of %s",
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600692 api_name, parameter_name.get_name().c_str(), flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600693 }
694
695 return skip_call;
696}
697
698/**
699* Validate an array of Vulkan bitmask values.
700*
701* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
702* for that type.
703*
704* @param report_data debug_report_data object for routing validation messages.
705* @param api_name Name of API call being validated.
706* @param count_name Name of parameter being validated.
707* @param array_name Name of parameter being validated.
708* @param flag_bits_name Name of the VkFlags type being validated.
709* @param all_flags A bitmask combining all valid flag bits for the VkFlags type being validated.
710* @param count Number of VkFlags values in the array.
711* @param array Array of VkFlags value to validate.
712* @param count_required The 'count' parameter may not be 0 when true.
713* @param array_required The 'array' parameter may not be NULL when true.
714* @return Boolean value indicating that the call should be skipped.
715*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600716static bool validate_flags_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
717 const ParameterName &array_name, const char *flag_bits_name, VkFlags all_flags, uint32_t count,
Dustin Graves78df8512016-04-28 17:58:59 -0600718 const VkFlags *array, bool count_required, bool array_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600719 bool skip_call = false;
720
721 if ((count == 0) || (array == NULL)) {
722 skip_call |= validate_array(report_data, api_name, count_name, array_name, count, array, count_required, array_required);
723 } else {
724 // Verify that all VkFlags values in the array
725 for (uint32_t i = 0; i < count; ++i) {
Dustin Graves78df8512016-04-28 17:58:59 -0600726 if (array[i] == 0) {
727 // Current XML registry logic for validity generation uses the array parameter's optional tag to determine if
728 // elements in the array are allowed be 0
729 if (array_required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600730 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
731 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: value of %s[%d] must not be 0", api_name,
732 array_name.get_name().c_str(), i);
Dustin Graves78df8512016-04-28 17:58:59 -0600733 }
734 } else if ((array[i] & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600735 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
736 __LINE__, UNRECOGNIZED_VALUE, LayerName,
737 "%s: value of %s[%d] contains flag bits that are not recognized members of %s", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600738 array_name.get_name().c_str(), i, flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600739 }
740 }
741 }
742
743 return skip_call;
744}
745
746/**
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600747* Get VkResult code description.
748*
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600749* Returns a string describing the specified VkResult code. The description is based on the language in the Vulkan API
750* specification.
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600751*
752* @param value VkResult code to process.
753* @return String describing the specified VkResult code.
754*/
755static std::string get_result_description(VkResult result) {
756 // clang-format off
757 switch (result) {
758 case VK_SUCCESS: return "a command completed successfully";
759 case VK_NOT_READY: return "a fence or query has not yet completed";
760 case VK_TIMEOUT: return "a wait operation has not completed in the specified time";
761 case VK_EVENT_SET: return "an event is signaled";
762 case VK_EVENT_RESET: return "an event is unsignalled";
763 case VK_INCOMPLETE: return "a return array was too small for the result";
764 case VK_ERROR_OUT_OF_HOST_MEMORY: return "a host memory allocation has failed";
765 case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "a device memory allocation has failed";
Dustin Graves2adca842016-05-16 18:35:55 -0600766 case VK_ERROR_INITIALIZATION_FAILED: return "initialization of an object has failed";
767 case VK_ERROR_DEVICE_LOST: return "the logical device has been lost";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600768 case VK_ERROR_MEMORY_MAP_FAILED: return "mapping of a memory object has failed";
769 case VK_ERROR_LAYER_NOT_PRESENT: return "the specified layer does not exist";
770 case VK_ERROR_EXTENSION_NOT_PRESENT: return "the specified extension does not exist";
771 case VK_ERROR_FEATURE_NOT_PRESENT: return "the requested feature is not available on this device";
772 case VK_ERROR_INCOMPATIBLE_DRIVER: return "a Vulkan driver could not be found";
773 case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects of the type have already been created";
774 case VK_ERROR_FORMAT_NOT_SUPPORTED: return "the requested format is not supported on this device";
775 case VK_ERROR_SURFACE_LOST_KHR: return "a surface is no longer available";
776 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "the requested window is already connected to another "
777 "VkSurfaceKHR object, or some other non-Vulkan surface object";
778 case VK_SUBOPTIMAL_KHR: return "an image became available, and the swapchain no longer "
779 "matches the surface properties exactly, but can still be used to "
780 "present to the surface successfully.";
781 case VK_ERROR_OUT_OF_DATE_KHR: return "a surface has changed in such a way that it is no "
782 "longer compatible with the swapchain";
783 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "the display used by a swapchain does not use the same "
784 "presentable image layout, or is incompatible in a way that prevents "
785 "sharing an image";
786 case VK_ERROR_VALIDATION_FAILED_EXT: return "API validation has detected an invalid use of the API";
787 case VK_ERROR_INVALID_SHADER_NV: return "one or more shaders failed to compile or link";
Eric Engestrombcbb0fd2016-04-02 22:06:13 +0100788 default: return "an error has occurred";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600789 };
790 // clang-format on
791}
792
793/**
794* Validate return code.
795*
796* Print a message describing the reason for failure when an error code is returned.
797*
798* @param report_data debug_report_data object for routing validation messages.
799* @param apiName Name of API call being validated.
800* @param value VkResult value to validate.
801*/
802static void validate_result(debug_report_data *report_data, const char *apiName, VkResult result) {
Chris Forbesf1f4e382016-10-13 14:44:03 +1300803 if (result < 0 && result != VK_ERROR_VALIDATION_FAILED_EXT) {
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600804 std::string resultName = string_VkResult(result);
805
806 if (resultName == UnsupportedResultString) {
807 // Unrecognized result code
Dustin Gravesf233e502016-05-05 13:44:21 -0600808 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
809 FAILURE_RETURN_CODE, LayerName, "%s: returned a result code indicating that an error has occurred", apiName);
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600810 } else {
811 std::string resultDesc = get_result_description(result);
Dustin Gravesf233e502016-05-05 13:44:21 -0600812 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
813 FAILURE_RETURN_CODE, LayerName, "%s: returned %s, indicating that %s", apiName, resultName.c_str(),
814 resultDesc.c_str());
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600815 }
816 }
817}
818
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600819} // namespace parameter_validation
820
Mark Lobodzinski739391a2016-03-17 15:08:18 -0600821#endif // PARAMETER_VALIDATION_UTILS_H