Home | History | Annotate | Download | only in layers
      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 (at) lunarg.com>
     26  * Author: Mark Lobodzinski <mark (at) lunarg.com>
     27  * Author: Mike Stroyan <mike (at) LunarG.com>
     28  * Author: Tobin Ehlis <tobin (at) lunarg.com>
     29  */
     30 
     31 #include <inttypes.h>
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <assert.h>
     36 #include <vector>
     37 #include <unordered_map>
     38 #include <memory>
     39 using namespace std;
     40 
     41 #include "vk_loader_platform.h"
     42 #include "vk_dispatch_table_helper.h"
     43 #include "vk_struct_string_helper_cpp.h"
     44 #include "vk_enum_validate_helper.h"
     45 #include "image.h"
     46 #include "vk_layer_config.h"
     47 #include "vk_layer_extension_utils.h"
     48 #include "vk_layer_table.h"
     49 #include "vk_layer_data.h"
     50 #include "vk_layer_extension_utils.h"
     51 #include "vk_layer_utils.h"
     52 #include "vk_layer_logging.h"
     53 
     54 using namespace std;
     55 
     56 struct layer_data {
     57     debug_report_data *report_data;
     58     vector<VkDebugReportCallbackEXT> logging_callback;
     59     VkLayerDispatchTable *device_dispatch_table;
     60     VkLayerInstanceDispatchTable *instance_dispatch_table;
     61     VkPhysicalDevice physicalDevice;
     62     VkPhysicalDeviceProperties physicalDeviceProperties;
     63 
     64     unordered_map<VkImage, IMAGE_STATE> imageMap;
     65 
     66     layer_data()
     67         : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), physicalDevice(0),
     68           physicalDeviceProperties(){};
     69 };
     70 
     71 static unordered_map<void *, layer_data *> layer_data_map;
     72 static int globalLockInitialized = 0;
     73 static loader_platform_thread_mutex globalLock;
     74 
     75 static void init_image(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
     76 
     77     layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_image");
     78 
     79     if (!globalLockInitialized) {
     80         loader_platform_thread_create_mutex(&globalLock);
     81         globalLockInitialized = 1;
     82     }
     83 }
     84 
     85 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
     86 vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
     87                                const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
     88     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     89     VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
     90     if (res == VK_SUCCESS) {
     91         res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
     92     }
     93     return res;
     94 }
     95 
     96 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(VkInstance instance,
     97                                                                            VkDebugReportCallbackEXT msgCallback,
     98                                                                            const VkAllocationCallbacks *pAllocator) {
     99     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    100     my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
    101     layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
    102 }
    103 
    104 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
    105 vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
    106                         size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
    107     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    108     my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
    109                                                             pMsg);
    110 }
    111 
    112 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
    113 vkCreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
    114     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    115 
    116     assert(chain_info->u.pLayerInfo);
    117     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    118     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
    119     if (fpCreateInstance == NULL) {
    120         return VK_ERROR_INITIALIZATION_FAILED;
    121     }
    122 
    123     // Advance the link info for the next element on the chain
    124     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    125 
    126     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
    127     if (result != VK_SUCCESS)
    128         return result;
    129 
    130     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
    131     my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
    132     layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
    133 
    134     my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
    135                                                         pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
    136 
    137     init_image(my_data, pAllocator);
    138 
    139     return result;
    140 }
    141 
    142 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
    143     // Grab the key before the instance is destroyed.
    144     dispatch_key key = get_dispatch_key(instance);
    145     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
    146     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
    147     pTable->DestroyInstance(instance, pAllocator);
    148 
    149     // Clean up logging callback, if any
    150     while (my_data->logging_callback.size() > 0) {
    151         VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
    152         layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
    153         my_data->logging_callback.pop_back();
    154     }
    155 
    156     layer_debug_report_destroy_instance(my_data->report_data);
    157     delete my_data->instance_dispatch_table;
    158     layer_data_map.erase(key);
    159 }
    160 
    161 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
    162                                                               const VkDeviceCreateInfo *pCreateInfo,
    163                                                               const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
    164     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    165 
    166     assert(chain_info->u.pLayerInfo);
    167     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    168     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
    169     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(NULL, "vkCreateDevice");
    170     if (fpCreateDevice == NULL) {
    171         return VK_ERROR_INITIALIZATION_FAILED;
    172     }
    173 
    174     // Advance the link info for the next element on the chain
    175     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    176 
    177     VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
    178     if (result != VK_SUCCESS) {
    179         return result;
    180     }
    181 
    182     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    183     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
    184 
    185     // Setup device dispatch table
    186     my_device_data->device_dispatch_table = new VkLayerDispatchTable;
    187     layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
    188 
    189     my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
    190     my_device_data->physicalDevice = physicalDevice;
    191 
    192     my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice,
    193                                                                            &(my_device_data->physicalDeviceProperties));
    194 
    195     return result;
    196 }
    197 
    198 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
    199     dispatch_key key = get_dispatch_key(device);
    200     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
    201     my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
    202     delete my_data->device_dispatch_table;
    203     layer_data_map.erase(key);
    204 }
    205 
    206 static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
    207 
    208 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
    209 vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
    210     return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
    211 }
    212 
    213 static const VkLayerProperties pc_global_layers[] = {{
    214     "VK_LAYER_LUNARG_image", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
    215 }};
    216 
    217 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
    218 vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
    219     return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties);
    220 }
    221 
    222 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
    223                                                                                     const char *pLayerName, uint32_t *pCount,
    224                                                                                     VkExtensionProperties *pProperties) {
    225     // Image does not have any physical device extensions
    226     if (pLayerName == NULL) {
    227         dispatch_key key = get_dispatch_key(physicalDevice);
    228         layer_data *my_data = get_my_data_ptr(key, layer_data_map);
    229         VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
    230         return pTable->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
    231     } else {
    232         return util_GetExtensionProperties(0, NULL, pCount, pProperties);
    233     }
    234 }
    235 
    236 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
    237 vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
    238     // ParamChecker's physical device layers are the same as global
    239     return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers, pCount, pProperties);
    240 }
    241 
    242 // Start of the Image layer proper
    243 
    244 // Returns TRUE if a format is a depth-compatible format
    245 bool is_depth_format(VkFormat format) {
    246     bool result = VK_FALSE;
    247     switch (format) {
    248     case VK_FORMAT_D16_UNORM:
    249     case VK_FORMAT_X8_D24_UNORM_PACK32:
    250     case VK_FORMAT_D32_SFLOAT:
    251     case VK_FORMAT_S8_UINT:
    252     case VK_FORMAT_D16_UNORM_S8_UINT:
    253     case VK_FORMAT_D24_UNORM_S8_UINT:
    254     case VK_FORMAT_D32_SFLOAT_S8_UINT:
    255         result = VK_TRUE;
    256         break;
    257     default:
    258         break;
    259     }
    260     return result;
    261 }
    262 
    263 static inline uint32_t validate_VkImageLayoutKHR(VkImageLayout input_value) {
    264     return ((validate_VkImageLayout(input_value) == 1) || (input_value == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR));
    265 }
    266 
    267 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
    268 vkCreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
    269     VkBool32 skipCall = VK_FALSE;
    270     VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
    271     VkImageFormatProperties ImageFormatProperties;
    272 
    273     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    274     VkPhysicalDevice physicalDevice = device_data->physicalDevice;
    275     layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    276 
    277     if (pCreateInfo->format != VK_FORMAT_UNDEFINED) {
    278         VkFormatProperties properties;
    279         phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFormatProperties(device_data->physicalDevice, pCreateInfo->format,
    280                                                                                  &properties);
    281 
    282         if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0)) {
    283             char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
    284             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    285             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    286                                 IMAGE_FORMAT_UNSUPPORTED, "IMAGE", str);
    287         }
    288     }
    289 
    290     // Internal call to get format info.  Still goes through layers, could potentially go directly to ICD.
    291     phy_dev_data->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(
    292         physicalDevice, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags,
    293         &ImageFormatProperties);
    294 
    295     VkDeviceSize imageGranularity = device_data->physicalDeviceProperties.limits.bufferImageGranularity;
    296     imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
    297 
    298     if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
    299         (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
    300         (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
    301         skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    302                             (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    303                             "CreateImage extents exceed allowable limits for format: "
    304                             "Width = %d Height = %d Depth = %d:  Limits for Width = %d Height = %d Depth = %d for format %s.",
    305                             pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
    306                             ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height,
    307                             ImageFormatProperties.maxExtent.depth, string_VkFormat(pCreateInfo->format));
    308     }
    309 
    310     uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
    311                               (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
    312                               (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
    313                           (uint64_t)imageGranularity) &
    314                          ~(uint64_t)imageGranularity;
    315 
    316     if (totalSize > ImageFormatProperties.maxResourceSize) {
    317         skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    318                             (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    319                             "CreateImage resource size exceeds allowable maximum "
    320                             "Image resource size = %#" PRIxLEAST64 ", maximum resource size = %#" PRIxLEAST64 " ",
    321                             totalSize, ImageFormatProperties.maxResourceSize);
    322     }
    323 
    324     if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
    325         skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    326                             (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    327                             "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
    328                             ImageFormatProperties.maxMipLevels);
    329     }
    330 
    331     if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
    332         skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    333                             (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    334                             "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d",
    335                             pCreateInfo->arrayLayers, ImageFormatProperties.maxArrayLayers);
    336     }
    337 
    338     if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
    339         skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    340                             (uint64_t)pImage, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    341                             "CreateImage samples %s is not supported by format 0x%.8X",
    342                             string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts);
    343     }
    344 
    345     if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
    346         skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    347                             (uint64_t)pImage, __LINE__, IMAGE_INVALID_LAYOUT, "Image",
    348                             "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
    349                             "VK_IMAGE_LAYOUT_PREINITIALIZED");
    350     }
    351 
    352     if (VK_FALSE == skipCall) {
    353         result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
    354     }
    355     if (result == VK_SUCCESS) {
    356         loader_platform_thread_lock_mutex(&globalLock);
    357         device_data->imageMap[*pImage] = IMAGE_STATE(pCreateInfo);
    358         loader_platform_thread_unlock_mutex(&globalLock);
    359     }
    360     return result;
    361 }
    362 
    363 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
    364     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    365     loader_platform_thread_lock_mutex(&globalLock);
    366     device_data->imageMap.erase(image);
    367     loader_platform_thread_unlock_mutex(&globalLock);
    368     device_data->device_dispatch_table->DestroyImage(device, image, pAllocator);
    369 }
    370 
    371 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
    372                                                                   const VkAllocationCallbacks *pAllocator,
    373                                                                   VkRenderPass *pRenderPass) {
    374     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    375     VkBool32 skipCall = VK_FALSE;
    376     for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
    377         if (pCreateInfo->pAttachments[i].format != VK_FORMAT_UNDEFINED) {
    378             VkFormatProperties properties;
    379             get_my_data_ptr(get_dispatch_key(my_data->physicalDevice), layer_data_map)
    380                 ->instance_dispatch_table->GetPhysicalDeviceFormatProperties(my_data->physicalDevice,
    381                                                                              pCreateInfo->pAttachments[i].format, &properties);
    382 
    383             if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0)) {
    384                 std::stringstream ss;
    385                 ss << "vkCreateRenderPass parameter, VkFormat in pCreateInfo->pAttachments[" << i
    386                    << "], contains unsupported format";
    387                 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    388                 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    389                                     IMAGE_FORMAT_UNSUPPORTED, "IMAGE", "%s", ss.str().c_str());
    390             }
    391         }
    392     }
    393 
    394     for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
    395         if (!validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].initialLayout) ||
    396             !validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].finalLayout)) {
    397             std::stringstream ss;
    398             ss << "vkCreateRenderPass parameter, VkImageLayout in pCreateInfo->pAttachments[" << i << "], is unrecognized";
    399             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    400             skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    401                                 IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    402         }
    403     }
    404 
    405     for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
    406         if (!validate_VkAttachmentLoadOp(pCreateInfo->pAttachments[i].loadOp)) {
    407             std::stringstream ss;
    408             ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
    409             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    410             skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    411                                 IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    412         }
    413     }
    414 
    415     for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
    416         if (!validate_VkAttachmentStoreOp(pCreateInfo->pAttachments[i].storeOp)) {
    417             std::stringstream ss;
    418             ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
    419             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    420             skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    421                                 IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    422         }
    423     }
    424 
    425     // Any depth buffers specified as attachments?
    426     bool depthFormatPresent = VK_FALSE;
    427     for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
    428         depthFormatPresent |= is_depth_format(pCreateInfo->pAttachments[i].format);
    429     }
    430 
    431     if (depthFormatPresent == VK_FALSE) {
    432         // No depth attachment is present, validate that subpasses set depthStencilAttachment to VK_ATTACHMENT_UNUSED;
    433         for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
    434             if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment &&
    435                 pCreateInfo->pSubpasses[i].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
    436                 std::stringstream ss;
    437                 ss << "vkCreateRenderPass has no depth/stencil attachment, yet subpass[" << i
    438                    << "] has VkSubpassDescription::depthStencilAttachment value that is not VK_ATTACHMENT_UNUSED";
    439                 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    440                                     IMAGE_RENDERPASS_INVALID_DS_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    441             }
    442         }
    443     }
    444     if (skipCall)
    445         return VK_ERROR_VALIDATION_FAILED_EXT;
    446 
    447     VkResult result = my_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
    448 
    449     return result;
    450 }
    451 
    452 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
    453                                                                  const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
    454     VkBool32 skipCall = VK_FALSE;
    455     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    456     auto imageEntry = device_data->imageMap.find(pCreateInfo->image);
    457     if (imageEntry != device_data->imageMap.end()) {
    458         if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->second.mipLevels) {
    459             std::stringstream ss;
    460             ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel << " for image "
    461                << pCreateInfo->image << " that only has " << imageEntry->second.mipLevels << " mip levels.";
    462             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    463                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    464         }
    465         if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->second.arraySize) {
    466             std::stringstream ss;
    467             ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image "
    468                << pCreateInfo->image << " that only has " << imageEntry->second.arraySize << " array layers.";
    469             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    470                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    471         }
    472         if (!pCreateInfo->subresourceRange.levelCount) {
    473             std::stringstream ss;
    474             ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.levelCount.";
    475             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    476                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    477         }
    478         if (!pCreateInfo->subresourceRange.layerCount) {
    479             std::stringstream ss;
    480             ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.layerCount.";
    481             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    482                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    483         }
    484 
    485         VkImageCreateFlags imageFlags = imageEntry->second.flags;
    486         VkFormat imageFormat = imageEntry->second.format;
    487         VkFormat ivciFormat = pCreateInfo->format;
    488         VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask;
    489 
    490         // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
    491         if (imageFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
    492             // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
    493             if (vk_format_get_compatibility_class(imageFormat) != vk_format_get_compatibility_class(ivciFormat)) {
    494                 std::stringstream ss;
    495                 ss << "vkCreateImageView(): ImageView format " << string_VkFormat(ivciFormat)
    496                    << " is not in the same format compatibility class as image (" << (uint64_t)pCreateInfo->image << ")  format "
    497                    << string_VkFormat(imageFormat) << ".  Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT "
    498                    << "can support ImageViews with differing formats but they must be in the same compatibility class.";
    499                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
    500                                     __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    501             }
    502         } else {
    503             // Format MUST be IDENTICAL to the format the image was created with
    504             if (imageFormat != ivciFormat) {
    505                 std::stringstream ss;
    506                 ss << "vkCreateImageView() format " << string_VkFormat(ivciFormat) << " differs from image "
    507                    << (uint64_t)pCreateInfo->image << " format " << string_VkFormat(imageFormat)
    508                    << ".  Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
    509                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
    510                                     __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    511             }
    512         }
    513 
    514         // Validate correct image aspect bits for desired formats and format consistency
    515         if (vk_format_is_color(imageFormat)) {
    516             if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
    517                 std::stringstream ss;
    518                 ss << "vkCreateImageView: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set";
    519                 skipCall |=
    520                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    521                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    522             }
    523             if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != aspectMask) {
    524                 std::stringstream ss;
    525                 ss << "vkCreateImageView: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set";
    526                 skipCall |=
    527                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    528                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    529             }
    530             if (VK_FALSE == vk_format_is_color(ivciFormat)) {
    531                 std::stringstream ss;
    532                 ss << "vkCreateImageView: The image view's format can differ from the parent image's format, but both must be "
    533                    << "color formats.  ImageFormat is " << string_VkFormat(imageFormat) << " ImageViewFormat is "
    534                    << string_VkFormat(ivciFormat);
    535                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    536                                     (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    537             }
    538             // TODO:  Uncompressed formats are compatible if they occupy they same number of bits per pixel.
    539             //        Compressed formats are compatible if the only difference between them is the numerical type of
    540             //        the uncompressed pixels (e.g. signed vs. unsigned, or sRGB vs. UNORM encoding).
    541         } else if (vk_format_is_depth_and_stencil(imageFormat)) {
    542             if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
    543                 std::stringstream ss;
    544                 ss << "vkCreateImageView: Depth/stencil image formats must have at least one of VK_IMAGE_ASPECT_DEPTH_BIT and "
    545                       "VK_IMAGE_ASPECT_STENCIL_BIT set";
    546                 skipCall |=
    547                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    548                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    549             }
    550             if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspectMask) {
    551                 std::stringstream ss;
    552                 ss << "vkCreateImageView: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and "
    553                       "VK_IMAGE_ASPECT_STENCIL_BIT set";
    554                 skipCall |=
    555                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    556                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    557             }
    558         } else if (vk_format_is_depth_only(imageFormat)) {
    559             if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
    560                 std::stringstream ss;
    561                 ss << "vkCreateImageView: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set";
    562                 skipCall |=
    563                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    564                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    565             }
    566             if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspectMask) {
    567                 std::stringstream ss;
    568                 ss << "vkCreateImageView: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set";
    569                 skipCall |=
    570                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    571                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    572             }
    573         } else if (vk_format_is_stencil_only(imageFormat)) {
    574             if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
    575                 std::stringstream ss;
    576                 ss << "vkCreateImageView: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set";
    577                 skipCall |=
    578                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    579                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    580             }
    581             if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspectMask) {
    582                 std::stringstream ss;
    583                 ss << "vkCreateImageView: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set";
    584                 skipCall |=
    585                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    586                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    587             }
    588         }
    589     }
    590 
    591     if (skipCall) {
    592         return VK_ERROR_VALIDATION_FAILED_EXT;
    593     }
    594 
    595     VkResult result = device_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView);
    596     return result;
    597 }
    598 
    599 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
    600                                                                 VkImageLayout imageLayout, const VkClearColorValue *pColor,
    601                                                                 uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
    602     VkBool32 skipCall = VK_FALSE;
    603     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    604 
    605     if (imageLayout != VK_IMAGE_LAYOUT_GENERAL && imageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
    606         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    607                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_LAYOUT, "IMAGE",
    608                             "vkCmdClearColorImage parameter, imageLayout, must be VK_IMAGE_LAYOUT_GENERAL or "
    609                             "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL");
    610     }
    611 
    612     // For each range, image aspect must be color only
    613     for (uint32_t i = 0; i < rangeCount; i++) {
    614         if (pRanges[i].aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
    615             char const str[] =
    616                 "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
    617             skipCall |=
    618                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    619                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    620         }
    621     }
    622 
    623     if (VK_FALSE == skipCall) {
    624         device_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
    625     }
    626 }
    627 
    628 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
    629 vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
    630                             const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
    631                             const VkImageSubresourceRange *pRanges) {
    632     VkBool32 skipCall = VK_FALSE;
    633     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    634     // For each range, Image aspect must be depth or stencil or both
    635     for (uint32_t i = 0; i < rangeCount; i++) {
    636         if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
    637             ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    638             char const str[] = "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
    639                                "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
    640             skipCall |=
    641                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    642                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    643         }
    644     }
    645 
    646     if (VK_FALSE == skipCall) {
    647         device_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount,
    648                                                                       pRanges);
    649     }
    650 }
    651 
    652 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
    653 vkCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
    654                VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions) {
    655     VkBool32 skipCall = VK_FALSE;
    656     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    657     auto srcImageEntry = device_data->imageMap.find(srcImage);
    658     auto dstImageEntry = device_data->imageMap.find(dstImage);
    659 
    660     // For each region, src and dst number of layers should not be zero
    661     // For each region, src and dst number of layers must match
    662     // For each region, src aspect mask must match dest aspect mask
    663     // For each region, color aspects cannot be mixed with depth/stencil aspects
    664     for (uint32_t i = 0; i < regionCount; i++) {
    665         if (pRegions[i].srcSubresource.layerCount == 0) {
    666             char const str[] = "vkCmdCopyImage: number of layers in source subresource is zero";
    667             // TODO: Verify against Valid Use section of spec
    668             skipCall |=
    669                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    670                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    671         }
    672 
    673         if (pRegions[i].dstSubresource.layerCount == 0) {
    674             char const str[] = "vkCmdCopyImage: number of layers in destination subresource is zero";
    675             // TODO: Verify against Valid Use section of spec
    676             skipCall |=
    677                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    678                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    679         }
    680 
    681         if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
    682             char const str[] = "vkCmdCopyImage: number of layers in source and destination subresources must match";
    683             skipCall |=
    684                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    685                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    686         }
    687 
    688         if (pRegions[i].srcSubresource.aspectMask != pRegions[i].dstSubresource.aspectMask) {
    689             char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
    690             skipCall |=
    691                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    692                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    693         }
    694         if ((pRegions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
    695             (pRegions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
    696             char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
    697             skipCall |=
    698                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    699                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    700         }
    701     }
    702 
    703     if ((srcImageEntry != device_data->imageMap.end()) && (dstImageEntry != device_data->imageMap.end())) {
    704         if (srcImageEntry->second.imageType != dstImageEntry->second.imageType) {
    705             char const str[] = "vkCmdCopyImage called with unmatched source and dest image types.";
    706             skipCall |=
    707                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    708                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
    709         }
    710         // Check that format is same size or exact stencil/depth
    711         if (is_depth_format(srcImageEntry->second.format)) {
    712             if (srcImageEntry->second.format != dstImageEntry->second.format) {
    713                 char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
    714                 skipCall |=
    715                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    716                             (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
    717             }
    718         } else {
    719             size_t srcSize = vk_format_get_size(srcImageEntry->second.format);
    720             size_t destSize = vk_format_get_size(dstImageEntry->second.format);
    721             if (srcSize != destSize) {
    722                 char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
    723                 skipCall |=
    724                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    725                             (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
    726             }
    727         }
    728     }
    729 
    730     if (VK_FALSE == skipCall) {
    731         device_data->device_dispatch_table->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
    732                                                          regionCount, pRegions);
    733     }
    734 }
    735 
    736 VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
    737                                                  const VkClearAttachment *pAttachments, uint32_t rectCount,
    738                                                  const VkClearRect *pRects) {
    739     VkBool32 skipCall = VK_FALSE;
    740     VkImageAspectFlags aspectMask;
    741     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    742     for (uint32_t i = 0; i < attachmentCount; i++) {
    743         aspectMask = pAttachments[i].aspectMask;
    744         if (aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
    745             if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
    746                 // VK_IMAGE_ASPECT_COLOR_BIT is not the only bit set for this attachment
    747                 char const str[] =
    748                     "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment.";
    749                 skipCall |=
    750                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    751                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
    752             }
    753         } else {
    754             // Image aspect must be depth or stencil or both
    755             if (((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
    756                 ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    757                 char const str[] = "vkCmdClearAttachments aspectMask [%d] must be set to VK_IMAGE_ASPECT_DEPTH_BIT and/or "
    758                                    "VK_IMAGE_ASPECT_STENCIL_BIT";
    759                 skipCall |=
    760                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    761                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
    762             }
    763         }
    764     }
    765 
    766     if (VK_FALSE == skipCall) {
    767         device_data->device_dispatch_table->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
    768     }
    769 }
    770 
    771 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
    772                                                                   VkImageLayout srcImageLayout, VkBuffer dstBuffer,
    773                                                                   uint32_t regionCount, const VkBufferImageCopy *pRegions) {
    774     VkBool32 skipCall = VK_FALSE;
    775     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    776     // For each region, the number of layers in the image subresource should not be zero
    777     // Image aspect must be ONE OF color, depth, stencil
    778     for (uint32_t i = 0; i < regionCount; i++) {
    779         if (pRegions[i].imageSubresource.layerCount == 0) {
    780             char const str[] = "vkCmdCopyImageToBuffer: number of layers in image subresource is zero";
    781             // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
    782             skipCall |=
    783                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    784                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    785         }
    786 
    787         VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
    788         if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) && (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
    789             (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    790             char const str[] = "vkCmdCopyImageToBuffer: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
    791             skipCall |=
    792                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    793                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    794         }
    795     }
    796 
    797     if (VK_FALSE == skipCall) {
    798         device_data->device_dispatch_table->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount,
    799                                                                  pRegions);
    800     }
    801 }
    802 
    803 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
    804                                                                   VkImage dstImage, VkImageLayout dstImageLayout,
    805                                                                   uint32_t regionCount, const VkBufferImageCopy *pRegions) {
    806     VkBool32 skipCall = VK_FALSE;
    807     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    808     // For each region, the number of layers in the image subresource should not be zero
    809     // Image aspect must be ONE OF color, depth, stencil
    810     for (uint32_t i = 0; i < regionCount; i++) {
    811         if (pRegions[i].imageSubresource.layerCount == 0) {
    812             char const str[] = "vkCmdCopyBufferToImage: number of layers in image subresource is zero";
    813             // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
    814             skipCall |=
    815                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    816                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    817         }
    818 
    819         VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
    820         if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) && (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
    821             (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    822             char const str[] = "vkCmdCopyBufferToImage: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
    823             skipCall |=
    824                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    825                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    826         }
    827     }
    828 
    829     if (VK_FALSE == skipCall) {
    830         device_data->device_dispatch_table->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount,
    831                                                                  pRegions);
    832     }
    833 }
    834 
    835 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
    836 vkCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
    837                VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
    838     VkBool32 skipCall = VK_FALSE;
    839     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    840 
    841     auto srcImageEntry = device_data->imageMap.find(srcImage);
    842     auto dstImageEntry = device_data->imageMap.find(dstImage);
    843 
    844     if ((srcImageEntry != device_data->imageMap.end()) && (dstImageEntry != device_data->imageMap.end())) {
    845 
    846         VkFormat srcFormat = srcImageEntry->second.format;
    847         VkFormat dstFormat = dstImageEntry->second.format;
    848 
    849         // Validate consistency for signed and unsigned formats
    850         if ((vk_format_is_sint(srcFormat) && !vk_format_is_sint(dstFormat)) ||
    851             (vk_format_is_uint(srcFormat) && !vk_format_is_uint(dstFormat))) {
    852             std::stringstream ss;
    853             ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed/unsigned integer format, "
    854                << "the other one must also have signed/unsigned integer format.  "
    855                << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
    856             skipCall |=
    857                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    858                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    859         }
    860 
    861         // Validate aspect bits and formats for depth/stencil images
    862         if (vk_format_is_depth_or_stencil(srcFormat) || vk_format_is_depth_or_stencil(dstFormat)) {
    863             if (srcFormat != dstFormat) {
    864                 std::stringstream ss;
    865                 ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
    866                    << "stencil, the other one must have exactly the same format.  "
    867                    << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
    868                 skipCall |=
    869                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    870                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    871             }
    872 
    873             for (uint32_t i = 0; i < regionCount; i++) {
    874                 if (pRegions[i].srcSubresource.layerCount == 0) {
    875                     char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
    876                     // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
    877                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    878                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    879                                         IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    880                 }
    881 
    882                 if (pRegions[i].dstSubresource.layerCount == 0) {
    883                     char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
    884                     // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
    885                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    886                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    887                                         IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    888                 }
    889 
    890                 if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
    891                     char const str[] = "vkCmdBlitImage: number of layers in source and destination subresources must match";
    892                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    893                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    894                                         IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    895                 }
    896 
    897                 VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
    898                 VkImageAspectFlags dstAspect = pRegions[i].dstSubresource.aspectMask;
    899 
    900                 if (srcAspect != dstAspect) {
    901                     std::stringstream ss;
    902                     ss << "vkCmdBlitImage: Image aspects of depth/stencil images should match";
    903                     // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
    904                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    905                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    906                                         IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    907                 }
    908                 if (vk_format_is_depth_and_stencil(srcFormat)) {
    909                     if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    910                         std::stringstream ss;
    911                         ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
    912                               "VK_IMAGE_ASPECT_DEPTH_BIT "
    913                            << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
    914                         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    915                                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    916                                             IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    917                     }
    918                 } else if (vk_format_is_stencil_only(srcFormat)) {
    919                     if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
    920                         std::stringstream ss;
    921                         ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
    922                            << "set in both the srcImage and dstImage";
    923                         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    924                                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    925                                             IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    926                     }
    927                 } else if (vk_format_is_depth_only(srcFormat)) {
    928                     if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
    929                         std::stringstream ss;
    930                         ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
    931                            << "set in both the srcImage and dstImage";
    932                         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    933                                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
    934                                             IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    935                     }
    936                 }
    937             }
    938         }
    939 
    940         // Validate filter
    941         if (vk_format_is_depth_or_stencil(srcFormat) || vk_format_is_int(srcFormat)) {
    942             if (filter != VK_FILTER_NEAREST) {
    943                 std::stringstream ss;
    944                 ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, depth stencil or integer-based format "
    945                    << "then filter must be VK_FILTER_NEAREST.";
    946                 skipCall |=
    947                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    948                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FILTER, "IMAGE", "%s", ss.str().c_str());
    949             }
    950         }
    951     }
    952 
    953     device_data->device_dispatch_table->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
    954                                                      pRegions, filter);
    955 }
    956 
    957 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
    958 vkCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
    959                      VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
    960                      uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
    961                      uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
    962     VkBool32 skipCall = VK_FALSE;
    963     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    964 
    965     for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
    966         VkImageMemoryBarrier const *const barrier = (VkImageMemoryBarrier const *const) & pImageMemoryBarriers[i];
    967         if (barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
    968             if (barrier->subresourceRange.layerCount == 0) {
    969                 std::stringstream ss;
    970                 ss << "vkCmdPipelineBarrier called with 0 in ppMemoryBarriers[" << i << "]->subresourceRange.layerCount.";
    971                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
    972                                     __LINE__, IMAGE_INVALID_IMAGE_RESOURCE, "IMAGE", "%s", ss.str().c_str());
    973             }
    974         }
    975     }
    976 
    977     if (skipCall) {
    978         return;
    979     }
    980 
    981     device_data->device_dispatch_table->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
    982                                                            memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
    983                                                            pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
    984 }
    985 
    986 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
    987 vkCmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
    988                   VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
    989     VkBool32 skipCall = VK_FALSE;
    990     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    991     auto srcImageEntry = device_data->imageMap.find(srcImage);
    992     auto dstImageEntry = device_data->imageMap.find(dstImage);
    993 
    994     // For each region, the number of layers in the image subresource should not be zero
    995     // For each region, src and dest image aspect must be color only
    996     for (uint32_t i = 0; i < regionCount; i++) {
    997         if (pRegions[i].srcSubresource.layerCount == 0) {
    998             char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
    999             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
   1000             skipCall |=
   1001                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1002                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1003         }
   1004 
   1005         if (pRegions[i].dstSubresource.layerCount == 0) {
   1006             char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
   1007 
   1008             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
   1009             skipCall |=
   1010                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1011                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1012         }
   1013 
   1014         if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
   1015             (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
   1016             char const str[] =
   1017                 "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
   1018             skipCall |=
   1019                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1020                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
   1021         }
   1022     }
   1023 
   1024     if ((srcImageEntry != device_data->imageMap.end()) && (dstImageEntry != device_data->imageMap.end())) {
   1025         if (srcImageEntry->second.format != dstImageEntry->second.format) {
   1026             char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
   1027             skipCall |=
   1028                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1029                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
   1030         }
   1031         if (srcImageEntry->second.imageType != dstImageEntry->second.imageType) {
   1032             char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
   1033             skipCall |=
   1034                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1035                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
   1036         }
   1037         if (srcImageEntry->second.samples == VK_SAMPLE_COUNT_1_BIT) {
   1038             char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
   1039             skipCall |=
   1040                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1041                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
   1042         }
   1043         if (dstImageEntry->second.samples != VK_SAMPLE_COUNT_1_BIT) {
   1044             char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
   1045             skipCall |=
   1046                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1047                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
   1048         }
   1049     }
   1050 
   1051     if (VK_FALSE == skipCall) {
   1052         device_data->device_dispatch_table->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
   1053                                                             regionCount, pRegions);
   1054     }
   1055 }
   1056 
   1057 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
   1058 vkGetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) {
   1059     VkBool32 skipCall = VK_FALSE;
   1060     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
   1061     VkFormat format;
   1062 
   1063     auto imageEntry = device_data->imageMap.find(image);
   1064 
   1065     // Validate that image aspects match formats
   1066     if (imageEntry != device_data->imageMap.end()) {
   1067         format = imageEntry->second.format;
   1068         if (vk_format_is_color(format)) {
   1069             if (pSubresource->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
   1070                 std::stringstream ss;
   1071                 ss << "vkGetImageSubresourceLayout: For color formats, the aspectMask field of VkImageSubresource must be "
   1072                       "VK_IMAGE_ASPECT_COLOR.";
   1073                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1074                                     (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1075             }
   1076         } else if (vk_format_is_depth_or_stencil(format)) {
   1077             if ((pSubresource->aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
   1078                 (pSubresource->aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
   1079                 std::stringstream ss;
   1080                 ss << "vkGetImageSubresourceLayout: For depth/stencil formats, the aspectMask selects either the depth or stencil "
   1081                       "image aspectMask.";
   1082                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1083                                     (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1084             }
   1085         }
   1086     }
   1087 
   1088     if (VK_FALSE == skipCall) {
   1089         device_data->device_dispatch_table->GetImageSubresourceLayout(device, image, pSubresource, pLayout);
   1090     }
   1091 }
   1092 
   1093 VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL
   1094 vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
   1095     layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
   1096     phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
   1097 }
   1098 
   1099 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName) {
   1100     if (!strcmp(funcName, "vkGetDeviceProcAddr"))
   1101         return (PFN_vkVoidFunction)vkGetDeviceProcAddr;
   1102     if (!strcmp(funcName, "vkDestroyDevice"))
   1103         return (PFN_vkVoidFunction)vkDestroyDevice;
   1104     if (!strcmp(funcName, "vkCreateImage"))
   1105         return (PFN_vkVoidFunction)vkCreateImage;
   1106     if (!strcmp(funcName, "vkDestroyImage"))
   1107         return (PFN_vkVoidFunction)vkDestroyImage;
   1108     if (!strcmp(funcName, "vkCreateImageView"))
   1109         return (PFN_vkVoidFunction)vkCreateImageView;
   1110     if (!strcmp(funcName, "vkCreateRenderPass"))
   1111         return (PFN_vkVoidFunction)vkCreateRenderPass;
   1112     if (!strcmp(funcName, "vkCmdClearColorImage"))
   1113         return (PFN_vkVoidFunction)vkCmdClearColorImage;
   1114     if (!strcmp(funcName, "vkCmdClearDepthStencilImage"))
   1115         return (PFN_vkVoidFunction)vkCmdClearDepthStencilImage;
   1116     if (!strcmp(funcName, "vkCmdClearAttachments"))
   1117         return (PFN_vkVoidFunction)vkCmdClearAttachments;
   1118     if (!strcmp(funcName, "vkCmdCopyImage"))
   1119         return (PFN_vkVoidFunction)vkCmdCopyImage;
   1120     if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
   1121         return (PFN_vkVoidFunction)vkCmdCopyImageToBuffer;
   1122     if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
   1123         return (PFN_vkVoidFunction)vkCmdCopyBufferToImage;
   1124     if (!strcmp(funcName, "vkCmdBlitImage"))
   1125         return (PFN_vkVoidFunction)vkCmdBlitImage;
   1126     if (!strcmp(funcName, "vkCmdPipelineBarrier"))
   1127         return (PFN_vkVoidFunction)vkCmdPipelineBarrier;
   1128     if (!strcmp(funcName, "vkCmdResolveImage"))
   1129         return (PFN_vkVoidFunction)vkCmdResolveImage;
   1130     if (!strcmp(funcName, "vkGetImageSubresourceLayout"))
   1131         return (PFN_vkVoidFunction)vkGetImageSubresourceLayout;
   1132 
   1133     if (device == NULL) {
   1134         return NULL;
   1135     }
   1136 
   1137     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
   1138 
   1139     VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
   1140     {
   1141         if (pTable->GetDeviceProcAddr == NULL)
   1142             return NULL;
   1143         return pTable->GetDeviceProcAddr(device, funcName);
   1144     }
   1145 }
   1146 
   1147 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
   1148     if (!strcmp(funcName, "vkGetInstanceProcAddr"))
   1149         return (PFN_vkVoidFunction)vkGetInstanceProcAddr;
   1150     if (!strcmp(funcName, "vkCreateInstance"))
   1151         return (PFN_vkVoidFunction)vkCreateInstance;
   1152     if (!strcmp(funcName, "vkDestroyInstance"))
   1153         return (PFN_vkVoidFunction)vkDestroyInstance;
   1154     if (!strcmp(funcName, "vkCreateDevice"))
   1155         return (PFN_vkVoidFunction)vkCreateDevice;
   1156     if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
   1157         return (PFN_vkVoidFunction)vkEnumerateInstanceLayerProperties;
   1158     if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
   1159         return (PFN_vkVoidFunction)vkEnumerateInstanceExtensionProperties;
   1160     if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
   1161         return (PFN_vkVoidFunction)vkEnumerateDeviceLayerProperties;
   1162     if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
   1163         return (PFN_vkVoidFunction)vkEnumerateDeviceExtensionProperties;
   1164     if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
   1165         return (PFN_vkVoidFunction)vkGetPhysicalDeviceProperties;
   1166 
   1167     if (instance == NULL) {
   1168         return NULL;
   1169     }
   1170 
   1171     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
   1172 
   1173     PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
   1174     if (fptr)
   1175         return fptr;
   1176 
   1177     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
   1178     if (pTable->GetInstanceProcAddr == NULL)
   1179         return NULL;
   1180     return pTable->GetInstanceProcAddr(instance, funcName);
   1181 }
   1182