1/* Copyright (c) 2015-2016 The Khronos Group Inc.
2 * Copyright (c) 2015-2016 Valve Corporation
3 * Copyright (c) 2015-2016 LunarG, Inc.
4 * Copyright (C) 2015-2016 Google Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials
11 * are furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice(s) and this permission notice shall be included
14 * in all copies or substantial portions of the Materials.
15 *
16 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS
24 *
25 * Author: Jeremy Hayes <jeremy@lunarg.com>
26 * Author: Tony Barbour <tony@LunarG.com>
27 * Author: Mark Lobodzinski <mark@LunarG.com>
28 * Author: Dustin Graves <dustin@lunarg.com>
29 */
30
31#include <stdio.h>
32#include <stdlib.h>
33#include <string.h>
34
35#include <iostream>
36#include <string>
37#include <sstream>
38#include <unordered_map>
39#include <unordered_set>
40#include <vector>
41
42#include "vk_loader_platform.h"
43#include "vulkan/vk_layer.h"
44#include "vk_layer_config.h"
45#include "vk_enum_validate_helper.h"
46#include "vk_struct_validate_helper.h"
47
48#include "vk_layer_table.h"
49#include "vk_layer_data.h"
50#include "vk_layer_logging.h"
51#include "vk_layer_extension_utils.h"
52#include "vk_layer_utils.h"
53
54#include "parameter_validation.h"
55
56struct layer_data {
57    debug_report_data *report_data;
58    std::vector<VkDebugReportCallbackEXT> logging_callback;
59
60    // TODO: Split instance/device structs
61    // Device Data
62    // Map for queue family index to queue count
63    std::unordered_map<uint32_t, uint32_t> queueFamilyIndexMap;
64
65    layer_data() : report_data(nullptr){};
66};
67
68static std::unordered_map<void *, layer_data *> layer_data_map;
69static device_table_map pc_device_table_map;
70static instance_table_map pc_instance_table_map;
71
72// "my instance data"
73debug_report_data *mid(VkInstance object) {
74    dispatch_key key = get_dispatch_key(object);
75    layer_data *data = get_my_data_ptr(key, layer_data_map);
76#if DISPATCH_MAP_DEBUG
77    fprintf(stderr, "MID: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
78#endif
79    assert(data != NULL);
80
81    return data->report_data;
82}
83
84// "my device data"
85debug_report_data *mdd(void *object) {
86    dispatch_key key = get_dispatch_key(object);
87    layer_data *data = get_my_data_ptr(key, layer_data_map);
88#if DISPATCH_MAP_DEBUG
89    fprintf(stderr, "MDD: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
90#endif
91    assert(data != NULL);
92    return data->report_data;
93}
94
95static void init_parameter_validation(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
96
97    layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_parameter_validation");
98}
99
100VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
101vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
102                               const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
103    VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
104    VkResult result = pTable->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
105
106    if (result == VK_SUCCESS) {
107        layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
108        result = layer_create_msg_callback(data->report_data, pCreateInfo, pAllocator, pMsgCallback);
109    }
110
111    return result;
112}
113
114VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
115                                                                           VkDebugReportCallbackEXT msgCallback,
116                                                                           const VkAllocationCallbacks *pAllocator) {
117    VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
118    pTable->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
119
120    layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
121    layer_destroy_msg_callback(data->report_data, msgCallback, pAllocator);
122}
123
124VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
125vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
126                        size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
127    VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
128    pTable->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
129}
130
131static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
132
133VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
134vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
135    return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
136}
137
138static const VkLayerProperties pc_global_layers[] = {{
139    "VK_LAYER_LUNARG_parameter_validation", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
140}};
141
142VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
143vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
144    return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties);
145}
146
147VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
148                                                                                    const char *pLayerName, uint32_t *pCount,
149                                                                                    VkExtensionProperties *pProperties) {
150    /* parameter_validation does not have any physical device extensions */
151    if (pLayerName == NULL) {
152        return get_dispatch_table(pc_instance_table_map, physicalDevice)
153            ->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
154    } else {
155        return util_GetExtensionProperties(0, NULL, pCount, pProperties);
156    }
157}
158
159VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
160vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
161
162    /* parameter_validation's physical device layers are the same as global */
163    return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties);
164}
165
166static std::string EnumeratorString(VkResult const &enumerator) {
167    switch (enumerator) {
168    case VK_RESULT_MAX_ENUM: {
169        return "VK_RESULT_MAX_ENUM";
170        break;
171    }
172    case VK_ERROR_LAYER_NOT_PRESENT: {
173        return "VK_ERROR_LAYER_NOT_PRESENT";
174        break;
175    }
176    case VK_ERROR_INCOMPATIBLE_DRIVER: {
177        return "VK_ERROR_INCOMPATIBLE_DRIVER";
178        break;
179    }
180    case VK_ERROR_MEMORY_MAP_FAILED: {
181        return "VK_ERROR_MEMORY_MAP_FAILED";
182        break;
183    }
184    case VK_INCOMPLETE: {
185        return "VK_INCOMPLETE";
186        break;
187    }
188    case VK_ERROR_OUT_OF_HOST_MEMORY: {
189        return "VK_ERROR_OUT_OF_HOST_MEMORY";
190        break;
191    }
192    case VK_ERROR_INITIALIZATION_FAILED: {
193        return "VK_ERROR_INITIALIZATION_FAILED";
194        break;
195    }
196    case VK_NOT_READY: {
197        return "VK_NOT_READY";
198        break;
199    }
200    case VK_ERROR_OUT_OF_DEVICE_MEMORY: {
201        return "VK_ERROR_OUT_OF_DEVICE_MEMORY";
202        break;
203    }
204    case VK_EVENT_SET: {
205        return "VK_EVENT_SET";
206        break;
207    }
208    case VK_TIMEOUT: {
209        return "VK_TIMEOUT";
210        break;
211    }
212    case VK_EVENT_RESET: {
213        return "VK_EVENT_RESET";
214        break;
215    }
216    case VK_SUCCESS: {
217        return "VK_SUCCESS";
218        break;
219    }
220    case VK_ERROR_EXTENSION_NOT_PRESENT: {
221        return "VK_ERROR_EXTENSION_NOT_PRESENT";
222        break;
223    }
224    case VK_ERROR_DEVICE_LOST: {
225        return "VK_ERROR_DEVICE_LOST";
226        break;
227    }
228    default: {
229        return "unrecognized enumerator";
230        break;
231    }
232    }
233}
234
235static bool ValidateEnumerator(VkFormatFeatureFlagBits const &enumerator) {
236    VkFormatFeatureFlagBits allFlags = (VkFormatFeatureFlagBits)(
237        VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT | VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT |
238        VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT |
239        VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT | VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT |
240        VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT | VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT |
241        VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_FORMAT_FEATURE_BLIT_SRC_BIT | VK_FORMAT_FEATURE_BLIT_DST_BIT |
242        VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT);
243    if (enumerator & (~allFlags)) {
244        return false;
245    }
246
247    return true;
248}
249
250static std::string EnumeratorString(VkFormatFeatureFlagBits const &enumerator) {
251    if (!ValidateEnumerator(enumerator)) {
252        return "unrecognized enumerator";
253    }
254
255    std::vector<std::string> strings;
256    if (enumerator & VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT) {
257        strings.push_back("VK_FORMAT_FEATURE_STORAGE_IMAGE_ATOMIC_BIT");
258    }
259    if (enumerator & VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT) {
260        strings.push_back("VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT");
261    }
262    if (enumerator & VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT) {
263        strings.push_back("VK_FORMAT_FEATURE_UNIFORM_TEXEL_BUFFER_BIT");
264    }
265    if (enumerator & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT) {
266        strings.push_back("VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_ATOMIC_BIT");
267    }
268    if (enumerator & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT) {
269        strings.push_back("VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT");
270    }
271    if (enumerator & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT) {
272        strings.push_back("VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BLEND_BIT");
273    }
274    if (enumerator & VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT) {
275        strings.push_back("VK_FORMAT_FEATURE_VERTEX_BUFFER_BIT");
276    }
277    if (enumerator & VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT) {
278        strings.push_back("VK_FORMAT_FEATURE_STORAGE_TEXEL_BUFFER_BIT");
279    }
280    if (enumerator & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) {
281        strings.push_back("VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT");
282    }
283    if (enumerator & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) {
284        strings.push_back("VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT");
285    }
286    if (enumerator & VK_FORMAT_FEATURE_BLIT_SRC_BIT) {
287        strings.push_back("VK_FORMAT_FEATURE_BLIT_SRC_BIT");
288    }
289    if (enumerator & VK_FORMAT_FEATURE_BLIT_DST_BIT) {
290        strings.push_back("VK_FORMAT_FEATURE_BLIT_DST_BIT");
291    }
292    if (enumerator & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) {
293        strings.push_back("VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT");
294    }
295
296    std::string enumeratorString;
297    for (auto const &string : strings) {
298        enumeratorString += string;
299
300        if (string != strings.back()) {
301            enumeratorString += '|';
302        }
303    }
304
305    return enumeratorString;
306}
307
308static bool ValidateEnumerator(VkImageUsageFlagBits const &enumerator) {
309    VkImageUsageFlagBits allFlags = (VkImageUsageFlagBits)(
310        VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT | VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
311        VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT |
312        VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
313    if (enumerator & (~allFlags)) {
314        return false;
315    }
316
317    return true;
318}
319
320static std::string EnumeratorString(VkImageUsageFlagBits const &enumerator) {
321    if (!ValidateEnumerator(enumerator)) {
322        return "unrecognized enumerator";
323    }
324
325    std::vector<std::string> strings;
326    if (enumerator & VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT) {
327        strings.push_back("VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT");
328    }
329    if (enumerator & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
330        strings.push_back("VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT");
331    }
332    if (enumerator & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
333        strings.push_back("VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT");
334    }
335    if (enumerator & VK_IMAGE_USAGE_STORAGE_BIT) {
336        strings.push_back("VK_IMAGE_USAGE_STORAGE_BIT");
337    }
338    if (enumerator & VK_IMAGE_USAGE_SAMPLED_BIT) {
339        strings.push_back("VK_IMAGE_USAGE_SAMPLED_BIT");
340    }
341    if (enumerator & VK_IMAGE_USAGE_TRANSFER_DST_BIT) {
342        strings.push_back("VK_IMAGE_USAGE_TRANSFER_DST_BIT");
343    }
344    if (enumerator & VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT) {
345        strings.push_back("VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT");
346    }
347    if (enumerator & VK_IMAGE_USAGE_TRANSFER_SRC_BIT) {
348        strings.push_back("VK_IMAGE_USAGE_TRANSFER_SRC_BIT");
349    }
350
351    std::string enumeratorString;
352    for (auto const &string : strings) {
353        enumeratorString += string;
354
355        if (string != strings.back()) {
356            enumeratorString += '|';
357        }
358    }
359
360    return enumeratorString;
361}
362
363static bool ValidateEnumerator(VkQueueFlagBits const &enumerator) {
364    VkQueueFlagBits allFlags =
365        (VkQueueFlagBits)(VK_QUEUE_TRANSFER_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_SPARSE_BINDING_BIT | VK_QUEUE_GRAPHICS_BIT);
366    if (enumerator & (~allFlags)) {
367        return false;
368    }
369
370    return true;
371}
372
373static std::string EnumeratorString(VkQueueFlagBits const &enumerator) {
374    if (!ValidateEnumerator(enumerator)) {
375        return "unrecognized enumerator";
376    }
377
378    std::vector<std::string> strings;
379    if (enumerator & VK_QUEUE_TRANSFER_BIT) {
380        strings.push_back("VK_QUEUE_TRANSFER_BIT");
381    }
382    if (enumerator & VK_QUEUE_COMPUTE_BIT) {
383        strings.push_back("VK_QUEUE_COMPUTE_BIT");
384    }
385    if (enumerator & VK_QUEUE_SPARSE_BINDING_BIT) {
386        strings.push_back("VK_QUEUE_SPARSE_BINDING_BIT");
387    }
388    if (enumerator & VK_QUEUE_GRAPHICS_BIT) {
389        strings.push_back("VK_QUEUE_GRAPHICS_BIT");
390    }
391
392    std::string enumeratorString;
393    for (auto const &string : strings) {
394        enumeratorString += string;
395
396        if (string != strings.back()) {
397            enumeratorString += '|';
398        }
399    }
400
401    return enumeratorString;
402}
403
404static bool ValidateEnumerator(VkMemoryPropertyFlagBits const &enumerator) {
405    VkMemoryPropertyFlagBits allFlags = (VkMemoryPropertyFlagBits)(
406        VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT |
407        VK_MEMORY_PROPERTY_HOST_CACHED_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT);
408    if (enumerator & (~allFlags)) {
409        return false;
410    }
411
412    return true;
413}
414
415static std::string EnumeratorString(VkMemoryPropertyFlagBits const &enumerator) {
416    if (!ValidateEnumerator(enumerator)) {
417        return "unrecognized enumerator";
418    }
419
420    std::vector<std::string> strings;
421    if (enumerator & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT) {
422        strings.push_back("VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT");
423    }
424    if (enumerator & VK_MEMORY_PROPERTY_HOST_COHERENT_BIT) {
425        strings.push_back("VK_MEMORY_PROPERTY_HOST_COHERENT_BIT");
426    }
427    if (enumerator & VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT) {
428        strings.push_back("VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT");
429    }
430    if (enumerator & VK_MEMORY_PROPERTY_HOST_CACHED_BIT) {
431        strings.push_back("VK_MEMORY_PROPERTY_HOST_CACHED_BIT");
432    }
433    if (enumerator & VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT) {
434        strings.push_back("VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT");
435    }
436
437    std::string enumeratorString;
438    for (auto const &string : strings) {
439        enumeratorString += string;
440
441        if (string != strings.back()) {
442            enumeratorString += '|';
443        }
444    }
445
446    return enumeratorString;
447}
448
449static bool ValidateEnumerator(VkMemoryHeapFlagBits const &enumerator) {
450    VkMemoryHeapFlagBits allFlags = (VkMemoryHeapFlagBits)(VK_MEMORY_HEAP_DEVICE_LOCAL_BIT);
451    if (enumerator & (~allFlags)) {
452        return false;
453    }
454
455    return true;
456}
457
458static std::string EnumeratorString(VkMemoryHeapFlagBits const &enumerator) {
459    if (!ValidateEnumerator(enumerator)) {
460        return "unrecognized enumerator";
461    }
462
463    std::vector<std::string> strings;
464    if (enumerator & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) {
465        strings.push_back("VK_MEMORY_HEAP_DEVICE_LOCAL_BIT");
466    }
467
468    std::string enumeratorString;
469    for (auto const &string : strings) {
470        enumeratorString += string;
471
472        if (string != strings.back()) {
473            enumeratorString += '|';
474        }
475    }
476
477    return enumeratorString;
478}
479
480static bool ValidateEnumerator(VkSparseImageFormatFlagBits const &enumerator) {
481    VkSparseImageFormatFlagBits allFlags =
482        (VkSparseImageFormatFlagBits)(VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT |
483                                      VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT | VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT);
484    if (enumerator & (~allFlags)) {
485        return false;
486    }
487
488    return true;
489}
490
491static std::string EnumeratorString(VkSparseImageFormatFlagBits const &enumerator) {
492    if (!ValidateEnumerator(enumerator)) {
493        return "unrecognized enumerator";
494    }
495
496    std::vector<std::string> strings;
497    if (enumerator & VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT) {
498        strings.push_back("VK_SPARSE_IMAGE_FORMAT_NONSTANDARD_BLOCK_SIZE_BIT");
499    }
500    if (enumerator & VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT) {
501        strings.push_back("VK_SPARSE_IMAGE_FORMAT_ALIGNED_MIP_SIZE_BIT");
502    }
503    if (enumerator & VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT) {
504        strings.push_back("VK_SPARSE_IMAGE_FORMAT_SINGLE_MIPTAIL_BIT");
505    }
506
507    std::string enumeratorString;
508    for (auto const &string : strings) {
509        enumeratorString += string;
510
511        if (string != strings.back()) {
512            enumeratorString += '|';
513        }
514    }
515
516    return enumeratorString;
517}
518
519static bool ValidateEnumerator(VkFenceCreateFlagBits const &enumerator) {
520    VkFenceCreateFlagBits allFlags = (VkFenceCreateFlagBits)(VK_FENCE_CREATE_SIGNALED_BIT);
521    if (enumerator & (~allFlags)) {
522        return false;
523    }
524
525    return true;
526}
527
528static std::string EnumeratorString(VkFenceCreateFlagBits const &enumerator) {
529    if (!ValidateEnumerator(enumerator)) {
530        return "unrecognized enumerator";
531    }
532
533    std::vector<std::string> strings;
534    if (enumerator & VK_FENCE_CREATE_SIGNALED_BIT) {
535        strings.push_back("VK_FENCE_CREATE_SIGNALED_BIT");
536    }
537
538    std::string enumeratorString;
539    for (auto const &string : strings) {
540        enumeratorString += string;
541
542        if (string != strings.back()) {
543            enumeratorString += '|';
544        }
545    }
546
547    return enumeratorString;
548}
549
550static bool ValidateEnumerator(VkQueryPipelineStatisticFlagBits const &enumerator) {
551    VkQueryPipelineStatisticFlagBits allFlags = (VkQueryPipelineStatisticFlagBits)(
552        VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT |
553        VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT |
554        VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT |
555        VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT | VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT |
556        VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT |
557        VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT |
558        VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT);
559    if (enumerator & (~allFlags)) {
560        return false;
561    }
562
563    return true;
564}
565
566static std::string EnumeratorString(VkQueryPipelineStatisticFlagBits const &enumerator) {
567    if (!ValidateEnumerator(enumerator)) {
568        return "unrecognized enumerator";
569    }
570
571    std::vector<std::string> strings;
572    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT) {
573        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_COMPUTE_SHADER_INVOCATIONS_BIT");
574    }
575    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT) {
576        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_VERTICES_BIT");
577    }
578    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT) {
579        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT");
580    }
581    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT) {
582        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_CLIPPING_INVOCATIONS_BIT");
583    }
584    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT) {
585        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_VERTEX_SHADER_INVOCATIONS_BIT");
586    }
587    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT) {
588        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_PRIMITIVES_BIT");
589    }
590    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT) {
591        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_FRAGMENT_SHADER_INVOCATIONS_BIT");
592    }
593    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT) {
594        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_CLIPPING_PRIMITIVES_BIT");
595    }
596    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT) {
597        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_CONTROL_SHADER_PATCHES_BIT");
598    }
599    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT) {
600        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_GEOMETRY_SHADER_INVOCATIONS_BIT");
601    }
602    if (enumerator & VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT) {
603        strings.push_back("VK_QUERY_PIPELINE_STATISTIC_TESSELLATION_EVALUATION_SHADER_INVOCATIONS_BIT");
604    }
605
606    std::string enumeratorString;
607    for (auto const &string : strings) {
608        enumeratorString += string;
609
610        if (string != strings.back()) {
611            enumeratorString += '|';
612        }
613    }
614
615    return enumeratorString;
616}
617
618static bool ValidateEnumerator(VkQueryResultFlagBits const &enumerator) {
619    VkQueryResultFlagBits allFlags = (VkQueryResultFlagBits)(VK_QUERY_RESULT_PARTIAL_BIT | VK_QUERY_RESULT_WITH_AVAILABILITY_BIT |
620                                                             VK_QUERY_RESULT_WAIT_BIT | VK_QUERY_RESULT_64_BIT);
621    if (enumerator & (~allFlags)) {
622        return false;
623    }
624
625    return true;
626}
627
628static std::string EnumeratorString(VkQueryResultFlagBits const &enumerator) {
629    if (!ValidateEnumerator(enumerator)) {
630        return "unrecognized enumerator";
631    }
632
633    std::vector<std::string> strings;
634    if (enumerator & VK_QUERY_RESULT_PARTIAL_BIT) {
635        strings.push_back("VK_QUERY_RESULT_PARTIAL_BIT");
636    }
637    if (enumerator & VK_QUERY_RESULT_WITH_AVAILABILITY_BIT) {
638        strings.push_back("VK_QUERY_RESULT_WITH_AVAILABILITY_BIT");
639    }
640    if (enumerator & VK_QUERY_RESULT_WAIT_BIT) {
641        strings.push_back("VK_QUERY_RESULT_WAIT_BIT");
642    }
643    if (enumerator & VK_QUERY_RESULT_64_BIT) {
644        strings.push_back("VK_QUERY_RESULT_64_BIT");
645    }
646
647    std::string enumeratorString;
648    for (auto const &string : strings) {
649        enumeratorString += string;
650
651        if (string != strings.back()) {
652            enumeratorString += '|';
653        }
654    }
655
656    return enumeratorString;
657}
658
659static bool ValidateEnumerator(VkBufferUsageFlagBits const &enumerator) {
660    VkBufferUsageFlagBits allFlags = (VkBufferUsageFlagBits)(
661        VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT |
662        VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT |
663        VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
664    if (enumerator & (~allFlags)) {
665        return false;
666    }
667
668    return true;
669}
670
671static std::string EnumeratorString(VkBufferUsageFlagBits const &enumerator) {
672    if (!ValidateEnumerator(enumerator)) {
673        return "unrecognized enumerator";
674    }
675
676    std::vector<std::string> strings;
677    if (enumerator & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) {
678        strings.push_back("VK_BUFFER_USAGE_VERTEX_BUFFER_BIT");
679    }
680    if (enumerator & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) {
681        strings.push_back("VK_BUFFER_USAGE_INDEX_BUFFER_BIT");
682    }
683    if (enumerator & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) {
684        strings.push_back("VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT");
685    }
686    if (enumerator & VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT) {
687        strings.push_back("VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT");
688    }
689    if (enumerator & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
690        strings.push_back("VK_BUFFER_USAGE_STORAGE_BUFFER_BIT");
691    }
692    if (enumerator & VK_BUFFER_USAGE_TRANSFER_DST_BIT) {
693        strings.push_back("VK_BUFFER_USAGE_TRANSFER_DST_BIT");
694    }
695    if (enumerator & VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT) {
696        strings.push_back("VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT");
697    }
698    if (enumerator & VK_BUFFER_USAGE_TRANSFER_SRC_BIT) {
699        strings.push_back("VK_BUFFER_USAGE_TRANSFER_SRC_BIT");
700    }
701    if (enumerator & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
702        strings.push_back("VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT");
703    }
704
705    std::string enumeratorString;
706    for (auto const &string : strings) {
707        enumeratorString += string;
708
709        if (string != strings.back()) {
710            enumeratorString += '|';
711        }
712    }
713
714    return enumeratorString;
715}
716
717static bool ValidateEnumerator(VkBufferCreateFlagBits const &enumerator) {
718    VkBufferCreateFlagBits allFlags = (VkBufferCreateFlagBits)(
719        VK_BUFFER_CREATE_SPARSE_ALIASED_BIT | VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT | VK_BUFFER_CREATE_SPARSE_BINDING_BIT);
720    if (enumerator & (~allFlags)) {
721        return false;
722    }
723
724    return true;
725}
726
727static std::string EnumeratorString(VkBufferCreateFlagBits const &enumerator) {
728    if (!ValidateEnumerator(enumerator)) {
729        return "unrecognized enumerator";
730    }
731
732    std::vector<std::string> strings;
733    if (enumerator & VK_BUFFER_CREATE_SPARSE_ALIASED_BIT) {
734        strings.push_back("VK_BUFFER_CREATE_SPARSE_ALIASED_BIT");
735    }
736    if (enumerator & VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT) {
737        strings.push_back("VK_BUFFER_CREATE_SPARSE_RESIDENCY_BIT");
738    }
739    if (enumerator & VK_BUFFER_CREATE_SPARSE_BINDING_BIT) {
740        strings.push_back("VK_BUFFER_CREATE_SPARSE_BINDING_BIT");
741    }
742
743    std::string enumeratorString;
744    for (auto const &string : strings) {
745        enumeratorString += string;
746
747        if (string != strings.back()) {
748            enumeratorString += '|';
749        }
750    }
751
752    return enumeratorString;
753}
754
755static bool ValidateEnumerator(VkImageCreateFlagBits const &enumerator) {
756    VkImageCreateFlagBits allFlags = (VkImageCreateFlagBits)(
757        VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT | VK_IMAGE_CREATE_SPARSE_ALIASED_BIT | VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT |
758        VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_SPARSE_BINDING_BIT);
759    if (enumerator & (~allFlags)) {
760        return false;
761    }
762
763    return true;
764}
765
766static std::string EnumeratorString(VkImageCreateFlagBits const &enumerator) {
767    if (!ValidateEnumerator(enumerator)) {
768        return "unrecognized enumerator";
769    }
770
771    std::vector<std::string> strings;
772    if (enumerator & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) {
773        strings.push_back("VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT");
774    }
775    if (enumerator & VK_IMAGE_CREATE_SPARSE_ALIASED_BIT) {
776        strings.push_back("VK_IMAGE_CREATE_SPARSE_ALIASED_BIT");
777    }
778    if (enumerator & VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT) {
779        strings.push_back("VK_IMAGE_CREATE_SPARSE_RESIDENCY_BIT");
780    }
781    if (enumerator & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
782        strings.push_back("VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT");
783    }
784    if (enumerator & VK_IMAGE_CREATE_SPARSE_BINDING_BIT) {
785        strings.push_back("VK_IMAGE_CREATE_SPARSE_BINDING_BIT");
786    }
787
788    std::string enumeratorString;
789    for (auto const &string : strings) {
790        enumeratorString += string;
791
792        if (string != strings.back()) {
793            enumeratorString += '|';
794        }
795    }
796
797    return enumeratorString;
798}
799
800static bool ValidateEnumerator(VkColorComponentFlagBits const &enumerator) {
801    VkColorComponentFlagBits allFlags = (VkColorComponentFlagBits)(VK_COLOR_COMPONENT_A_BIT | VK_COLOR_COMPONENT_B_BIT |
802                                                                   VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_R_BIT);
803    if (enumerator & (~allFlags)) {
804        return false;
805    }
806
807    return true;
808}
809
810static std::string EnumeratorString(VkColorComponentFlagBits const &enumerator) {
811    if (!ValidateEnumerator(enumerator)) {
812        return "unrecognized enumerator";
813    }
814
815    std::vector<std::string> strings;
816    if (enumerator & VK_COLOR_COMPONENT_A_BIT) {
817        strings.push_back("VK_COLOR_COMPONENT_A_BIT");
818    }
819    if (enumerator & VK_COLOR_COMPONENT_B_BIT) {
820        strings.push_back("VK_COLOR_COMPONENT_B_BIT");
821    }
822    if (enumerator & VK_COLOR_COMPONENT_G_BIT) {
823        strings.push_back("VK_COLOR_COMPONENT_G_BIT");
824    }
825    if (enumerator & VK_COLOR_COMPONENT_R_BIT) {
826        strings.push_back("VK_COLOR_COMPONENT_R_BIT");
827    }
828
829    std::string enumeratorString;
830    for (auto const &string : strings) {
831        enumeratorString += string;
832
833        if (string != strings.back()) {
834            enumeratorString += '|';
835        }
836    }
837
838    return enumeratorString;
839}
840
841static bool ValidateEnumerator(VkPipelineCreateFlagBits const &enumerator) {
842    VkPipelineCreateFlagBits allFlags = (VkPipelineCreateFlagBits)(
843        VK_PIPELINE_CREATE_DERIVATIVE_BIT | VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT | VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT);
844    if (enumerator & (~allFlags)) {
845        return false;
846    }
847
848    return true;
849}
850
851static std::string EnumeratorString(VkPipelineCreateFlagBits const &enumerator) {
852    if (!ValidateEnumerator(enumerator)) {
853        return "unrecognized enumerator";
854    }
855
856    std::vector<std::string> strings;
857    if (enumerator & VK_PIPELINE_CREATE_DERIVATIVE_BIT) {
858        strings.push_back("VK_PIPELINE_CREATE_DERIVATIVE_BIT");
859    }
860    if (enumerator & VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT) {
861        strings.push_back("VK_PIPELINE_CREATE_ALLOW_DERIVATIVES_BIT");
862    }
863    if (enumerator & VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT) {
864        strings.push_back("VK_PIPELINE_CREATE_DISABLE_OPTIMIZATION_BIT");
865    }
866
867    std::string enumeratorString;
868    for (auto const &string : strings) {
869        enumeratorString += string;
870
871        if (string != strings.back()) {
872            enumeratorString += '|';
873        }
874    }
875
876    return enumeratorString;
877}
878
879static bool ValidateEnumerator(VkShaderStageFlagBits const &enumerator) {
880    VkShaderStageFlagBits allFlags = (VkShaderStageFlagBits)(
881        VK_SHADER_STAGE_ALL | VK_SHADER_STAGE_FRAGMENT_BIT | VK_SHADER_STAGE_GEOMETRY_BIT | VK_SHADER_STAGE_COMPUTE_BIT |
882        VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT | VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT | VK_SHADER_STAGE_VERTEX_BIT);
883    if (enumerator & (~allFlags)) {
884        return false;
885    }
886
887    return true;
888}
889
890static std::string EnumeratorString(VkShaderStageFlagBits const &enumerator) {
891    if (!ValidateEnumerator(enumerator)) {
892        return "unrecognized enumerator";
893    }
894
895    std::vector<std::string> strings;
896    if (enumerator & VK_SHADER_STAGE_ALL) {
897        strings.push_back("VK_SHADER_STAGE_ALL");
898    }
899    if (enumerator & VK_SHADER_STAGE_FRAGMENT_BIT) {
900        strings.push_back("VK_SHADER_STAGE_FRAGMENT_BIT");
901    }
902    if (enumerator & VK_SHADER_STAGE_GEOMETRY_BIT) {
903        strings.push_back("VK_SHADER_STAGE_GEOMETRY_BIT");
904    }
905    if (enumerator & VK_SHADER_STAGE_COMPUTE_BIT) {
906        strings.push_back("VK_SHADER_STAGE_COMPUTE_BIT");
907    }
908    if (enumerator & VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT) {
909        strings.push_back("VK_SHADER_STAGE_TESSELLATION_EVALUATION_BIT");
910    }
911    if (enumerator & VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT) {
912        strings.push_back("VK_SHADER_STAGE_TESSELLATION_CONTROL_BIT");
913    }
914    if (enumerator & VK_SHADER_STAGE_VERTEX_BIT) {
915        strings.push_back("VK_SHADER_STAGE_VERTEX_BIT");
916    }
917
918    std::string enumeratorString;
919    for (auto const &string : strings) {
920        enumeratorString += string;
921
922        if (string != strings.back()) {
923            enumeratorString += '|';
924        }
925    }
926
927    return enumeratorString;
928}
929
930static bool ValidateEnumerator(VkPipelineStageFlagBits const &enumerator) {
931    VkPipelineStageFlagBits allFlags = (VkPipelineStageFlagBits)(
932        VK_PIPELINE_STAGE_ALL_COMMANDS_BIT | VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT | VK_PIPELINE_STAGE_HOST_BIT |
933        VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT | VK_PIPELINE_STAGE_TRANSFER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT |
934        VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT |
935        VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT |
936        VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT | VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT |
937        VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_INPUT_BIT | VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT |
938        VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT);
939    if (enumerator & (~allFlags)) {
940        return false;
941    }
942
943    return true;
944}
945
946static std::string EnumeratorString(VkPipelineStageFlagBits const &enumerator) {
947    if (!ValidateEnumerator(enumerator)) {
948        return "unrecognized enumerator";
949    }
950
951    std::vector<std::string> strings;
952    if (enumerator & VK_PIPELINE_STAGE_ALL_COMMANDS_BIT) {
953        strings.push_back("VK_PIPELINE_STAGE_ALL_COMMANDS_BIT");
954    }
955    if (enumerator & VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT) {
956        strings.push_back("VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT");
957    }
958    if (enumerator & VK_PIPELINE_STAGE_HOST_BIT) {
959        strings.push_back("VK_PIPELINE_STAGE_HOST_BIT");
960    }
961    if (enumerator & VK_PIPELINE_STAGE_TRANSFER_BIT) {
962        strings.push_back("VK_PIPELINE_STAGE_TRANSFER_BIT");
963    }
964    if (enumerator & VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT) {
965        strings.push_back("VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT");
966    }
967    if (enumerator & VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT) {
968        strings.push_back("VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT");
969    }
970    if (enumerator & VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT) {
971        strings.push_back("VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT");
972    }
973    if (enumerator & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) {
974        strings.push_back("VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT");
975    }
976    if (enumerator & VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT) {
977        strings.push_back("VK_PIPELINE_STAGE_TESSELLATION_CONTROL_SHADER_BIT");
978    }
979    if (enumerator & VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT) {
980        strings.push_back("VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT");
981    }
982    if (enumerator & VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT) {
983        strings.push_back("VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT");
984    }
985    if (enumerator & VK_PIPELINE_STAGE_VERTEX_SHADER_BIT) {
986        strings.push_back("VK_PIPELINE_STAGE_VERTEX_SHADER_BIT");
987    }
988    if (enumerator & VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT) {
989        strings.push_back("VK_PIPELINE_STAGE_TESSELLATION_EVALUATION_SHADER_BIT");
990    }
991    if (enumerator & VK_PIPELINE_STAGE_VERTEX_INPUT_BIT) {
992        strings.push_back("VK_PIPELINE_STAGE_VERTEX_INPUT_BIT");
993    }
994    if (enumerator & VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT) {
995        strings.push_back("VK_PIPELINE_STAGE_GEOMETRY_SHADER_BIT");
996    }
997    if (enumerator & VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) {
998        strings.push_back("VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT");
999    }
1000    if (enumerator & VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT) {
1001        strings.push_back("VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT");
1002    }
1003
1004    std::string enumeratorString;
1005    for (auto const &string : strings) {
1006        enumeratorString += string;
1007
1008        if (string != strings.back()) {
1009            enumeratorString += '|';
1010        }
1011    }
1012
1013    return enumeratorString;
1014}
1015
1016static bool ValidateEnumerator(VkAccessFlagBits const &enumerator) {
1017    VkAccessFlagBits allFlags = (VkAccessFlagBits)(
1018        VK_ACCESS_INDIRECT_COMMAND_READ_BIT | VK_ACCESS_INDEX_READ_BIT | VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT |
1019        VK_ACCESS_UNIFORM_READ_BIT | VK_ACCESS_INPUT_ATTACHMENT_READ_BIT | VK_ACCESS_SHADER_READ_BIT | VK_ACCESS_SHADER_WRITE_BIT |
1020        VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT |
1021        VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT | VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT |
1022        VK_ACCESS_HOST_READ_BIT | VK_ACCESS_HOST_WRITE_BIT | VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
1023
1024    if (enumerator & (~allFlags)) {
1025        return false;
1026    }
1027
1028    return true;
1029}
1030
1031static std::string EnumeratorString(VkAccessFlagBits const &enumerator) {
1032    if (!ValidateEnumerator(enumerator)) {
1033        return "unrecognized enumerator";
1034    }
1035
1036    std::vector<std::string> strings;
1037    if (enumerator & VK_ACCESS_INDIRECT_COMMAND_READ_BIT) {
1038        strings.push_back("VK_ACCESS_INDIRECT_COMMAND_READ_BIT");
1039    }
1040    if (enumerator & VK_ACCESS_INDEX_READ_BIT) {
1041        strings.push_back("VK_ACCESS_INDEX_READ_BIT");
1042    }
1043    if (enumerator & VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT) {
1044        strings.push_back("VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT");
1045    }
1046    if (enumerator & VK_ACCESS_UNIFORM_READ_BIT) {
1047        strings.push_back("VK_ACCESS_UNIFORM_READ_BIT");
1048    }
1049    if (enumerator & VK_ACCESS_INPUT_ATTACHMENT_READ_BIT) {
1050        strings.push_back("VK_ACCESS_INPUT_ATTACHMENT_READ_BIT");
1051    }
1052    if (enumerator & VK_ACCESS_SHADER_READ_BIT) {
1053        strings.push_back("VK_ACCESS_SHADER_READ_BIT");
1054    }
1055    if (enumerator & VK_ACCESS_SHADER_WRITE_BIT) {
1056        strings.push_back("VK_ACCESS_SHADER_WRITE_BIT");
1057    }
1058    if (enumerator & VK_ACCESS_COLOR_ATTACHMENT_READ_BIT) {
1059        strings.push_back("VK_ACCESS_COLOR_ATTACHMENT_READ_BIT");
1060    }
1061    if (enumerator & VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT) {
1062        strings.push_back("VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT");
1063    }
1064    if (enumerator & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT) {
1065        strings.push_back("VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT");
1066    }
1067    if (enumerator & VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT) {
1068        strings.push_back("VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT");
1069    }
1070    if (enumerator & VK_ACCESS_TRANSFER_READ_BIT) {
1071        strings.push_back("VK_ACCESS_TRANSFER_READ_BIT");
1072    }
1073    if (enumerator & VK_ACCESS_TRANSFER_WRITE_BIT) {
1074        strings.push_back("VK_ACCESS_TRANSFER_WRITE_BIT");
1075    }
1076    if (enumerator & VK_ACCESS_HOST_READ_BIT) {
1077        strings.push_back("VK_ACCESS_HOST_READ_BIT");
1078    }
1079    if (enumerator & VK_ACCESS_HOST_WRITE_BIT) {
1080        strings.push_back("VK_ACCESS_HOST_WRITE_BIT");
1081    }
1082    if (enumerator & VK_ACCESS_MEMORY_READ_BIT) {
1083        strings.push_back("VK_ACCESS_MEMORY_READ_BIT");
1084    }
1085    if (enumerator & VK_ACCESS_MEMORY_WRITE_BIT) {
1086        strings.push_back("VK_ACCESS_MEMORY_WRITE_BIT");
1087    }
1088
1089    std::string enumeratorString;
1090    for (auto const &string : strings) {
1091        enumeratorString += string;
1092
1093        if (string != strings.back()) {
1094            enumeratorString += '|';
1095        }
1096    }
1097
1098    return enumeratorString;
1099}
1100
1101static bool ValidateEnumerator(VkCommandPoolCreateFlagBits const &enumerator) {
1102    VkCommandPoolCreateFlagBits allFlags =
1103        (VkCommandPoolCreateFlagBits)(VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT | VK_COMMAND_POOL_CREATE_TRANSIENT_BIT);
1104    if (enumerator & (~allFlags)) {
1105        return false;
1106    }
1107
1108    return true;
1109}
1110
1111static std::string EnumeratorString(VkCommandPoolCreateFlagBits const &enumerator) {
1112    if (!ValidateEnumerator(enumerator)) {
1113        return "unrecognized enumerator";
1114    }
1115
1116    std::vector<std::string> strings;
1117    if (enumerator & VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT) {
1118        strings.push_back("VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT");
1119    }
1120    if (enumerator & VK_COMMAND_POOL_CREATE_TRANSIENT_BIT) {
1121        strings.push_back("VK_COMMAND_POOL_CREATE_TRANSIENT_BIT");
1122    }
1123
1124    std::string enumeratorString;
1125    for (auto const &string : strings) {
1126        enumeratorString += string;
1127
1128        if (string != strings.back()) {
1129            enumeratorString += '|';
1130        }
1131    }
1132
1133    return enumeratorString;
1134}
1135
1136static bool ValidateEnumerator(VkCommandPoolResetFlagBits const &enumerator) {
1137    VkCommandPoolResetFlagBits allFlags = (VkCommandPoolResetFlagBits)(VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT);
1138    if (enumerator & (~allFlags)) {
1139        return false;
1140    }
1141
1142    return true;
1143}
1144
1145static std::string EnumeratorString(VkCommandPoolResetFlagBits const &enumerator) {
1146    if (!ValidateEnumerator(enumerator)) {
1147        return "unrecognized enumerator";
1148    }
1149
1150    std::vector<std::string> strings;
1151    if (enumerator & VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT) {
1152        strings.push_back("VK_COMMAND_POOL_RESET_RELEASE_RESOURCES_BIT");
1153    }
1154
1155    std::string enumeratorString;
1156    for (auto const &string : strings) {
1157        enumeratorString += string;
1158
1159        if (string != strings.back()) {
1160            enumeratorString += '|';
1161        }
1162    }
1163
1164    return enumeratorString;
1165}
1166
1167static bool ValidateEnumerator(VkCommandBufferUsageFlags const &enumerator) {
1168    VkCommandBufferUsageFlags allFlags =
1169        (VkCommandBufferUsageFlags)(VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT | VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT |
1170                                    VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT);
1171    if (enumerator & (~allFlags)) {
1172        return false;
1173    }
1174
1175    return true;
1176}
1177
1178static std::string EnumeratorString(VkCommandBufferUsageFlags const &enumerator) {
1179    if (!ValidateEnumerator(enumerator)) {
1180        return "unrecognized enumerator";
1181    }
1182
1183    std::vector<std::string> strings;
1184    if (enumerator & VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT) {
1185        strings.push_back("VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT");
1186    }
1187    if (enumerator & VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT) {
1188        strings.push_back("VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT");
1189    }
1190    if (enumerator & VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT) {
1191        strings.push_back("VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT");
1192    }
1193
1194    std::string enumeratorString;
1195    for (auto const &string : strings) {
1196        enumeratorString += string;
1197
1198        if (string != strings.back()) {
1199            enumeratorString += '|';
1200        }
1201    }
1202
1203    return enumeratorString;
1204}
1205
1206static bool ValidateEnumerator(VkCommandBufferResetFlagBits const &enumerator) {
1207    VkCommandBufferResetFlagBits allFlags = (VkCommandBufferResetFlagBits)(VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT);
1208    if (enumerator & (~allFlags)) {
1209        return false;
1210    }
1211
1212    return true;
1213}
1214
1215static std::string EnumeratorString(VkCommandBufferResetFlagBits const &enumerator) {
1216    if (!ValidateEnumerator(enumerator)) {
1217        return "unrecognized enumerator";
1218    }
1219
1220    std::vector<std::string> strings;
1221    if (enumerator & VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT) {
1222        strings.push_back("VK_COMMAND_BUFFER_RESET_RELEASE_RESOURCES_BIT");
1223    }
1224
1225    std::string enumeratorString;
1226    for (auto const &string : strings) {
1227        enumeratorString += string;
1228
1229        if (string != strings.back()) {
1230            enumeratorString += '|';
1231        }
1232    }
1233
1234    return enumeratorString;
1235}
1236
1237static bool ValidateEnumerator(VkImageAspectFlagBits const &enumerator) {
1238    VkImageAspectFlagBits allFlags = (VkImageAspectFlagBits)(VK_IMAGE_ASPECT_METADATA_BIT | VK_IMAGE_ASPECT_STENCIL_BIT |
1239                                                             VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_COLOR_BIT);
1240    if (enumerator & (~allFlags)) {
1241        return false;
1242    }
1243
1244    return true;
1245}
1246
1247static std::string EnumeratorString(VkImageAspectFlagBits const &enumerator) {
1248    if (!ValidateEnumerator(enumerator)) {
1249        return "unrecognized enumerator";
1250    }
1251
1252    std::vector<std::string> strings;
1253    if (enumerator & VK_IMAGE_ASPECT_METADATA_BIT) {
1254        strings.push_back("VK_IMAGE_ASPECT_METADATA_BIT");
1255    }
1256    if (enumerator & VK_IMAGE_ASPECT_STENCIL_BIT) {
1257        strings.push_back("VK_IMAGE_ASPECT_STENCIL_BIT");
1258    }
1259    if (enumerator & VK_IMAGE_ASPECT_DEPTH_BIT) {
1260        strings.push_back("VK_IMAGE_ASPECT_DEPTH_BIT");
1261    }
1262    if (enumerator & VK_IMAGE_ASPECT_COLOR_BIT) {
1263        strings.push_back("VK_IMAGE_ASPECT_COLOR_BIT");
1264    }
1265
1266    std::string enumeratorString;
1267    for (auto const &string : strings) {
1268        enumeratorString += string;
1269
1270        if (string != strings.back()) {
1271            enumeratorString += '|';
1272        }
1273    }
1274
1275    return enumeratorString;
1276}
1277
1278static bool validate_queue_family_indices(VkDevice device, const char *function_name, const uint32_t count,
1279                                          const uint32_t *indices) {
1280    bool skipCall = false;
1281    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1282
1283    for (auto i = 0u; i < count; i++) {
1284        if (indices[i] == VK_QUEUE_FAMILY_IGNORED) {
1285            skipCall |=
1286                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1287                        "%s: the specified queueFamilyIndex cannot be VK_QUEUE_FAMILY_IGNORED.", function_name);
1288        } else {
1289            const auto &queue_data = my_device_data->queueFamilyIndexMap.find(indices[i]);
1290            if (queue_data == my_device_data->queueFamilyIndexMap.end()) {
1291                skipCall |= log_msg(
1292                    mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1293                    "VkGetDeviceQueue parameter, uint32_t queueFamilyIndex %d, must have been given when the device was created.",
1294                    indices[i]);
1295                return false;
1296            }
1297        }
1298    }
1299    return skipCall;
1300}
1301
1302static bool ValidateEnumerator(VkQueryControlFlagBits const &enumerator) {
1303    VkQueryControlFlagBits allFlags = (VkQueryControlFlagBits)(VK_QUERY_CONTROL_PRECISE_BIT);
1304    if (enumerator & (~allFlags)) {
1305        return false;
1306    }
1307
1308    return true;
1309}
1310
1311static std::string EnumeratorString(VkQueryControlFlagBits const &enumerator) {
1312    if (!ValidateEnumerator(enumerator)) {
1313        return "unrecognized enumerator";
1314    }
1315
1316    std::vector<std::string> strings;
1317    if (enumerator & VK_QUERY_CONTROL_PRECISE_BIT) {
1318        strings.push_back("VK_QUERY_CONTROL_PRECISE_BIT");
1319    }
1320
1321    std::string enumeratorString;
1322    for (auto const &string : strings) {
1323        enumeratorString += string;
1324
1325        if (string != strings.back()) {
1326            enumeratorString += '|';
1327        }
1328    }
1329
1330    return enumeratorString;
1331}
1332
1333static const int MaxParamCheckerStringLength = 256;
1334
1335static VkBool32 validate_string(debug_report_data *report_data, const char *apiName, const char *stringName,
1336                                const char *validateString) {
1337    assert(apiName != nullptr);
1338    assert(stringName != nullptr);
1339    assert(validateString != nullptr);
1340
1341    VkBool32 skipCall = VK_FALSE;
1342
1343    VkStringErrorFlags result = vk_string_validate(MaxParamCheckerStringLength, validateString);
1344
1345    if (result == VK_STRING_ERROR_NONE) {
1346        return skipCall;
1347    } else if (result & VK_STRING_ERROR_LENGTH) {
1348        skipCall = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1349                           "%s: string %s exceeds max length %d", apiName, stringName, MaxParamCheckerStringLength);
1350    } else if (result & VK_STRING_ERROR_BAD_DATA) {
1351        skipCall = log_msg(report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1352                           "%s: string %s contains invalid characters or is badly formed", apiName, stringName);
1353    }
1354    return skipCall;
1355}
1356
1357VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1358vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
1359    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1360
1361    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1362    assert(chain_info != nullptr);
1363    assert(chain_info->u.pLayerInfo != nullptr);
1364
1365    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1366    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
1367    if (fpCreateInstance == NULL) {
1368        return VK_ERROR_INITIALIZATION_FAILED;
1369    }
1370
1371    // Advance the link info for the next element on the chain
1372    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1373
1374    result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
1375    if (result != VK_SUCCESS) {
1376        return result;
1377    }
1378
1379    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
1380    assert(my_instance_data != nullptr);
1381
1382    VkLayerInstanceDispatchTable *pTable = initInstanceTable(*pInstance, fpGetInstanceProcAddr, pc_instance_table_map);
1383
1384    my_instance_data->report_data =
1385        debug_report_create_instance(pTable, *pInstance, pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
1386
1387    init_parameter_validation(my_instance_data, pAllocator);
1388
1389    // Ordinarily we'd check these before calling down the chain, but none of the layer
1390    // support is in place until now, if we survive we can report the issue now.
1391    parameter_validation_vkCreateInstance(my_instance_data->report_data, pCreateInfo, pAllocator, pInstance);
1392
1393    if (pCreateInfo->pApplicationInfo) {
1394        if (pCreateInfo->pApplicationInfo->pApplicationName) {
1395            validate_string(my_instance_data->report_data, "vkCreateInstance", "pCreateInfo->VkApplicationInfo->pApplicationName",
1396                            pCreateInfo->pApplicationInfo->pApplicationName);
1397        }
1398
1399        if (pCreateInfo->pApplicationInfo->pEngineName) {
1400            validate_string(my_instance_data->report_data, "vkCreateInstance", "pCreateInfo->VkApplicationInfo->pEngineName",
1401                            pCreateInfo->pApplicationInfo->pEngineName);
1402        }
1403    }
1404
1405    return result;
1406}
1407
1408VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
1409    // Grab the key before the instance is destroyed.
1410    dispatch_key key = get_dispatch_key(instance);
1411    VkBool32 skipCall = VK_FALSE;
1412    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
1413    assert(my_data != NULL);
1414
1415    skipCall |= parameter_validation_vkDestroyInstance(my_data->report_data, pAllocator);
1416
1417    if (skipCall == VK_FALSE) {
1418        VkLayerInstanceDispatchTable *pTable = get_dispatch_table(pc_instance_table_map, instance);
1419        pTable->DestroyInstance(instance, pAllocator);
1420
1421        // Clean up logging callback, if any
1422        while (my_data->logging_callback.size() > 0) {
1423            VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
1424            layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
1425            my_data->logging_callback.pop_back();
1426        }
1427
1428        layer_debug_report_destroy_instance(mid(instance));
1429        layer_data_map.erase(pTable);
1430
1431        pc_instance_table_map.erase(key);
1432        layer_data_map.erase(key);
1433    }
1434}
1435
1436bool PostEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices,
1437                                  VkResult result) {
1438    if (result < VK_SUCCESS) {
1439        std::string reason = "vkEnumeratePhysicalDevices parameter, VkResult result, is " + EnumeratorString(result);
1440        log_msg(mid(instance), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1441                reason.c_str());
1442        return false;
1443    }
1444
1445    return true;
1446}
1447
1448VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1449vkEnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
1450    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1451    VkBool32 skipCall = VK_FALSE;
1452    layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
1453    assert(my_data != NULL);
1454
1455    skipCall |= parameter_validation_vkEnumeratePhysicalDevices(my_data->report_data, pPhysicalDeviceCount, pPhysicalDevices);
1456
1457    if (skipCall == VK_FALSE) {
1458        result = get_dispatch_table(pc_instance_table_map, instance)
1459                     ->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
1460
1461        PostEnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices, result);
1462    }
1463
1464    return result;
1465}
1466
1467VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1468vkGetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
1469    VkBool32 skipCall = VK_FALSE;
1470    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1471    assert(my_data != NULL);
1472
1473    skipCall |= parameter_validation_vkGetPhysicalDeviceFeatures(my_data->report_data, pFeatures);
1474
1475    if (skipCall == VK_FALSE) {
1476        get_dispatch_table(pc_instance_table_map, physicalDevice)->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
1477    }
1478}
1479
1480bool PostGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format,
1481                                           VkFormatProperties *pFormatProperties) {
1482
1483    if (format < VK_FORMAT_BEGIN_RANGE || format > VK_FORMAT_END_RANGE) {
1484        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1485                "vkGetPhysicalDeviceFormatProperties parameter, VkFormat format, is an unrecognized enumerator");
1486        return false;
1487    }
1488
1489    return true;
1490}
1491
1492VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1493vkGetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
1494    VkBool32 skipCall = VK_FALSE;
1495    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1496    assert(my_data != NULL);
1497
1498    skipCall |= parameter_validation_vkGetPhysicalDeviceFormatProperties(my_data->report_data, format, pFormatProperties);
1499
1500    if (skipCall == VK_FALSE) {
1501        get_dispatch_table(pc_instance_table_map, physicalDevice)
1502            ->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
1503
1504        PostGetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
1505    }
1506}
1507
1508bool PostGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
1509                                                VkImageTiling tiling, VkImageUsageFlags usage, VkImageCreateFlags flags,
1510                                                VkImageFormatProperties *pImageFormatProperties, VkResult result) {
1511
1512    if (format < VK_FORMAT_BEGIN_RANGE || format > VK_FORMAT_END_RANGE) {
1513        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1514                "vkGetPhysicalDeviceImageFormatProperties parameter, VkFormat format, is an unrecognized enumerator");
1515        return false;
1516    }
1517
1518    if (type < VK_IMAGE_TYPE_BEGIN_RANGE || type > VK_IMAGE_TYPE_END_RANGE) {
1519        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1520                "vkGetPhysicalDeviceImageFormatProperties parameter, VkImageType type, is an unrecognized enumerator");
1521        return false;
1522    }
1523
1524    if (tiling < VK_IMAGE_TILING_BEGIN_RANGE || tiling > VK_IMAGE_TILING_END_RANGE) {
1525        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1526                "vkGetPhysicalDeviceImageFormatProperties parameter, VkImageTiling tiling, is an unrecognized enumerator");
1527        return false;
1528    }
1529
1530    if (result < VK_SUCCESS) {
1531        std::string reason = "vkGetPhysicalDeviceImageFormatProperties parameter, VkResult result, is " + EnumeratorString(result);
1532        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1533                "%s", reason.c_str());
1534        return false;
1535    }
1536
1537    return true;
1538}
1539
1540VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1541vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
1542                                         VkImageUsageFlags usage, VkImageCreateFlags flags,
1543                                         VkImageFormatProperties *pImageFormatProperties) {
1544    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1545    VkBool32 skipCall = VK_FALSE;
1546    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1547    assert(my_data != NULL);
1548
1549    skipCall |= parameter_validation_vkGetPhysicalDeviceImageFormatProperties(my_data->report_data, format, type, tiling, usage, flags,
1550                                                                     pImageFormatProperties);
1551
1552    if (skipCall == VK_FALSE) {
1553        result = get_dispatch_table(pc_instance_table_map, physicalDevice)
1554                     ->GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags,
1555                                                              pImageFormatProperties);
1556
1557        PostGetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags, pImageFormatProperties,
1558                                                   result);
1559    }
1560
1561    return result;
1562}
1563
1564bool PostGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
1565
1566    if (pProperties != nullptr) {
1567        if (pProperties->deviceType < VK_PHYSICAL_DEVICE_TYPE_BEGIN_RANGE ||
1568            pProperties->deviceType > VK_PHYSICAL_DEVICE_TYPE_END_RANGE) {
1569            log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1570                    "vkGetPhysicalDeviceProperties parameter, VkPhysicalDeviceType pProperties->deviceType, is an unrecognized "
1571                    "enumerator");
1572            return false;
1573        }
1574    }
1575
1576    return true;
1577}
1578
1579VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1580vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
1581    VkBool32 skipCall = VK_FALSE;
1582    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1583    assert(my_data != NULL);
1584
1585    skipCall |= parameter_validation_vkGetPhysicalDeviceProperties(my_data->report_data, pProperties);
1586
1587    if (skipCall == VK_FALSE) {
1588        get_dispatch_table(pc_instance_table_map, physicalDevice)->GetPhysicalDeviceProperties(physicalDevice, pProperties);
1589
1590        PostGetPhysicalDeviceProperties(physicalDevice, pProperties);
1591    }
1592}
1593
1594VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1595vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pQueueFamilyPropertyCount,
1596                                         VkQueueFamilyProperties *pQueueFamilyProperties) {
1597    VkBool32 skipCall = VK_FALSE;
1598    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1599    assert(my_data != NULL);
1600
1601    skipCall |= parameter_validation_vkGetPhysicalDeviceQueueFamilyProperties(my_data->report_data, pQueueFamilyPropertyCount,
1602                                                                     pQueueFamilyProperties);
1603
1604    if (skipCall == VK_FALSE) {
1605        get_dispatch_table(pc_instance_table_map, physicalDevice)
1606            ->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pQueueFamilyPropertyCount, pQueueFamilyProperties);
1607    }
1608}
1609
1610VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1611vkGetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
1612    VkBool32 skipCall = VK_FALSE;
1613    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1614    assert(my_data != NULL);
1615
1616    skipCall |= parameter_validation_vkGetPhysicalDeviceMemoryProperties(my_data->report_data, pMemoryProperties);
1617
1618    if (skipCall == VK_FALSE) {
1619        get_dispatch_table(pc_instance_table_map, physicalDevice)
1620            ->GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
1621    }
1622}
1623
1624void validateDeviceCreateInfo(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo *pCreateInfo,
1625                              const std::vector<VkQueueFamilyProperties> properties) {
1626    std::unordered_set<uint32_t> set;
1627
1628    if ((pCreateInfo != nullptr) && (pCreateInfo->pQueueCreateInfos != nullptr)) {
1629        for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; ++i) {
1630            if (set.count(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex)) {
1631                log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
1632                        "PARAMCHECK",
1633                        "VkDeviceCreateInfo parameter, uint32_t pQueueCreateInfos[%d]->queueFamilyIndex, is not unique within this "
1634                        "structure.",
1635                        i);
1636            } else {
1637                set.insert(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex);
1638            }
1639
1640            if (pCreateInfo->pQueueCreateInfos[i].queueCount == 0) {
1641                log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
1642                        "PARAMCHECK", "VkDeviceCreateInfo parameter, uint32_t pQueueCreateInfos[%d]->queueCount, cannot be zero.",
1643                        i);
1644            }
1645
1646            if (pCreateInfo->pQueueCreateInfos[i].pQueuePriorities != nullptr) {
1647                for (uint32_t j = 0; j < pCreateInfo->pQueueCreateInfos[i].queueCount; ++j) {
1648                    if ((pCreateInfo->pQueueCreateInfos[i].pQueuePriorities[j] < 0.f) ||
1649                        (pCreateInfo->pQueueCreateInfos[i].pQueuePriorities[j] > 1.f)) {
1650                        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1,
1651                                "PARAMCHECK",
1652                                "VkDeviceCreateInfo parameter, uint32_t pQueueCreateInfos[%d]->pQueuePriorities[%d], must be "
1653                                "between 0 and 1. Actual value is %f",
1654                                i, j, pCreateInfo->pQueueCreateInfos[i].pQueuePriorities[j]);
1655                    }
1656                }
1657            }
1658
1659            if (pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex >= properties.size()) {
1660                log_msg(
1661                    mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1662                    "VkDeviceCreateInfo parameter, uint32_t pQueueCreateInfos[%d]->queueFamilyIndex cannot be more than the number "
1663                    "of queue families.",
1664                    i);
1665            } else if (pCreateInfo->pQueueCreateInfos[i].queueCount >
1666                       properties[pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex].queueCount) {
1667                log_msg(
1668                    mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1669                    "VkDeviceCreateInfo parameter, uint32_t pQueueCreateInfos[%d]->queueCount cannot be more than the number of "
1670                    "queues for the given family index.",
1671                    i);
1672            }
1673        }
1674    }
1675}
1676
1677void storeCreateDeviceData(VkDevice device, const VkDeviceCreateInfo *pCreateInfo) {
1678    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1679
1680    if ((pCreateInfo != nullptr) && (pCreateInfo->pQueueCreateInfos != nullptr)) {
1681        for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; ++i) {
1682            my_device_data->queueFamilyIndexMap.insert(
1683                std::make_pair(pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex, pCreateInfo->pQueueCreateInfos[i].queueCount));
1684        }
1685    }
1686}
1687
1688VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
1689                                                              const VkDeviceCreateInfo *pCreateInfo,
1690                                                              const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
1691    /*
1692     * NOTE: We do not validate physicalDevice or any dispatchable
1693     * object as the first parameter. We couldn't get here if it was wrong!
1694     */
1695
1696    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1697    VkBool32 skipCall = VK_FALSE;
1698    layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1699    assert(my_instance_data != nullptr);
1700
1701    skipCall |= parameter_validation_vkCreateDevice(my_instance_data->report_data, pCreateInfo, pAllocator, pDevice);
1702
1703    if (pCreateInfo != NULL) {
1704        if ((pCreateInfo->enabledLayerCount > 0) && (pCreateInfo->ppEnabledLayerNames != NULL)) {
1705            for (auto i = 0; i < pCreateInfo->enabledLayerCount; i++) {
1706                skipCall |= validate_string(my_instance_data->report_data, "vkCreateDevice", "pCreateInfo->ppEnabledLayerNames",
1707                                            pCreateInfo->ppEnabledLayerNames[i]);
1708            }
1709        }
1710
1711        if ((pCreateInfo->enabledExtensionCount > 0) && (pCreateInfo->ppEnabledExtensionNames != NULL)) {
1712            for (auto i = 0; i < pCreateInfo->enabledExtensionCount; i++) {
1713                skipCall |= validate_string(my_instance_data->report_data, "vkCreateDevice", "pCreateInfo->ppEnabledExtensionNames",
1714                                            pCreateInfo->ppEnabledExtensionNames[i]);
1715            }
1716        }
1717    }
1718
1719    if (skipCall == VK_FALSE) {
1720        VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
1721        assert(chain_info != nullptr);
1722        assert(chain_info->u.pLayerInfo != nullptr);
1723
1724        PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
1725        PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
1726        PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
1727        if (fpCreateDevice == NULL) {
1728            return VK_ERROR_INITIALIZATION_FAILED;
1729        }
1730
1731        // Advance the link info for the next element on the chain
1732        chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
1733
1734        result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
1735        if (result != VK_SUCCESS) {
1736            return result;
1737        }
1738
1739        layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
1740        assert(my_device_data != nullptr);
1741
1742        my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
1743        initDeviceTable(*pDevice, fpGetDeviceProcAddr, pc_device_table_map);
1744
1745        uint32_t count;
1746        get_dispatch_table(pc_instance_table_map, physicalDevice)
1747            ->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr);
1748        std::vector<VkQueueFamilyProperties> properties(count);
1749        get_dispatch_table(pc_instance_table_map, physicalDevice)
1750            ->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, &properties[0]);
1751
1752        validateDeviceCreateInfo(physicalDevice, pCreateInfo, properties);
1753        storeCreateDeviceData(*pDevice, pCreateInfo);
1754    }
1755
1756    return result;
1757}
1758
1759VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
1760    dispatch_key key = get_dispatch_key(device);
1761    VkBool32 skipCall = VK_FALSE;
1762    layer_data *my_data = get_my_data_ptr(key, layer_data_map);
1763    assert(my_data != NULL);
1764
1765    skipCall |= parameter_validation_vkDestroyDevice(my_data->report_data, pAllocator);
1766
1767    if (skipCall == VK_FALSE) {
1768        layer_debug_report_destroy_device(device);
1769
1770#if DISPATCH_MAP_DEBUG
1771        fprintf(stderr, "Device: %p, key: %p\n", device, key);
1772#endif
1773
1774        get_dispatch_table(pc_device_table_map, device)->DestroyDevice(device, pAllocator);
1775        pc_device_table_map.erase(key);
1776    }
1777}
1778
1779bool PreGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex) {
1780    layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1781    assert(my_device_data != nullptr);
1782
1783    validate_queue_family_indices(device, "vkGetDeviceQueue", 1, &queueFamilyIndex);
1784
1785    const auto &queue_data = my_device_data->queueFamilyIndexMap.find(queueFamilyIndex);
1786    if (queue_data->second <= queueIndex) {
1787        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
1788                "VkGetDeviceQueue parameter, uint32_t queueIndex %d, must be less than the number of queues given when the device "
1789                "was created.",
1790                queueIndex);
1791        return false;
1792    }
1793
1794    return true;
1795}
1796
1797VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1798vkGetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
1799    VkBool32 skipCall = VK_FALSE;
1800    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1801    assert(my_data != NULL);
1802
1803    skipCall |= parameter_validation_vkGetDeviceQueue(my_data->report_data, queueFamilyIndex, queueIndex, pQueue);
1804
1805    if (skipCall == VK_FALSE) {
1806        PreGetDeviceQueue(device, queueFamilyIndex, queueIndex);
1807
1808        get_dispatch_table(pc_device_table_map, device)->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
1809    }
1810}
1811
1812bool PostQueueSubmit(VkQueue queue, uint32_t commandBufferCount, VkFence fence, VkResult result) {
1813    if (result < VK_SUCCESS) {
1814        std::string reason = "vkQueueSubmit parameter, VkResult result, is " + EnumeratorString(result);
1815        log_msg(mdd(queue), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1816                reason.c_str());
1817        return false;
1818    }
1819
1820    return true;
1821}
1822
1823VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1824vkQueueSubmit(VkQueue queue, uint32_t submitCount, const VkSubmitInfo *pSubmits, VkFence fence) {
1825    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1826    VkBool32 skipCall = VK_FALSE;
1827    layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
1828    assert(my_data != NULL);
1829
1830    skipCall |= parameter_validation_vkQueueSubmit(my_data->report_data, submitCount, pSubmits, fence);
1831
1832    if (skipCall == VK_FALSE) {
1833        result = get_dispatch_table(pc_device_table_map, queue)->QueueSubmit(queue, submitCount, pSubmits, fence);
1834
1835        PostQueueSubmit(queue, submitCount, fence, result);
1836    }
1837
1838    return result;
1839}
1840
1841bool PostQueueWaitIdle(VkQueue queue, VkResult result) {
1842
1843    if (result < VK_SUCCESS) {
1844        std::string reason = "vkQueueWaitIdle parameter, VkResult result, is " + EnumeratorString(result);
1845        log_msg(mdd(queue), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1846                reason.c_str());
1847        return false;
1848    }
1849
1850    return true;
1851}
1852
1853VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue) {
1854    VkResult result = get_dispatch_table(pc_device_table_map, queue)->QueueWaitIdle(queue);
1855
1856    PostQueueWaitIdle(queue, result);
1857
1858    return result;
1859}
1860
1861bool PostDeviceWaitIdle(VkDevice device, VkResult result) {
1862
1863    if (result < VK_SUCCESS) {
1864        std::string reason = "vkDeviceWaitIdle parameter, VkResult result, is " + EnumeratorString(result);
1865        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1866                reason.c_str());
1867        return false;
1868    }
1869
1870    return true;
1871}
1872
1873VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device) {
1874    VkResult result = get_dispatch_table(pc_device_table_map, device)->DeviceWaitIdle(device);
1875
1876    PostDeviceWaitIdle(device, result);
1877
1878    return result;
1879}
1880
1881bool PostAllocateMemory(VkDevice device, VkDeviceMemory *pMemory, VkResult result) {
1882    if (result < VK_SUCCESS) {
1883        std::string reason = "vkAllocateMemory parameter, VkResult result, is " + EnumeratorString(result);
1884        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1885                reason.c_str());
1886        return false;
1887    }
1888
1889    return true;
1890}
1891
1892VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkAllocateMemory(VkDevice device, const VkMemoryAllocateInfo *pAllocateInfo,
1893                                                                const VkAllocationCallbacks *pAllocator, VkDeviceMemory *pMemory) {
1894    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1895    VkBool32 skipCall = VK_FALSE;
1896    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1897    assert(my_data != NULL);
1898
1899    skipCall |= parameter_validation_vkAllocateMemory(my_data->report_data, pAllocateInfo, pAllocator, pMemory);
1900
1901    if (skipCall == VK_FALSE) {
1902        result = get_dispatch_table(pc_device_table_map, device)->AllocateMemory(device, pAllocateInfo, pAllocator, pMemory);
1903
1904        PostAllocateMemory(device, pMemory, result);
1905    }
1906
1907    return result;
1908}
1909
1910VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
1911vkFreeMemory(VkDevice device, VkDeviceMemory memory, const VkAllocationCallbacks *pAllocator) {
1912    VkBool32 skipCall = VK_FALSE;
1913    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1914    assert(my_data != NULL);
1915
1916    skipCall |= parameter_validation_vkFreeMemory(my_data->report_data, memory, pAllocator);
1917
1918    if (skipCall == VK_FALSE) {
1919        get_dispatch_table(pc_device_table_map, device)->FreeMemory(device, memory, pAllocator);
1920    }
1921}
1922
1923bool PostMapMemory(VkDevice device, VkDeviceMemory mem, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags,
1924                   void **ppData, VkResult result) {
1925    if (result < VK_SUCCESS) {
1926        std::string reason = "vkMapMemory parameter, VkResult result, is " + EnumeratorString(result);
1927        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1928                reason.c_str());
1929        return false;
1930    }
1931
1932    return true;
1933}
1934
1935VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1936vkMapMemory(VkDevice device, VkDeviceMemory memory, VkDeviceSize offset, VkDeviceSize size, VkMemoryMapFlags flags, void **ppData) {
1937    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1938    VkBool32 skipCall = VK_FALSE;
1939    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1940    assert(my_data != NULL);
1941
1942    skipCall |= parameter_validation_vkMapMemory(my_data->report_data, memory, offset, size, flags, ppData);
1943
1944    if (skipCall == VK_FALSE) {
1945        result = get_dispatch_table(pc_device_table_map, device)->MapMemory(device, memory, offset, size, flags, ppData);
1946
1947        PostMapMemory(device, memory, offset, size, flags, ppData, result);
1948    }
1949
1950    return result;
1951}
1952
1953bool PostFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, VkResult result) {
1954
1955    if (result < VK_SUCCESS) {
1956        std::string reason = "vkFlushMappedMemoryRanges parameter, VkResult result, is " + EnumeratorString(result);
1957        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1958                reason.c_str());
1959        return false;
1960    }
1961
1962    return true;
1963}
1964
1965VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1966vkFlushMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) {
1967    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1968    VkBool32 skipCall = VK_FALSE;
1969    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1970    assert(my_data != NULL);
1971
1972    skipCall |= parameter_validation_vkFlushMappedMemoryRanges(my_data->report_data, memoryRangeCount, pMemoryRanges);
1973
1974    if (skipCall == VK_FALSE) {
1975        result = get_dispatch_table(pc_device_table_map, device)->FlushMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
1976
1977        PostFlushMappedMemoryRanges(device, memoryRangeCount, result);
1978    }
1979
1980    return result;
1981}
1982
1983bool PostInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, VkResult result) {
1984
1985    if (result < VK_SUCCESS) {
1986        std::string reason = "vkInvalidateMappedMemoryRanges parameter, VkResult result, is " + EnumeratorString(result);
1987        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
1988                reason.c_str());
1989        return false;
1990    }
1991
1992    return true;
1993}
1994
1995VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
1996vkInvalidateMappedMemoryRanges(VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges) {
1997    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
1998    VkBool32 skipCall = VK_FALSE;
1999    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2000    assert(my_data != NULL);
2001
2002    skipCall |= parameter_validation_vkInvalidateMappedMemoryRanges(my_data->report_data, memoryRangeCount, pMemoryRanges);
2003
2004    if (skipCall == VK_FALSE) {
2005        result =
2006            get_dispatch_table(pc_device_table_map, device)->InvalidateMappedMemoryRanges(device, memoryRangeCount, pMemoryRanges);
2007
2008        PostInvalidateMappedMemoryRanges(device, memoryRangeCount, result);
2009    }
2010
2011    return result;
2012}
2013
2014VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2015vkGetDeviceMemoryCommitment(VkDevice device, VkDeviceMemory memory, VkDeviceSize *pCommittedMemoryInBytes) {
2016    VkBool32 skipCall = VK_FALSE;
2017    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2018    assert(my_data != NULL);
2019
2020    skipCall |= parameter_validation_vkGetDeviceMemoryCommitment(my_data->report_data, memory, pCommittedMemoryInBytes);
2021
2022    if (skipCall == VK_FALSE) {
2023        get_dispatch_table(pc_device_table_map, device)->GetDeviceMemoryCommitment(device, memory, pCommittedMemoryInBytes);
2024    }
2025}
2026
2027bool PostBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset, VkResult result) {
2028
2029    if (result < VK_SUCCESS) {
2030        std::string reason = "vkBindBufferMemory parameter, VkResult result, is " + EnumeratorString(result);
2031        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2032                reason.c_str());
2033        return false;
2034    }
2035
2036    return true;
2037}
2038
2039VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2040vkBindBufferMemory(VkDevice device, VkBuffer buffer, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
2041    VkResult result = get_dispatch_table(pc_device_table_map, device)->BindBufferMemory(device, buffer, mem, memoryOffset);
2042
2043    PostBindBufferMemory(device, buffer, mem, memoryOffset, result);
2044
2045    return result;
2046}
2047
2048bool PostBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset, VkResult result) {
2049
2050    if (result < VK_SUCCESS) {
2051        std::string reason = "vkBindImageMemory parameter, VkResult result, is " + EnumeratorString(result);
2052        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2053                reason.c_str());
2054        return false;
2055    }
2056
2057    return true;
2058}
2059
2060VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2061vkBindImageMemory(VkDevice device, VkImage image, VkDeviceMemory mem, VkDeviceSize memoryOffset) {
2062    VkResult result = get_dispatch_table(pc_device_table_map, device)->BindImageMemory(device, image, mem, memoryOffset);
2063
2064    PostBindImageMemory(device, image, mem, memoryOffset, result);
2065
2066    return result;
2067}
2068
2069VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2070vkGetBufferMemoryRequirements(VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements) {
2071    VkBool32 skipCall = VK_FALSE;
2072    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2073    assert(my_data != NULL);
2074
2075    skipCall |= parameter_validation_vkGetBufferMemoryRequirements(my_data->report_data, buffer, pMemoryRequirements);
2076
2077    if (skipCall == VK_FALSE) {
2078        get_dispatch_table(pc_device_table_map, device)->GetBufferMemoryRequirements(device, buffer, pMemoryRequirements);
2079    }
2080}
2081
2082VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2083vkGetImageMemoryRequirements(VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements) {
2084    VkBool32 skipCall = VK_FALSE;
2085    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2086    assert(my_data != NULL);
2087
2088    skipCall |= parameter_validation_vkGetImageMemoryRequirements(my_data->report_data, image, pMemoryRequirements);
2089
2090    if (skipCall == VK_FALSE) {
2091        get_dispatch_table(pc_device_table_map, device)->GetImageMemoryRequirements(device, image, pMemoryRequirements);
2092    }
2093}
2094
2095bool PostGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t *pNumRequirements,
2096                                          VkSparseImageMemoryRequirements *pSparseMemoryRequirements) {
2097    if (pSparseMemoryRequirements != nullptr) {
2098        if ((pSparseMemoryRequirements->formatProperties.aspectMask &
2099             (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT |
2100              VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
2101            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2102                    "vkGetImageSparseMemoryRequirements parameter, VkImageAspect "
2103                    "pSparseMemoryRequirements->formatProperties.aspectMask, is an unrecognized enumerator");
2104            return false;
2105        }
2106    }
2107
2108    return true;
2109}
2110
2111VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2112vkGetImageSparseMemoryRequirements(VkDevice device, VkImage image, uint32_t *pSparseMemoryRequirementCount,
2113                                   VkSparseImageMemoryRequirements *pSparseMemoryRequirements) {
2114    VkBool32 skipCall = VK_FALSE;
2115    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2116    assert(my_data != NULL);
2117
2118    skipCall |= parameter_validation_vkGetImageSparseMemoryRequirements(my_data->report_data, image, pSparseMemoryRequirementCount,
2119                                                               pSparseMemoryRequirements);
2120
2121    if (skipCall == VK_FALSE) {
2122        get_dispatch_table(pc_device_table_map, device)
2123            ->GetImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
2124
2125        PostGetImageSparseMemoryRequirements(device, image, pSparseMemoryRequirementCount, pSparseMemoryRequirements);
2126    }
2127}
2128
2129bool PostGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
2130                                                      VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
2131                                                      uint32_t *pNumProperties, VkSparseImageFormatProperties *pProperties) {
2132
2133    if (format < VK_FORMAT_BEGIN_RANGE || format > VK_FORMAT_END_RANGE) {
2134        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2135                "vkGetPhysicalDeviceSparseImageFormatProperties parameter, VkFormat format, is an unrecognized enumerator");
2136        return false;
2137    }
2138
2139    if (type < VK_IMAGE_TYPE_BEGIN_RANGE || type > VK_IMAGE_TYPE_END_RANGE) {
2140        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2141                "vkGetPhysicalDeviceSparseImageFormatProperties parameter, VkImageType type, is an unrecognized enumerator");
2142        return false;
2143    }
2144
2145    if (tiling < VK_IMAGE_TILING_BEGIN_RANGE || tiling > VK_IMAGE_TILING_END_RANGE) {
2146        log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2147                "vkGetPhysicalDeviceSparseImageFormatProperties parameter, VkImageTiling tiling, is an unrecognized enumerator");
2148        return false;
2149    }
2150
2151    if (pProperties != nullptr) {
2152        if ((pProperties->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT |
2153                                        VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
2154            log_msg(mdd(physicalDevice), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2155                    "vkGetPhysicalDeviceSparseImageFormatProperties parameter, VkImageAspect pProperties->aspectMask, is an "
2156                    "unrecognized enumerator");
2157            return false;
2158        }
2159    }
2160
2161    return true;
2162}
2163
2164VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2165vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
2166                                               VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
2167                                               uint32_t *pPropertyCount, VkSparseImageFormatProperties *pProperties) {
2168    VkBool32 skipCall = VK_FALSE;
2169    layer_data *my_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
2170    assert(my_data != NULL);
2171
2172    skipCall |= parameter_validation_vkGetPhysicalDeviceSparseImageFormatProperties(my_data->report_data, format, type, samples, usage,
2173                                                                           tiling, pPropertyCount, pProperties);
2174
2175    if (skipCall == VK_FALSE) {
2176        get_dispatch_table(pc_instance_table_map, physicalDevice)
2177            ->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pPropertyCount,
2178                                                           pProperties);
2179
2180        PostGetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage, tiling, pPropertyCount,
2181                                                         pProperties);
2182    }
2183}
2184
2185bool PostQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence, VkResult result) {
2186
2187    if (result < VK_SUCCESS) {
2188        std::string reason = "vkQueueBindSparse parameter, VkResult result, is " + EnumeratorString(result);
2189        log_msg(mdd(queue), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2190                reason.c_str());
2191        return false;
2192    }
2193
2194    return true;
2195}
2196
2197VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2198vkQueueBindSparse(VkQueue queue, uint32_t bindInfoCount, const VkBindSparseInfo *pBindInfo, VkFence fence) {
2199    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2200    VkBool32 skipCall = VK_FALSE;
2201    layer_data *my_data = get_my_data_ptr(get_dispatch_key(queue), layer_data_map);
2202    assert(my_data != NULL);
2203
2204    skipCall |= parameter_validation_vkQueueBindSparse(my_data->report_data, bindInfoCount, pBindInfo, fence);
2205
2206    if (skipCall == VK_FALSE) {
2207        result = get_dispatch_table(pc_device_table_map, queue)->QueueBindSparse(queue, bindInfoCount, pBindInfo, fence);
2208
2209        PostQueueBindSparse(queue, bindInfoCount, pBindInfo, fence, result);
2210    }
2211
2212    return result;
2213}
2214
2215bool PostCreateFence(VkDevice device, VkFence *pFence, VkResult result) {
2216    if (result < VK_SUCCESS) {
2217        std::string reason = "vkCreateFence parameter, VkResult result, is " + EnumeratorString(result);
2218        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2219                reason.c_str());
2220        return false;
2221    }
2222
2223    return true;
2224}
2225
2226VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2227vkCreateFence(VkDevice device, const VkFenceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkFence *pFence) {
2228    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2229    VkBool32 skipCall = VK_FALSE;
2230    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2231    assert(my_data != NULL);
2232
2233    skipCall |= parameter_validation_vkCreateFence(my_data->report_data, pCreateInfo, pAllocator, pFence);
2234
2235    if (skipCall == VK_FALSE) {
2236        result = get_dispatch_table(pc_device_table_map, device)->CreateFence(device, pCreateInfo, pAllocator, pFence);
2237
2238        PostCreateFence(device, pFence, result);
2239    }
2240
2241    return result;
2242}
2243
2244VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device, VkFence fence, const VkAllocationCallbacks *pAllocator) {
2245    VkBool32 skipCall = VK_FALSE;
2246    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2247    assert(my_data != NULL);
2248
2249    skipCall |= parameter_validation_vkDestroyFence(my_data->report_data, fence, pAllocator);
2250
2251    if (skipCall == VK_FALSE) {
2252        get_dispatch_table(pc_device_table_map, device)->DestroyFence(device, fence, pAllocator);
2253    }
2254}
2255
2256bool PostResetFences(VkDevice device, uint32_t fenceCount, VkResult result) {
2257
2258    if (result < VK_SUCCESS) {
2259        std::string reason = "vkResetFences parameter, VkResult result, is " + EnumeratorString(result);
2260        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2261                reason.c_str());
2262        return false;
2263    }
2264
2265    return true;
2266}
2267
2268VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences) {
2269    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2270    VkBool32 skipCall = VK_FALSE;
2271    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2272    assert(my_data != NULL);
2273
2274    skipCall |= parameter_validation_vkResetFences(my_data->report_data, fenceCount, pFences);
2275
2276    if (skipCall == VK_FALSE) {
2277        result = get_dispatch_table(pc_device_table_map, device)->ResetFences(device, fenceCount, pFences);
2278
2279        PostResetFences(device, fenceCount, result);
2280    }
2281
2282    return result;
2283}
2284
2285bool PostGetFenceStatus(VkDevice device, VkFence fence, VkResult result) {
2286
2287    if (result < VK_SUCCESS) {
2288        std::string reason = "vkGetFenceStatus parameter, VkResult result, is " + EnumeratorString(result);
2289        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2290                reason.c_str());
2291        return false;
2292    }
2293
2294    return true;
2295}
2296
2297VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, VkFence fence) {
2298    VkResult result = get_dispatch_table(pc_device_table_map, device)->GetFenceStatus(device, fence);
2299
2300    PostGetFenceStatus(device, fence, result);
2301
2302    return result;
2303}
2304
2305bool PostWaitForFences(VkDevice device, uint32_t fenceCount, VkBool32 waitAll, uint64_t timeout, VkResult result) {
2306
2307    if (result < VK_SUCCESS) {
2308        std::string reason = "vkWaitForFences parameter, VkResult result, is " + EnumeratorString(result);
2309        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2310                reason.c_str());
2311        return false;
2312    }
2313
2314    return true;
2315}
2316
2317VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2318vkWaitForFences(VkDevice device, uint32_t fenceCount, const VkFence *pFences, VkBool32 waitAll, uint64_t timeout) {
2319    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2320    VkBool32 skipCall = VK_FALSE;
2321    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2322    assert(my_data != NULL);
2323
2324    skipCall |= parameter_validation_vkWaitForFences(my_data->report_data, fenceCount, pFences, waitAll, timeout);
2325
2326    if (skipCall == VK_FALSE) {
2327        result = get_dispatch_table(pc_device_table_map, device)->WaitForFences(device, fenceCount, pFences, waitAll, timeout);
2328
2329        PostWaitForFences(device, fenceCount, waitAll, timeout, result);
2330    }
2331
2332    return result;
2333}
2334
2335bool PostCreateSemaphore(VkDevice device, VkSemaphore *pSemaphore, VkResult result) {
2336    if (result < VK_SUCCESS) {
2337        std::string reason = "vkCreateSemaphore parameter, VkResult result, is " + EnumeratorString(result);
2338        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2339                reason.c_str());
2340        return false;
2341    }
2342
2343    return true;
2344}
2345
2346VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSemaphore(VkDevice device, const VkSemaphoreCreateInfo *pCreateInfo,
2347                                                                 const VkAllocationCallbacks *pAllocator, VkSemaphore *pSemaphore) {
2348    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2349    VkBool32 skipCall = VK_FALSE;
2350    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2351    assert(my_data != NULL);
2352
2353    skipCall |= parameter_validation_vkCreateSemaphore(my_data->report_data, pCreateInfo, pAllocator, pSemaphore);
2354
2355    if (skipCall == VK_FALSE) {
2356        result = get_dispatch_table(pc_device_table_map, device)->CreateSemaphore(device, pCreateInfo, pAllocator, pSemaphore);
2357
2358        PostCreateSemaphore(device, pSemaphore, result);
2359    }
2360
2361    return result;
2362}
2363
2364VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2365vkDestroySemaphore(VkDevice device, VkSemaphore semaphore, const VkAllocationCallbacks *pAllocator) {
2366    VkBool32 skipCall = VK_FALSE;
2367    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2368    assert(my_data != NULL);
2369
2370    skipCall |= parameter_validation_vkDestroySemaphore(my_data->report_data, semaphore, pAllocator);
2371
2372    if (skipCall == VK_FALSE) {
2373        get_dispatch_table(pc_device_table_map, device)->DestroySemaphore(device, semaphore, pAllocator);
2374    }
2375}
2376
2377bool PostCreateEvent(VkDevice device, VkEvent *pEvent, VkResult result) {
2378    if (result < VK_SUCCESS) {
2379        std::string reason = "vkCreateEvent parameter, VkResult result, is " + EnumeratorString(result);
2380        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2381                reason.c_str());
2382        return false;
2383    }
2384
2385    return true;
2386}
2387
2388VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2389vkCreateEvent(VkDevice device, const VkEventCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkEvent *pEvent) {
2390    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2391    VkBool32 skipCall = VK_FALSE;
2392    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2393    assert(my_data != NULL);
2394
2395    skipCall |= parameter_validation_vkCreateEvent(my_data->report_data, pCreateInfo, pAllocator, pEvent);
2396
2397    if (skipCall == VK_FALSE) {
2398        result = get_dispatch_table(pc_device_table_map, device)->CreateEvent(device, pCreateInfo, pAllocator, pEvent);
2399
2400        PostCreateEvent(device, pEvent, result);
2401    }
2402
2403    return result;
2404}
2405
2406VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device, VkEvent event, const VkAllocationCallbacks *pAllocator) {
2407    VkBool32 skipCall = VK_FALSE;
2408    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2409    assert(my_data != NULL);
2410
2411    skipCall |= parameter_validation_vkDestroyEvent(my_data->report_data, event, pAllocator);
2412
2413    if (skipCall == VK_FALSE) {
2414        get_dispatch_table(pc_device_table_map, device)->DestroyEvent(device, event, pAllocator);
2415    }
2416}
2417
2418bool PostGetEventStatus(VkDevice device, VkEvent event, VkResult result) {
2419
2420    if (result < VK_SUCCESS) {
2421        std::string reason = "vkGetEventStatus parameter, VkResult result, is " + EnumeratorString(result);
2422        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2423                reason.c_str());
2424        return false;
2425    }
2426
2427    return true;
2428}
2429
2430VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(VkDevice device, VkEvent event) {
2431    VkResult result = get_dispatch_table(pc_device_table_map, device)->GetEventStatus(device, event);
2432
2433    PostGetEventStatus(device, event, result);
2434
2435    return result;
2436}
2437
2438bool PostSetEvent(VkDevice device, VkEvent event, VkResult result) {
2439
2440    if (result < VK_SUCCESS) {
2441        std::string reason = "vkSetEvent parameter, VkResult result, is " + EnumeratorString(result);
2442        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2443                reason.c_str());
2444        return false;
2445    }
2446
2447    return true;
2448}
2449
2450VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event) {
2451    VkResult result = get_dispatch_table(pc_device_table_map, device)->SetEvent(device, event);
2452
2453    PostSetEvent(device, event, result);
2454
2455    return result;
2456}
2457
2458bool PostResetEvent(VkDevice device, VkEvent event, VkResult result) {
2459
2460    if (result < VK_SUCCESS) {
2461        std::string reason = "vkResetEvent parameter, VkResult result, is " + EnumeratorString(result);
2462        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2463                reason.c_str());
2464        return false;
2465    }
2466
2467    return true;
2468}
2469
2470VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(VkDevice device, VkEvent event) {
2471    VkResult result = get_dispatch_table(pc_device_table_map, device)->ResetEvent(device, event);
2472
2473    PostResetEvent(device, event, result);
2474
2475    return result;
2476}
2477
2478bool PreCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo) {
2479    if (pCreateInfo != nullptr) {
2480        if (pCreateInfo->queryType < VK_QUERY_TYPE_BEGIN_RANGE || pCreateInfo->queryType > VK_QUERY_TYPE_END_RANGE) {
2481            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2482                    "vkCreateQueryPool parameter, VkQueryType pCreateInfo->queryType, is an unrecognized enumerator");
2483            return false;
2484        }
2485    }
2486
2487    return true;
2488}
2489
2490bool PostCreateQueryPool(VkDevice device, VkQueryPool *pQueryPool, VkResult result) {
2491    if (result < VK_SUCCESS) {
2492        std::string reason = "vkCreateQueryPool parameter, VkResult result, is " + EnumeratorString(result);
2493        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2494                reason.c_str());
2495        return false;
2496    }
2497
2498    return true;
2499}
2500
2501VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateQueryPool(VkDevice device, const VkQueryPoolCreateInfo *pCreateInfo,
2502                                                                 const VkAllocationCallbacks *pAllocator, VkQueryPool *pQueryPool) {
2503    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2504    VkBool32 skipCall = VK_FALSE;
2505    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2506    assert(my_data != NULL);
2507
2508    skipCall |= parameter_validation_vkCreateQueryPool(my_data->report_data, pCreateInfo, pAllocator, pQueryPool);
2509
2510    if (skipCall == VK_FALSE) {
2511        PreCreateQueryPool(device, pCreateInfo);
2512
2513        result = get_dispatch_table(pc_device_table_map, device)->CreateQueryPool(device, pCreateInfo, pAllocator, pQueryPool);
2514
2515        PostCreateQueryPool(device, pQueryPool, result);
2516    }
2517
2518    return result;
2519}
2520
2521VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2522vkDestroyQueryPool(VkDevice device, VkQueryPool queryPool, const VkAllocationCallbacks *pAllocator) {
2523    VkBool32 skipCall = VK_FALSE;
2524    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2525    assert(my_data != NULL);
2526
2527    skipCall |= parameter_validation_vkDestroyQueryPool(my_data->report_data, queryPool, pAllocator);
2528
2529    if (skipCall == VK_FALSE) {
2530        get_dispatch_table(pc_device_table_map, device)->DestroyQueryPool(device, queryPool, pAllocator);
2531    }
2532}
2533
2534bool PostGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, size_t dataSize,
2535                             void *pData, VkDeviceSize stride, VkQueryResultFlags flags, VkResult result) {
2536    if (result < VK_SUCCESS) {
2537        std::string reason = "vkGetQueryPoolResults parameter, VkResult result, is " + EnumeratorString(result);
2538        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2539                reason.c_str());
2540        return false;
2541    }
2542
2543    return true;
2544}
2545
2546VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(VkDevice device, VkQueryPool queryPool, uint32_t firstQuery,
2547                                                                     uint32_t queryCount, size_t dataSize, void *pData,
2548                                                                     VkDeviceSize stride, VkQueryResultFlags flags) {
2549    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2550    VkBool32 skipCall = VK_FALSE;
2551    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2552    assert(my_data != NULL);
2553
2554    skipCall |=
2555        parameter_validation_vkGetQueryPoolResults(my_data->report_data, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
2556
2557    if (skipCall == VK_FALSE) {
2558        result = get_dispatch_table(pc_device_table_map, device)
2559                     ->GetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags);
2560
2561        PostGetQueryPoolResults(device, queryPool, firstQuery, queryCount, dataSize, pData, stride, flags, result);
2562    }
2563
2564    return result;
2565}
2566
2567bool PreCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo) {
2568    if (pCreateInfo != nullptr) {
2569        if (pCreateInfo->sharingMode < VK_SHARING_MODE_BEGIN_RANGE || pCreateInfo->sharingMode > VK_SHARING_MODE_END_RANGE) {
2570            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2571                    "vkCreateBuffer parameter, VkSharingMode pCreateInfo->sharingMode, is an unrecognized enumerator");
2572            return false;
2573        } else if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
2574            validate_queue_family_indices(device, "vkCreateBuffer", pCreateInfo->queueFamilyIndexCount,
2575                                          pCreateInfo->pQueueFamilyIndices);
2576        }
2577    }
2578
2579    return true;
2580}
2581
2582bool PostCreateBuffer(VkDevice device, VkBuffer *pBuffer, VkResult result) {
2583    if (result < VK_SUCCESS) {
2584        std::string reason = "vkCreateBuffer parameter, VkResult result, is " + EnumeratorString(result);
2585        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2586                reason.c_str());
2587        return false;
2588    }
2589
2590    return true;
2591}
2592
2593VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2594vkCreateBuffer(VkDevice device, const VkBufferCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkBuffer *pBuffer) {
2595    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2596    VkBool32 skipCall = VK_FALSE;
2597    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2598    assert(my_data != NULL);
2599
2600    skipCall |= parameter_validation_vkCreateBuffer(my_data->report_data, pCreateInfo, pAllocator, pBuffer);
2601
2602    if (skipCall == VK_FALSE) {
2603        PreCreateBuffer(device, pCreateInfo);
2604
2605        result = get_dispatch_table(pc_device_table_map, device)->CreateBuffer(device, pCreateInfo, pAllocator, pBuffer);
2606
2607        PostCreateBuffer(device, pBuffer, result);
2608    }
2609
2610    return result;
2611}
2612
2613VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2614vkDestroyBuffer(VkDevice device, VkBuffer buffer, const VkAllocationCallbacks *pAllocator) {
2615    VkBool32 skipCall = VK_FALSE;
2616    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2617    assert(my_data != NULL);
2618
2619    skipCall |= parameter_validation_vkDestroyBuffer(my_data->report_data, buffer, pAllocator);
2620
2621    if (skipCall == VK_FALSE) {
2622        get_dispatch_table(pc_device_table_map, device)->DestroyBuffer(device, buffer, pAllocator);
2623    }
2624}
2625
2626bool PreCreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo) {
2627    if (pCreateInfo != nullptr) {
2628        if (pCreateInfo->format < VK_FORMAT_BEGIN_RANGE || pCreateInfo->format > VK_FORMAT_END_RANGE) {
2629            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2630                    "vkCreateBufferView parameter, VkFormat pCreateInfo->format, is an unrecognized enumerator");
2631            return false;
2632        }
2633    }
2634
2635    return true;
2636}
2637
2638bool PostCreateBufferView(VkDevice device, VkBufferView *pView, VkResult result) {
2639    if (result < VK_SUCCESS) {
2640        std::string reason = "vkCreateBufferView parameter, VkResult result, is " + EnumeratorString(result);
2641        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2642                reason.c_str());
2643        return false;
2644    }
2645
2646    return true;
2647}
2648
2649VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateBufferView(VkDevice device, const VkBufferViewCreateInfo *pCreateInfo,
2650                                                                  const VkAllocationCallbacks *pAllocator, VkBufferView *pView) {
2651    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2652    VkBool32 skipCall = VK_FALSE;
2653    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2654    assert(my_data != NULL);
2655
2656    skipCall |= parameter_validation_vkCreateBufferView(my_data->report_data, pCreateInfo, pAllocator, pView);
2657
2658    if (skipCall == VK_FALSE) {
2659        PreCreateBufferView(device, pCreateInfo);
2660
2661        result = get_dispatch_table(pc_device_table_map, device)->CreateBufferView(device, pCreateInfo, pAllocator, pView);
2662
2663        PostCreateBufferView(device, pView, result);
2664    }
2665
2666    return result;
2667}
2668
2669VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2670vkDestroyBufferView(VkDevice device, VkBufferView bufferView, const VkAllocationCallbacks *pAllocator) {
2671    VkBool32 skipCall = VK_FALSE;
2672    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2673    assert(my_data != NULL);
2674
2675    skipCall |= parameter_validation_vkDestroyBufferView(my_data->report_data, bufferView, pAllocator);
2676
2677    if (skipCall == VK_FALSE) {
2678        get_dispatch_table(pc_device_table_map, device)->DestroyBufferView(device, bufferView, pAllocator);
2679    }
2680}
2681
2682bool PreCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo) {
2683    if (pCreateInfo != nullptr) {
2684        if (pCreateInfo->imageType < VK_IMAGE_TYPE_BEGIN_RANGE || pCreateInfo->imageType > VK_IMAGE_TYPE_END_RANGE) {
2685            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2686                    "vkCreateImage parameter, VkImageType pCreateInfo->imageType, is an unrecognized enumerator");
2687            return false;
2688        }
2689        if (pCreateInfo->format < VK_FORMAT_BEGIN_RANGE || pCreateInfo->format > VK_FORMAT_END_RANGE) {
2690            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2691                    "vkCreateImage parameter, VkFormat pCreateInfo->format, is an unrecognized enumerator");
2692            return false;
2693        }
2694        if (pCreateInfo->tiling < VK_IMAGE_TILING_BEGIN_RANGE || pCreateInfo->tiling > VK_IMAGE_TILING_END_RANGE) {
2695            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2696                    "vkCreateImage parameter, VkImageTiling pCreateInfo->tiling, is an unrecognized enumerator");
2697            return false;
2698        }
2699        if (pCreateInfo->sharingMode < VK_SHARING_MODE_BEGIN_RANGE || pCreateInfo->sharingMode > VK_SHARING_MODE_END_RANGE) {
2700            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2701                    "vkCreateImage parameter, VkSharingMode pCreateInfo->sharingMode, is an unrecognized enumerator");
2702            return false;
2703        } else if (pCreateInfo->sharingMode == VK_SHARING_MODE_CONCURRENT) {
2704            validate_queue_family_indices(device, "vkCreateImage", pCreateInfo->queueFamilyIndexCount,
2705                                          pCreateInfo->pQueueFamilyIndices);
2706        }
2707    }
2708
2709    return true;
2710}
2711
2712bool PostCreateImage(VkDevice device, VkImage *pImage, VkResult result) {
2713    if (result < VK_SUCCESS) {
2714        std::string reason = "vkCreateImage parameter, VkResult result, is " + EnumeratorString(result);
2715        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2716                reason.c_str());
2717        return false;
2718    }
2719
2720    return true;
2721}
2722
2723VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2724vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
2725    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2726    VkBool32 skipCall = VK_FALSE;
2727    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2728    assert(my_data != NULL);
2729
2730    skipCall |= parameter_validation_vkCreateImage(my_data->report_data, pCreateInfo, pAllocator, pImage);
2731
2732    if (skipCall == VK_FALSE) {
2733        PreCreateImage(device, pCreateInfo);
2734
2735        result = get_dispatch_table(pc_device_table_map, device)->CreateImage(device, pCreateInfo, pAllocator, pImage);
2736
2737        PostCreateImage(device, pImage, result);
2738    }
2739
2740    return result;
2741}
2742
2743VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
2744    VkBool32 skipCall = VK_FALSE;
2745    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2746    assert(my_data != NULL);
2747
2748    skipCall |= parameter_validation_vkDestroyImage(my_data->report_data, image, pAllocator);
2749
2750    if (skipCall == VK_FALSE) {
2751        get_dispatch_table(pc_device_table_map, device)->DestroyImage(device, image, pAllocator);
2752    }
2753}
2754
2755bool PreGetImageSubresourceLayout(VkDevice device, const VkImageSubresource *pSubresource) {
2756    if (pSubresource != nullptr) {
2757        if ((pSubresource->aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT |
2758                                         VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
2759            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2760                    "vkGetImageSubresourceLayout parameter, VkImageAspect pSubresource->aspectMask, is an unrecognized enumerator");
2761            return false;
2762        }
2763    }
2764
2765    return true;
2766}
2767
2768VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2769vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) {
2770    VkBool32 skipCall = VK_FALSE;
2771    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2772    assert(my_data != NULL);
2773
2774    skipCall |= parameter_validation_vkGetImageSubresourceLayout(my_data->report_data, image, pSubresource, pLayout);
2775
2776    if (skipCall == VK_FALSE) {
2777        PreGetImageSubresourceLayout(device, pSubresource);
2778
2779        get_dispatch_table(pc_device_table_map, device)->GetImageSubresourceLayout(device, image, pSubresource, pLayout);
2780    }
2781}
2782
2783bool PreCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo) {
2784    if (pCreateInfo != nullptr) {
2785        if (pCreateInfo->viewType < VK_IMAGE_VIEW_TYPE_BEGIN_RANGE || pCreateInfo->viewType > VK_IMAGE_VIEW_TYPE_END_RANGE) {
2786            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2787                    "vkCreateImageView parameter, VkImageViewType pCreateInfo->viewType, is an unrecognized enumerator");
2788            return false;
2789        }
2790        if (pCreateInfo->format < VK_FORMAT_BEGIN_RANGE || pCreateInfo->format > VK_FORMAT_END_RANGE) {
2791            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2792                    "vkCreateImageView parameter, VkFormat pCreateInfo->format, is an unrecognized enumerator");
2793            return false;
2794        }
2795        if (pCreateInfo->components.r < VK_COMPONENT_SWIZZLE_BEGIN_RANGE ||
2796            pCreateInfo->components.r > VK_COMPONENT_SWIZZLE_END_RANGE) {
2797            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2798                    "vkCreateImageView parameter, VkComponentSwizzle pCreateInfo->components.r, is an unrecognized enumerator");
2799            return false;
2800        }
2801        if (pCreateInfo->components.g < VK_COMPONENT_SWIZZLE_BEGIN_RANGE ||
2802            pCreateInfo->components.g > VK_COMPONENT_SWIZZLE_END_RANGE) {
2803            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2804                    "vkCreateImageView parameter, VkComponentSwizzle pCreateInfo->components.g, is an unrecognized enumerator");
2805            return false;
2806        }
2807        if (pCreateInfo->components.b < VK_COMPONENT_SWIZZLE_BEGIN_RANGE ||
2808            pCreateInfo->components.b > VK_COMPONENT_SWIZZLE_END_RANGE) {
2809            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2810                    "vkCreateImageView parameter, VkComponentSwizzle pCreateInfo->components.b, is an unrecognized enumerator");
2811            return false;
2812        }
2813        if (pCreateInfo->components.a < VK_COMPONENT_SWIZZLE_BEGIN_RANGE ||
2814            pCreateInfo->components.a > VK_COMPONENT_SWIZZLE_END_RANGE) {
2815            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
2816                    "vkCreateImageView parameter, VkComponentSwizzle pCreateInfo->components.a, is an unrecognized enumerator");
2817            return false;
2818        }
2819    }
2820
2821    return true;
2822}
2823
2824bool PostCreateImageView(VkDevice device, VkImageView *pView, VkResult result) {
2825    if (result < VK_SUCCESS) {
2826        std::string reason = "vkCreateImageView parameter, VkResult result, is " + EnumeratorString(result);
2827        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2828                reason.c_str());
2829        return false;
2830    }
2831
2832    return true;
2833}
2834
2835VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
2836                                                                 const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
2837    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2838    VkBool32 skipCall = VK_FALSE;
2839    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2840    assert(my_data != NULL);
2841
2842    skipCall |= parameter_validation_vkCreateImageView(my_data->report_data, pCreateInfo, pAllocator, pView);
2843
2844    if (skipCall == VK_FALSE) {
2845        PreCreateImageView(device, pCreateInfo);
2846
2847        result = get_dispatch_table(pc_device_table_map, device)->CreateImageView(device, pCreateInfo, pAllocator, pView);
2848
2849        PostCreateImageView(device, pView, result);
2850    }
2851
2852    return result;
2853}
2854
2855VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2856vkDestroyImageView(VkDevice device, VkImageView imageView, const VkAllocationCallbacks *pAllocator) {
2857    VkBool32 skipCall = VK_FALSE;
2858    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2859    assert(my_data != NULL);
2860
2861    skipCall |= parameter_validation_vkDestroyImageView(my_data->report_data, imageView, pAllocator);
2862
2863    if (skipCall == VK_FALSE) {
2864        get_dispatch_table(pc_device_table_map, device)->DestroyImageView(device, imageView, pAllocator);
2865    }
2866}
2867
2868bool PostCreateShaderModule(VkDevice device, VkShaderModule *pShaderModule, VkResult result) {
2869    if (result < VK_SUCCESS) {
2870        std::string reason = "vkCreateShaderModule parameter, VkResult result, is " + EnumeratorString(result);
2871        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2872                reason.c_str());
2873        return false;
2874    }
2875
2876    return true;
2877}
2878
2879VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateShaderModule(VkDevice device, const VkShaderModuleCreateInfo *pCreateInfo,
2880                                                                    const VkAllocationCallbacks *pAllocator,
2881                                                                    VkShaderModule *pShaderModule) {
2882    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2883    VkBool32 skipCall = VK_FALSE;
2884    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2885    assert(my_data != NULL);
2886
2887    skipCall |= parameter_validation_vkCreateShaderModule(my_data->report_data, pCreateInfo, pAllocator, pShaderModule);
2888
2889    if (skipCall == VK_FALSE) {
2890        result =
2891            get_dispatch_table(pc_device_table_map, device)->CreateShaderModule(device, pCreateInfo, pAllocator, pShaderModule);
2892
2893        PostCreateShaderModule(device, pShaderModule, result);
2894    }
2895
2896    return result;
2897}
2898
2899VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2900vkDestroyShaderModule(VkDevice device, VkShaderModule shaderModule, const VkAllocationCallbacks *pAllocator) {
2901    VkBool32 skipCall = VK_FALSE;
2902    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2903    assert(my_data != NULL);
2904
2905    skipCall |= parameter_validation_vkDestroyShaderModule(my_data->report_data, shaderModule, pAllocator);
2906
2907    if (skipCall == VK_FALSE) {
2908        get_dispatch_table(pc_device_table_map, device)->DestroyShaderModule(device, shaderModule, pAllocator);
2909    }
2910}
2911
2912bool PostCreatePipelineCache(VkDevice device, VkPipelineCache *pPipelineCache, VkResult result) {
2913    if (result < VK_SUCCESS) {
2914        std::string reason = "vkCreatePipelineCache parameter, VkResult result, is " + EnumeratorString(result);
2915        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2916                reason.c_str());
2917        return false;
2918    }
2919
2920    return true;
2921}
2922
2923VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreatePipelineCache(VkDevice device, const VkPipelineCacheCreateInfo *pCreateInfo,
2924                                                                     const VkAllocationCallbacks *pAllocator,
2925                                                                     VkPipelineCache *pPipelineCache) {
2926    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2927    VkBool32 skipCall = VK_FALSE;
2928    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2929    assert(my_data != NULL);
2930
2931    skipCall |= parameter_validation_vkCreatePipelineCache(my_data->report_data, pCreateInfo, pAllocator, pPipelineCache);
2932
2933    if (skipCall == VK_FALSE) {
2934        result =
2935            get_dispatch_table(pc_device_table_map, device)->CreatePipelineCache(device, pCreateInfo, pAllocator, pPipelineCache);
2936
2937        PostCreatePipelineCache(device, pPipelineCache, result);
2938    }
2939
2940    return result;
2941}
2942
2943VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
2944vkDestroyPipelineCache(VkDevice device, VkPipelineCache pipelineCache, const VkAllocationCallbacks *pAllocator) {
2945    VkBool32 skipCall = VK_FALSE;
2946    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2947    assert(my_data != NULL);
2948
2949    skipCall |= parameter_validation_vkDestroyPipelineCache(my_data->report_data, pipelineCache, pAllocator);
2950
2951    if (skipCall == VK_FALSE) {
2952        get_dispatch_table(pc_device_table_map, device)->DestroyPipelineCache(device, pipelineCache, pAllocator);
2953    }
2954}
2955
2956bool PostGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData, VkResult result) {
2957    if (result < VK_SUCCESS) {
2958        std::string reason = "vkGetPipelineCacheData parameter, VkResult result, is " + EnumeratorString(result);
2959        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2960                reason.c_str());
2961        return false;
2962    }
2963
2964    return true;
2965}
2966
2967VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2968vkGetPipelineCacheData(VkDevice device, VkPipelineCache pipelineCache, size_t *pDataSize, void *pData) {
2969    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
2970    VkBool32 skipCall = VK_FALSE;
2971    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
2972    assert(my_data != NULL);
2973
2974    skipCall |= parameter_validation_vkGetPipelineCacheData(my_data->report_data, pipelineCache, pDataSize, pData);
2975
2976    if (skipCall == VK_FALSE) {
2977        result = get_dispatch_table(pc_device_table_map, device)->GetPipelineCacheData(device, pipelineCache, pDataSize, pData);
2978
2979        PostGetPipelineCacheData(device, pipelineCache, pDataSize, pData, result);
2980    }
2981
2982    return result;
2983}
2984
2985bool PostMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, VkResult result) {
2986
2987    if (result < VK_SUCCESS) {
2988        std::string reason = "vkMergePipelineCaches parameter, VkResult result, is " + EnumeratorString(result);
2989        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
2990                reason.c_str());
2991        return false;
2992    }
2993
2994    return true;
2995}
2996
2997VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
2998vkMergePipelineCaches(VkDevice device, VkPipelineCache dstCache, uint32_t srcCacheCount, const VkPipelineCache *pSrcCaches) {
2999    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3000    VkBool32 skipCall = VK_FALSE;
3001    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3002    assert(my_data != NULL);
3003
3004    skipCall |= parameter_validation_vkMergePipelineCaches(my_data->report_data, dstCache, srcCacheCount, pSrcCaches);
3005
3006    if (skipCall == VK_FALSE) {
3007        result = get_dispatch_table(pc_device_table_map, device)->MergePipelineCaches(device, dstCache, srcCacheCount, pSrcCaches);
3008
3009        PostMergePipelineCaches(device, dstCache, srcCacheCount, result);
3010    }
3011
3012    return result;
3013}
3014
3015bool PreCreateGraphicsPipelines(VkDevice device, const VkGraphicsPipelineCreateInfo *pCreateInfos) {
3016    layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3017
3018    // TODO: Handle count
3019    if (pCreateInfos != nullptr) {
3020        if (pCreateInfos->flags | VK_PIPELINE_CREATE_DERIVATIVE_BIT) {
3021            if (pCreateInfos->basePipelineIndex != -1) {
3022                if (pCreateInfos->basePipelineHandle != VK_NULL_HANDLE) {
3023                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3024                            "vkCreateGraphicsPipelines parameter, pCreateInfos->basePipelineHandle, must be VK_NULL_HANDLE if "
3025                            "pCreateInfos->flags "
3026                            "contains the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag and pCreateInfos->basePipelineIndex is not -1");
3027                    return false;
3028                }
3029            }
3030
3031            if (pCreateInfos->basePipelineHandle != VK_NULL_HANDLE) {
3032                if (pCreateInfos->basePipelineIndex != -1) {
3033                    log_msg(
3034                        mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3035                        "vkCreateGraphicsPipelines parameter, pCreateInfos->basePipelineIndex, must be -1 if pCreateInfos->flags "
3036                        "contains the VK_PIPELINE_CREATE_DERIVATIVE_BIT flag and pCreateInfos->basePipelineHandle is not "
3037                        "VK_NULL_HANDLE");
3038                    return false;
3039                }
3040            }
3041        }
3042
3043        if (pCreateInfos->pVertexInputState != nullptr) {
3044            if (pCreateInfos->pVertexInputState->pVertexBindingDescriptions != nullptr) {
3045                if (pCreateInfos->pVertexInputState->pVertexBindingDescriptions->inputRate < VK_VERTEX_INPUT_RATE_BEGIN_RANGE ||
3046                    pCreateInfos->pVertexInputState->pVertexBindingDescriptions->inputRate > VK_VERTEX_INPUT_RATE_END_RANGE) {
3047                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3048                            "vkCreateGraphicsPipelines parameter, VkVertexInputRate "
3049                            "pCreateInfos->pVertexInputState->pVertexBindingDescriptions->inputRate, is an unrecognized "
3050                            "enumerator");
3051                    return false;
3052                }
3053            }
3054            if (pCreateInfos->pVertexInputState->pVertexAttributeDescriptions != nullptr) {
3055                if (pCreateInfos->pVertexInputState->pVertexAttributeDescriptions->format < VK_FORMAT_BEGIN_RANGE ||
3056                    pCreateInfos->pVertexInputState->pVertexAttributeDescriptions->format > VK_FORMAT_END_RANGE) {
3057                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3058                            "vkCreateGraphicsPipelines parameter, VkFormat "
3059                            "pCreateInfos->pVertexInputState->pVertexAttributeDescriptions->format, is an unrecognized enumerator");
3060                    return false;
3061                }
3062            }
3063        }
3064        if (pCreateInfos->pInputAssemblyState != nullptr) {
3065            if (pCreateInfos->pInputAssemblyState->topology < VK_PRIMITIVE_TOPOLOGY_BEGIN_RANGE ||
3066                pCreateInfos->pInputAssemblyState->topology > VK_PRIMITIVE_TOPOLOGY_END_RANGE) {
3067                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3068                        "vkCreateGraphicsPipelines parameter, VkPrimitiveTopology pCreateInfos->pInputAssemblyState->topology, is "
3069                        "an unrecognized enumerator");
3070                return false;
3071            }
3072        }
3073        if (pCreateInfos->pRasterizationState != nullptr) {
3074            if (pCreateInfos->pRasterizationState->polygonMode < VK_POLYGON_MODE_BEGIN_RANGE ||
3075                pCreateInfos->pRasterizationState->polygonMode > VK_POLYGON_MODE_END_RANGE) {
3076                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3077                        "vkCreateGraphicsPipelines parameter, VkPolygonMode pCreateInfos->pRasterizationState->polygonMode, is an "
3078                        "unrecognized enumerator");
3079                return false;
3080            }
3081            if (pCreateInfos->pRasterizationState->cullMode & ~VK_CULL_MODE_FRONT_AND_BACK) {
3082                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3083                        "vkCreateGraphicsPipelines parameter, VkCullMode pCreateInfos->pRasterizationState->cullMode, is an "
3084                        "unrecognized enumerator");
3085                return false;
3086            }
3087            if (pCreateInfos->pRasterizationState->frontFace < VK_FRONT_FACE_BEGIN_RANGE ||
3088                pCreateInfos->pRasterizationState->frontFace > VK_FRONT_FACE_END_RANGE) {
3089                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3090                        "vkCreateGraphicsPipelines parameter, VkFrontFace pCreateInfos->pRasterizationState->frontFace, is an "
3091                        "unrecognized enumerator");
3092                return false;
3093            }
3094        }
3095        if (pCreateInfos->pDepthStencilState != nullptr) {
3096            if (pCreateInfos->pDepthStencilState->depthCompareOp < VK_COMPARE_OP_BEGIN_RANGE ||
3097                pCreateInfos->pDepthStencilState->depthCompareOp > VK_COMPARE_OP_END_RANGE) {
3098                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3099                        "vkCreateGraphicsPipelines parameter, VkCompareOp pCreateInfos->pDepthStencilState->depthCompareOp, is an "
3100                        "unrecognized enumerator");
3101                return false;
3102            }
3103            if (pCreateInfos->pDepthStencilState->front.failOp < VK_STENCIL_OP_BEGIN_RANGE ||
3104                pCreateInfos->pDepthStencilState->front.failOp > VK_STENCIL_OP_END_RANGE) {
3105                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3106                        "vkCreateGraphicsPipelines parameter, VkStencilOp pCreateInfos->pDepthStencilState->front.failOp, is an "
3107                        "unrecognized enumerator");
3108                return false;
3109            }
3110            if (pCreateInfos->pDepthStencilState->front.passOp < VK_STENCIL_OP_BEGIN_RANGE ||
3111                pCreateInfos->pDepthStencilState->front.passOp > VK_STENCIL_OP_END_RANGE) {
3112                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3113                        "vkCreateGraphicsPipelines parameter, VkStencilOp pCreateInfos->pDepthStencilState->front.passOp, is an "
3114                        "unrecognized enumerator");
3115                return false;
3116            }
3117            if (pCreateInfos->pDepthStencilState->front.depthFailOp < VK_STENCIL_OP_BEGIN_RANGE ||
3118                pCreateInfos->pDepthStencilState->front.depthFailOp > VK_STENCIL_OP_END_RANGE) {
3119                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3120                        "vkCreateGraphicsPipelines parameter, VkStencilOp pCreateInfos->pDepthStencilState->front.depthFailOp, is "
3121                        "an unrecognized enumerator");
3122                return false;
3123            }
3124            if (pCreateInfos->pDepthStencilState->front.compareOp < VK_COMPARE_OP_BEGIN_RANGE ||
3125                pCreateInfos->pDepthStencilState->front.compareOp > VK_COMPARE_OP_END_RANGE) {
3126                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3127                        "vkCreateGraphicsPipelines parameter, VkCompareOp pCreateInfos->pDepthStencilState->front.compareOp, is an "
3128                        "unrecognized enumerator");
3129                return false;
3130            }
3131            if (pCreateInfos->pDepthStencilState->back.failOp < VK_STENCIL_OP_BEGIN_RANGE ||
3132                pCreateInfos->pDepthStencilState->back.failOp > VK_STENCIL_OP_END_RANGE) {
3133                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3134                        "vkCreateGraphicsPipelines parameter, VkStencilOp pCreateInfos->pDepthStencilState->back.failOp, is an "
3135                        "unrecognized enumerator");
3136                return false;
3137            }
3138            if (pCreateInfos->pDepthStencilState->back.passOp < VK_STENCIL_OP_BEGIN_RANGE ||
3139                pCreateInfos->pDepthStencilState->back.passOp > VK_STENCIL_OP_END_RANGE) {
3140                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3141                        "vkCreateGraphicsPipelines parameter, VkStencilOp pCreateInfos->pDepthStencilState->back.passOp, is an "
3142                        "unrecognized enumerator");
3143                return false;
3144            }
3145            if (pCreateInfos->pDepthStencilState->back.depthFailOp < VK_STENCIL_OP_BEGIN_RANGE ||
3146                pCreateInfos->pDepthStencilState->back.depthFailOp > VK_STENCIL_OP_END_RANGE) {
3147                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3148                        "vkCreateGraphicsPipelines parameter, VkStencilOp pCreateInfos->pDepthStencilState->back.depthFailOp, is "
3149                        "an unrecognized enumerator");
3150                return false;
3151            }
3152            if (pCreateInfos->pDepthStencilState->back.compareOp < VK_COMPARE_OP_BEGIN_RANGE ||
3153                pCreateInfos->pDepthStencilState->back.compareOp > VK_COMPARE_OP_END_RANGE) {
3154                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3155                        "vkCreateGraphicsPipelines parameter, VkCompareOp pCreateInfos->pDepthStencilState->back.compareOp, is an "
3156                        "unrecognized enumerator");
3157                return false;
3158            }
3159        }
3160        if (pCreateInfos->pColorBlendState != nullptr) {
3161            if (pCreateInfos->pColorBlendState->logicOpEnable == VK_TRUE &&
3162                (pCreateInfos->pColorBlendState->logicOp < VK_LOGIC_OP_BEGIN_RANGE ||
3163                 pCreateInfos->pColorBlendState->logicOp > VK_LOGIC_OP_END_RANGE)) {
3164                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3165                        "vkCreateGraphicsPipelines parameter, VkLogicOp pCreateInfos->pColorBlendState->logicOp, is an "
3166                        "unrecognized enumerator");
3167                return false;
3168            }
3169            if (pCreateInfos->pColorBlendState->pAttachments != nullptr &&
3170                pCreateInfos->pColorBlendState->pAttachments->blendEnable == VK_TRUE) {
3171                if (pCreateInfos->pColorBlendState->pAttachments->srcColorBlendFactor < VK_BLEND_FACTOR_BEGIN_RANGE ||
3172                    pCreateInfos->pColorBlendState->pAttachments->srcColorBlendFactor > VK_BLEND_FACTOR_END_RANGE) {
3173                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3174                            "vkCreateGraphicsPipelines parameter, VkBlendFactor "
3175                            "pCreateInfos->pColorBlendState->pAttachments->srcColorBlendFactor, is an unrecognized enumerator");
3176                    return false;
3177                }
3178                if (pCreateInfos->pColorBlendState->pAttachments->dstColorBlendFactor < VK_BLEND_FACTOR_BEGIN_RANGE ||
3179                    pCreateInfos->pColorBlendState->pAttachments->dstColorBlendFactor > VK_BLEND_FACTOR_END_RANGE) {
3180                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3181                            "vkCreateGraphicsPipelines parameter, VkBlendFactor "
3182                            "pCreateInfos->pColorBlendState->pAttachments->dstColorBlendFactor, is an unrecognized enumerator");
3183                    return false;
3184                }
3185                if (pCreateInfos->pColorBlendState->pAttachments->colorBlendOp < VK_BLEND_OP_BEGIN_RANGE ||
3186                    pCreateInfos->pColorBlendState->pAttachments->colorBlendOp > VK_BLEND_OP_END_RANGE) {
3187                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3188                            "vkCreateGraphicsPipelines parameter, VkBlendOp "
3189                            "pCreateInfos->pColorBlendState->pAttachments->colorBlendOp, is an unrecognized enumerator");
3190                    return false;
3191                }
3192                if (pCreateInfos->pColorBlendState->pAttachments->srcAlphaBlendFactor < VK_BLEND_FACTOR_BEGIN_RANGE ||
3193                    pCreateInfos->pColorBlendState->pAttachments->srcAlphaBlendFactor > VK_BLEND_FACTOR_END_RANGE) {
3194                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3195                            "vkCreateGraphicsPipelines parameter, VkBlendFactor "
3196                            "pCreateInfos->pColorBlendState->pAttachments->srcAlphaBlendFactor, is an unrecognized enumerator");
3197                    return false;
3198                }
3199                if (pCreateInfos->pColorBlendState->pAttachments->dstAlphaBlendFactor < VK_BLEND_FACTOR_BEGIN_RANGE ||
3200                    pCreateInfos->pColorBlendState->pAttachments->dstAlphaBlendFactor > VK_BLEND_FACTOR_END_RANGE) {
3201                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3202                            "vkCreateGraphicsPipelines parameter, VkBlendFactor "
3203                            "pCreateInfos->pColorBlendState->pAttachments->dstAlphaBlendFactor, is an unrecognized enumerator");
3204                    return false;
3205                }
3206                if (pCreateInfos->pColorBlendState->pAttachments->alphaBlendOp < VK_BLEND_OP_BEGIN_RANGE ||
3207                    pCreateInfos->pColorBlendState->pAttachments->alphaBlendOp > VK_BLEND_OP_END_RANGE) {
3208                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3209                            "vkCreateGraphicsPipelines parameter, VkBlendOp "
3210                            "pCreateInfos->pColorBlendState->pAttachments->alphaBlendOp, is an unrecognized enumerator");
3211                    return false;
3212                }
3213            }
3214        }
3215        if (pCreateInfos->renderPass == VK_NULL_HANDLE) {
3216            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3217                    "vkCreateGraphicsPipelines parameter, VkRenderPass pCreateInfos->renderPass, is null pointer");
3218        }
3219
3220        int i = 0;
3221        for (auto j = 0; j < pCreateInfos[i].stageCount; j++) {
3222            validate_string(data->report_data, "vkCreateGraphicsPipelines", "pCreateInfos[i].pStages[j].pName",
3223                            pCreateInfos[i].pStages[j].pName);
3224        }
3225    }
3226
3227    return true;
3228}
3229
3230bool PostCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, VkPipeline *pPipelines,
3231                                 VkResult result) {
3232    if (result < VK_SUCCESS) {
3233        std::string reason = "vkCreateGraphicsPipelines parameter, VkResult result, is " + EnumeratorString(result);
3234        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3235                reason.c_str());
3236        return false;
3237    }
3238
3239    return true;
3240}
3241
3242VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3243vkCreateGraphicsPipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
3244                          const VkGraphicsPipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
3245                          VkPipeline *pPipelines) {
3246    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3247    VkBool32 skipCall = VK_FALSE;
3248    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3249    assert(my_data != NULL);
3250
3251    skipCall |= parameter_validation_vkCreateGraphicsPipelines(my_data->report_data, pipelineCache, createInfoCount, pCreateInfos,
3252                                                      pAllocator, pPipelines);
3253
3254    if (skipCall == VK_FALSE) {
3255        PreCreateGraphicsPipelines(device, pCreateInfos);
3256
3257        result = get_dispatch_table(pc_device_table_map, device)
3258                     ->CreateGraphicsPipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
3259
3260        PostCreateGraphicsPipelines(device, pipelineCache, createInfoCount, pPipelines, result);
3261    }
3262
3263    return result;
3264}
3265
3266bool PreCreateComputePipelines(VkDevice device, const VkComputePipelineCreateInfo *pCreateInfos) {
3267    layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3268
3269    if (pCreateInfos != nullptr) {
3270        // TODO: Handle count!
3271        int i = 0;
3272        validate_string(data->report_data, "vkCreateComputePipelines", "pCreateInfos[i].stage.pName", pCreateInfos[i].stage.pName);
3273    }
3274
3275    return true;
3276}
3277
3278bool PostCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t count, VkPipeline *pPipelines,
3279                                VkResult result) {
3280    if (result < VK_SUCCESS) {
3281        std::string reason = "vkCreateComputePipelines parameter, VkResult result, is " + EnumeratorString(result);
3282        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3283                reason.c_str());
3284        return false;
3285    }
3286
3287    return true;
3288}
3289
3290VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3291vkCreateComputePipelines(VkDevice device, VkPipelineCache pipelineCache, uint32_t createInfoCount,
3292                         const VkComputePipelineCreateInfo *pCreateInfos, const VkAllocationCallbacks *pAllocator,
3293                         VkPipeline *pPipelines) {
3294    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3295    VkBool32 skipCall = VK_FALSE;
3296    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3297    assert(my_data != NULL);
3298
3299    skipCall |= parameter_validation_vkCreateComputePipelines(my_data->report_data, pipelineCache, createInfoCount, pCreateInfos, pAllocator,
3300                                                     pPipelines);
3301
3302    if (skipCall == VK_FALSE) {
3303        PreCreateComputePipelines(device, pCreateInfos);
3304
3305        result = get_dispatch_table(pc_device_table_map, device)
3306                     ->CreateComputePipelines(device, pipelineCache, createInfoCount, pCreateInfos, pAllocator, pPipelines);
3307
3308        PostCreateComputePipelines(device, pipelineCache, createInfoCount, pPipelines, result);
3309    }
3310
3311    return result;
3312}
3313
3314VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3315vkDestroyPipeline(VkDevice device, VkPipeline pipeline, const VkAllocationCallbacks *pAllocator) {
3316    VkBool32 skipCall = VK_FALSE;
3317    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3318    assert(my_data != NULL);
3319
3320    skipCall |= parameter_validation_vkDestroyPipeline(my_data->report_data, pipeline, pAllocator);
3321
3322    if (skipCall == VK_FALSE) {
3323        get_dispatch_table(pc_device_table_map, device)->DestroyPipeline(device, pipeline, pAllocator);
3324    }
3325}
3326
3327bool PostCreatePipelineLayout(VkDevice device, VkPipelineLayout *pPipelineLayout, VkResult result) {
3328    if (result < VK_SUCCESS) {
3329        std::string reason = "vkCreatePipelineLayout parameter, VkResult result, is " + EnumeratorString(result);
3330        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3331                reason.c_str());
3332        return false;
3333    }
3334
3335    return true;
3336}
3337
3338VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3339vkCreatePipelineLayout(VkDevice device, const VkPipelineLayoutCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
3340                       VkPipelineLayout *pPipelineLayout) {
3341    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3342    VkBool32 skipCall = VK_FALSE;
3343    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3344    assert(my_data != NULL);
3345
3346    skipCall |= parameter_validation_vkCreatePipelineLayout(my_data->report_data, pCreateInfo, pAllocator, pPipelineLayout);
3347
3348    if (skipCall == VK_FALSE) {
3349        result =
3350            get_dispatch_table(pc_device_table_map, device)->CreatePipelineLayout(device, pCreateInfo, pAllocator, pPipelineLayout);
3351
3352        PostCreatePipelineLayout(device, pPipelineLayout, result);
3353    }
3354
3355    return result;
3356}
3357
3358VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3359vkDestroyPipelineLayout(VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *pAllocator) {
3360    VkBool32 skipCall = VK_FALSE;
3361    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3362    assert(my_data != NULL);
3363
3364    skipCall |= parameter_validation_vkDestroyPipelineLayout(my_data->report_data, pipelineLayout, pAllocator);
3365
3366    if (skipCall == VK_FALSE) {
3367        get_dispatch_table(pc_device_table_map, device)->DestroyPipelineLayout(device, pipelineLayout, pAllocator);
3368    }
3369}
3370
3371bool PreCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo) {
3372    if (pCreateInfo != nullptr) {
3373        if (pCreateInfo->magFilter < VK_FILTER_BEGIN_RANGE || pCreateInfo->magFilter > VK_FILTER_END_RANGE) {
3374            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3375                    "vkCreateSampler parameter, VkFilter pCreateInfo->magFilter, is an unrecognized enumerator");
3376            return false;
3377        }
3378        if (pCreateInfo->minFilter < VK_FILTER_BEGIN_RANGE || pCreateInfo->minFilter > VK_FILTER_END_RANGE) {
3379            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3380                    "vkCreateSampler parameter, VkFilter pCreateInfo->minFilter, is an unrecognized enumerator");
3381            return false;
3382        }
3383        if (pCreateInfo->mipmapMode < VK_SAMPLER_MIPMAP_MODE_BEGIN_RANGE ||
3384            pCreateInfo->mipmapMode > VK_SAMPLER_MIPMAP_MODE_END_RANGE) {
3385            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3386                    "vkCreateSampler parameter, VkSamplerMipmapMode pCreateInfo->mipmapMode, is an unrecognized enumerator");
3387            return false;
3388        }
3389        if (pCreateInfo->addressModeU < VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE ||
3390            pCreateInfo->addressModeU > VK_SAMPLER_ADDRESS_MODE_END_RANGE) {
3391            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3392                    "vkCreateSampler parameter, VkTexAddress pCreateInfo->addressModeU, is an unrecognized enumerator");
3393            return false;
3394        }
3395        if (pCreateInfo->addressModeV < VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE ||
3396            pCreateInfo->addressModeV > VK_SAMPLER_ADDRESS_MODE_END_RANGE) {
3397            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3398                    "vkCreateSampler parameter, VkTexAddress pCreateInfo->addressModeV, is an unrecognized enumerator");
3399            return false;
3400        }
3401        if (pCreateInfo->addressModeW < VK_SAMPLER_ADDRESS_MODE_BEGIN_RANGE ||
3402            pCreateInfo->addressModeW > VK_SAMPLER_ADDRESS_MODE_END_RANGE) {
3403            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3404                    "vkCreateSampler parameter, VkTexAddress pCreateInfo->addressModeW, is an unrecognized enumerator");
3405            return false;
3406        }
3407        if (pCreateInfo->anisotropyEnable > VK_TRUE) {
3408            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3409                    "vkCreateSampler parameter, VkBool32 pCreateInfo->anisotropyEnable, is an unrecognized boolean");
3410            return false;
3411        }
3412        if (pCreateInfo->compareEnable > VK_TRUE) {
3413            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3414                    "vkCreateSampler parameter, VkBool32 pCreateInfo->compareEnable, is an unrecognized boolean");
3415            return false;
3416        }
3417        if (pCreateInfo->compareEnable) {
3418            if (pCreateInfo->compareOp < VK_COMPARE_OP_BEGIN_RANGE || pCreateInfo->compareOp > VK_COMPARE_OP_END_RANGE) {
3419                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3420                        "vkCreateSampler parameter, VkCompareOp pCreateInfo->compareOp, is an unrecognized enumerator");
3421                return false;
3422            }
3423        }
3424        if (pCreateInfo->borderColor < VK_BORDER_COLOR_BEGIN_RANGE || pCreateInfo->borderColor > VK_BORDER_COLOR_END_RANGE) {
3425            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3426                    "vkCreateSampler parameter, VkBorderColor pCreateInfo->borderColor, is an unrecognized enumerator");
3427            return false;
3428        }
3429        if (pCreateInfo->unnormalizedCoordinates > VK_TRUE) {
3430            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3431                    "vkCreateSampler parameter, VkBool32 pCreateInfo->unnormalizedCoordinates, is an unrecognized boolean");
3432            return false;
3433        }
3434    }
3435
3436    return true;
3437}
3438
3439bool PostCreateSampler(VkDevice device, VkSampler *pSampler, VkResult result) {
3440    if (result < VK_SUCCESS) {
3441        std::string reason = "vkCreateSampler parameter, VkResult result, is " + EnumeratorString(result);
3442        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3443                reason.c_str());
3444        return false;
3445    }
3446
3447    return true;
3448}
3449
3450VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device, const VkSamplerCreateInfo *pCreateInfo,
3451                                                               const VkAllocationCallbacks *pAllocator, VkSampler *pSampler) {
3452    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3453    VkBool32 skipCall = VK_FALSE;
3454    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3455    assert(my_data != NULL);
3456
3457    skipCall |= parameter_validation_vkCreateSampler(my_data->report_data, pCreateInfo, pAllocator, pSampler);
3458
3459    if (skipCall == VK_FALSE) {
3460        PreCreateSampler(device, pCreateInfo);
3461
3462        result = get_dispatch_table(pc_device_table_map, device)->CreateSampler(device, pCreateInfo, pAllocator, pSampler);
3463
3464        PostCreateSampler(device, pSampler, result);
3465    }
3466
3467    return result;
3468}
3469
3470VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3471vkDestroySampler(VkDevice device, VkSampler sampler, const VkAllocationCallbacks *pAllocator) {
3472    VkBool32 skipCall = VK_FALSE;
3473    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3474    assert(my_data != NULL);
3475
3476    skipCall |= parameter_validation_vkDestroySampler(my_data->report_data, sampler, pAllocator);
3477
3478    if (skipCall == VK_FALSE) {
3479        get_dispatch_table(pc_device_table_map, device)->DestroySampler(device, sampler, pAllocator);
3480    }
3481}
3482
3483bool PreCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo) {
3484    if (pCreateInfo != nullptr) {
3485        if (pCreateInfo->pBindings != nullptr) {
3486            if (pCreateInfo->pBindings->descriptorType < VK_DESCRIPTOR_TYPE_BEGIN_RANGE ||
3487                pCreateInfo->pBindings->descriptorType > VK_DESCRIPTOR_TYPE_END_RANGE) {
3488                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3489                        "vkCreateDescriptorSetLayout parameter, VkDescriptorType pCreateInfo->pBindings->descriptorType, is an "
3490                        "unrecognized enumerator");
3491                return false;
3492            }
3493        }
3494    }
3495
3496    return true;
3497}
3498
3499bool PostCreateDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout *pSetLayout, VkResult result) {
3500    if (result < VK_SUCCESS) {
3501        std::string reason = "vkCreateDescriptorSetLayout parameter, VkResult result, is " + EnumeratorString(result);
3502        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3503                reason.c_str());
3504        return false;
3505    }
3506
3507    return true;
3508}
3509
3510VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3511vkCreateDescriptorSetLayout(VkDevice device, const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
3512                            const VkAllocationCallbacks *pAllocator, VkDescriptorSetLayout *pSetLayout) {
3513    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3514    VkBool32 skipCall = VK_FALSE;
3515    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3516    assert(my_data != NULL);
3517
3518    skipCall |= parameter_validation_vkCreateDescriptorSetLayout(my_data->report_data, pCreateInfo, pAllocator, pSetLayout);
3519
3520    if (skipCall == VK_FALSE) {
3521        PreCreateDescriptorSetLayout(device, pCreateInfo);
3522
3523        result =
3524            get_dispatch_table(pc_device_table_map, device)->CreateDescriptorSetLayout(device, pCreateInfo, pAllocator, pSetLayout);
3525
3526        PostCreateDescriptorSetLayout(device, pSetLayout, result);
3527    }
3528
3529    return result;
3530}
3531
3532VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3533vkDestroyDescriptorSetLayout(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const VkAllocationCallbacks *pAllocator) {
3534    VkBool32 skipCall = VK_FALSE;
3535    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3536    assert(my_data != NULL);
3537
3538    skipCall |= parameter_validation_vkDestroyDescriptorSetLayout(my_data->report_data, descriptorSetLayout, pAllocator);
3539
3540    if (skipCall == VK_FALSE) {
3541        get_dispatch_table(pc_device_table_map, device)->DestroyDescriptorSetLayout(device, descriptorSetLayout, pAllocator);
3542    }
3543}
3544
3545bool PreCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo) {
3546    if (pCreateInfo != nullptr) {
3547        if (pCreateInfo->pPoolSizes != nullptr) {
3548            if (pCreateInfo->pPoolSizes->type < VK_DESCRIPTOR_TYPE_BEGIN_RANGE ||
3549                pCreateInfo->pPoolSizes->type > VK_DESCRIPTOR_TYPE_END_RANGE) {
3550                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3551                        "vkCreateDescriptorPool parameter, VkDescriptorType pCreateInfo->pTypeCount->type, is an unrecognized "
3552                        "enumerator");
3553                return false;
3554            }
3555        }
3556    }
3557
3558    return true;
3559}
3560
3561bool PostCreateDescriptorPool(VkDevice device, uint32_t maxSets, VkDescriptorPool *pDescriptorPool, VkResult result) {
3562
3563    /* TODOVV: How do we validate maxSets? Probably belongs in the limits layer? */
3564
3565    if (result < VK_SUCCESS) {
3566        std::string reason = "vkCreateDescriptorPool parameter, VkResult result, is " + EnumeratorString(result);
3567        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3568                reason.c_str());
3569        return false;
3570    }
3571
3572    return true;
3573}
3574
3575VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3576vkCreateDescriptorPool(VkDevice device, const VkDescriptorPoolCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator,
3577                       VkDescriptorPool *pDescriptorPool) {
3578    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3579    VkBool32 skipCall = VK_FALSE;
3580    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3581    assert(my_data != NULL);
3582
3583    skipCall |= parameter_validation_vkCreateDescriptorPool(my_data->report_data, pCreateInfo, pAllocator, pDescriptorPool);
3584
3585    if (skipCall == VK_FALSE) {
3586        PreCreateDescriptorPool(device, pCreateInfo);
3587
3588        result =
3589            get_dispatch_table(pc_device_table_map, device)->CreateDescriptorPool(device, pCreateInfo, pAllocator, pDescriptorPool);
3590
3591        PostCreateDescriptorPool(device, pCreateInfo->maxSets, pDescriptorPool, result);
3592    }
3593
3594    return result;
3595}
3596
3597VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3598vkDestroyDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *pAllocator) {
3599    VkBool32 skipCall = VK_FALSE;
3600    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3601    assert(my_data != NULL);
3602
3603    skipCall |= parameter_validation_vkDestroyDescriptorPool(my_data->report_data, descriptorPool, pAllocator);
3604
3605    if (skipCall == VK_FALSE) {
3606        get_dispatch_table(pc_device_table_map, device)->DestroyDescriptorPool(device, descriptorPool, pAllocator);
3607    }
3608}
3609
3610bool PostResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkResult result) {
3611
3612    if (result < VK_SUCCESS) {
3613        std::string reason = "vkResetDescriptorPool parameter, VkResult result, is " + EnumeratorString(result);
3614        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3615                reason.c_str());
3616        return false;
3617    }
3618
3619    return true;
3620}
3621
3622VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3623vkResetDescriptorPool(VkDevice device, VkDescriptorPool descriptorPool, VkDescriptorPoolResetFlags flags) {
3624    VkResult result = get_dispatch_table(pc_device_table_map, device)->ResetDescriptorPool(device, descriptorPool, flags);
3625
3626    PostResetDescriptorPool(device, descriptorPool, result);
3627
3628    return result;
3629}
3630
3631bool PostAllocateDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, VkDescriptorSet *pDescriptorSets,
3632                                VkResult result) {
3633    if (result < VK_SUCCESS) {
3634        std::string reason = "vkAllocateDescriptorSets parameter, VkResult result, is " + EnumeratorString(result);
3635        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3636                reason.c_str());
3637        return false;
3638    }
3639
3640    return true;
3641}
3642
3643VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
3644vkAllocateDescriptorSets(VkDevice device, const VkDescriptorSetAllocateInfo *pAllocateInfo, VkDescriptorSet *pDescriptorSets) {
3645    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3646    VkBool32 skipCall = VK_FALSE;
3647    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3648    assert(my_data != NULL);
3649
3650    skipCall |= parameter_validation_vkAllocateDescriptorSets(my_data->report_data, pAllocateInfo, pDescriptorSets);
3651
3652    if (skipCall == VK_FALSE) {
3653        result = get_dispatch_table(pc_device_table_map, device)->AllocateDescriptorSets(device, pAllocateInfo, pDescriptorSets);
3654
3655        PostAllocateDescriptorSets(device, pAllocateInfo->descriptorPool, pAllocateInfo->descriptorSetCount, pDescriptorSets,
3656                                   result);
3657    }
3658
3659    return result;
3660}
3661
3662bool PostFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool, uint32_t count, VkResult result) {
3663
3664    if (result < VK_SUCCESS) {
3665        std::string reason = "vkFreeDescriptorSets parameter, VkResult result, is " + EnumeratorString(result);
3666        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3667                reason.c_str());
3668        return false;
3669    }
3670
3671    return true;
3672}
3673
3674VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkFreeDescriptorSets(VkDevice device, VkDescriptorPool descriptorPool,
3675                                                                    uint32_t descriptorSetCount,
3676                                                                    const VkDescriptorSet *pDescriptorSets) {
3677    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3678    VkBool32 skipCall = VK_FALSE;
3679    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3680    assert(my_data != NULL);
3681
3682    skipCall |= parameter_validation_vkFreeDescriptorSets(my_data->report_data, descriptorPool, descriptorSetCount, pDescriptorSets);
3683
3684    if (skipCall == VK_FALSE) {
3685        result = get_dispatch_table(pc_device_table_map, device)
3686                     ->FreeDescriptorSets(device, descriptorPool, descriptorSetCount, pDescriptorSets);
3687
3688        PostFreeDescriptorSets(device, descriptorPool, descriptorSetCount, result);
3689    }
3690
3691    return result;
3692}
3693
3694bool PreUpdateDescriptorSets(VkDevice device, const VkWriteDescriptorSet *pDescriptorWrites,
3695                             const VkCopyDescriptorSet *pDescriptorCopies) {
3696    if (pDescriptorWrites != nullptr) {
3697        if (pDescriptorWrites->descriptorType < VK_DESCRIPTOR_TYPE_BEGIN_RANGE ||
3698            pDescriptorWrites->descriptorType > VK_DESCRIPTOR_TYPE_END_RANGE) {
3699            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3700                    "vkUpdateDescriptorSets parameter, VkDescriptorType pDescriptorWrites->descriptorType, is an unrecognized "
3701                    "enumerator");
3702            return false;
3703        }
3704        /* TODO: Validate other parts of pImageInfo, pBufferInfo, pTexelBufferView? */
3705        /* TODO: This test should probably only be done if descriptorType is correct type of descriptor */
3706        if (pDescriptorWrites->pImageInfo != nullptr) {
3707            if (((pDescriptorWrites->pImageInfo->imageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3708                 (pDescriptorWrites->pImageInfo->imageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3709                (pDescriptorWrites->pImageInfo->imageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3710                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3711                        "vkUpdateDescriptorSets parameter, VkImageLayout pDescriptorWrites->pDescriptors->imageLayout, is an "
3712                        "unrecognized enumerator");
3713                return false;
3714            }
3715        }
3716    }
3717
3718    return true;
3719}
3720
3721VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3722vkUpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
3723                       uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
3724    VkBool32 skipCall = VK_FALSE;
3725    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3726    assert(my_data != NULL);
3727
3728    skipCall |= parameter_validation_vkUpdateDescriptorSets(my_data->report_data, descriptorWriteCount, pDescriptorWrites,
3729                                                   descriptorCopyCount, pDescriptorCopies);
3730
3731    if (skipCall == VK_FALSE) {
3732        PreUpdateDescriptorSets(device, pDescriptorWrites, pDescriptorCopies);
3733
3734        get_dispatch_table(pc_device_table_map, device)
3735            ->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount, pDescriptorCopies);
3736    }
3737}
3738
3739bool PostCreateFramebuffer(VkDevice device, VkFramebuffer *pFramebuffer, VkResult result) {
3740    if (result < VK_SUCCESS) {
3741        std::string reason = "vkCreateFramebuffer parameter, VkResult result, is " + EnumeratorString(result);
3742        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3743                reason.c_str());
3744        return false;
3745    }
3746
3747    return true;
3748}
3749
3750VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateFramebuffer(VkDevice device, const VkFramebufferCreateInfo *pCreateInfo,
3751                                                                   const VkAllocationCallbacks *pAllocator,
3752                                                                   VkFramebuffer *pFramebuffer) {
3753    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3754    VkBool32 skipCall = VK_FALSE;
3755    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3756    assert(my_data != NULL);
3757
3758    skipCall |= parameter_validation_vkCreateFramebuffer(my_data->report_data, pCreateInfo, pAllocator, pFramebuffer);
3759
3760    if (skipCall == VK_FALSE) {
3761        result = get_dispatch_table(pc_device_table_map, device)->CreateFramebuffer(device, pCreateInfo, pAllocator, pFramebuffer);
3762
3763        PostCreateFramebuffer(device, pFramebuffer, result);
3764    }
3765
3766    return result;
3767}
3768
3769VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3770vkDestroyFramebuffer(VkDevice device, VkFramebuffer framebuffer, const VkAllocationCallbacks *pAllocator) {
3771    VkBool32 skipCall = VK_FALSE;
3772    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3773    assert(my_data != NULL);
3774
3775    skipCall |= parameter_validation_vkDestroyFramebuffer(my_data->report_data, framebuffer, pAllocator);
3776
3777    if (skipCall == VK_FALSE) {
3778        get_dispatch_table(pc_device_table_map, device)->DestroyFramebuffer(device, framebuffer, pAllocator);
3779    }
3780}
3781
3782bool PreCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo) {
3783    if (pCreateInfo != nullptr) {
3784        if (pCreateInfo->pAttachments != nullptr) {
3785            if (pCreateInfo->pAttachments->format < VK_FORMAT_BEGIN_RANGE ||
3786                pCreateInfo->pAttachments->format > VK_FORMAT_END_RANGE) {
3787                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3788                        "vkCreateRenderPass parameter, VkFormat pCreateInfo->pAttachments->format, is an unrecognized enumerator");
3789                return false;
3790            }
3791            if (pCreateInfo->pAttachments->loadOp < VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE ||
3792                pCreateInfo->pAttachments->loadOp > VK_ATTACHMENT_LOAD_OP_END_RANGE) {
3793                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3794                        "vkCreateRenderPass parameter, VkAttachmentLoadOp pCreateInfo->pAttachments->loadOp, is an unrecognized "
3795                        "enumerator");
3796                return false;
3797            }
3798            if (pCreateInfo->pAttachments->storeOp < VK_ATTACHMENT_STORE_OP_BEGIN_RANGE ||
3799                pCreateInfo->pAttachments->storeOp > VK_ATTACHMENT_STORE_OP_END_RANGE) {
3800                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3801                        "vkCreateRenderPass parameter, VkAttachmentStoreOp pCreateInfo->pAttachments->storeOp, is an unrecognized "
3802                        "enumerator");
3803                return false;
3804            }
3805            if (pCreateInfo->pAttachments->stencilLoadOp < VK_ATTACHMENT_LOAD_OP_BEGIN_RANGE ||
3806                pCreateInfo->pAttachments->stencilLoadOp > VK_ATTACHMENT_LOAD_OP_END_RANGE) {
3807                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3808                        "vkCreateRenderPass parameter, VkAttachmentLoadOp pCreateInfo->pAttachments->stencilLoadOp, is an "
3809                        "unrecognized enumerator");
3810                return false;
3811            }
3812            if (pCreateInfo->pAttachments->stencilStoreOp < VK_ATTACHMENT_STORE_OP_BEGIN_RANGE ||
3813                pCreateInfo->pAttachments->stencilStoreOp > VK_ATTACHMENT_STORE_OP_END_RANGE) {
3814                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3815                        "vkCreateRenderPass parameter, VkAttachmentStoreOp pCreateInfo->pAttachments->stencilStoreOp, is an "
3816                        "unrecognized enumerator");
3817                return false;
3818            }
3819            if (((pCreateInfo->pAttachments->initialLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3820                 (pCreateInfo->pAttachments->initialLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3821                (pCreateInfo->pAttachments->initialLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3822                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3823                        "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pAttachments->initialLayout, is an unrecognized "
3824                        "enumerator");
3825                return false;
3826            }
3827            if (((pCreateInfo->pAttachments->initialLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3828                 (pCreateInfo->pAttachments->initialLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3829                (pCreateInfo->pAttachments->initialLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3830                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3831                        "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pAttachments->finalLayout, is an unrecognized "
3832                        "enumerator");
3833                return false;
3834            }
3835        }
3836        if (pCreateInfo->pSubpasses != nullptr) {
3837            if (pCreateInfo->pSubpasses->pipelineBindPoint < VK_PIPELINE_BIND_POINT_BEGIN_RANGE ||
3838                pCreateInfo->pSubpasses->pipelineBindPoint > VK_PIPELINE_BIND_POINT_END_RANGE) {
3839                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3840                        "vkCreateRenderPass parameter, VkPipelineBindPoint pCreateInfo->pSubpasses->pipelineBindPoint, is an "
3841                        "unrecognized enumerator");
3842                return false;
3843            }
3844            if (pCreateInfo->pSubpasses->pInputAttachments != nullptr) {
3845                if (((pCreateInfo->pSubpasses->pInputAttachments->layout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3846                     (pCreateInfo->pSubpasses->pInputAttachments->layout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3847                    (pCreateInfo->pSubpasses->pInputAttachments->layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3848                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3849                            "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pSubpasses->pInputAttachments->layout, is an "
3850                            "unrecognized enumerator");
3851                    return false;
3852                }
3853            }
3854            if (pCreateInfo->pSubpasses->pColorAttachments != nullptr) {
3855                if (((pCreateInfo->pSubpasses->pColorAttachments->layout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3856                     (pCreateInfo->pSubpasses->pColorAttachments->layout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3857                    (pCreateInfo->pSubpasses->pColorAttachments->layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3858                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3859                            "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pSubpasses->pColorAttachments->layout, is an "
3860                            "unrecognized enumerator");
3861                    return false;
3862                }
3863            }
3864            if (pCreateInfo->pSubpasses->pResolveAttachments != nullptr) {
3865                if (((pCreateInfo->pSubpasses->pResolveAttachments->layout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3866                     (pCreateInfo->pSubpasses->pResolveAttachments->layout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3867                    (pCreateInfo->pSubpasses->pResolveAttachments->layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3868                    log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3869                            "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pSubpasses->pResolveAttachments->layout, is "
3870                            "an unrecognized enumerator");
3871                    return false;
3872                }
3873            }
3874            if (pCreateInfo->pSubpasses->pDepthStencilAttachment &&
3875                ((pCreateInfo->pSubpasses->pDepthStencilAttachment->layout < VK_IMAGE_LAYOUT_BEGIN_RANGE) ||
3876                 (pCreateInfo->pSubpasses->pDepthStencilAttachment->layout > VK_IMAGE_LAYOUT_END_RANGE)) &&
3877                (pCreateInfo->pSubpasses->pDepthStencilAttachment->layout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
3878                log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
3879                        "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pSubpasses->pDepthStencilAttachment->layout, is "
3880                        "an unrecognized enumerator");
3881                return false;
3882            }
3883        }
3884    }
3885
3886    return true;
3887}
3888
3889bool PostCreateRenderPass(VkDevice device, VkRenderPass *pRenderPass, VkResult result) {
3890    if (result < VK_SUCCESS) {
3891        std::string reason = "vkCreateRenderPass parameter, VkResult result, is " + EnumeratorString(result);
3892        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3893                reason.c_str());
3894        return false;
3895    }
3896
3897    return true;
3898}
3899
3900VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
3901                                                                  const VkAllocationCallbacks *pAllocator,
3902                                                                  VkRenderPass *pRenderPass) {
3903    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3904    VkBool32 skipCall = VK_FALSE;
3905    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3906    assert(my_data != NULL);
3907
3908    skipCall |= parameter_validation_vkCreateRenderPass(my_data->report_data, pCreateInfo, pAllocator, pRenderPass);
3909
3910    if (skipCall == VK_FALSE) {
3911        PreCreateRenderPass(device, pCreateInfo);
3912
3913        result = get_dispatch_table(pc_device_table_map, device)->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
3914
3915        PostCreateRenderPass(device, pRenderPass, result);
3916    }
3917
3918    return result;
3919}
3920
3921VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3922vkDestroyRenderPass(VkDevice device, VkRenderPass renderPass, const VkAllocationCallbacks *pAllocator) {
3923    VkBool32 skipCall = VK_FALSE;
3924    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3925    assert(my_data != NULL);
3926
3927    skipCall |= parameter_validation_vkDestroyRenderPass(my_data->report_data, renderPass, pAllocator);
3928
3929    if (skipCall == VK_FALSE) {
3930        get_dispatch_table(pc_device_table_map, device)->DestroyRenderPass(device, renderPass, pAllocator);
3931    }
3932}
3933
3934VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3935vkGetRenderAreaGranularity(VkDevice device, VkRenderPass renderPass, VkExtent2D *pGranularity) {
3936    VkBool32 skipCall = VK_FALSE;
3937    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3938    assert(my_data != NULL);
3939
3940    skipCall |= parameter_validation_vkGetRenderAreaGranularity(my_data->report_data, renderPass, pGranularity);
3941
3942    if (skipCall == VK_FALSE) {
3943        get_dispatch_table(pc_device_table_map, device)->GetRenderAreaGranularity(device, renderPass, pGranularity);
3944    }
3945}
3946
3947bool PostCreateCommandPool(VkDevice device, VkCommandPool *pCommandPool, VkResult result) {
3948    if (result < VK_SUCCESS) {
3949        std::string reason = "vkCreateCommandPool parameter, VkResult result, is " + EnumeratorString(result);
3950        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3951                reason.c_str());
3952        return false;
3953    }
3954
3955    return true;
3956}
3957
3958VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
3959                                                                   const VkAllocationCallbacks *pAllocator,
3960                                                                   VkCommandPool *pCommandPool) {
3961    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
3962    bool skipCall = false;
3963    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3964    assert(my_data != NULL);
3965
3966    skipCall |= validate_queue_family_indices(device, "vkCreateCommandPool", 1, &(pCreateInfo->queueFamilyIndex));
3967
3968    skipCall |= parameter_validation_vkCreateCommandPool(my_data->report_data, pCreateInfo, pAllocator, pCommandPool);
3969
3970    if (skipCall == VK_FALSE) {
3971        result = get_dispatch_table(pc_device_table_map, device)->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
3972
3973        PostCreateCommandPool(device, pCommandPool, result);
3974    }
3975
3976    return result;
3977}
3978
3979VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
3980vkDestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
3981    VkBool32 skipCall = VK_FALSE;
3982    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
3983    assert(my_data != NULL);
3984
3985    skipCall |= parameter_validation_vkDestroyCommandPool(my_data->report_data, commandPool, pAllocator);
3986
3987    if (skipCall == VK_FALSE) {
3988        get_dispatch_table(pc_device_table_map, device)->DestroyCommandPool(device, commandPool, pAllocator);
3989    }
3990}
3991
3992bool PostResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags, VkResult result) {
3993
3994    if (result < VK_SUCCESS) {
3995        std::string reason = "vkResetCommandPool parameter, VkResult result, is " + EnumeratorString(result);
3996        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
3997                reason.c_str());
3998        return false;
3999    }
4000
4001    return true;
4002}
4003
4004VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4005vkResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
4006    VkResult result = get_dispatch_table(pc_device_table_map, device)->ResetCommandPool(device, commandPool, flags);
4007
4008    PostResetCommandPool(device, commandPool, flags, result);
4009
4010    return result;
4011}
4012
4013bool PreCreateCommandBuffer(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo) {
4014    if (pCreateInfo != nullptr) {
4015        if (pCreateInfo->level < VK_COMMAND_BUFFER_LEVEL_BEGIN_RANGE || pCreateInfo->level > VK_COMMAND_BUFFER_LEVEL_END_RANGE) {
4016            log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4017                    "vkAllocateCommandBuffers parameter, VkCommandBufferLevel pCreateInfo->level, is an unrecognized enumerator");
4018            return false;
4019        }
4020    }
4021
4022    return true;
4023}
4024
4025bool PostCreateCommandBuffer(VkDevice device, VkCommandBuffer *pCommandBuffer, VkResult result) {
4026    if (result < VK_SUCCESS) {
4027        std::string reason = "vkAllocateCommandBuffers parameter, VkResult result, is " + EnumeratorString(result);
4028        log_msg(mdd(device), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK", "%s",
4029                reason.c_str());
4030        return false;
4031    }
4032
4033    return true;
4034}
4035
4036VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4037vkAllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pAllocateInfo, VkCommandBuffer *pCommandBuffers) {
4038    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
4039    VkBool32 skipCall = VK_FALSE;
4040    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4041    assert(my_data != NULL);
4042
4043    skipCall |= parameter_validation_vkAllocateCommandBuffers(my_data->report_data, pAllocateInfo, pCommandBuffers);
4044
4045    if (skipCall == VK_FALSE) {
4046        PreCreateCommandBuffer(device, pAllocateInfo);
4047
4048        result = get_dispatch_table(pc_device_table_map, device)->AllocateCommandBuffers(device, pAllocateInfo, pCommandBuffers);
4049
4050        PostCreateCommandBuffer(device, pCommandBuffers, result);
4051    }
4052
4053    return result;
4054}
4055
4056VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool,
4057                                                                uint32_t commandBufferCount,
4058                                                                const VkCommandBuffer *pCommandBuffers) {
4059    VkBool32 skipCall = VK_FALSE;
4060    layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4061    assert(my_data != NULL);
4062
4063    skipCall |= parameter_validation_vkFreeCommandBuffers(my_data->report_data, commandPool, commandBufferCount, pCommandBuffers);
4064
4065    if (skipCall == VK_FALSE) {
4066        get_dispatch_table(pc_device_table_map, device)
4067            ->FreeCommandBuffers(device, commandPool, commandBufferCount, pCommandBuffers);
4068    }
4069}
4070
4071bool PostBeginCommandBuffer(VkCommandBuffer commandBuffer, VkResult result) {
4072
4073    if (result < VK_SUCCESS) {
4074        std::string reason = "vkBeginCommandBuffer parameter, VkResult result, is " + EnumeratorString(result);
4075        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4076                "%s", reason.c_str());
4077        return false;
4078    }
4079
4080    return true;
4081}
4082
4083VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4084vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
4085    VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
4086    VkBool32 skipCall = VK_FALSE;
4087    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4088    assert(my_data != NULL);
4089
4090    skipCall |= parameter_validation_vkBeginCommandBuffer(my_data->report_data, pBeginInfo);
4091
4092    if (skipCall == VK_FALSE) {
4093        result = get_dispatch_table(pc_device_table_map, commandBuffer)->BeginCommandBuffer(commandBuffer, pBeginInfo);
4094
4095        PostBeginCommandBuffer(commandBuffer, result);
4096    }
4097
4098    return result;
4099}
4100
4101bool PostEndCommandBuffer(VkCommandBuffer commandBuffer, VkResult result) {
4102
4103    if (result < VK_SUCCESS) {
4104        std::string reason = "vkEndCommandBuffer parameter, VkResult result, is " + EnumeratorString(result);
4105        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4106                "%s", reason.c_str());
4107        return false;
4108    }
4109
4110    return true;
4111}
4112
4113VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer) {
4114    VkResult result = get_dispatch_table(pc_device_table_map, commandBuffer)->EndCommandBuffer(commandBuffer);
4115
4116    PostEndCommandBuffer(commandBuffer, result);
4117
4118    return result;
4119}
4120
4121bool PostResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags, VkResult result) {
4122
4123    if (result < VK_SUCCESS) {
4124        std::string reason = "vkResetCommandBuffer parameter, VkResult result, is " + EnumeratorString(result);
4125        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4126                "%s", reason.c_str());
4127        return false;
4128    }
4129
4130    return true;
4131}
4132
4133VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
4134vkResetCommandBuffer(VkCommandBuffer commandBuffer, VkCommandBufferResetFlags flags) {
4135    VkResult result = get_dispatch_table(pc_device_table_map, commandBuffer)->ResetCommandBuffer(commandBuffer, flags);
4136
4137    PostResetCommandBuffer(commandBuffer, flags, result);
4138
4139    return result;
4140}
4141
4142bool PostCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
4143
4144    if (pipelineBindPoint < VK_PIPELINE_BIND_POINT_BEGIN_RANGE || pipelineBindPoint > VK_PIPELINE_BIND_POINT_END_RANGE) {
4145        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4146                "vkCmdBindPipeline parameter, VkPipelineBindPoint pipelineBindPoint, is an unrecognized enumerator");
4147        return false;
4148    }
4149
4150    return true;
4151}
4152
4153VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4154vkCmdBindPipeline(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipeline pipeline) {
4155    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
4156
4157    PostCmdBindPipeline(commandBuffer, pipelineBindPoint, pipeline);
4158}
4159
4160VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4161vkCmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
4162    VkBool32 skipCall = VK_FALSE;
4163    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4164    assert(my_data != NULL);
4165
4166    skipCall |= parameter_validation_vkCmdSetViewport(my_data->report_data, firstViewport, viewportCount, pViewports);
4167
4168    if (skipCall == VK_FALSE) {
4169        get_dispatch_table(pc_device_table_map, commandBuffer)
4170            ->CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
4171    }
4172}
4173
4174VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4175vkCmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
4176    VkBool32 skipCall = VK_FALSE;
4177    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4178    assert(my_data != NULL);
4179
4180    skipCall |= parameter_validation_vkCmdSetScissor(my_data->report_data, firstScissor, scissorCount, pScissors);
4181
4182    if (skipCall == VK_FALSE) {
4183        get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
4184    }
4185}
4186
4187VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(VkCommandBuffer commandBuffer, float lineWidth) {
4188    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetLineWidth(commandBuffer, lineWidth);
4189}
4190
4191VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4192vkCmdSetDepthBias(VkCommandBuffer commandBuffer, float depthBiasConstantFactor, float depthBiasClamp, float depthBiasSlopeFactor) {
4193    get_dispatch_table(pc_device_table_map, commandBuffer)
4194        ->CmdSetDepthBias(commandBuffer, depthBiasConstantFactor, depthBiasClamp, depthBiasSlopeFactor);
4195}
4196
4197VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(VkCommandBuffer commandBuffer, const float blendConstants[4]) {
4198    VkBool32 skipCall = VK_FALSE;
4199    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4200    assert(my_data != NULL);
4201
4202    skipCall |= parameter_validation_vkCmdSetBlendConstants(my_data->report_data, blendConstants);
4203
4204    if (skipCall == VK_FALSE) {
4205        get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetBlendConstants(commandBuffer, blendConstants);
4206    }
4207}
4208
4209VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4210vkCmdSetDepthBounds(VkCommandBuffer commandBuffer, float minDepthBounds, float maxDepthBounds) {
4211    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetDepthBounds(commandBuffer, minDepthBounds, maxDepthBounds);
4212}
4213
4214VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4215vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t compareMask) {
4216    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetStencilCompareMask(commandBuffer, faceMask, compareMask);
4217}
4218
4219VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4220vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t writeMask) {
4221    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetStencilWriteMask(commandBuffer, faceMask, writeMask);
4222}
4223
4224VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4225vkCmdSetStencilReference(VkCommandBuffer commandBuffer, VkStencilFaceFlags faceMask, uint32_t reference) {
4226    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetStencilReference(commandBuffer, faceMask, reference);
4227}
4228
4229bool PostCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
4230                               uint32_t firstSet, uint32_t setCount, uint32_t dynamicOffsetCount) {
4231
4232    if (pipelineBindPoint < VK_PIPELINE_BIND_POINT_BEGIN_RANGE || pipelineBindPoint > VK_PIPELINE_BIND_POINT_END_RANGE) {
4233        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4234                "vkCmdBindDescriptorSets parameter, VkPipelineBindPoint pipelineBindPoint, is an unrecognized enumerator");
4235        return false;
4236    }
4237
4238    return true;
4239}
4240
4241VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4242vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer, VkPipelineBindPoint pipelineBindPoint, VkPipelineLayout layout,
4243                        uint32_t firstSet, uint32_t descriptorSetCount, const VkDescriptorSet *pDescriptorSets,
4244                        uint32_t dynamicOffsetCount, const uint32_t *pDynamicOffsets) {
4245    VkBool32 skipCall = VK_FALSE;
4246    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4247    assert(my_data != NULL);
4248
4249    skipCall |= parameter_validation_vkCmdBindDescriptorSets(my_data->report_data, pipelineBindPoint, layout, firstSet, descriptorSetCount,
4250                                                    pDescriptorSets, dynamicOffsetCount, pDynamicOffsets);
4251
4252    if (skipCall == VK_FALSE) {
4253        get_dispatch_table(pc_device_table_map, commandBuffer)
4254            ->CmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, pDescriptorSets,
4255                                    dynamicOffsetCount, pDynamicOffsets);
4256
4257        PostCmdBindDescriptorSets(commandBuffer, pipelineBindPoint, layout, firstSet, descriptorSetCount, dynamicOffsetCount);
4258    }
4259}
4260
4261bool PostCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
4262
4263    if (indexType < VK_INDEX_TYPE_BEGIN_RANGE || indexType > VK_INDEX_TYPE_END_RANGE) {
4264        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4265                "vkCmdBindIndexBuffer parameter, VkIndexType indexType, is an unrecognized enumerator");
4266        return false;
4267    }
4268
4269    return true;
4270}
4271
4272VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4273vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, VkIndexType indexType) {
4274    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
4275
4276    PostCmdBindIndexBuffer(commandBuffer, buffer, offset, indexType);
4277}
4278
4279VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer, uint32_t firstBinding,
4280                                                                  uint32_t bindingCount, const VkBuffer *pBuffers,
4281                                                                  const VkDeviceSize *pOffsets) {
4282    VkBool32 skipCall = VK_FALSE;
4283    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4284    assert(my_data != NULL);
4285
4286    skipCall |= parameter_validation_vkCmdBindVertexBuffers(my_data->report_data, firstBinding, bindingCount, pBuffers, pOffsets);
4287
4288    if (skipCall == VK_FALSE) {
4289        get_dispatch_table(pc_device_table_map, commandBuffer)
4290            ->CmdBindVertexBuffers(commandBuffer, firstBinding, bindingCount, pBuffers, pOffsets);
4291    }
4292}
4293
4294bool PreCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount, uint32_t firstVertex,
4295                uint32_t firstInstance) {
4296    if (vertexCount == 0) {
4297        // TODO: Verify against Valid Usage section. I don't see a non-zero vertexCount listed, may need to add that and make
4298        // this an error or leave as is.
4299        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4300                "vkCmdDraw parameter, uint32_t vertexCount, is 0");
4301        return false;
4302    }
4303
4304    if (instanceCount == 0) {
4305        // TODO: Verify against Valid Usage section. I don't see a non-zero instanceCount listed, may need to add that and make
4306        // this an error or leave as is.
4307        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_WARNING_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4308                "vkCmdDraw parameter, uint32_t instanceCount, is 0");
4309        return false;
4310    }
4311
4312    return true;
4313}
4314
4315VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDraw(VkCommandBuffer commandBuffer, uint32_t vertexCount, uint32_t instanceCount,
4316                                                     uint32_t firstVertex, uint32_t firstInstance) {
4317    PreCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
4318
4319    get_dispatch_table(pc_device_table_map, commandBuffer)
4320        ->CmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
4321}
4322
4323VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(VkCommandBuffer commandBuffer, uint32_t indexCount,
4324                                                            uint32_t instanceCount, uint32_t firstIndex, int32_t vertexOffset,
4325                                                            uint32_t firstInstance) {
4326    get_dispatch_table(pc_device_table_map, commandBuffer)
4327        ->CmdDrawIndexed(commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance);
4328}
4329
4330VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4331vkCmdDrawIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
4332    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdDrawIndirect(commandBuffer, buffer, offset, count, stride);
4333}
4334
4335VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4336vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset, uint32_t count, uint32_t stride) {
4337    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdDrawIndexedIndirect(commandBuffer, buffer, offset, count, stride);
4338}
4339
4340VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(VkCommandBuffer commandBuffer, uint32_t x, uint32_t y, uint32_t z) {
4341    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdDispatch(commandBuffer, x, y, z);
4342}
4343
4344VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4345vkCmdDispatchIndirect(VkCommandBuffer commandBuffer, VkBuffer buffer, VkDeviceSize offset) {
4346    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdDispatchIndirect(commandBuffer, buffer, offset);
4347}
4348
4349VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer,
4350                                                           uint32_t regionCount, const VkBufferCopy *pRegions) {
4351    VkBool32 skipCall = VK_FALSE;
4352    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4353    assert(my_data != NULL);
4354
4355    skipCall |= parameter_validation_vkCmdCopyBuffer(my_data->report_data, srcBuffer, dstBuffer, regionCount, pRegions);
4356
4357    if (skipCall == VK_FALSE) {
4358        get_dispatch_table(pc_device_table_map, commandBuffer)
4359            ->CmdCopyBuffer(commandBuffer, srcBuffer, dstBuffer, regionCount, pRegions);
4360    }
4361}
4362
4363bool PreCmdCopyImage(VkCommandBuffer commandBuffer, const VkImageCopy *pRegions) {
4364    if (pRegions != nullptr) {
4365        if ((pRegions->srcSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4366                                                    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4367            log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4368                    "vkCmdCopyImage parameter, VkImageAspect pRegions->srcSubresource.aspectMask, is an unrecognized enumerator");
4369            return false;
4370        }
4371        if ((pRegions->dstSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4372                                                    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4373            log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4374                    "vkCmdCopyImage parameter, VkImageAspect pRegions->dstSubresource.aspectMask, is an unrecognized enumerator");
4375            return false;
4376        }
4377    }
4378
4379    return true;
4380}
4381
4382bool PostCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
4383                      VkImageLayout dstImageLayout, uint32_t regionCount) {
4384    if (((srcImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (srcImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4385        (srcImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4386        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4387                "vkCmdCopyImage parameter, VkImageLayout srcImageLayout, is an unrecognized enumerator");
4388        return false;
4389    }
4390
4391    if (((dstImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (dstImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4392        (dstImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4393        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4394                "vkCmdCopyImage parameter, VkImageLayout dstImageLayout, is an unrecognized enumerator");
4395        return false;
4396    }
4397
4398    return true;
4399}
4400
4401VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4402vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
4403               VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
4404    VkBool32 skipCall = VK_FALSE;
4405    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4406    assert(my_data != NULL);
4407
4408    skipCall |=
4409        parameter_validation_vkCmdCopyImage(my_data->report_data, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
4410
4411    if (skipCall == VK_FALSE) {
4412        PreCmdCopyImage(commandBuffer, pRegions);
4413
4414        get_dispatch_table(pc_device_table_map, commandBuffer)
4415            ->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
4416
4417        PostCmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount);
4418    }
4419}
4420
4421bool PreCmdBlitImage(VkCommandBuffer commandBuffer, const VkImageBlit *pRegions) {
4422    if (pRegions != nullptr) {
4423        if ((pRegions->srcSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4424                                                    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4425            log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4426                    "vkCmdCopyImage parameter, VkImageAspect pRegions->srcSubresource.aspectMask, is an unrecognized enumerator");
4427            return false;
4428        }
4429        if ((pRegions->dstSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4430                                                    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4431            log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4432                    "vkCmdCopyImage parameter, VkImageAspect pRegions->dstSubresource.aspectMask, is an unrecognized enumerator");
4433            return false;
4434        }
4435    }
4436
4437    return true;
4438}
4439
4440bool PostCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
4441                      VkImageLayout dstImageLayout, uint32_t regionCount, VkFilter filter) {
4442
4443    if (((srcImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (srcImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4444        (srcImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4445        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4446                "vkCmdBlitImage parameter, VkImageLayout srcImageLayout, is an unrecognized enumerator");
4447        return false;
4448    }
4449
4450    if (((dstImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (dstImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4451        (dstImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4452        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4453                "vkCmdBlitImage parameter, VkImageLayout dstImageLayout, is an unrecognized enumerator");
4454        return false;
4455    }
4456
4457    if (filter < VK_FILTER_BEGIN_RANGE || filter > VK_FILTER_END_RANGE) {
4458        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4459                "vkCmdBlitImage parameter, VkFilter filter, is an unrecognized enumerator");
4460        return false;
4461    }
4462
4463    return true;
4464}
4465
4466VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4467vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
4468               VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
4469    VkBool32 skipCall = VK_FALSE;
4470    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4471    assert(my_data != NULL);
4472
4473    skipCall |= parameter_validation_vkCmdBlitImage(my_data->report_data, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
4474                                           pRegions, filter);
4475
4476    if (skipCall == VK_FALSE) {
4477        PreCmdBlitImage(commandBuffer, pRegions);
4478
4479        get_dispatch_table(pc_device_table_map, commandBuffer)
4480            ->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
4481
4482        PostCmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, filter);
4483    }
4484}
4485
4486bool PreCmdCopyBufferToImage(VkCommandBuffer commandBuffer, const VkBufferImageCopy *pRegions) {
4487    if (pRegions != nullptr) {
4488        if ((pRegions->imageSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4489                                                      VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4490            log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4491                    "vkCmdCopyBufferToImage parameter, VkImageAspect pRegions->imageSubresource.aspectMask, is an unrecognized "
4492                    "enumerator");
4493            return false;
4494        }
4495    }
4496
4497    return true;
4498}
4499
4500bool PostCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage, VkImageLayout dstImageLayout,
4501                              uint32_t regionCount) {
4502
4503    if (((dstImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (dstImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4504        (dstImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4505        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4506                "vkCmdCopyBufferToImage parameter, VkImageLayout dstImageLayout, is an unrecognized enumerator");
4507        return false;
4508    }
4509
4510    return true;
4511}
4512
4513VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
4514                                                                  VkImage dstImage, VkImageLayout dstImageLayout,
4515                                                                  uint32_t regionCount, const VkBufferImageCopy *pRegions) {
4516    VkBool32 skipCall = VK_FALSE;
4517    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4518    assert(my_data != NULL);
4519
4520    skipCall |=
4521        parameter_validation_vkCmdCopyBufferToImage(my_data->report_data, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
4522
4523    if (skipCall == VK_FALSE) {
4524        PreCmdCopyBufferToImage(commandBuffer, pRegions);
4525
4526        get_dispatch_table(pc_device_table_map, commandBuffer)
4527            ->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
4528
4529        PostCmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount);
4530    }
4531}
4532
4533bool PreCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, const VkBufferImageCopy *pRegions) {
4534    if (pRegions != nullptr) {
4535        if ((pRegions->imageSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4536                                                      VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4537            log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4538                    "vkCmdCopyImageToBuffer parameter, VkImageAspect pRegions->imageSubresource.aspectMask, is an unrecognized "
4539                    "enumerator");
4540            return false;
4541        }
4542    }
4543
4544    return true;
4545}
4546
4547bool PostCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkBuffer dstBuffer,
4548                              uint32_t regionCount) {
4549
4550    if (((srcImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (srcImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4551        (srcImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4552        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4553                "vkCmdCopyImageToBuffer parameter, VkImageLayout srcImageLayout, is an unrecognized enumerator");
4554        return false;
4555    }
4556
4557    return true;
4558}
4559
4560VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
4561                                                                  VkImageLayout srcImageLayout, VkBuffer dstBuffer,
4562                                                                  uint32_t regionCount, const VkBufferImageCopy *pRegions) {
4563    VkBool32 skipCall = VK_FALSE;
4564    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4565    assert(my_data != NULL);
4566
4567    skipCall |=
4568        parameter_validation_vkCmdCopyImageToBuffer(my_data->report_data, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
4569
4570    if (skipCall == VK_FALSE) {
4571        PreCmdCopyImageToBuffer(commandBuffer, pRegions);
4572
4573        get_dispatch_table(pc_device_table_map, commandBuffer)
4574            ->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
4575
4576        PostCmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount);
4577    }
4578}
4579
4580VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
4581                                                             VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) {
4582    VkBool32 skipCall = VK_FALSE;
4583    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4584    assert(my_data != NULL);
4585
4586    skipCall |= parameter_validation_vkCmdUpdateBuffer(my_data->report_data, dstBuffer, dstOffset, dataSize, pData);
4587
4588    if (skipCall == VK_FALSE) {
4589        get_dispatch_table(pc_device_table_map, commandBuffer)
4590            ->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
4591    }
4592}
4593
4594VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4595vkCmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
4596    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
4597}
4598
4599bool PostCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout, uint32_t rangeCount) {
4600
4601    if (((imageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (imageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4602        (imageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4603        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4604                "vkCmdClearColorImage parameter, VkImageLayout imageLayout, is an unrecognized enumerator");
4605        return false;
4606    }
4607
4608    return true;
4609}
4610
4611VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
4612                                                                VkImageLayout imageLayout, const VkClearColorValue *pColor,
4613                                                                uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
4614    VkBool32 skipCall = VK_FALSE;
4615    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4616    assert(my_data != NULL);
4617
4618    skipCall |= parameter_validation_vkCmdClearColorImage(my_data->report_data, image, imageLayout, pColor, rangeCount, pRanges);
4619
4620    if (skipCall == VK_FALSE) {
4621        get_dispatch_table(pc_device_table_map, commandBuffer)
4622            ->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
4623
4624        PostCmdClearColorImage(commandBuffer, image, imageLayout, rangeCount);
4625    }
4626}
4627
4628bool PostCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
4629                                   const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount) {
4630
4631    if (((imageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (imageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4632        (imageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4633        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4634                "vkCmdClearDepthStencilImage parameter, VkImageLayout imageLayout, is an unrecognized enumerator");
4635        return false;
4636    }
4637
4638    return true;
4639}
4640
4641VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4642vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
4643                            const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
4644                            const VkImageSubresourceRange *pRanges) {
4645    VkBool32 skipCall = VK_FALSE;
4646    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4647    assert(my_data != NULL);
4648
4649    skipCall |=
4650        parameter_validation_vkCmdClearDepthStencilImage(my_data->report_data, image, imageLayout, pDepthStencil, rangeCount, pRanges);
4651
4652    if (skipCall == VK_FALSE) {
4653        get_dispatch_table(pc_device_table_map, commandBuffer)
4654            ->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount, pRanges);
4655
4656        PostCmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount);
4657    }
4658}
4659
4660VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
4661                                                                 const VkClearAttachment *pAttachments, uint32_t rectCount,
4662                                                                 const VkClearRect *pRects) {
4663    VkBool32 skipCall = VK_FALSE;
4664    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4665    assert(my_data != NULL);
4666
4667    skipCall |= parameter_validation_vkCmdClearAttachments(my_data->report_data, attachmentCount, pAttachments, rectCount, pRects);
4668
4669    if (skipCall == VK_FALSE) {
4670        get_dispatch_table(pc_device_table_map, commandBuffer)
4671            ->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
4672    }
4673}
4674
4675bool PreCmdResolveImage(VkCommandBuffer commandBuffer, const VkImageResolve *pRegions) {
4676    if (pRegions != nullptr) {
4677        if ((pRegions->srcSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4678                                                    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4679            log_msg(
4680                mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4681                "vkCmdResolveImage parameter, VkImageAspect pRegions->srcSubresource.aspectMask, is an unrecognized enumerator");
4682            return false;
4683        }
4684        if ((pRegions->dstSubresource.aspectMask & (VK_IMAGE_ASPECT_COLOR_BIT | VK_IMAGE_ASPECT_DEPTH_BIT |
4685                                                    VK_IMAGE_ASPECT_STENCIL_BIT | VK_IMAGE_ASPECT_METADATA_BIT)) == 0) {
4686            log_msg(
4687                mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4688                "vkCmdResolveImage parameter, VkImageAspect pRegions->dstSubresource.aspectMask, is an unrecognized enumerator");
4689            return false;
4690        }
4691    }
4692
4693    return true;
4694}
4695
4696bool PostCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
4697                         VkImageLayout dstImageLayout, uint32_t regionCount) {
4698
4699    if (((srcImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (srcImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4700        (srcImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4701        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4702                "vkCmdResolveImage parameter, VkImageLayout srcImageLayout, is an unrecognized enumerator");
4703        return false;
4704    }
4705
4706    if (((dstImageLayout < VK_IMAGE_LAYOUT_BEGIN_RANGE) || (dstImageLayout > VK_IMAGE_LAYOUT_END_RANGE)) &&
4707        (dstImageLayout != VK_IMAGE_LAYOUT_PRESENT_SRC_KHR)) {
4708        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4709                "vkCmdResolveImage parameter, VkImageLayout dstImageLayout, is an unrecognized enumerator");
4710        return false;
4711    }
4712
4713    return true;
4714}
4715
4716VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4717vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
4718                  VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
4719    VkBool32 skipCall = VK_FALSE;
4720    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4721    assert(my_data != NULL);
4722
4723    skipCall |= parameter_validation_vkCmdResolveImage(my_data->report_data, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
4724                                              pRegions);
4725
4726    if (skipCall == VK_FALSE) {
4727        PreCmdResolveImage(commandBuffer, pRegions);
4728
4729        get_dispatch_table(pc_device_table_map, commandBuffer)
4730            ->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
4731
4732        PostCmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount);
4733    }
4734}
4735
4736VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4737vkCmdSetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
4738    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdSetEvent(commandBuffer, event, stageMask);
4739}
4740
4741VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4742vkCmdResetEvent(VkCommandBuffer commandBuffer, VkEvent event, VkPipelineStageFlags stageMask) {
4743    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdResetEvent(commandBuffer, event, stageMask);
4744}
4745
4746VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4747vkCmdWaitEvents(VkCommandBuffer commandBuffer, uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags srcStageMask,
4748                VkPipelineStageFlags dstStageMask, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
4749                uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
4750                uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
4751    VkBool32 skipCall = VK_FALSE;
4752    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4753    assert(my_data != NULL);
4754
4755    skipCall |= parameter_validation_vkCmdWaitEvents(my_data->report_data, eventCount, pEvents, srcStageMask, dstStageMask,
4756                                            memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount, pBufferMemoryBarriers,
4757                                            imageMemoryBarrierCount, pImageMemoryBarriers);
4758
4759    if (skipCall == VK_FALSE) {
4760        get_dispatch_table(pc_device_table_map, commandBuffer)
4761            ->CmdWaitEvents(commandBuffer, eventCount, pEvents, srcStageMask, dstStageMask, memoryBarrierCount, pMemoryBarriers,
4762                            bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
4763    }
4764}
4765
4766VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4767vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
4768                     VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
4769                     uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
4770                     uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
4771    VkBool32 skipCall = VK_FALSE;
4772    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4773    assert(my_data != NULL);
4774
4775    skipCall |= parameter_validation_vkCmdPipelineBarrier(my_data->report_data, srcStageMask, dstStageMask, dependencyFlags,
4776                                                 memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
4777                                                 pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
4778
4779    if (skipCall == VK_FALSE) {
4780        get_dispatch_table(pc_device_table_map, commandBuffer)
4781            ->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags, memoryBarrierCount, pMemoryBarriers,
4782                                 bufferMemoryBarrierCount, pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
4783    }
4784}
4785
4786VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4787vkCmdBeginQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot, VkQueryControlFlags flags) {
4788    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdBeginQuery(commandBuffer, queryPool, slot, flags);
4789}
4790
4791VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t slot) {
4792    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdEndQuery(commandBuffer, queryPool, slot);
4793}
4794
4795VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4796vkCmdResetQueryPool(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {
4797    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdResetQueryPool(commandBuffer, queryPool, firstQuery, queryCount);
4798}
4799
4800bool PostCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool,
4801                           uint32_t slot) {
4802
4803    ValidateEnumerator(pipelineStage);
4804
4805    return true;
4806}
4807
4808VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4809vkCmdWriteTimestamp(VkCommandBuffer commandBuffer, VkPipelineStageFlagBits pipelineStage, VkQueryPool queryPool, uint32_t slot) {
4810    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
4811
4812    PostCmdWriteTimestamp(commandBuffer, pipelineStage, queryPool, slot);
4813}
4814
4815VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4816vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer, VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount,
4817                          VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags) {
4818    get_dispatch_table(pc_device_table_map, commandBuffer)
4819        ->CmdCopyQueryPoolResults(commandBuffer, queryPool, firstQuery, queryCount, dstBuffer, dstOffset, stride, flags);
4820}
4821
4822VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(VkCommandBuffer commandBuffer, VkPipelineLayout layout,
4823                                                              VkShaderStageFlags stageFlags, uint32_t offset, uint32_t size,
4824                                                              const void *pValues) {
4825    VkBool32 skipCall = VK_FALSE;
4826    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4827    assert(my_data != NULL);
4828
4829    skipCall |= parameter_validation_vkCmdPushConstants(my_data->report_data, layout, stageFlags, offset, size, pValues);
4830
4831    if (skipCall == VK_FALSE) {
4832        get_dispatch_table(pc_device_table_map, commandBuffer)
4833            ->CmdPushConstants(commandBuffer, layout, stageFlags, offset, size, pValues);
4834    }
4835}
4836
4837bool PostCmdBeginRenderPass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
4838
4839    if (contents < VK_SUBPASS_CONTENTS_BEGIN_RANGE || contents > VK_SUBPASS_CONTENTS_END_RANGE) {
4840        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4841                "vkCmdBeginRenderPass parameter, VkSubpassContents contents, is an unrecognized enumerator");
4842        return false;
4843    }
4844
4845    return true;
4846}
4847
4848VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4849vkCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin, VkSubpassContents contents) {
4850    VkBool32 skipCall = VK_FALSE;
4851    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4852    assert(my_data != NULL);
4853
4854    skipCall |= parameter_validation_vkCmdBeginRenderPass(my_data->report_data, pRenderPassBegin, contents);
4855
4856    if (skipCall == VK_FALSE) {
4857        get_dispatch_table(pc_device_table_map, commandBuffer)->CmdBeginRenderPass(commandBuffer, pRenderPassBegin, contents);
4858
4859        PostCmdBeginRenderPass(commandBuffer, contents);
4860    }
4861}
4862
4863bool PostCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
4864
4865    if (contents < VK_SUBPASS_CONTENTS_BEGIN_RANGE || contents > VK_SUBPASS_CONTENTS_END_RANGE) {
4866        log_msg(mdd(commandBuffer), VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, 1, "PARAMCHECK",
4867                "vkCmdNextSubpass parameter, VkSubpassContents contents, is an unrecognized enumerator");
4868        return false;
4869    }
4870
4871    return true;
4872}
4873
4874VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) {
4875    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdNextSubpass(commandBuffer, contents);
4876
4877    PostCmdNextSubpass(commandBuffer, contents);
4878}
4879
4880VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer) {
4881    get_dispatch_table(pc_device_table_map, commandBuffer)->CmdEndRenderPass(commandBuffer);
4882}
4883
4884VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
4885vkCmdExecuteCommands(VkCommandBuffer commandBuffer, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) {
4886    VkBool32 skipCall = VK_FALSE;
4887    layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
4888    assert(my_data != NULL);
4889
4890    skipCall |= parameter_validation_vkCmdExecuteCommands(my_data->report_data, commandBufferCount, pCommandBuffers);
4891
4892    if (skipCall == VK_FALSE) {
4893        get_dispatch_table(pc_device_table_map, commandBuffer)
4894            ->CmdExecuteCommands(commandBuffer, commandBufferCount, pCommandBuffers);
4895    }
4896}
4897
4898VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
4899    layer_data *data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
4900
4901    if (validate_string(data->report_data, "vkGetDeviceProcAddr", "funcName", funcName) == VK_TRUE) {
4902        return NULL;
4903    }
4904
4905    if (!strcmp(funcName, "vkGetDeviceProcAddr"))
4906        return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
4907    if (!strcmp(funcName, "vkDestroyDevice"))
4908        return (PFN_vkVoidFunction)vkDestroyDevice;
4909    if (!strcmp(funcName, "vkGetDeviceQueue"))
4910        return (PFN_vkVoidFunction)vkGetDeviceQueue;
4911    if (!strcmp(funcName, "vkQueueSubmit"))
4912        return (PFN_vkVoidFunction)vkQueueSubmit;
4913    if (!strcmp(funcName, "vkQueueWaitIdle"))
4914        return (PFN_vkVoidFunction)vkQueueWaitIdle;
4915    if (!strcmp(funcName, "vkDeviceWaitIdle"))
4916        return (PFN_vkVoidFunction)vkDeviceWaitIdle;
4917    if (!strcmp(funcName, "vkAllocateMemory"))
4918        return (PFN_vkVoidFunction)vkAllocateMemory;
4919    if (!strcmp(funcName, "vkFreeMemory"))
4920        return (PFN_vkVoidFunction)vkFreeMemory;
4921    if (!strcmp(funcName, "vkMapMemory"))
4922        return (PFN_vkVoidFunction)vkMapMemory;
4923    if (!strcmp(funcName, "vkFlushMappedMemoryRanges"))
4924        return (PFN_vkVoidFunction)vkFlushMappedMemoryRanges;
4925    if (!strcmp(funcName, "vkInvalidateMappedMemoryRanges"))
4926        return (PFN_vkVoidFunction)vkInvalidateMappedMemoryRanges;
4927    if (!strcmp(funcName, "vkCreateFence"))
4928        return (PFN_vkVoidFunction)vkCreateFence;
4929    if (!strcmp(funcName, "vkDestroyFence"))
4930        return (PFN_vkVoidFunction)vkDestroyFence;
4931    if (!strcmp(funcName, "vkResetFences"))
4932        return (PFN_vkVoidFunction)vkResetFences;
4933    if (!strcmp(funcName, "vkGetFenceStatus"))
4934        return (PFN_vkVoidFunction)vkGetFenceStatus;
4935    if (!strcmp(funcName, "vkWaitForFences"))
4936        return (PFN_vkVoidFunction)vkWaitForFences;
4937    if (!strcmp(funcName, "vkCreateSemaphore"))
4938        return (PFN_vkVoidFunction)vkCreateSemaphore;
4939    if (!strcmp(funcName, "vkDestroySemaphore"))
4940        return (PFN_vkVoidFunction)vkDestroySemaphore;
4941    if (!strcmp(funcName, "vkCreateEvent"))
4942        return (PFN_vkVoidFunction)vkCreateEvent;
4943    if (!strcmp(funcName, "vkDestroyEvent"))
4944        return (PFN_vkVoidFunction)vkDestroyEvent;
4945    if (!strcmp(funcName, "vkGetEventStatus"))
4946        return (PFN_vkVoidFunction)vkGetEventStatus;
4947    if (!strcmp(funcName, "vkSetEvent"))
4948        return (PFN_vkVoidFunction)vkSetEvent;
4949    if (!strcmp(funcName, "vkResetEvent"))
4950        return (PFN_vkVoidFunction)vkResetEvent;
4951    if (!strcmp(funcName, "vkCreateQueryPool"))
4952        return (PFN_vkVoidFunction)vkCreateQueryPool;
4953    if (!strcmp(funcName, "vkDestroyQueryPool"))
4954        return (PFN_vkVoidFunction)vkDestroyQueryPool;
4955    if (!strcmp(funcName, "vkGetQueryPoolResults"))
4956        return (PFN_vkVoidFunction)vkGetQueryPoolResults;
4957    if (!strcmp(funcName, "vkCreateBuffer"))
4958        return (PFN_vkVoidFunction)vkCreateBuffer;
4959    if (!strcmp(funcName, "vkDestroyBuffer"))
4960        return (PFN_vkVoidFunction)vkDestroyBuffer;
4961    if (!strcmp(funcName, "vkCreateBufferView"))
4962        return (PFN_vkVoidFunction)vkCreateBufferView;
4963    if (!strcmp(funcName, "vkDestroyBufferView"))
4964        return (PFN_vkVoidFunction)vkDestroyBufferView;
4965    if (!strcmp(funcName, "vkCreateImage"))
4966        return (PFN_vkVoidFunction)vkCreateImage;
4967    if (!strcmp(funcName, "vkDestroyImage"))
4968        return (PFN_vkVoidFunction)vkDestroyImage;
4969    if (!strcmp(funcName, "vkGetImageSubresourceLayout"))
4970        return (PFN_vkVoidFunction)vkGetImageSubresourceLayout;
4971    if (!strcmp(funcName, "vkCreateImageView"))
4972        return (PFN_vkVoidFunction)vkCreateImageView;
4973    if (!strcmp(funcName, "vkDestroyImageView"))
4974        return (PFN_vkVoidFunction)vkDestroyImageView;
4975    if (!strcmp(funcName, "vkCreateShaderModule"))
4976        return (PFN_vkVoidFunction)vkCreateShaderModule;
4977    if (!strcmp(funcName, "vkDestroyShaderModule"))
4978        return (PFN_vkVoidFunction)vkDestroyShaderModule;
4979    if (!strcmp(funcName, "vkCreatePipelineCache"))
4980        return (PFN_vkVoidFunction)vkCreatePipelineCache;
4981    if (!strcmp(funcName, "vkDestroyPipelineCache"))
4982        return (PFN_vkVoidFunction)vkDestroyPipelineCache;
4983    if (!strcmp(funcName, "vkGetPipelineCacheData"))
4984        return (PFN_vkVoidFunction)vkGetPipelineCacheData;
4985    if (!strcmp(funcName, "vkMergePipelineCaches"))
4986        return (PFN_vkVoidFunction)vkMergePipelineCaches;
4987    if (!strcmp(funcName, "vkCreateGraphicsPipelines"))
4988        return (PFN_vkVoidFunction)vkCreateGraphicsPipelines;
4989    if (!strcmp(funcName, "vkCreateComputePipelines"))
4990        return (PFN_vkVoidFunction)vkCreateComputePipelines;
4991    if (!strcmp(funcName, "vkDestroyPipeline"))
4992        return (PFN_vkVoidFunction)vkDestroyPipeline;
4993    if (!strcmp(funcName, "vkCreatePipelineLayout"))
4994        return (PFN_vkVoidFunction)vkCreatePipelineLayout;
4995    if (!strcmp(funcName, "vkDestroyPipelineLayout"))
4996        return (PFN_vkVoidFunction)vkDestroyPipelineLayout;
4997    if (!strcmp(funcName, "vkCreateSampler"))
4998        return (PFN_vkVoidFunction)vkCreateSampler;
4999    if (!strcmp(funcName, "vkDestroySampler"))
5000        return (PFN_vkVoidFunction)vkDestroySampler;
5001    if (!strcmp(funcName, "vkCreateDescriptorSetLayout"))
5002        return (PFN_vkVoidFunction)vkCreateDescriptorSetLayout;
5003    if (!strcmp(funcName, "vkDestroyDescriptorSetLayout"))
5004        return (PFN_vkVoidFunction)vkDestroyDescriptorSetLayout;
5005    if (!strcmp(funcName, "vkCreateDescriptorPool"))
5006        return (PFN_vkVoidFunction)vkCreateDescriptorPool;
5007    if (!strcmp(funcName, "vkDestroyDescriptorPool"))
5008        return (PFN_vkVoidFunction)vkDestroyDescriptorPool;
5009    if (!strcmp(funcName, "vkResetDescriptorPool"))
5010        return (PFN_vkVoidFunction)vkResetDescriptorPool;
5011    if (!strcmp(funcName, "vkAllocateDescriptorSets"))
5012        return (PFN_vkVoidFunction)vkAllocateDescriptorSets;
5013    if (!strcmp(funcName, "vkCmdSetViewport"))
5014        return (PFN_vkVoidFunction)vkCmdSetViewport;
5015    if (!strcmp(funcName, "vkCmdSetScissor"))
5016        return (PFN_vkVoidFunction)vkCmdSetScissor;
5017    if (!strcmp(funcName, "vkCmdSetLineWidth"))
5018        return (PFN_vkVoidFunction)vkCmdSetLineWidth;
5019    if (!strcmp(funcName, "vkCmdSetDepthBias"))
5020        return (PFN_vkVoidFunction)vkCmdSetDepthBias;
5021    if (!strcmp(funcName, "vkCmdSetBlendConstants"))
5022        return (PFN_vkVoidFunction)vkCmdSetBlendConstants;
5023    if (!strcmp(funcName, "vkCmdSetDepthBounds"))
5024        return (PFN_vkVoidFunction)vkCmdSetDepthBounds;
5025    if (!strcmp(funcName, "vkCmdSetStencilCompareMask"))
5026        return (PFN_vkVoidFunction)vkCmdSetStencilCompareMask;
5027    if (!strcmp(funcName, "vkCmdSetStencilWriteMask"))
5028        return (PFN_vkVoidFunction)vkCmdSetStencilWriteMask;
5029    if (!strcmp(funcName, "vkCmdSetStencilReference"))
5030        return (PFN_vkVoidFunction)vkCmdSetStencilReference;
5031    if (!strcmp(funcName, "vkAllocateCommandBuffers"))
5032        return (PFN_vkVoidFunction)vkAllocateCommandBuffers;
5033    if (!strcmp(funcName, "vkFreeCommandBuffers"))
5034        return (PFN_vkVoidFunction)vkFreeCommandBuffers;
5035    if (!strcmp(funcName, "vkBeginCommandBuffer"))
5036        return (PFN_vkVoidFunction)vkBeginCommandBuffer;
5037    if (!strcmp(funcName, "vkEndCommandBuffer"))
5038        return (PFN_vkVoidFunction)vkEndCommandBuffer;
5039    if (!strcmp(funcName, "vkResetCommandBuffer"))
5040        return (PFN_vkVoidFunction)vkResetCommandBuffer;
5041    if (!strcmp(funcName, "vkCmdBindPipeline"))
5042        return (PFN_vkVoidFunction)vkCmdBindPipeline;
5043    if (!strcmp(funcName, "vkCmdBindDescriptorSets"))
5044        return (PFN_vkVoidFunction)vkCmdBindDescriptorSets;
5045    if (!strcmp(funcName, "vkCmdBindVertexBuffers"))
5046        return (PFN_vkVoidFunction)vkCmdBindVertexBuffers;
5047    if (!strcmp(funcName, "vkCmdBindIndexBuffer"))
5048        return (PFN_vkVoidFunction)vkCmdBindIndexBuffer;
5049    if (!strcmp(funcName, "vkCmdDraw"))
5050        return (PFN_vkVoidFunction)vkCmdDraw;
5051    if (!strcmp(funcName, "vkCmdDrawIndexed"))
5052        return (PFN_vkVoidFunction)vkCmdDrawIndexed;
5053    if (!strcmp(funcName, "vkCmdDrawIndirect"))
5054        return (PFN_vkVoidFunction)vkCmdDrawIndirect;
5055    if (!strcmp(funcName, "vkCmdDrawIndexedIndirect"))
5056        return (PFN_vkVoidFunction)vkCmdDrawIndexedIndirect;
5057    if (!strcmp(funcName, "vkCmdDispatch"))
5058        return (PFN_vkVoidFunction)vkCmdDispatch;
5059    if (!strcmp(funcName, "vkCmdDispatchIndirect"))
5060        return (PFN_vkVoidFunction)vkCmdDispatchIndirect;
5061    if (!strcmp(funcName, "vkCmdCopyBuffer"))
5062        return (PFN_vkVoidFunction)vkCmdCopyBuffer;
5063    if (!strcmp(funcName, "vkCmdCopyImage"))
5064        return (PFN_vkVoidFunction)vkCmdCopyImage;
5065    if (!strcmp(funcName, "vkCmdBlitImage"))
5066        return (PFN_vkVoidFunction)vkCmdBlitImage;
5067    if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
5068        return (PFN_vkVoidFunction)vkCmdCopyBufferToImage;
5069    if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
5070        return (PFN_vkVoidFunction)vkCmdCopyImageToBuffer;
5071    if (!strcmp(funcName, "vkCmdUpdateBuffer"))
5072        return (PFN_vkVoidFunction)vkCmdUpdateBuffer;
5073    if (!strcmp(funcName, "vkCmdFillBuffer"))
5074        return (PFN_vkVoidFunction)vkCmdFillBuffer;
5075    if (!strcmp(funcName, "vkCmdClearColorImage"))
5076        return (PFN_vkVoidFunction)vkCmdClearColorImage;
5077    if (!strcmp(funcName, "vkCmdResolveImage"))
5078        return (PFN_vkVoidFunction)vkCmdResolveImage;
5079    if (!strcmp(funcName, "vkCmdSetEvent"))
5080        return (PFN_vkVoidFunction)vkCmdSetEvent;
5081    if (!strcmp(funcName, "vkCmdResetEvent"))
5082        return (PFN_vkVoidFunction)vkCmdResetEvent;
5083    if (!strcmp(funcName, "vkCmdWaitEvents"))
5084        return (PFN_vkVoidFunction)vkCmdWaitEvents;
5085    if (!strcmp(funcName, "vkCmdPipelineBarrier"))
5086        return (PFN_vkVoidFunction)vkCmdPipelineBarrier;
5087    if (!strcmp(funcName, "vkCmdBeginQuery"))
5088        return (PFN_vkVoidFunction)vkCmdBeginQuery;
5089    if (!strcmp(funcName, "vkCmdEndQuery"))
5090        return (PFN_vkVoidFunction)vkCmdEndQuery;
5091    if (!strcmp(funcName, "vkCmdResetQueryPool"))
5092        return (PFN_vkVoidFunction)vkCmdResetQueryPool;
5093    if (!strcmp(funcName, "vkCmdWriteTimestamp"))
5094        return (PFN_vkVoidFunction)vkCmdWriteTimestamp;
5095    if (!strcmp(funcName, "vkCmdCopyQueryPoolResults"))
5096        return (PFN_vkVoidFunction)vkCmdCopyQueryPoolResults;
5097    if (!strcmp(funcName, "vkCreateFramebuffer"))
5098        return (PFN_vkVoidFunction)vkCreateFramebuffer;
5099    if (!strcmp(funcName, "vkDestroyFramebuffer"))
5100        return (PFN_vkVoidFunction)vkDestroyFramebuffer;
5101    if (!strcmp(funcName, "vkCreateRenderPass"))
5102        return (PFN_vkVoidFunction)vkCreateRenderPass;
5103    if (!strcmp(funcName, "vkDestroyRenderPass"))
5104        return (PFN_vkVoidFunction)vkDestroyRenderPass;
5105    if (!strcmp(funcName, "vkGetRenderAreaGranularity"))
5106        return (PFN_vkVoidFunction)vkGetRenderAreaGranularity;
5107    if (!strcmp(funcName, "vkCreateCommandPool"))
5108        return (PFN_vkVoidFunction)vkCreateCommandPool;
5109    if (!strcmp(funcName, "vkDestroyCommandPool"))
5110        return (PFN_vkVoidFunction)vkDestroyCommandPool;
5111    if (!strcmp(funcName, "vkCmdBeginRenderPass"))
5112        return (PFN_vkVoidFunction)vkCmdBeginRenderPass;
5113    if (!strcmp(funcName, "vkCmdNextSubpass"))
5114        return (PFN_vkVoidFunction)vkCmdNextSubpass;
5115
5116    if (device == NULL) {
5117        return NULL;
5118    }
5119
5120    if (get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr == NULL)
5121        return NULL;
5122    return get_dispatch_table(pc_device_table_map, device)->GetDeviceProcAddr(device, funcName);
5123}
5124
5125VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
5126    if (!strcmp(funcName, "vkGetInstanceProcAddr"))
5127        return (PFN_vkVoidFunction)vkGetInstanceProcAddr;
5128    if (!strcmp(funcName, "vkCreateInstance"))
5129        return (PFN_vkVoidFunction)vkCreateInstance;
5130    if (!strcmp(funcName, "vkDestroyInstance"))
5131        return (PFN_vkVoidFunction)vkDestroyInstance;
5132    if (!strcmp(funcName, "vkCreateDevice"))
5133        return (PFN_vkVoidFunction)vkCreateDevice;
5134    if (!strcmp(funcName, "vkEnumeratePhysicalDevices"))
5135        return (PFN_vkVoidFunction)vkEnumeratePhysicalDevices;
5136    if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
5137        return (PFN_vkVoidFunction)vkGetPhysicalDeviceProperties;
5138    if (!strcmp(funcName, "vkGetPhysicalDeviceFeatures"))
5139        return (PFN_vkVoidFunction)vkGetPhysicalDeviceFeatures;
5140    if (!strcmp(funcName, "vkGetPhysicalDeviceFormatProperties"))
5141        return (PFN_vkVoidFunction)vkGetPhysicalDeviceFormatProperties;
5142    if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
5143        return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
5144    if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
5145        return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
5146    if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
5147        return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
5148    if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
5149        return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
5150
5151    if (instance == NULL) {
5152        return NULL;
5153    }
5154
5155    layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
5156
5157    PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
5158    if (fptr)
5159        return fptr;
5160
5161    if (get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr == NULL)
5162        return NULL;
5163    return get_dispatch_table(pc_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
5164}
5165