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