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  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Jeremy Hayes <jeremy (at) lunarg.com>
     19  * Author: Mark Lobodzinski <mark (at) lunarg.com>
     20  * Author: Mike Stroyan <mike (at) LunarG.com>
     21  * Author: Tobin Ehlis <tobin (at) lunarg.com>
     22  */
     23 
     24 // Allow use of STL min and max functions in Windows
     25 #define NOMINMAX
     26 
     27 #include <algorithm>
     28 #include <assert.h>
     29 #include <cinttypes>
     30 #include <memory>
     31 #include <mutex>
     32 #include <stdio.h>
     33 #include <stdlib.h>
     34 #include <string.h>
     35 #include <unordered_map>
     36 #include <vector>
     37 
     38 #include "vk_loader_platform.h"
     39 #include "vk_dispatch_table_helper.h"
     40 #include "vk_struct_string_helper_cpp.h"
     41 #include "vk_enum_validate_helper.h"
     42 #include "image.h"
     43 #include "vk_layer_config.h"
     44 #include "vk_layer_extension_utils.h"
     45 #include "vk_layer_table.h"
     46 #include "vk_layer_data.h"
     47 #include "vk_layer_extension_utils.h"
     48 #include "vk_layer_utils.h"
     49 #include "vk_layer_logging.h"
     50 #include "vk_validation_error_messages.h"
     51 
     52 using namespace std;
     53 
     54 namespace image {
     55 
     56 struct layer_data {
     57     VkInstance instance;
     58 
     59     debug_report_data *report_data;
     60     vector<VkDebugReportCallbackEXT> logging_callback;
     61     VkLayerDispatchTable *device_dispatch_table;
     62     VkLayerInstanceDispatchTable *instance_dispatch_table;
     63     VkPhysicalDevice physicalDevice;
     64     VkPhysicalDeviceProperties physicalDeviceProperties;
     65 
     66     unordered_map<VkImage, IMAGE_STATE> imageMap;
     67 
     68     layer_data()
     69         : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), physicalDevice(0),
     70           physicalDeviceProperties(){};
     71 };
     72 
     73 static unordered_map<void *, layer_data *> layer_data_map;
     74 static std::mutex global_lock;
     75 
     76 static void init_image(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
     77     layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_image");
     78 }
     79 
     80 static IMAGE_STATE const *getImageState(layer_data const *dev_data, VkImage image) {
     81     auto it = dev_data->imageMap.find(image);
     82     if (it == dev_data->imageMap.end()) {
     83         return nullptr;
     84     }
     85     return &it->second;
     86 }
     87 
     88 VKAPI_ATTR VkResult VKAPI_CALL
     89 CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
     90                              const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
     91     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
     92     VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
     93     if (res == VK_SUCCESS) {
     94         res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
     95     }
     96     return res;
     97 }
     98 
     99 VKAPI_ATTR void VKAPI_CALL DestroyDebugReportCallbackEXT(VkInstance instance,
    100                                                          VkDebugReportCallbackEXT msgCallback,
    101                                                          const VkAllocationCallbacks *pAllocator) {
    102     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    103     my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
    104     layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
    105 }
    106 
    107 VKAPI_ATTR void VKAPI_CALL
    108 DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
    109                       size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
    110     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
    111     my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
    112                                                             pMsg);
    113 }
    114 
    115 VKAPI_ATTR VkResult VKAPI_CALL
    116 CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
    117     VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    118 
    119     assert(chain_info->u.pLayerInfo);
    120     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    121     PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
    122     if (fpCreateInstance == NULL) {
    123         return VK_ERROR_INITIALIZATION_FAILED;
    124     }
    125 
    126     // Advance the link info for the next element on the chain
    127     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    128 
    129     VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
    130     if (result != VK_SUCCESS)
    131         return result;
    132 
    133     layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
    134     my_data->instance = *pInstance;
    135     my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
    136     layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
    137 
    138     my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
    139                                                         pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
    140 
    141     init_image(my_data, pAllocator);
    142 
    143     return result;
    144 }
    145 
    146 VKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
    147     // Grab the key before the instance is destroyed.
    148     dispatch_key key = get_dispatch_key(instance);
    149     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
    150     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
    151     pTable->DestroyInstance(instance, pAllocator);
    152 
    153     // Clean up logging callback, if any
    154     while (my_data->logging_callback.size() > 0) {
    155         VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
    156         layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
    157         my_data->logging_callback.pop_back();
    158     }
    159 
    160     layer_debug_report_destroy_instance(my_data->report_data);
    161     delete my_data->instance_dispatch_table;
    162     layer_data_map.erase(key);
    163 }
    164 
    165 VKAPI_ATTR VkResult VKAPI_CALL CreateDevice(VkPhysicalDevice physicalDevice,
    166                                             const VkDeviceCreateInfo *pCreateInfo,
    167                                             const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
    168     layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    169     VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
    170 
    171     assert(chain_info->u.pLayerInfo);
    172     PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
    173     PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
    174     PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(my_instance_data->instance, "vkCreateDevice");
    175     if (fpCreateDevice == NULL) {
    176         return VK_ERROR_INITIALIZATION_FAILED;
    177     }
    178 
    179     // Advance the link info for the next element on the chain
    180     chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
    181 
    182     VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
    183     if (result != VK_SUCCESS) {
    184         return result;
    185     }
    186 
    187     layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
    188 
    189     // Setup device dispatch table
    190     my_device_data->device_dispatch_table = new VkLayerDispatchTable;
    191     layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
    192 
    193     my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
    194     my_device_data->physicalDevice = physicalDevice;
    195 
    196     my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice,
    197                                                                            &(my_device_data->physicalDeviceProperties));
    198 
    199     return result;
    200 }
    201 
    202 VKAPI_ATTR void VKAPI_CALL DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
    203     dispatch_key key = get_dispatch_key(device);
    204     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
    205     my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
    206     delete my_data->device_dispatch_table;
    207     layer_data_map.erase(key);
    208 }
    209 
    210 static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
    211 
    212 static const VkLayerProperties global_layer = {
    213     "VK_LAYER_LUNARG_image", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
    214 };
    215 
    216 // Start of the Image layer proper
    217 
    218 static inline uint32_t validate_VkImageLayoutKHR(VkImageLayout input_value) {
    219     return ((validate_VkImageLayout(input_value) == 1) || (input_value == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR));
    220 }
    221 
    222 VKAPI_ATTR VkResult VKAPI_CALL CreateImage(VkDevice device, const VkImageCreateInfo *pCreateInfo,
    223                                            const VkAllocationCallbacks *pAllocator, VkImage *pImage) {
    224     bool skip_call = false;
    225     VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
    226     VkImageFormatProperties ImageFormatProperties;
    227 
    228     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    229     VkPhysicalDevice physicalDevice = device_data->physicalDevice;
    230     layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
    231 
    232     if (pCreateInfo->format != VK_FORMAT_UNDEFINED) {
    233         VkFormatProperties properties;
    234         phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFormatProperties(device_data->physicalDevice, pCreateInfo->format,
    235                                                                                  &properties);
    236         if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0)) {
    237             std::stringstream ss;
    238             ss << "vkCreateImage format parameter (" << string_VkFormat(pCreateInfo->format) << ") is an unsupported format";
    239             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    240             skip_call |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT,
    241                                  0, __LINE__, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", "%s", ss.str().c_str());
    242         }
    243 
    244         // Validate that format supports usage as color attachment
    245         if (pCreateInfo->usage & VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT) {
    246             if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
    247                 ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
    248                 std::stringstream ss;
    249                 ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
    250                    << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
    251                 skip_call |=
    252                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
    253                             __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    254             }
    255             if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
    256                 ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT) == 0)) {
    257                 std::stringstream ss;
    258                 ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
    259                    << ") does not support requested Image usage type VK_IMAGE_USAGE_COLOR_ATTACHMENT";
    260                 skip_call |=
    261                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
    262                             __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    263             }
    264         }
    265         // Validate that format supports usage as depth/stencil attachment
    266         if (pCreateInfo->usage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) {
    267             if ((pCreateInfo->tiling == VK_IMAGE_TILING_OPTIMAL) &&
    268                 ((properties.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
    269                 std::stringstream ss;
    270                 ss << "vkCreateImage: VkFormat for TILING_OPTIMAL image (" << string_VkFormat(pCreateInfo->format)
    271                    << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
    272                 skip_call |=
    273                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
    274                             __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    275             }
    276             if ((pCreateInfo->tiling == VK_IMAGE_TILING_LINEAR) &&
    277                 ((properties.linearTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) == 0)) {
    278                 std::stringstream ss;
    279                 ss << "vkCreateImage: VkFormat for TILING_LINEAR image (" << string_VkFormat(pCreateInfo->format)
    280                    << ") does not support requested Image usage type VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT";
    281                 skip_call |=
    282                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0,
    283                             __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    284             }
    285         }
    286     } else {
    287         skip_call |=
    288             log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, 0, __LINE__,
    289                     IMAGE_INVALID_FORMAT, "IMAGE", "vkCreateImage: VkFormat for image must not be VK_FORMAT_UNDEFINED");
    290     }
    291 
    292     // Internal call to get format info.  Still goes through layers, could potentially go directly to ICD.
    293     phy_dev_data->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(
    294         physicalDevice, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling, pCreateInfo->usage, pCreateInfo->flags,
    295         &ImageFormatProperties);
    296 
    297     VkDeviceSize imageGranularity = device_data->physicalDeviceProperties.limits.bufferImageGranularity;
    298     imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
    299 
    300     // Make sure all required dimension are non-zero at least.
    301     bool failedMinSize = false;
    302     switch (pCreateInfo->imageType) {
    303     case VK_IMAGE_TYPE_3D:
    304         if (pCreateInfo->extent.depth == 0) {
    305             failedMinSize = true;
    306         }
    307     // Intentional fall-through
    308     case VK_IMAGE_TYPE_2D:
    309         if (pCreateInfo->extent.height == 0) {
    310             failedMinSize = true;
    311         }
    312     // Intentional fall-through
    313     case VK_IMAGE_TYPE_1D:
    314         if (pCreateInfo->extent.width == 0) {
    315             failedMinSize = true;
    316         }
    317         break;
    318     default:
    319         break;
    320     }
    321     if (failedMinSize) {
    322         skip_call |=
    323             log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    324                     0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    325                     "CreateImage extents is 0 for at least one required dimension for image of type %d: "
    326                     "Width = %d Height = %d Depth = %d.",
    327                     pCreateInfo->imageType, pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth);
    328     }
    329 
    330     if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
    331         (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
    332         (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
    333         skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    334                             0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    335                             "CreateImage extents exceed allowable limits for format: "
    336                             "Width = %d Height = %d Depth = %d:  Limits for Width = %d Height = %d Depth = %d for format %s.",
    337                             pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
    338                             ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height,
    339                             ImageFormatProperties.maxExtent.depth, string_VkFormat(pCreateInfo->format));
    340     }
    341 
    342     uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width * (uint64_t)pCreateInfo->extent.height *
    343                               (uint64_t)pCreateInfo->extent.depth * (uint64_t)pCreateInfo->arrayLayers *
    344                               (uint64_t)pCreateInfo->samples * (uint64_t)vk_format_get_size(pCreateInfo->format) +
    345                           (uint64_t)imageGranularity) &
    346                          ~(uint64_t)imageGranularity;
    347 
    348     if (totalSize > ImageFormatProperties.maxResourceSize) {
    349         skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    350                             0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    351                             "CreateImage resource size exceeds allowable maximum "
    352                             "Image resource size = 0x%" PRIxLEAST64 ", maximum resource size = 0x%" PRIxLEAST64 " ",
    353                             totalSize, ImageFormatProperties.maxResourceSize);
    354     }
    355 
    356     if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
    357         skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    358                             0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    359                             "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d", pCreateInfo->mipLevels,
    360                             ImageFormatProperties.maxMipLevels);
    361     }
    362 
    363     if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
    364         skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    365                             0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    366                             "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d",
    367                             pCreateInfo->arrayLayers, ImageFormatProperties.maxArrayLayers);
    368     }
    369 
    370     if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
    371         skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    372                             0, __LINE__, IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
    373                             "CreateImage samples %s is not supported by format 0x%.8X",
    374                             string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts);
    375     }
    376 
    377     if (pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_UNDEFINED && pCreateInfo->initialLayout != VK_IMAGE_LAYOUT_PREINITIALIZED) {
    378         skip_call |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    379                             0, __LINE__, IMAGE_INVALID_LAYOUT, "Image",
    380                             "vkCreateImage parameter, pCreateInfo->initialLayout, must be VK_IMAGE_LAYOUT_UNDEFINED or "
    381                             "VK_IMAGE_LAYOUT_PREINITIALIZED");
    382     }
    383 
    384     if (!skip_call) {
    385         result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
    386     }
    387     if (result == VK_SUCCESS) {
    388         std::lock_guard<std::mutex> lock(global_lock);
    389         device_data->imageMap[*pImage] = IMAGE_STATE(pCreateInfo);
    390     }
    391     return result;
    392 }
    393 
    394 VKAPI_ATTR void VKAPI_CALL DestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks *pAllocator) {
    395     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    396     std::unique_lock<std::mutex> lock(global_lock);
    397     device_data->imageMap.erase(image);
    398     lock.unlock();
    399     device_data->device_dispatch_table->DestroyImage(device, image, pAllocator);
    400 }
    401 
    402 VKAPI_ATTR VkResult VKAPI_CALL CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
    403                                                 const VkAllocationCallbacks *pAllocator, VkRenderPass *pRenderPass) {
    404     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    405     bool skip_call = false;
    406     bool depth_format_present = false;
    407 
    408     for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i) {
    409         if (pCreateInfo->pAttachments[i].format == VK_FORMAT_UNDEFINED) {
    410             std::stringstream ss;
    411             ss << "vkCreateRenderPass: pCreateInfo->pAttachments[" << i << "].format is VK_FORMAT_UNDEFINED";
    412             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    413                                  IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    414         }
    415 
    416         if (!validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].initialLayout) ||
    417             !validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].finalLayout)) {
    418             std::stringstream ss;
    419             ss << "vkCreateRenderPass parameter, VkImageLayout in pCreateInfo->pAttachments[" << i << "], is unrecognized";
    420             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    421             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    422                                  IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    423         }
    424 
    425         if (!validate_VkAttachmentLoadOp(pCreateInfo->pAttachments[i].loadOp)) {
    426             std::stringstream ss;
    427             ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
    428             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    429             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    430                                  IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    431         }
    432 
    433         if (!validate_VkAttachmentStoreOp(pCreateInfo->pAttachments[i].storeOp)) {
    434             std::stringstream ss;
    435             ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
    436             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
    437             skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    438                                  IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    439         }
    440 
    441         // Any depth buffers specified as attachments?
    442         depth_format_present |= vk_format_is_depth_or_stencil(pCreateInfo->pAttachments[i].format);
    443     }
    444 
    445     if (!depth_format_present) {
    446         // No depth attachment is present, validate that subpasses set depthStencilAttachment to VK_ATTACHMENT_UNUSED;
    447         for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
    448             if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment &&
    449                 pCreateInfo->pSubpasses[i].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
    450                 std::stringstream ss;
    451                 ss << "vkCreateRenderPass has no depth/stencil attachment, yet subpass[" << i
    452                    << "] has VkSubpassDescription::depthStencilAttachment value that is not VK_ATTACHMENT_UNUSED";
    453                 skip_call |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
    454                                      __LINE__, IMAGE_RENDERPASS_INVALID_DS_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
    455             }
    456         }
    457     }
    458     if (skip_call) {
    459         return VK_ERROR_VALIDATION_FAILED_EXT;
    460     }
    461 
    462     VkResult result = my_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
    463 
    464     return result;
    465 }
    466 
    467 VKAPI_ATTR VkResult VKAPI_CALL CreateImageView(VkDevice device, const VkImageViewCreateInfo *pCreateInfo,
    468                                                const VkAllocationCallbacks *pAllocator, VkImageView *pView) {
    469     bool skipCall = false;
    470     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
    471     auto imageEntry = getImageState(device_data, pCreateInfo->image);
    472     if (imageEntry) {
    473         if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->mipLevels) {
    474             std::stringstream ss;
    475             ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel << " for image "
    476                << pCreateInfo->image << " that only has " << imageEntry->mipLevels << " mip levels.";
    477             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    478                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    479         }
    480         if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->arraySize) {
    481             std::stringstream ss;
    482             ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image "
    483                << pCreateInfo->image << " that only has " << imageEntry->arraySize << " array layers.";
    484             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    485                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    486         }
    487         if (!pCreateInfo->subresourceRange.levelCount) {
    488             std::stringstream ss;
    489             ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.levelCount.";
    490             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    491                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    492         }
    493         if (!pCreateInfo->subresourceRange.layerCount) {
    494             std::stringstream ss;
    495             ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.layerCount.";
    496             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
    497                                 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    498         }
    499 
    500         VkImageCreateFlags imageFlags = imageEntry->flags;
    501         VkFormat imageFormat = imageEntry->format;
    502         VkFormat ivciFormat = pCreateInfo->format;
    503         VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask;
    504 
    505         // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
    506         if (imageFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
    507             // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
    508             if (vk_format_get_compatibility_class(imageFormat) != vk_format_get_compatibility_class(ivciFormat)) {
    509                 std::stringstream ss;
    510                 ss << "vkCreateImageView(): ImageView format " << string_VkFormat(ivciFormat)
    511                    << " is not in the same format compatibility class as image (" << (uint64_t)pCreateInfo->image << ")  format "
    512                    << string_VkFormat(imageFormat) << ".  Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT "
    513                    << "can support ImageViews with differing formats but they must be in the same compatibility class.";
    514                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
    515                                     __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    516             }
    517         } else {
    518             // Format MUST be IDENTICAL to the format the image was created with
    519             if (imageFormat != ivciFormat) {
    520                 std::stringstream ss;
    521                 ss << "vkCreateImageView() format " << string_VkFormat(ivciFormat) << " differs from image "
    522                    << (uint64_t)pCreateInfo->image << " format " << string_VkFormat(imageFormat)
    523                    << ".  Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
    524                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
    525                                     __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
    526             }
    527         }
    528 
    529         // Validate correct image aspect bits for desired formats and format consistency
    530         if (vk_format_is_color(imageFormat)) {
    531             if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
    532                 std::stringstream ss;
    533                 ss << "vkCreateImageView: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set";
    534                 skipCall |=
    535                     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_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    537             }
    538             if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != aspectMask) {
    539                 std::stringstream ss;
    540                 ss << "vkCreateImageView: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set";
    541                 skipCall |=
    542                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    543                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    544             }
    545             if (!vk_format_is_color(ivciFormat)) {
    546                 std::stringstream ss;
    547                 ss << "vkCreateImageView: The image view's format can differ from the parent image's format, but both must be "
    548                    << "color formats.  ImageFormat is " << string_VkFormat(imageFormat) << " ImageViewFormat is "
    549                    << string_VkFormat(ivciFormat);
    550                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    551                                     (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
    552             }
    553             // TODO:  Uncompressed formats are compatible if they occupy they same number of bits per pixel.
    554             //        Compressed formats are compatible if the only difference between them is the numerical type of
    555             //        the uncompressed pixels (e.g. signed vs. unsigned, or sRGB vs. UNORM encoding).
    556         } else if (vk_format_is_depth_and_stencil(imageFormat)) {
    557             if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
    558                 std::stringstream ss;
    559                 ss << "vkCreateImageView: Depth/stencil image formats must have at least one of VK_IMAGE_ASPECT_DEPTH_BIT and "
    560                       "VK_IMAGE_ASPECT_STENCIL_BIT set";
    561                 skipCall |=
    562                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    563                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    564             }
    565             if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspectMask) {
    566                 std::stringstream ss;
    567                 ss << "vkCreateImageView: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and "
    568                       "VK_IMAGE_ASPECT_STENCIL_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_depth_only(imageFormat)) {
    574             if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
    575                 std::stringstream ss;
    576                 ss << "vkCreateImageView: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_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_DEPTH_BIT) != aspectMask) {
    582                 std::stringstream ss;
    583                 ss << "vkCreateImageView: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_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         } else if (vk_format_is_stencil_only(imageFormat)) {
    589             if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
    590                 std::stringstream ss;
    591                 ss << "vkCreateImageView: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set";
    592                 skipCall |=
    593                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    594                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    595             }
    596             if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspectMask) {
    597                 std::stringstream ss;
    598                 ss << "vkCreateImageView: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set";
    599                 skipCall |=
    600                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    601                             (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    602             }
    603         }
    604     }
    605 
    606     if (skipCall) {
    607         return VK_ERROR_VALIDATION_FAILED_EXT;
    608     }
    609 
    610     VkResult result = device_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView);
    611     return result;
    612 }
    613 
    614 VKAPI_ATTR void VKAPI_CALL CmdClearColorImage(VkCommandBuffer commandBuffer, VkImage image,
    615                                               VkImageLayout imageLayout, const VkClearColorValue *pColor,
    616                                               uint32_t rangeCount, const VkImageSubresourceRange *pRanges) {
    617     bool skipCall = false;
    618     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    619 
    620     if (imageLayout != VK_IMAGE_LAYOUT_GENERAL && imageLayout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL) {
    621         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    622                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_LAYOUT, "IMAGE",
    623                             "vkCmdClearColorImage parameter, imageLayout, must be VK_IMAGE_LAYOUT_GENERAL or "
    624                             "VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL");
    625     }
    626 
    627     // For each range, image aspect must be color only
    628     for (uint32_t i = 0; i < rangeCount; i++) {
    629         if (pRanges[i].aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
    630             char const str[] =
    631                 "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
    632             skipCall |=
    633                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    634                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    635         }
    636     }
    637 
    638     auto image_state = getImageState(device_data, image);
    639     if (image_state) {
    640         if (vk_format_is_depth_or_stencil(image_state->format)) {
    641             char const str[] = "vkCmdClearColorImage called with depth/stencil image.";
    642             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    643                                 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
    644         } else if (vk_format_is_compressed(image_state->format)) {
    645             char const str[] = "vkCmdClearColorImage called with compressed image.";
    646             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    647                                 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
    648         }
    649 
    650         if (!(image_state->usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)) {
    651             char const str[] = "vkCmdClearColorImage called with image created without VK_IMAGE_USAGE_TRANSFER_DST_BIT.";
    652             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    653                                 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_USAGE, "IMAGE", str);
    654         }
    655     }
    656 
    657     if (!skipCall) {
    658         device_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout, pColor, rangeCount, pRanges);
    659     }
    660 }
    661 
    662 VKAPI_ATTR void VKAPI_CALL
    663 CmdClearDepthStencilImage(VkCommandBuffer commandBuffer, VkImage image, VkImageLayout imageLayout,
    664                           const VkClearDepthStencilValue *pDepthStencil, uint32_t rangeCount,
    665                           const VkImageSubresourceRange *pRanges) {
    666     bool skipCall = false;
    667     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    668     // For each range, Image aspect must be depth or stencil or both
    669     for (uint32_t i = 0; i < rangeCount; i++) {
    670         if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
    671             ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    672             char const str[] = "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
    673                                "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
    674             skipCall |=
    675                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    676                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    677         }
    678     }
    679 
    680     auto image_state = getImageState(device_data, image);
    681     if (image_state && !vk_format_is_depth_or_stencil(image_state->format)) {
    682         char const str[] = "vkCmdClearDepthStencilImage called without a depth/stencil image.";
    683         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
    684                             reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", str);
    685     }
    686 
    687     if (!skipCall) {
    688         device_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer, image, imageLayout, pDepthStencil, rangeCount,
    689                                                                       pRanges);
    690     }
    691 }
    692 
    693 // Returns true if [x, xoffset] and [y, yoffset] overlap
    694 static bool RangesIntersect(int32_t start, uint32_t start_offset, int32_t end, uint32_t end_offset) {
    695     bool result = false;
    696     uint32_t intersection_min = std::max(static_cast<uint32_t>(start), static_cast<uint32_t>(end));
    697     uint32_t intersection_max = std::min(static_cast<uint32_t>(start) + start_offset, static_cast<uint32_t>(end) + end_offset);
    698 
    699     if (intersection_max > intersection_min) {
    700         result = true;
    701     }
    702     return result;
    703 }
    704 
    705 // Returns true if two VkImageCopy structures overlap
    706 static bool RegionIntersects(const VkImageCopy *src, const VkImageCopy *dst, VkImageType type) {
    707     bool result = true;
    708     if ((src->srcSubresource.mipLevel == dst->dstSubresource.mipLevel) &&
    709         (RangesIntersect(src->srcSubresource.baseArrayLayer, src->srcSubresource.layerCount, dst->dstSubresource.baseArrayLayer,
    710                          dst->dstSubresource.layerCount))) {
    711 
    712         switch (type) {
    713         case VK_IMAGE_TYPE_3D:
    714             result &= RangesIntersect(src->srcOffset.z, src->extent.depth, dst->dstOffset.z, dst->extent.depth);
    715         // Intentionally fall through to 2D case
    716         case VK_IMAGE_TYPE_2D:
    717             result &= RangesIntersect(src->srcOffset.y, src->extent.height, dst->dstOffset.y, dst->extent.height);
    718         // Intentionally fall through to 1D case
    719         case VK_IMAGE_TYPE_1D:
    720             result &= RangesIntersect(src->srcOffset.x, src->extent.width, dst->dstOffset.x, dst->extent.width);
    721             break;
    722         default:
    723             // Unrecognized or new IMAGE_TYPE enums will be caught in parameter_validation
    724             assert(false);
    725         }
    726     }
    727     return result;
    728 }
    729 
    730 // Returns true if offset and extent exceed image extents
    731 static bool ExceedsBounds(const VkOffset3D *offset, const VkExtent3D *extent, const IMAGE_STATE *image) {
    732     bool result = false;
    733     // Extents/depths cannot be negative but checks left in for clarity
    734     switch (image->imageType) {
    735     case VK_IMAGE_TYPE_3D: // Validate z and depth
    736         if ((offset->z + extent->depth > image->extent.depth) || (offset->z < 0) ||
    737             ((offset->z + static_cast<int32_t>(extent->depth)) < 0)) {
    738             result = true;
    739         }
    740         // Intentionally fall through to 2D case to check height
    741     case VK_IMAGE_TYPE_2D: // Validate y and height
    742         if ((offset->y + extent->height > image->extent.height) || (offset->y < 0) ||
    743             ((offset->y + static_cast<int32_t>(extent->height)) < 0)) {
    744             result = true;
    745         }
    746         // Intentionally fall through to 1D case to check width
    747     case VK_IMAGE_TYPE_1D: // Validate x and width
    748         if ((offset->x + extent->width > image->extent.width) || (offset->x < 0) ||
    749             ((offset->x + static_cast<int32_t>(extent->width)) < 0)) {
    750             result = true;
    751         }
    752         break;
    753     default:
    754         assert(false);
    755     }
    756     return result;
    757 }
    758 
    759 bool PreCallValidateCmdCopyImage(VkCommandBuffer command_buffer, VkImage src_image, VkImage dst_image, uint32_t region_count,
    760                                  const VkImageCopy *regions) {
    761     bool skip = false;
    762     layer_data *device_data = get_my_data_ptr(get_dispatch_key(command_buffer), layer_data_map);
    763     auto src_image_entry = getImageState(device_data, src_image);
    764     auto dst_image_entry = getImageState(device_data, dst_image);
    765 
    766     // TODO: This does not cover swapchain-created images. This should fall out when this layer is moved
    767     // into the core_validation layer
    768     if (src_image_entry && dst_image_entry) {
    769 
    770         for (uint32_t i = 0; i < region_count; i++) {
    771 
    772             if (regions[i].srcSubresource.layerCount == 0) {
    773                 std::stringstream ss;
    774                 ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] srcSubresource is zero";
    775                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
    776                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    777                                 __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    778             }
    779 
    780             if (regions[i].dstSubresource.layerCount == 0) {
    781                 std::stringstream ss;
    782                 ss << "vkCmdCopyImage: number of layers in pRegions[" << i << "] dstSubresource is zero";
    783                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
    784                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    785                                 __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    786             }
    787 
    788             // For each region the layerCount member of srcSubresource and dstSubresource must match
    789             if (regions[i].srcSubresource.layerCount != regions[i].dstSubresource.layerCount) {
    790                 std::stringstream ss;
    791                 ss << "vkCmdCopyImage: number of layers in source and destination subresources for pRegions[" << i
    792                    << "] do not match";
    793                 skip |=
    794                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    795                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01198, "IMAGE", "%s. %s",
    796                             ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01198]);
    797             }
    798 
    799             // For each region, the aspectMask member of srcSubresource and dstSubresource must match
    800             if (regions[i].srcSubresource.aspectMask != regions[i].dstSubresource.aspectMask) {
    801                 char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
    802                 skip |=
    803                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    804                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
    805             }
    806 
    807             // AspectMask must not contain VK_IMAGE_ASPECT_METADATA_BIT
    808             if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT) ||
    809                 (regions[i].dstSubresource.aspectMask & VK_IMAGE_ASPECT_METADATA_BIT)) {
    810                 std::stringstream ss;
    811                 ss << "vkCmdCopyImage: pRegions[" << i << "] may not specify aspectMask containing VK_IMAGE_ASPECT_METADATA_BIT";
    812                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    813                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    814                                 __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
    815             }
    816 
    817             // For each region, if aspectMask contains VK_IMAGE_ASPECT_COLOR_BIT, it must not contain either of
    818             // VK_IMAGE_ASPECT_DEPTH_BIT or VK_IMAGE_ASPECT_STENCIL_BIT
    819             if ((regions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
    820                 (regions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
    821                 char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
    822                 skip |=
    823                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    824                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
    825             }
    826 
    827             // If either of the calling command's src_image or dst_image parameters are of VkImageType VK_IMAGE_TYPE_3D,
    828             // the baseArrayLayer and layerCount members of both srcSubresource and dstSubresource must be 0 and 1, respectively
    829             if (((src_image_entry->imageType == VK_IMAGE_TYPE_3D) || (dst_image_entry->imageType == VK_IMAGE_TYPE_3D)) &&
    830                 ((regions[i].srcSubresource.baseArrayLayer != 0) || (regions[i].srcSubresource.layerCount != 1) ||
    831                  (regions[i].dstSubresource.baseArrayLayer != 0) || (regions[i].dstSubresource.layerCount != 1))) {
    832                 std::stringstream ss;
    833                 ss << "vkCmdCopyImage: src or dstImage type was IMAGE_TYPE_3D, but in subRegion[" << i
    834                    << "] baseArrayLayer was not zero or layerCount was not 1.";
    835                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    836                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    837                                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
    838             }
    839 
    840             // MipLevel must be less than the mipLevels specified in VkImageCreateInfo when the image was created
    841             if (regions[i].srcSubresource.mipLevel >= src_image_entry->mipLevels) {
    842                 std::stringstream ss;
    843                 ss << "vkCmdCopyImage: pRegions[" << i
    844                    << "] specifies a src mipLevel greater than the number specified when the srcImage was created.";
    845                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    846                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    847                                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
    848             }
    849             if (regions[i].dstSubresource.mipLevel >= dst_image_entry->mipLevels) {
    850                 std::stringstream ss;
    851                 ss << "vkCmdCopyImage: pRegions[" << i
    852                    << "] specifies a dst mipLevel greater than the number specified when the dstImage was created.";
    853                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    854                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    855                                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
    856             }
    857 
    858             // (baseArrayLayer + layerCount) must be less than or equal to the arrayLayers specified in VkImageCreateInfo when the
    859             // image was created
    860             if ((regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount) > src_image_entry->arraySize) {
    861                 std::stringstream ss;
    862                 ss << "vkCmdCopyImage: srcImage arrayLayers was " << src_image_entry->arraySize << " but subRegion[" << i
    863                    << "] baseArrayLayer + layerCount is "
    864                    << (regions[i].srcSubresource.baseArrayLayer + regions[i].srcSubresource.layerCount);
    865                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    866                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    867                                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
    868             }
    869             if ((regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount) > dst_image_entry->arraySize) {
    870                 std::stringstream ss;
    871                 ss << "vkCmdCopyImage: dstImage arrayLayers was " << dst_image_entry->arraySize << " but subRegion[" << i
    872                    << "] baseArrayLayer + layerCount is "
    873                    << (regions[i].dstSubresource.baseArrayLayer + regions[i].dstSubresource.layerCount);
    874                 skip |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    875                                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    876                                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
    877             }
    878 
    879             // The source region specified by a given element of regions must be a region that is contained within srcImage
    880             if (ExceedsBounds(&regions[i].srcOffset, &regions[i].extent, src_image_entry)) {
    881                 std::stringstream ss;
    882                 ss << "vkCmdCopyImage: srcSubResource in pRegions[" << i << "] exceeds extents srcImage was created with";
    883                 skip |=
    884                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    885                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01175, "IMAGE", "%s. %s",
    886                             ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01175]);
    887             }
    888 
    889             // The destination region specified by a given element of regions must be a region that is contained within dst_image
    890             if (ExceedsBounds(&regions[i].dstOffset, &regions[i].extent, dst_image_entry)) {
    891                 std::stringstream ss;
    892                 ss << "vkCmdCopyImage: dstSubResource in pRegions[" << i << "] exceeds extents dstImage was created with";
    893                 skip |=
    894                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    895                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01176, "IMAGE", "%s. %s",
    896                             ss.str().c_str(), validation_error_map[VALIDATION_ERROR_01176]);
    897             }
    898 
    899             // The union of all source regions, and the union of all destination regions, specified by the elements of regions,
    900             // must not overlap in memory
    901             if (src_image == dst_image) {
    902                 for (uint32_t j = 0; j < region_count; j++) {
    903                     if (RegionIntersects(&regions[i], &regions[j], src_image_entry->imageType)) {
    904                         std::stringstream ss;
    905                         ss << "vkCmdCopyImage: pRegions[" << i << "] src overlaps with pRegions[" << j << "].";
    906                         skip |=
    907                             log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
    908                                     VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t &>(command_buffer),
    909                                     __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
    910                     }
    911                 }
    912             }
    913         }
    914 
    915         // The formats of src_image and dst_image must be compatible. Formats are considered compatible if their texel size in bytes
    916         // is the same between both formats. For example, VK_FORMAT_R8G8B8A8_UNORM is compatible with VK_FORMAT_R32_UINT because
    917         // because both texels are 4 bytes in size. Depth/stencil formats must match exactly.
    918         if (vk_format_is_depth_or_stencil(src_image_entry->format) || vk_format_is_depth_or_stencil(dst_image_entry->format)) {
    919             if (src_image_entry->format != dst_image_entry->format) {
    920                 char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
    921                 skip |=
    922                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    923                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
    924             }
    925         } else {
    926             size_t srcSize = vk_format_get_size(src_image_entry->format);
    927             size_t destSize = vk_format_get_size(dst_image_entry->format);
    928             if (srcSize != destSize) {
    929                 char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
    930                 skip |=
    931                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    932                             reinterpret_cast<uint64_t &>(command_buffer), __LINE__, VALIDATION_ERROR_01184, "IMAGE", "%s. %s", str,
    933                             validation_error_map[VALIDATION_ERROR_01184]);
    934             }
    935         }
    936     }
    937     return skip;
    938 }
    939 
    940 VKAPI_ATTR void VKAPI_CALL CmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage,
    941                                         VkImageLayout srcImageLayout, VkImage dstImage,
    942                                         VkImageLayout dstImageLayout, uint32_t regionCount,
    943                                         const VkImageCopy *pRegions) {
    944 
    945     bool skip = false;
    946     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    947 
    948     skip = PreCallValidateCmdCopyImage(commandBuffer, srcImage, dstImage, regionCount, pRegions);
    949 
    950     if (!skip) {
    951         device_data->device_dispatch_table->CmdCopyImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
    952                                                          regionCount, pRegions);
    953     }
    954 }
    955 
    956 VKAPI_ATTR void VKAPI_CALL CmdClearAttachments(VkCommandBuffer commandBuffer, uint32_t attachmentCount,
    957                                                const VkClearAttachment *pAttachments, uint32_t rectCount,
    958                                                const VkClearRect *pRects) {
    959     bool skipCall = false;
    960     VkImageAspectFlags aspectMask;
    961     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
    962     for (uint32_t i = 0; i < attachmentCount; i++) {
    963         aspectMask = pAttachments[i].aspectMask;
    964         if (aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
    965             if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
    966                 // VK_IMAGE_ASPECT_COLOR_BIT is not the only bit set for this attachment
    967                 char const str[] =
    968                     "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment.";
    969                 skipCall |=
    970                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    971                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
    972             }
    973         } else {
    974             // Image aspect must be depth or stencil or both
    975             if (((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
    976                 ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT)) {
    977                 char const str[] = "vkCmdClearAttachments aspectMask [%d] must be set to VK_IMAGE_ASPECT_DEPTH_BIT and/or "
    978                                    "VK_IMAGE_ASPECT_STENCIL_BIT";
    979                 skipCall |=
    980                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
    981                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
    982             }
    983         }
    984     }
    985 
    986     if (!skipCall) {
    987         device_data->device_dispatch_table->CmdClearAttachments(commandBuffer, attachmentCount, pAttachments, rectCount, pRects);
    988     }
    989 }
    990 
    991 static bool ValidateBufferToImageData(layer_data *dev_data, uint32_t regionCount, const VkBufferImageCopy *pRegions, VkImage image,
    992                                       const char *function) {
    993     bool skip = false;
    994 
    995     for (uint32_t i = 0; i < regionCount; i++) {
    996 
    997         auto image_info = getImageState(dev_data, image);
    998         if (image_info) {
    999             // BufferOffset must be a multiple of the calling command's VkImage parameter's texel size
   1000             auto texel_size = vk_format_get_size(image_info->format);
   1001             if (vk_safe_modulo(pRegions[i].bufferOffset, texel_size) != 0) {
   1002                 skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1003                                 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE",
   1004                                 "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64
   1005                                 " must be a multiple of this format's texel size (" PRINTF_SIZE_T_SPECIFIER ")",
   1006                                 function, i, pRegions[i].bufferOffset, texel_size);
   1007             }
   1008             //  BufferOffset must be a multiple of 4
   1009             if (vk_safe_modulo(pRegions[i].bufferOffset, 4) != 0) {
   1010                 skip |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1011                                 reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE",
   1012                                 "%s(): pRegion[%d] bufferOffset 0x%" PRIxLEAST64 " must be a multiple of 4", function, i,
   1013                                 pRegions[i].bufferOffset);
   1014             }
   1015 
   1016             //  BufferRowLength must be 0, or greater than or equal to the width member of imageExtent
   1017             if ((pRegions[i].bufferRowLength != 0) && (pRegions[i].bufferRowLength < pRegions[i].imageExtent.width)) {
   1018                 skip |= log_msg(
   1019                     dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1020                     reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE",
   1021                     "%s(): pRegion[%d] bufferRowLength (%d) must be zero or greater-than-or-equal-to imageExtent.width (%d).",
   1022                     function, i, pRegions[i].bufferRowLength, pRegions[i].imageExtent.width);
   1023             }
   1024 
   1025             //  BufferImageHeight must be 0, or greater than or equal to the height member of imageExtent
   1026             if ((pRegions[i].bufferImageHeight != 0) && (pRegions[i].bufferImageHeight < pRegions[i].imageExtent.height)) {
   1027                 skip |= log_msg(
   1028                     dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1029                     reinterpret_cast<uint64_t &>(image), __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE",
   1030                     "%s(): pRegion[%d] bufferImageHeight (%d) must be zero or greater-than-or-equal-to imageExtent.height (%d).",
   1031                     function, i, pRegions[i].bufferImageHeight, pRegions[i].imageExtent.height);
   1032             }
   1033         }
   1034     }
   1035 
   1036     return skip;
   1037 }
   1038 
   1039 VKAPI_ATTR void VKAPI_CALL CmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage,
   1040                                                 VkImageLayout srcImageLayout, VkBuffer dstBuffer,
   1041                                                 uint32_t regionCount, const VkBufferImageCopy *pRegions) {
   1042     bool skip_call = false;
   1043     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
   1044 
   1045     skip_call |= ValidateBufferToImageData(device_data, regionCount, pRegions, srcImage, "vkCmdCopyImageToBuffer");
   1046 
   1047     // For each region, the number of layers in the image subresource should not be zero
   1048     // Image aspect must be ONE OF color, depth, stencil
   1049     for (uint32_t i = 0; i < regionCount; i++) {
   1050         if (pRegions[i].imageSubresource.layerCount == 0) {
   1051             char const str[] = "vkCmdCopyImageToBuffer: number of layers in image subresource is zero";
   1052             // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
   1053             skip_call |=
   1054                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1055                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1056         }
   1057 
   1058         VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
   1059         if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) && (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
   1060             (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
   1061             char const str[] = "vkCmdCopyImageToBuffer: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
   1062             skip_call |=
   1063                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1064                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
   1065         }
   1066     }
   1067 
   1068     if (!skip_call) {
   1069         device_data->device_dispatch_table->CmdCopyImageToBuffer(commandBuffer, srcImage, srcImageLayout, dstBuffer, regionCount,
   1070                                                                  pRegions);
   1071     }
   1072 }
   1073 
   1074 VKAPI_ATTR void VKAPI_CALL CmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer,
   1075                                                 VkImage dstImage, VkImageLayout dstImageLayout,
   1076                                                 uint32_t regionCount, const VkBufferImageCopy *pRegions) {
   1077     bool skip_call = false;
   1078     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
   1079 
   1080     skip_call |= ValidateBufferToImageData(device_data, regionCount, pRegions, dstImage, "vkCmdCopyBufferToImage");
   1081 
   1082     // For each region, the number of layers in the image subresource should not be zero
   1083     // Image aspect must be ONE OF color, depth, stencil
   1084     for (uint32_t i = 0; i < regionCount; i++) {
   1085         if (pRegions[i].imageSubresource.layerCount == 0) {
   1086             char const str[] = "vkCmdCopyBufferToImage: number of layers in image subresource is zero";
   1087             // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
   1088             skip_call |=
   1089                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1090                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1091         }
   1092 
   1093         VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
   1094         if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) && (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
   1095             (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
   1096             char const str[] = "vkCmdCopyBufferToImage: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
   1097             skip_call |=
   1098                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1099                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
   1100         }
   1101     }
   1102 
   1103     if (!skip_call) {
   1104         device_data->device_dispatch_table->CmdCopyBufferToImage(commandBuffer, srcBuffer, dstImage, dstImageLayout, regionCount,
   1105                                                                  pRegions);
   1106     }
   1107 }
   1108 
   1109 VKAPI_ATTR void VKAPI_CALL
   1110 CmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
   1111              VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions, VkFilter filter) {
   1112     bool skipCall = false;
   1113     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
   1114 
   1115     // Warn for zero-sized regions
   1116     for (uint32_t i = 0; i < regionCount; i++) {
   1117         if ((pRegions[i].srcOffsets[0].x == pRegions[i].srcOffsets[1].x) ||
   1118             (pRegions[i].srcOffsets[0].y == pRegions[i].srcOffsets[1].y) ||
   1119             (pRegions[i].srcOffsets[0].z == pRegions[i].srcOffsets[1].z)) {
   1120             std::stringstream ss;
   1121             ss << "vkCmdBlitImage: pRegions[" << i << "].srcOffsets specify a zero-volume area.";
   1122             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
   1123                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer),
   1124                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
   1125         }
   1126         if ((pRegions[i].dstOffsets[0].x == pRegions[i].dstOffsets[1].x) ||
   1127             (pRegions[i].dstOffsets[0].y == pRegions[i].dstOffsets[1].y) ||
   1128             (pRegions[i].dstOffsets[0].z == pRegions[i].dstOffsets[1].z)) {
   1129             std::stringstream ss;
   1130             ss << "vkCmdBlitImage: pRegions[" << i << "].dstOffsets specify a zero-volume area.";
   1131             skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
   1132                 VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, reinterpret_cast<uint64_t>(commandBuffer),
   1133                 __LINE__, IMAGE_INVALID_EXTENTS, "IMAGE", "%s", ss.str().c_str());
   1134         }
   1135     }
   1136 
   1137     auto srcImageEntry = getImageState(device_data, srcImage);
   1138     auto dstImageEntry = getImageState(device_data, dstImage);
   1139 
   1140     if (srcImageEntry && dstImageEntry) {
   1141 
   1142         VkFormat srcFormat = srcImageEntry->format;
   1143         VkFormat dstFormat = dstImageEntry->format;
   1144 
   1145         // Validate consistency for signed and unsigned formats
   1146         if ((vk_format_is_sint(srcFormat) && !vk_format_is_sint(dstFormat)) ||
   1147             (vk_format_is_uint(srcFormat) && !vk_format_is_uint(dstFormat))) {
   1148             std::stringstream ss;
   1149             ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed/unsigned integer format, "
   1150                << "the other one must also have signed/unsigned integer format.  "
   1151                << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
   1152             skipCall |=
   1153                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1154                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
   1155         }
   1156 
   1157         // Validate aspect bits and formats for depth/stencil images
   1158         if (vk_format_is_depth_or_stencil(srcFormat) || vk_format_is_depth_or_stencil(dstFormat)) {
   1159             if (srcFormat != dstFormat) {
   1160                 std::stringstream ss;
   1161                 ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
   1162                    << "stencil, the other one must have exactly the same format.  "
   1163                    << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
   1164                 skipCall |=
   1165                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1166                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
   1167             }
   1168 
   1169             for (uint32_t i = 0; i < regionCount; i++) {
   1170                 if (pRegions[i].srcSubresource.layerCount == 0) {
   1171                     char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
   1172                     // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
   1173                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1174                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1175                                         IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1176                 }
   1177 
   1178                 if (pRegions[i].dstSubresource.layerCount == 0) {
   1179                     char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
   1180                     // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
   1181                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1182                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1183                                         IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1184                 }
   1185 
   1186                 if (pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount) {
   1187                     char const str[] = "vkCmdBlitImage: number of layers in source and destination subresources must match";
   1188                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1189                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1190                                         IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1191                 }
   1192 
   1193                 VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
   1194                 VkImageAspectFlags dstAspect = pRegions[i].dstSubresource.aspectMask;
   1195 
   1196                 if (srcAspect != dstAspect) {
   1197                     std::stringstream ss;
   1198                     ss << "vkCmdBlitImage: Image aspects of depth/stencil images should match";
   1199                     // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
   1200                     skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1201                                         VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1202                                         IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1203                 }
   1204                 if (vk_format_is_depth_and_stencil(srcFormat)) {
   1205                     if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
   1206                         std::stringstream ss;
   1207                         ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of "
   1208                               "VK_IMAGE_ASPECT_DEPTH_BIT "
   1209                            << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
   1210                         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1211                                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1212                                             IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1213                     }
   1214                 } else if (vk_format_is_stencil_only(srcFormat)) {
   1215                     if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
   1216                         std::stringstream ss;
   1217                         ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
   1218                            << "set in both the srcImage and dstImage";
   1219                         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1220                                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1221                                             IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1222                     }
   1223                 } else if (vk_format_is_depth_only(srcFormat)) {
   1224                     if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
   1225                         std::stringstream ss;
   1226                         ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
   1227                            << "set in both the srcImage and dstImage";
   1228                         skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
   1229                                             VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, (uint64_t)commandBuffer, __LINE__,
   1230                                             IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1231                     }
   1232                 }
   1233             }
   1234         }
   1235 
   1236         // Validate filter
   1237         if (vk_format_is_depth_or_stencil(srcFormat) || vk_format_is_int(srcFormat)) {
   1238             if (filter != VK_FILTER_NEAREST) {
   1239                 std::stringstream ss;
   1240                 ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, depth stencil or integer-based format "
   1241                    << "then filter must be VK_FILTER_NEAREST.";
   1242                 skipCall |=
   1243                     log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1244                             (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FILTER, "IMAGE", "%s", ss.str().c_str());
   1245             }
   1246         }
   1247     }
   1248 
   1249     if (!skipCall) {
   1250         device_data->device_dispatch_table->CmdBlitImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout, regionCount,
   1251                                                          pRegions, filter);
   1252     }
   1253 }
   1254 
   1255 VKAPI_ATTR void VKAPI_CALL
   1256 CmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
   1257                    VkDependencyFlags dependencyFlags, uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
   1258                    uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
   1259                    uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers) {
   1260     bool skipCall = false;
   1261     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
   1262 
   1263     for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i) {
   1264         VkImageMemoryBarrier const *const barrier = (VkImageMemoryBarrier const *const) & pImageMemoryBarriers[i];
   1265         if (barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER) {
   1266             if (barrier->subresourceRange.layerCount == 0) {
   1267                 std::stringstream ss;
   1268                 ss << "vkCmdPipelineBarrier called with 0 in ppMemoryBarriers[" << i << "]->subresourceRange.layerCount.";
   1269                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0,
   1270                                     __LINE__, IMAGE_INVALID_IMAGE_RESOURCE, "IMAGE", "%s", ss.str().c_str());
   1271             }
   1272         }
   1273     }
   1274 
   1275     if (skipCall) {
   1276         return;
   1277     }
   1278 
   1279     device_data->device_dispatch_table->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
   1280                                                            memoryBarrierCount, pMemoryBarriers, bufferMemoryBarrierCount,
   1281                                                            pBufferMemoryBarriers, imageMemoryBarrierCount, pImageMemoryBarriers);
   1282 }
   1283 
   1284 VKAPI_ATTR void VKAPI_CALL
   1285 CmdResolveImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
   1286                 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageResolve *pRegions) {
   1287     bool skipCall = false;
   1288     layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
   1289     auto srcImageEntry = getImageState(device_data, srcImage);
   1290     auto dstImageEntry = getImageState(device_data, dstImage);
   1291 
   1292     // For each region, the number of layers in the image subresource should not be zero
   1293     // For each region, src and dest image aspect must be color only
   1294     for (uint32_t i = 0; i < regionCount; i++) {
   1295         if (pRegions[i].srcSubresource.layerCount == 0) {
   1296             char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
   1297             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
   1298             skipCall |=
   1299                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1300                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1301         }
   1302 
   1303         if (pRegions[i].dstSubresource.layerCount == 0) {
   1304             char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
   1305 
   1306             // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
   1307             skipCall |=
   1308                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1309                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
   1310         }
   1311 
   1312         if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
   1313             (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
   1314             char const str[] =
   1315                 "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
   1316             skipCall |=
   1317                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1318                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
   1319         }
   1320     }
   1321 
   1322     if (srcImageEntry && dstImageEntry) {
   1323         if (srcImageEntry->format != dstImageEntry->format) {
   1324             char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
   1325             skipCall |=
   1326                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1327                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
   1328         }
   1329         if (srcImageEntry->imageType != dstImageEntry->imageType) {
   1330             char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
   1331             skipCall |=
   1332                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1333                         (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
   1334         }
   1335         if (srcImageEntry->samples == VK_SAMPLE_COUNT_1_BIT) {
   1336             char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
   1337             skipCall |=
   1338                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1339                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
   1340         }
   1341         if (dstImageEntry->samples != VK_SAMPLE_COUNT_1_BIT) {
   1342             char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
   1343             skipCall |=
   1344                 log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
   1345                         (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
   1346         }
   1347     }
   1348 
   1349     if (!skipCall) {
   1350         device_data->device_dispatch_table->CmdResolveImage(commandBuffer, srcImage, srcImageLayout, dstImage, dstImageLayout,
   1351                                                             regionCount, pRegions);
   1352     }
   1353 }
   1354 
   1355 VKAPI_ATTR void VKAPI_CALL
   1356 GetImageSubresourceLayout(VkDevice device, VkImage image, const VkImageSubresource *pSubresource, VkSubresourceLayout *pLayout) {
   1357     bool skipCall = false;
   1358     layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
   1359     VkFormat format;
   1360 
   1361     auto imageEntry = getImageState(device_data, image);
   1362 
   1363     // Validate that image aspects match formats
   1364     if (imageEntry) {
   1365         format = imageEntry->format;
   1366         if (vk_format_is_color(format)) {
   1367             if (pSubresource->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
   1368                 std::stringstream ss;
   1369                 ss << "vkGetImageSubresourceLayout: For color formats, the aspectMask field of VkImageSubresource must be "
   1370                       "VK_IMAGE_ASPECT_COLOR.";
   1371                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1372                                     (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1373             }
   1374         } else if (vk_format_is_depth_or_stencil(format)) {
   1375             if ((pSubresource->aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
   1376                 (pSubresource->aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
   1377                 std::stringstream ss;
   1378                 ss << "vkGetImageSubresourceLayout: For depth/stencil formats, the aspectMask selects either the depth or stencil "
   1379                       "image aspectMask.";
   1380                 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
   1381                                     (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
   1382             }
   1383         }
   1384     }
   1385 
   1386     if (!skipCall) {
   1387         device_data->device_dispatch_table->GetImageSubresourceLayout(device, image, pSubresource, pLayout);
   1388     }
   1389 }
   1390 
   1391 VKAPI_ATTR void VKAPI_CALL
   1392 GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
   1393     layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
   1394     phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
   1395 }
   1396 
   1397 VKAPI_ATTR VkResult VKAPI_CALL
   1398 EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
   1399     return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
   1400 }
   1401 
   1402 VKAPI_ATTR VkResult VKAPI_CALL
   1403 EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
   1404     return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
   1405 }
   1406 
   1407 VKAPI_ATTR VkResult VKAPI_CALL
   1408 EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
   1409     if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
   1410         return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
   1411 
   1412     return VK_ERROR_LAYER_NOT_PRESENT;
   1413 }
   1414 
   1415 VKAPI_ATTR VkResult VKAPI_CALL EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
   1416                                                                   const char *pLayerName, uint32_t *pCount,
   1417                                                                   VkExtensionProperties *pProperties) {
   1418     // Image does not have any physical device extensions
   1419     if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
   1420         return util_GetExtensionProperties(0, NULL, pCount, pProperties);
   1421 
   1422     assert(physicalDevice);
   1423 
   1424     dispatch_key key = get_dispatch_key(physicalDevice);
   1425     layer_data *my_data = get_my_data_ptr(key, layer_data_map);
   1426     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
   1427     return pTable->EnumerateDeviceExtensionProperties(physicalDevice, NULL, pCount, pProperties);
   1428 }
   1429 
   1430 static PFN_vkVoidFunction
   1431 intercept_core_instance_command(const char *name);
   1432 static PFN_vkVoidFunction
   1433 intercept_core_device_command(const char *name);
   1434 
   1435 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetDeviceProcAddr(VkDevice device, const char *funcName) {
   1436     PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
   1437     if (proc)
   1438         return proc;
   1439 
   1440     assert(device);
   1441 
   1442     layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
   1443 
   1444     VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
   1445     {
   1446         if (pTable->GetDeviceProcAddr == NULL)
   1447             return NULL;
   1448         return pTable->GetDeviceProcAddr(device, funcName);
   1449     }
   1450 }
   1451 
   1452 VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char *funcName) {
   1453     PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
   1454     if (!proc)
   1455         proc = intercept_core_device_command(funcName);
   1456     if (proc)
   1457         return proc;
   1458 
   1459     assert(instance);
   1460     layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
   1461 
   1462     proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
   1463     if (proc)
   1464         return proc;
   1465 
   1466     VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
   1467     if (pTable->GetInstanceProcAddr == NULL)
   1468         return NULL;
   1469     return pTable->GetInstanceProcAddr(instance, funcName);
   1470 }
   1471 
   1472 static PFN_vkVoidFunction
   1473 intercept_core_instance_command(const char *name) {
   1474     static const struct {
   1475         const char *name;
   1476         PFN_vkVoidFunction proc;
   1477     } core_instance_commands[] = {
   1478         { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
   1479         { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
   1480         { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
   1481         { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
   1482         { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
   1483         { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
   1484         { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
   1485         { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
   1486         { "vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties) },
   1487     };
   1488 
   1489     for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
   1490         if (!strcmp(core_instance_commands[i].name, name))
   1491             return core_instance_commands[i].proc;
   1492     }
   1493 
   1494     return nullptr;
   1495 }
   1496 
   1497 static PFN_vkVoidFunction
   1498 intercept_core_device_command(const char *name) {
   1499     static const struct {
   1500         const char *name;
   1501         PFN_vkVoidFunction proc;
   1502     } core_device_commands[] = {
   1503         { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
   1504         { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
   1505         { "vkCreateImage", reinterpret_cast<PFN_vkVoidFunction>(CreateImage) },
   1506         { "vkDestroyImage", reinterpret_cast<PFN_vkVoidFunction>(DestroyImage) },
   1507         { "vkCreateImageView", reinterpret_cast<PFN_vkVoidFunction>(CreateImageView) },
   1508         { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
   1509         { "vkCmdClearColorImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearColorImage) },
   1510         { "vkCmdClearDepthStencilImage", reinterpret_cast<PFN_vkVoidFunction>(CmdClearDepthStencilImage) },
   1511         { "vkCmdClearAttachments", reinterpret_cast<PFN_vkVoidFunction>(CmdClearAttachments) },
   1512         { "vkCmdCopyImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImage) },
   1513         { "vkCmdCopyImageToBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyImageToBuffer) },
   1514         { "vkCmdCopyBufferToImage", reinterpret_cast<PFN_vkVoidFunction>(CmdCopyBufferToImage) },
   1515         { "vkCmdBlitImage", reinterpret_cast<PFN_vkVoidFunction>(CmdBlitImage) },
   1516         { "vkCmdPipelineBarrier", reinterpret_cast<PFN_vkVoidFunction>(CmdPipelineBarrier) },
   1517         { "vkCmdResolveImage", reinterpret_cast<PFN_vkVoidFunction>(CmdResolveImage) },
   1518         { "vkGetImageSubresourceLayout", reinterpret_cast<PFN_vkVoidFunction>(GetImageSubresourceLayout) },
   1519     };
   1520 
   1521     for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
   1522         if (!strcmp(core_device_commands[i].name, name))
   1523             return core_device_commands[i].proc;
   1524     }
   1525 
   1526     return nullptr;
   1527 }
   1528 
   1529 } // namespace image
   1530 
   1531 // vk_layer_logging.h expects these to be defined
   1532 
   1533 VKAPI_ATTR VkResult VKAPI_CALL
   1534 vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
   1535                                const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
   1536     return image::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
   1537 }
   1538 
   1539 VKAPI_ATTR void VKAPI_CALL
   1540 vkDestroyDebugReportCallbackEXT(VkInstance instance,
   1541                                 VkDebugReportCallbackEXT msgCallback,
   1542                                 const VkAllocationCallbacks *pAllocator) {
   1543     image::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
   1544 }
   1545 
   1546 VKAPI_ATTR void VKAPI_CALL
   1547 vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
   1548                         size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
   1549     image::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
   1550 }
   1551 
   1552 // loader-layer interface v0, just wrappers since there is only a layer
   1553 
   1554 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
   1555 vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
   1556     return image::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
   1557 }
   1558 
   1559 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
   1560 vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
   1561     return image::EnumerateInstanceLayerProperties(pCount, pProperties);
   1562 }
   1563 
   1564 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
   1565 vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
   1566     // the layer command handles VK_NULL_HANDLE just fine internally
   1567     assert(physicalDevice == VK_NULL_HANDLE);
   1568     return image::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
   1569 }
   1570 
   1571 VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
   1572                                                                                     const char *pLayerName, uint32_t *pCount,
   1573                                                                                     VkExtensionProperties *pProperties) {
   1574     // the layer command handles VK_NULL_HANDLE just fine internally
   1575     assert(physicalDevice == VK_NULL_HANDLE);
   1576     return image::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
   1577 }
   1578 
   1579 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
   1580     return image::GetDeviceProcAddr(dev, funcName);
   1581 }
   1582 
   1583 VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
   1584     return image::GetInstanceProcAddr(instance, funcName);
   1585 }
   1586