blob: e85531d6773c7c62e5aec8374575ffba24b0a3f4 [file] [log] [blame]
Dustin Graves1e92cd72016-02-09 14:00:18 -07001/* Copyright (c) 2015-2016 The Khronos Group Inc.
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 * Copyright (C) 2015-2016 Google Inc.
5 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06006 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
Dustin Graves1e92cd72016-02-09 14:00:18 -07009 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060010 * http://www.apache.org/licenses/LICENSE-2.0
Dustin Graves1e92cd72016-02-09 14:00:18 -070011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
Dustin Graves1e92cd72016-02-09 14:00:18 -070017 *
18 * Author: Dustin Graves <dustin@lunarg.com>
19 */
20
Mark Lobodzinski739391a2016-03-17 15:08:18 -060021#ifndef PARAMETER_VALIDATION_UTILS_H
22#define PARAMETER_VALIDATION_UTILS_H
Dustin Graves1e92cd72016-02-09 14:00:18 -070023
Dustin Graves58c2f662016-03-08 17:48:20 -070024#include <algorithm>
Dustin Graves29148ff2016-03-23 19:44:00 -060025#include <cstdlib>
Dustin Graves58c2f662016-03-08 17:48:20 -070026#include <string>
27
Dustin Graves1e92cd72016-02-09 14:00:18 -070028#include "vulkan/vulkan.h"
Dustin Graves58c2f662016-03-08 17:48:20 -070029#include "vk_enum_string_helper.h"
Dustin Graves1e92cd72016-02-09 14:00:18 -070030#include "vk_layer_logging.h"
Karl Schultza9ef1e52016-10-06 17:53:48 -060031#include "vk_validation_error_messages.h"
Dustin Graves1e92cd72016-02-09 14:00:18 -070032
Dustin Graves8ffbbf62016-07-22 13:19:46 -060033#include "parameter_name.h"
34
Dustin Gravesb83fc2d2016-05-04 12:56:08 -060035namespace parameter_validation {
36
Dustin Gravesf233e502016-05-05 13:44:21 -060037enum ErrorCode {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -070038 NONE, // Used for INFO & other non-error messages
39 INVALID_USAGE, // The value of a parameter is not consistent
40 // with the valid usage criteria defined in
41 // the Vulkan specification.
42 INVALID_STRUCT_STYPE, // The sType field of a Vulkan structure does
43 // not contain the value expected for a structure
44 // of that type.
45 INVALID_STRUCT_PNEXT, // The pNext field of a Vulkan structure references
46 // a value that is not compatible with a structure of
47 // that type or is not NULL when a structure of that
48 // type has no compatible pNext values.
49 REQUIRED_PARAMETER, // A required parameter was specified as 0 or NULL.
50 RESERVED_PARAMETER, // A parameter reserved for future use was not
51 // specified as 0 or NULL.
52 UNRECOGNIZED_VALUE, // A Vulkan enumeration, VkFlags, or VkBool32 parameter
53 // contains a value that is not recognized as valid for
54 // that type.
55 DEVICE_LIMIT, // A specified parameter exceeds the limits returned
56 // by the physical device
57 DEVICE_FEATURE, // Use of a requested feature is not supported by
58 // the device
59 FAILURE_RETURN_CODE, // A Vulkan return code indicating a failure condition
60 // was encountered.
61 EXTENSION_NOT_ENABLED, // An extension entrypoint was called, but the required
62 // extension was not enabled at CreateInstance or
63 // CreateDevice time.
Dustin Gravesf233e502016-05-05 13:44:21 -060064};
65
Dustin Graves58c2f662016-03-08 17:48:20 -070066struct GenericHeader {
67 VkStructureType sType;
68 const void *pNext;
69};
Dustin Graves58c2f662016-03-08 17:48:20 -070070
Dustin Graves29148ff2016-03-23 19:44:00 -060071// Layer name string to be logged with validation messages.
Dustin Gravesb83fc2d2016-05-04 12:56:08 -060072const char LayerName[] = "ParameterValidation";
Dustin Graves29148ff2016-03-23 19:44:00 -060073
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 Young39389872017-01-19 21:10:49 -070084 bool khr_get_phys_dev_properties2_enabled;
Mark Young0f183a82017-02-28 09:58:04 -070085 bool khx_device_group_creation_enabled;
86 bool khx_external_fence_capabilities_enabled;
87 bool khx_external_memory_capabilities_enabled;
88 bool khx_external_semaphore_capabilities_enabled;
Mark Young39389872017-01-19 21:10:49 -070089 bool ext_acquire_xlib_display_enabled;
90 bool ext_direct_mode_display_enabled;
91 bool ext_display_surface_counter_enabled;
92 bool nv_external_memory_capabilities_enabled;
Mark Lobodzinskiaf00fa82016-08-09 10:44:38 -060093};
94
Dustin Graves29148ff2016-03-23 19:44:00 -060095// String returned by string_VkStructureType for an unrecognized type.
Dustin Graves58c2f662016-03-08 17:48:20 -070096const std::string UnsupportedStructureTypeString = "Unhandled VkStructureType";
97
Dustin Gravesca7aa7c2016-03-25 15:13:28 -060098// String returned by string_VkResult for an unrecognized type.
99const std::string UnsupportedResultString = "Unhandled VkResult";
100
Dustin Graves29148ff2016-03-23 19:44:00 -0600101// The base value used when computing the offset for an enumeration token value that is added by an extension.
102// When validating enumeration tokens, any value >= to this value is considered to be provided by an extension.
103// See Appendix C.10 "Assigning Extension Token Values" from the Vulkan specification
104const uint32_t ExtEnumBaseValue = 1000000000;
105
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700106template <typename T>
107bool is_extension_added_token(T value) {
Jamie Madill6069c822016-12-15 09:35:36 -0500108 return (static_cast<uint32_t>(std::abs(static_cast<int32_t>(value))) >= ExtEnumBaseValue);
Dustin Graves29148ff2016-03-23 19:44:00 -0600109}
110
111// VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE token is a special case that was converted from a core token to an
112// extension added token. Its original value was intentionally preserved after the conversion, so it does not use
113// the base value that other extension added tokens use, and it does not fall within the enum's begin/end range.
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700114template <>
115bool is_extension_added_token(VkSamplerAddressMode value) {
Jamie Madill6069c822016-12-15 09:35:36 -0500116 bool result = (static_cast<uint32_t>(std::abs(static_cast<int32_t>(value))) >= ExtEnumBaseValue);
Dustin Graves29148ff2016-03-23 19:44:00 -0600117 return (result || (value == VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE));
118}
119
Dustin Graves1e92cd72016-02-09 14:00:18 -0700120/**
Dustin Gravesf8032f22016-05-11 18:31:44 -0600121* Validate a minimum value.
122*
123* Verify that the specified value is greater than the specified lower bound.
124*
125* @param report_data debug_report_data object for routing validation messages.
126* @param api_name Name of API call being validated.
127* @param parameter_name Name of parameter being validated.
128* @param value Value to validate.
129* @param lower_bound Lower bound value to use for validation.
130* @return Boolean value indicating that the call should be skipped.
131*/
132template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600133bool ValidateGreaterThan(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name, T value,
134 T lower_bound) {
Dustin Gravesf8032f22016-05-11 18:31:44 -0600135 bool skip_call = false;
136
137 if (value <= lower_bound) {
Mark Lobodzinskieb9e73f2017-04-13 10:06:48 -0600138 skip_call |=
139 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__, 1, LayerName,
140 "%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 -0600141 }
142
143 return skip_call;
144}
145
146/**
Dustin Graves1e92cd72016-02-09 14:00:18 -0700147 * Validate a required pointer.
148 *
Dustin Graves58c2f662016-03-08 17:48:20 -0700149 * Verify that a required pointer is not NULL.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700150 *
151 * @param report_data debug_report_data object for routing validation messages.
152 * @param apiName Name of API call being validated.
153 * @param parameterName Name of parameter being validated.
154 * @param value Pointer to validate.
155 * @return Boolean value indicating that the call should be skipped.
156 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600157static bool validate_required_pointer(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
Dustin Graves080069b2016-04-05 13:48:15 -0600158 const void *value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600159 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700160
161 if (value == NULL) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600162 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 -0600163 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
164 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700165 }
166
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600167 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700168}
169
170/**
171 * Validate array count and pointer to array.
172 *
Dustin Graves58d114b2016-03-08 14:42:59 -0700173 * Verify that required count and array parameters are not 0 or NULL. If the
174 * count parameter is not optional, verify that it is not 0. If the array
175 * parameter is NULL, and it is not optional, verify that count is 0.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700176 *
177 * @param report_data debug_report_data object for routing validation messages.
178 * @param apiName Name of API call being validated.
179 * @param countName Name of count parameter.
180 * @param arrayName Name of array parameter.
181 * @param count Number of elements in the array.
182 * @param array Array to validate.
183 * @param countRequired The 'count' parameter may not be 0 when true.
184 * @param arrayRequired The 'array' parameter may not be NULL when true.
185 * @return Boolean value indicating that the call should be skipped.
186 */
187template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600188bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
189 const ParameterName &arrayName, T count, const void *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600190 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700191
192 // Count parameters not tagged as optional cannot be 0
Józef Kucia20bb8fb2016-09-23 12:45:04 +0200193 if (countRequired && (count == 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600194 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700195 REQUIRED_PARAMETER, LayerName, "%s: parameter %s must be greater than 0", apiName,
196 countName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700197 }
198
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600199 // Array parameters not tagged as optional cannot be NULL, unless the count is 0
Dustin Graves080069b2016-04-05 13:48:15 -0600200 if ((array == NULL) && arrayRequired && (count != 0)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600201 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700202 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
203 arrayName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600204 }
205
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600206 return skip_call;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600207}
208
209/**
210* Validate pointer to array count and pointer to array.
211*
212* Verify that required count and array parameters are not NULL. If count
213* is not NULL and its value is not optional, verify that it is not 0. If the
214* array parameter is NULL, and it is not optional, verify that count is 0.
215* The array parameter will typically be optional for this case (where count is
216* a pointer), allowing the caller to retrieve the available count.
217*
218* @param report_data debug_report_data object for routing validation messages.
219* @param apiName Name of API call being validated.
220* @param countName Name of count parameter.
221* @param arrayName Name of array parameter.
222* @param count Pointer to the number of elements in the array.
223* @param array Array to validate.
224* @param countPtrRequired The 'count' parameter may not be NULL when true.
225* @param countValueRequired The '*count' value may not be 0 when true.
226* @param arrayRequired The 'array' parameter may not be NULL when true.
227* @return Boolean value indicating that the call should be skipped.
228*/
229template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600230bool validate_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
231 const ParameterName &arrayName, const T *count, const void *array, bool countPtrRequired,
232 bool countValueRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600233 bool skip_call = false;
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600234
235 if (count == NULL) {
236 if (countPtrRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600237 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 -0600238 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
239 countName.get_name().c_str());
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600240 }
Mark Lobodzinski729a8d32017-01-26 12:16:30 -0700241 } else {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600242 skip_call |= validate_array(report_data, apiName, countName, arrayName, (*count), array, countValueRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700243 }
244
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600245 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700246}
247
248/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600249 * Validate a pointer to a Vulkan structure.
250 *
251 * Verify that a required pointer to a structure is not NULL. If the pointer is
252 * not NULL, verify that each structure's sType field is set to the correct
253 * VkStructureType value.
Dustin Graves1e92cd72016-02-09 14:00:18 -0700254 *
255 * @param report_data debug_report_data object for routing validation messages.
256 * @param apiName Name of API call being validated.
257 * @param parameterName Name of struct parameter being validated.
258 * @param sTypeName Name of expected VkStructureType value.
259 * @param value Pointer to the struct to validate.
260 * @param sType VkStructureType for structure validation.
261 * @param required The parameter may not be NULL when true.
262 * @return Boolean value indicating that the call should be skipped.
263 */
264template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600265bool validate_struct_type(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
266 const char *sTypeName, const T *value, VkStructureType sType, bool required) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600267 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700268
269 if (value == NULL) {
Dustin Graves080069b2016-04-05 13:48:15 -0600270 if (required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600271 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
272 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
273 parameterName.get_name().c_str());
Dustin Graves1e92cd72016-02-09 14:00:18 -0700274 }
275 } else if (value->sType != sType) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600276 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
277 INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s->sType must be %s", apiName,
278 parameterName.get_name().c_str(), sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700279 }
280
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600281 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700282}
283
284/**
Dustin Graves1e92cd72016-02-09 14:00:18 -0700285 * Validate an array of Vulkan structures
286 *
287 * Verify that required count and array parameters are not 0 or NULL. If
288 * the array contains 1 or more structures, verify that each structure's
289 * sType field is set to the correct VkStructureType value.
290 *
291 * @param report_data debug_report_data object for routing validation messages.
292 * @param apiName Name of API call being validated.
293 * @param countName Name of count parameter.
294 * @param arrayName Name of array parameter.
295 * @param sTypeName Name of expected VkStructureType value.
296 * @param count Number of elements in the array.
297 * @param array Array to validate.
298 * @param sType VkStructureType for structure validation.
299 * @param countRequired The 'count' parameter may not be 0 when true.
300 * @param arrayRequired The 'array' parameter may not be NULL when true.
301 * @return Boolean value indicating that the call should be skipped.
302 */
303template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600304bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
305 const ParameterName &arrayName, const char *sTypeName, uint32_t count, const T *array,
306 VkStructureType sType, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600307 bool skip_call = false;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700308
309 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600310 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700311 } else {
312 // Verify that all structs in the array have the correct type
313 for (uint32_t i = 0; i < count; ++i) {
314 if (array[i].sType != sType) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600315 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 -0600316 __LINE__, INVALID_STRUCT_STYPE, LayerName, "%s: parameter %s[%d].sType must be %s", apiName,
317 arrayName.get_name().c_str(), i, sTypeName);
Dustin Graves1e92cd72016-02-09 14:00:18 -0700318 }
319 }
320 }
321
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600322 return skip_call;
Dustin Graves1e92cd72016-02-09 14:00:18 -0700323}
324
Dustin Graves58d114b2016-03-08 14:42:59 -0700325/**
Mark Young39389872017-01-19 21:10:49 -0700326 * Validate an array of Vulkan structures.
327 *
328 * Verify that required count and array parameters are not NULL. If count
329 * is not NULL and its value is not optional, verify that it is not 0.
330 * If the array contains 1 or more structures, verify that each structure's
331 * sType field is set to the correct VkStructureType value.
332 *
333 * @param report_data debug_report_data object for routing validation messages.
334 * @param apiName Name of API call being validated.
335 * @param countName Name of count parameter.
336 * @param arrayName Name of array parameter.
337 * @param sTypeName Name of expected VkStructureType value.
338 * @param count Pointer to the number of elements in the array.
339 * @param array Array to validate.
340 * @param sType VkStructureType for structure validation.
341 * @param countPtrRequired The 'count' parameter may not be NULL when true.
342 * @param countValueRequired The '*count' value may not be 0 when true.
343 * @param arrayRequired The 'array' parameter may not be NULL when true.
344 * @return Boolean value indicating that the call should be skipped.
345 */
346template <typename T>
347bool validate_struct_type_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
348 const ParameterName &arrayName, const char *sTypeName, uint32_t *count, const T *array,
349 VkStructureType sType, bool countPtrRequired, bool countValueRequired, bool arrayRequired) {
350 bool skip_call = false;
351
352 if (count == NULL) {
353 if (countPtrRequired) {
354 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
355 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as NULL", apiName,
356 countName.get_name().c_str());
357 }
358 } else {
359 skip_call |= validate_struct_type_array(report_data, apiName, countName, arrayName, sTypeName, (*count), array, sType,
360 countValueRequired, arrayRequired);
361 }
362
363 return skip_call;
364}
365
366/**
Dustin Graves20fd66f2016-04-18 18:33:21 -0600367* Validate a Vulkan handle.
368*
369* Verify that the specified handle is not VK_NULL_HANDLE.
370*
371* @param report_data debug_report_data object for routing validation messages.
372* @param api_name Name of API call being validated.
373* @param parameter_name Name of struct parameter being validated.
374* @param value Handle to validate.
375* @return Boolean value indicating that the call should be skipped.
376*/
377template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600378bool 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 -0600379 bool skip_call = false;
380
381 if (value == VK_NULL_HANDLE) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600382 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
383 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s specified as VK_NULL_HANDLE", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600384 parameter_name.get_name().c_str());
Dustin Graves20fd66f2016-04-18 18:33:21 -0600385 }
386
387 return skip_call;
388}
389
390/**
391* Validate an array of Vulkan handles.
392*
393* Verify that required count and array parameters are not NULL. If count
394* is not NULL and its value is not optional, verify that it is not 0.
395* If the array contains 1 or more handles, verify that no handle is set to
396* VK_NULL_HANDLE.
397*
398* @note This function is only intended to validate arrays of handles when none
399* of the handles are allowed to be VK_NULL_HANDLE. For arrays of handles
400* that are allowed to contain VK_NULL_HANDLE, use validate_array() instead.
401*
402* @param report_data debug_report_data object for routing validation messages.
403* @param api_name Name of API call being validated.
404* @param count_name Name of count parameter.
405* @param array_name Name of array parameter.
406* @param count Number of elements in the array.
407* @param array Array to validate.
408* @param count_required The 'count' parameter may not be 0 when true.
409* @param array_required The 'array' parameter may not be NULL when true.
410* @return Boolean value indicating that the call should be skipped.
411*/
412template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600413bool validate_handle_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
414 const ParameterName &array_name, uint32_t count, const T *array, bool count_required,
415 bool array_required) {
Dustin Graves20fd66f2016-04-18 18:33:21 -0600416 bool skip_call = false;
417
418 if ((count == 0) || (array == NULL)) {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600419 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 -0600420 } else {
421 // Verify that no handles in the array are VK_NULL_HANDLE
422 for (uint32_t i = 0; i < count; ++i) {
423 if (array[i] == VK_NULL_HANDLE) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600424 skip_call |=
425 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
426 REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as VK_NULL_HANDLE", api_name,
427 array_name.get_name().c_str(), i);
Dustin Graves20fd66f2016-04-18 18:33:21 -0600428 }
429 }
430 }
431
432 return skip_call;
433}
434
435/**
Dustin Graves58d114b2016-03-08 14:42:59 -0700436 * Validate string array count and content.
437 *
438 * Verify that required count and array parameters are not 0 or NULL. If the
439 * count parameter is not optional, verify that it is not 0. If the array
440 * parameter is NULL, and it is not optional, verify that count is 0. If the
441 * array parameter is not NULL, verify that none of the strings are NULL.
442 *
443 * @param report_data debug_report_data object for routing validation messages.
444 * @param apiName Name of API call being validated.
445 * @param countName Name of count parameter.
446 * @param arrayName Name of array parameter.
447 * @param count Number of strings in the array.
448 * @param array Array of strings to validate.
449 * @param countRequired The 'count' parameter may not be 0 when true.
450 * @param arrayRequired The 'array' parameter may not be NULL when true.
451 * @return Boolean value indicating that the call should be skipped.
452 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600453static bool validate_string_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
454 const ParameterName &arrayName, uint32_t count, const char *const *array, bool countRequired,
455 bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600456 bool skip_call = false;
Dustin Graves58d114b2016-03-08 14:42:59 -0700457
458 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600459 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves58d114b2016-03-08 14:42:59 -0700460 } else {
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600461 // Verify that strings in the array are not NULL
Dustin Graves58d114b2016-03-08 14:42:59 -0700462 for (uint32_t i = 0; i < count; ++i) {
463 if (array[i] == NULL) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600464 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 -0600465 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: required parameter %s[%d] specified as NULL",
466 apiName, arrayName.get_name().c_str(), i);
Dustin Graves58d114b2016-03-08 14:42:59 -0700467 }
468 }
469 }
470
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600471 return skip_call;
Dustin Graves58d114b2016-03-08 14:42:59 -0700472}
473
Dustin Graves58c2f662016-03-08 17:48:20 -0700474/**
475 * Validate a structure's pNext member.
476 *
477 * Verify that the specified pNext value points to the head of a list of
478 * allowed extension structures. If no extension structures are allowed,
479 * verify that pNext is null.
480 *
481 * @param report_data debug_report_data object for routing validation messages.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600482 * @param api_name Name of API call being validated.
483 * @param parameter_name Name of parameter being validated.
484 * @param allowed_struct_names Names of allowed structs.
Dustin Graves58c2f662016-03-08 17:48:20 -0700485 * @param next Pointer to validate.
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600486 * @param allowed_type_count Total number of allowed structure types.
487 * @param allowed_types Array of strcuture types allowed for pNext.
488 * @param header_version Version of header defining the pNext validation rules.
Dustin Graves58c2f662016-03-08 17:48:20 -0700489 * @return Boolean value indicating that the call should be skipped.
490 */
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600491static bool validate_struct_pnext(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600492 const char *allowed_struct_names, const void *next, size_t allowed_type_count,
493 const VkStructureType *allowed_types, uint32_t header_version) {
494 bool skip_call = false;
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600495 std::unordered_set<const void *> cycle_check;
496 std::unordered_set<VkStructureType, std::hash<int>> unique_stype_check;
497
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700498 const char disclaimer[] =
499 "This warning is based on the Valid Usage documentation for version %d of the Vulkan header. It "
500 "is possible that you are using a struct from a private extension or an extension that was added "
501 "to a later version of the Vulkan header, in which case your use of %s is perfectly valid but "
502 "is not guaranteed to work correctly with validation enabled";
Dustin Graves58c2f662016-03-08 17:48:20 -0700503
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600504 // TODO: The valid pNext structure types are not recursive. Each structure has its own list of valid sTypes for pNext.
505 // Codegen a map of vectors containing the allowable pNext types for each struct and use that here -- also simplifies parms.
Dustin Graves58c2f662016-03-08 17:48:20 -0700506 if (next != NULL) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600507 if (allowed_type_count == 0) {
508 std::string message = "%s: value of %s must be NULL. ";
509 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600510 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
511 INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name, parameter_name.get_name().c_str(),
512 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700513 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600514 const VkStructureType *start = allowed_types;
515 const VkStructureType *end = allowed_types + allowed_type_count;
Dustin Graves58c2f662016-03-08 17:48:20 -0700516 const GenericHeader *current = reinterpret_cast<const GenericHeader *>(next);
517
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600518 cycle_check.insert(next);
Dustin Graves58c2f662016-03-08 17:48:20 -0700519
Mark Lobodzinskic9b74d32017-03-27 11:52:02 -0600520
521 while (current != NULL) {
522 if (cycle_check.find(current->pNext) != cycle_check.end()) {
523 std::string message = "%s: %s chain contains a cycle -- pNext pointer " PRIx64 " is repeated.";
524 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
525 __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
526 parameter_name.get_name().c_str(), reinterpret_cast<uint64_t>(next));
527 break;
528 } else {
529 cycle_check.insert(current->pNext);
530 }
531
532 std::string type_name = string_VkStructureType(current->sType);
533 if (unique_stype_check.find(current->sType) != unique_stype_check.end()) {
534 std::string message = "%s: %s chain contains duplicate structure types: %s appears multiple times.";
535 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
536 __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
537 parameter_name.get_name().c_str(), type_name.c_str());
538 } else {
539 unique_stype_check.insert(current->sType);
540 }
541
542 if (std::find(start, end, current->sType) == end) {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600543 if (type_name == UnsupportedStructureTypeString) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700544 std::string message =
545 "%s: %s chain includes a structure with unexpected VkStructureType (%d); Allowed "
546 "structures are [%s]. ";
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600547 message += disclaimer;
548 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
549 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600550 parameter_name.get_name().c_str(), current->sType, allowed_struct_names,
551 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700552 } else {
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600553 std::string message =
554 "%s: %s chain includes a structure with unexpected VkStructureType %s; Allowed structures are [%s]. ";
555 message += disclaimer;
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600556 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
557 0, __LINE__, INVALID_STRUCT_PNEXT, LayerName, message.c_str(), api_name,
558 parameter_name.get_name().c_str(), type_name.c_str(), allowed_struct_names,
559 header_version, parameter_name.get_name().c_str());
Dustin Graves58c2f662016-03-08 17:48:20 -0700560 }
561 }
Dustin Graves58c2f662016-03-08 17:48:20 -0700562 current = reinterpret_cast<const GenericHeader *>(current->pNext);
563 }
564 }
565 }
566
Dustin Gravesaf5c0292016-07-19 13:43:53 -0600567 return skip_call;
Dustin Graves58c2f662016-03-08 17:48:20 -0700568}
569
Dustin Graves29148ff2016-03-23 19:44:00 -0600570/**
571* Validate a VkBool32 value.
572*
573* Generate a warning if a VkBool32 value is neither VK_TRUE nor VK_FALSE.
574*
575* @param report_data debug_report_data object for routing validation messages.
576* @param apiName Name of API call being validated.
577* @param parameterName Name of parameter being validated.
578* @param value Boolean value to validate.
579* @return Boolean value indicating that the call should be skipped.
580*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600581static bool validate_bool32(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
582 VkBool32 value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600583 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600584
585 if ((value != VK_TRUE) && (value != VK_FALSE)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600586 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 -0600587 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s (%d) is neither VK_TRUE nor VK_FALSE", apiName,
588 parameterName.get_name().c_str(), value);
Dustin Graves29148ff2016-03-23 19:44:00 -0600589 }
590
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600591 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600592}
593
594/**
595* Validate a Vulkan enumeration value.
596*
597* Generate a warning if an enumeration token value does not fall within the core enumeration
598* begin and end token values, and was not added to the enumeration by an extension. Extension
599* provided enumerations use the equation specified in Appendix C.10 of the Vulkan specification,
600* with 1,000,000,000 as the base token value.
601*
602* @note This function does not expect to process enumerations defining bitmask flag bits.
603*
604* @param report_data debug_report_data object for routing validation messages.
605* @param apiName Name of API call being validated.
606* @param parameterName Name of parameter being validated.
607* @param enumName Name of the enumeration being validated.
608* @param begin The begin range value for the enumeration.
609* @param end The end range value for the enumeration.
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600610* @param value Enumeration value to validate.
Dustin Graves29148ff2016-03-23 19:44:00 -0600611* @return Boolean value indicating that the call should be skipped.
612*/
613template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600614bool validate_ranged_enum(debug_report_data *report_data, const char *apiName, const ParameterName &parameterName,
615 const char *enumName, T begin, T end, T value) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600616 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600617
618 if (((value < begin) || (value > end)) && !is_extension_added_token(value)) {
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700619 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
620 UNRECOGNIZED_VALUE, LayerName,
621 "%s: value of %s (%d) does not fall within the begin..end range of the core %s "
622 "enumeration tokens and is not an extension added token",
623 apiName, parameterName.get_name().c_str(), value, enumName);
Dustin Graves29148ff2016-03-23 19:44:00 -0600624 }
625
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600626 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600627}
628
629/**
630* Validate an array of Vulkan enumeration value.
631*
632* Process all enumeration token values in the specified array and generate a warning if a value
633* does not fall within the core enumeration begin and end token values, and was not added to
634* the enumeration by an extension. Extension provided enumerations use the equation specified
635* in Appendix C.10 of the Vulkan specification, with 1,000,000,000 as the base token value.
636*
637* @note This function does not expect to process enumerations defining bitmask flag bits.
638*
639* @param report_data debug_report_data object for routing validation messages.
640* @param apiName Name of API call being validated.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600641* @param countName Name of count parameter.
642* @param arrayName Name of array parameter.
Dustin Graves29148ff2016-03-23 19:44:00 -0600643* @param enumName Name of the enumeration being validated.
644* @param begin The begin range value for the enumeration.
645* @param end The end range value for the enumeration.
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600646* @param count Number of enumeration values in the array.
647* @param array Array of enumeration values to validate.
648* @param countRequired The 'count' parameter may not be 0 when true.
649* @param arrayRequired The 'array' parameter may not be NULL when true.
Dustin Graves29148ff2016-03-23 19:44:00 -0600650* @return Boolean value indicating that the call should be skipped.
651*/
652template <typename T>
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600653static bool validate_ranged_enum_array(debug_report_data *report_data, const char *apiName, const ParameterName &countName,
654 const ParameterName &arrayName, const char *enumName, T begin, T end, uint32_t count,
655 const T *array, bool countRequired, bool arrayRequired) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600656 bool skip_call = false;
Dustin Graves29148ff2016-03-23 19:44:00 -0600657
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600658 if ((count == 0) || (array == NULL)) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600659 skip_call |= validate_array(report_data, apiName, countName, arrayName, count, array, countRequired, arrayRequired);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600660 } else {
661 for (uint32_t i = 0; i < count; ++i) {
662 if (((array[i] < begin) || (array[i] > end)) && !is_extension_added_token(array[i])) {
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600663 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 -0600664 __LINE__, UNRECOGNIZED_VALUE, LayerName,
665 "%s: value of %s[%d] (%d) does not fall within the begin..end range of the core %s "
666 "enumeration tokens and is not an extension added token",
667 apiName, arrayName.get_name().c_str(), i, array[i], enumName);
Dustin Graves0d15c6e2016-04-26 16:34:10 -0600668 }
Dustin Graves29148ff2016-03-23 19:44:00 -0600669 }
670 }
671
Mark Lobodzinski72ecd912016-08-11 13:25:38 -0600672 return skip_call;
Dustin Graves29148ff2016-03-23 19:44:00 -0600673}
674
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600675/**
Dustin Graves78df8512016-04-28 17:58:59 -0600676* Verify that a reserved VkFlags value is zero.
677*
678* Verify that the specified value is zero, to check VkFlags values that are reserved for
679* future use.
680*
681* @param report_data debug_report_data object for routing validation messages.
682* @param api_name Name of API call being validated.
683* @param parameter_name Name of parameter being validated.
684* @param value Value to validate.
685* @return Boolean value indicating that the call should be skipped.
686*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600687static bool validate_reserved_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600688 VkFlags value) {
689 bool skip_call = false;
690
691 if (value != 0) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600692 skip_call |=
693 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
694 RESERVED_PARAMETER, LayerName, "%s: parameter %s must be 0", api_name, parameter_name.get_name().c_str());
Dustin Graves78df8512016-04-28 17:58:59 -0600695 }
696
697 return skip_call;
698}
699
700/**
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600701* Validate a Vulkan bitmask value.
702*
703* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
704* for that type.
705*
706* @param report_data debug_report_data object for routing validation messages.
707* @param api_name Name of API call being validated.
708* @param parameter_name Name of parameter being validated.
709* @param flag_bits_name Name of the VkFlags type being validated.
710* @param all_flags A bit mask combining all valid flag bits for the VkFlags type being validated.
711* @param value VkFlags value to validate.
712* @param flags_required The 'value' parameter may not be 0 when true.
713* @return Boolean value indicating that the call should be skipped.
714*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600715static bool validate_flags(debug_report_data *report_data, const char *api_name, const ParameterName &parameter_name,
Dustin Graves78df8512016-04-28 17:58:59 -0600716 const char *flag_bits_name, VkFlags all_flags, VkFlags value, bool flags_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600717 bool skip_call = false;
718
719 if (value == 0) {
720 if (flags_required) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600721 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 -0600722 REQUIRED_PARAMETER, LayerName, "%s: value of %s must not be 0", api_name,
723 parameter_name.get_name().c_str());
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600724 }
725 } else if ((value & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600726 skip_call |=
727 log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
728 UNRECOGNIZED_VALUE, LayerName, "%s: value of %s contains flag bits that are not recognized members of %s",
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600729 api_name, parameter_name.get_name().c_str(), flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600730 }
731
732 return skip_call;
733}
734
735/**
736* Validate an array of Vulkan bitmask values.
737*
738* Generate a warning if a value with a VkFlags derived type does not contain valid flag bits
739* for that type.
740*
741* @param report_data debug_report_data object for routing validation messages.
742* @param api_name Name of API call being validated.
743* @param count_name Name of parameter being validated.
744* @param array_name Name of parameter being validated.
745* @param flag_bits_name Name of the VkFlags type being validated.
746* @param all_flags A bitmask combining all valid flag bits for the VkFlags type being validated.
747* @param count Number of VkFlags values in the array.
748* @param array Array of VkFlags value to validate.
749* @param count_required The 'count' parameter may not be 0 when true.
750* @param array_required The 'array' parameter may not be NULL when true.
751* @return Boolean value indicating that the call should be skipped.
752*/
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600753static bool validate_flags_array(debug_report_data *report_data, const char *api_name, const ParameterName &count_name,
754 const ParameterName &array_name, const char *flag_bits_name, VkFlags all_flags, uint32_t count,
Dustin Graves78df8512016-04-28 17:58:59 -0600755 const VkFlags *array, bool count_required, bool array_required) {
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600756 bool skip_call = false;
757
758 if ((count == 0) || (array == NULL)) {
759 skip_call |= validate_array(report_data, api_name, count_name, array_name, count, array, count_required, array_required);
760 } else {
761 // Verify that all VkFlags values in the array
762 for (uint32_t i = 0; i < count; ++i) {
Dustin Graves78df8512016-04-28 17:58:59 -0600763 if (array[i] == 0) {
764 // Current XML registry logic for validity generation uses the array parameter's optional tag to determine if
765 // elements in the array are allowed be 0
766 if (array_required) {
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600767 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
768 __LINE__, REQUIRED_PARAMETER, LayerName, "%s: value of %s[%d] must not be 0", api_name,
769 array_name.get_name().c_str(), i);
Dustin Graves78df8512016-04-28 17:58:59 -0600770 }
771 } else if ((array[i] & (~all_flags)) != 0) {
Dustin Gravesf233e502016-05-05 13:44:21 -0600772 skip_call |= log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
773 __LINE__, UNRECOGNIZED_VALUE, LayerName,
774 "%s: value of %s[%d] contains flag bits that are not recognized members of %s", api_name,
Dustin Graves8ffbbf62016-07-22 13:19:46 -0600775 array_name.get_name().c_str(), i, flag_bits_name);
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600776 }
777 }
778 }
779
780 return skip_call;
781}
782
783/**
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600784* Get VkResult code description.
785*
Dustin Graves9c6b62b2016-04-26 15:37:10 -0600786* Returns a string describing the specified VkResult code. The description is based on the language in the Vulkan API
787* specification.
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600788*
789* @param value VkResult code to process.
790* @return String describing the specified VkResult code.
791*/
792static std::string get_result_description(VkResult result) {
793 // clang-format off
794 switch (result) {
795 case VK_SUCCESS: return "a command completed successfully";
796 case VK_NOT_READY: return "a fence or query has not yet completed";
797 case VK_TIMEOUT: return "a wait operation has not completed in the specified time";
798 case VK_EVENT_SET: return "an event is signaled";
799 case VK_EVENT_RESET: return "an event is unsignalled";
800 case VK_INCOMPLETE: return "a return array was too small for the result";
801 case VK_ERROR_OUT_OF_HOST_MEMORY: return "a host memory allocation has failed";
802 case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "a device memory allocation has failed";
Dustin Graves2adca842016-05-16 18:35:55 -0600803 case VK_ERROR_INITIALIZATION_FAILED: return "initialization of an object has failed";
804 case VK_ERROR_DEVICE_LOST: return "the logical device has been lost";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600805 case VK_ERROR_MEMORY_MAP_FAILED: return "mapping of a memory object has failed";
806 case VK_ERROR_LAYER_NOT_PRESENT: return "the specified layer does not exist";
807 case VK_ERROR_EXTENSION_NOT_PRESENT: return "the specified extension does not exist";
808 case VK_ERROR_FEATURE_NOT_PRESENT: return "the requested feature is not available on this device";
809 case VK_ERROR_INCOMPATIBLE_DRIVER: return "a Vulkan driver could not be found";
810 case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects of the type have already been created";
811 case VK_ERROR_FORMAT_NOT_SUPPORTED: return "the requested format is not supported on this device";
812 case VK_ERROR_SURFACE_LOST_KHR: return "a surface is no longer available";
813 case VK_ERROR_NATIVE_WINDOW_IN_USE_KHR: return "the requested window is already connected to another "
814 "VkSurfaceKHR object, or some other non-Vulkan surface object";
815 case VK_SUBOPTIMAL_KHR: return "an image became available, and the swapchain no longer "
816 "matches the surface properties exactly, but can still be used to "
817 "present to the surface successfully.";
818 case VK_ERROR_OUT_OF_DATE_KHR: return "a surface has changed in such a way that it is no "
819 "longer compatible with the swapchain";
820 case VK_ERROR_INCOMPATIBLE_DISPLAY_KHR: return "the display used by a swapchain does not use the same "
821 "presentable image layout, or is incompatible in a way that prevents "
822 "sharing an image";
823 case VK_ERROR_VALIDATION_FAILED_EXT: return "API validation has detected an invalid use of the API";
824 case VK_ERROR_INVALID_SHADER_NV: return "one or more shaders failed to compile or link";
Eric Engestrombcbb0fd2016-04-02 22:06:13 +0100825 default: return "an error has occurred";
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600826 };
827 // clang-format on
828}
829
830/**
831* Validate return code.
832*
833* Print a message describing the reason for failure when an error code is returned.
834*
835* @param report_data debug_report_data object for routing validation messages.
836* @param apiName Name of API call being validated.
837* @param value VkResult value to validate.
838*/
839static void validate_result(debug_report_data *report_data, const char *apiName, VkResult result) {
Chris Forbesf1f4e382016-10-13 14:44:03 +1300840 if (result < 0 && result != VK_ERROR_VALIDATION_FAILED_EXT) {
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600841 std::string resultName = string_VkResult(result);
842
843 if (resultName == UnsupportedResultString) {
844 // Unrecognized result code
Dustin Gravesf233e502016-05-05 13:44:21 -0600845 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
846 FAILURE_RETURN_CODE, LayerName, "%s: returned a result code indicating that an error has occurred", apiName);
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600847 } else {
848 std::string resultDesc = get_result_description(result);
Dustin Gravesf233e502016-05-05 13:44:21 -0600849 log_msg(report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
850 FAILURE_RETURN_CODE, LayerName, "%s: returned %s, indicating that %s", apiName, resultName.c_str(),
851 resultDesc.c_str());
Dustin Gravesca7aa7c2016-03-25 15:13:28 -0600852 }
853 }
854}
855
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700856} // namespace parameter_validation
Dustin Gravesb83fc2d2016-05-04 12:56:08 -0600857
Mark Lobodzinski64318ba2017-01-26 13:34:13 -0700858#endif // PARAMETER_VALIDATION_UTILS_H