17b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young/* Copyright (c) 2015-2017 The Khronos Group Inc.
27b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young * Copyright (c) 2015-2017 Valve Corporation
37b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young * Copyright (c) 2015-2017 LunarG, Inc.
47b06221f2c4cb2205e0363afe1ce59b81aa144a1Mark Young * Copyright (C) 2015-2017 Google Inc.
5acab8885d3e8c1fdcbfb8ebf9c52168148da63b5Tobin Ehlis *
643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Licensed under the Apache License, Version 2.0 (the "License");
743b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * you may not use this file except in compliance with the License.
843b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * You may obtain a copy of the License at
9acab8885d3e8c1fdcbfb8ebf9c52168148da63b5Tobin Ehlis *
1043b53e83705f02245da6ae61e31273866a35b833Jon Ashburn *     http://www.apache.org/licenses/LICENSE-2.0
11acab8885d3e8c1fdcbfb8ebf9c52168148da63b5Tobin Ehlis *
1243b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * Unless required by applicable law or agreed to in writing, software
1343b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * distributed under the License is distributed on an "AS IS" BASIS,
1443b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1543b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * See the License for the specific language governing permissions and
1643b53e83705f02245da6ae61e31273866a35b833Jon Ashburn * limitations under the License.
1796cd795bb585711057cd90d37a2251419384c937Courtney Goeltzenleuchter *
1896cd795bb585711057cd90d37a2251419384c937Courtney Goeltzenleuchter * Author: Mark Lobodzinski <mark@lunarg.com>
192faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski * Author: Jon Ashburn <jon@lunarg.com>
2096cd795bb585711057cd90d37a2251419384c937Courtney Goeltzenleuchter * Author: Tobin Ehlis <tobin@lunarg.com>
21acab8885d3e8c1fdcbfb8ebf9c52168148da63b5Tobin Ehlis */
22acab8885d3e8c1fdcbfb8ebf9c52168148da63b5Tobin Ehlis
23241a2dbc046af61b3af566c7429f3e42aa49b286Jeremy Hayes#include <mutex>
2454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include <cinttypes>
2554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include <stdio.h>
2654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include <stdlib.h>
2754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include <string.h>
2854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include <unordered_map>
29241a2dbc046af61b3af566c7429f3e42aa49b286Jeremy Hayes
3054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_loader_platform.h"
3154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vulkan/vulkan.h"
3254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_layer_config.h"
3354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_layer_data.h"
3454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_layer_logging.h"
3554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_layer_table.h"
3654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_object_types.h"
3754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vulkan/vk_layer.h"
3854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_object_types.h"
391c7c65d3f9d68d5869da97ceb1a365a739623fe9Courtney Goeltzenleuchter#include "vk_enum_string_helper.h"
402faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski#include "vk_layer_extension_utils.h"
412bdf6da2d55b916479f90c87797ff20ddbb14fd9Courtney Goeltzenleuchter#include "vk_layer_table.h"
42d11c4ee2bd2a5672093d76630d895e824ee1a571Mark Lobodzinski#include "vk_layer_utils.h"
432faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski#include "vulkan/vk_layer.h"
4454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_dispatch_table_helper.h"
4554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski#include "vk_validation_error_messages.h"
4614305ad4363dd22e47118a76bc89376e5b291645Mark Lobodzinski
471c0b73114010d6eb49ff34243fa9474493ef6eaeChia-I Wunamespace object_tracker {
481c0b73114010d6eb49ff34243fa9474493ef6eaeChia-I Wu
493c26a547b82bacdf9a378eb5bff0a5e7782f9379Tobin Ehlis// Object Tracker ERROR codes
50da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinskienum ObjectTrackerError {
5154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    OBJTRACK_NONE,            // Used for INFO & other non-error messages
5254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    OBJTRACK_UNKNOWN_OBJECT,  // Updating uses of object that's not in global object list
5354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    OBJTRACK_INTERNAL_ERROR,  // Bug with data tracking within the layer
5454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    OBJTRACK_OBJECT_LEAK,     // OBJECT was not correctly freed/destroyed
556cb97f9b4cb894c01e9efbc065ef11fc9f6221b6Mark Lobodzinski};
563c26a547b82bacdf9a378eb5bff0a5e7782f9379Tobin Ehlis
57235c20eeb60a1b09c15001ff90c48b89012eb0b9Tobin Ehlis// Object Status -- used to track state of individual objects
587d2d5ac7de9151a23b866b0b1e1380d184b41e69Mark Lobodzinskitypedef VkFlags ObjectStatusFlags;
596cb97f9b4cb894c01e9efbc065ef11fc9f6221b6Mark Lobodzinskienum ObjectStatusFlagBits {
60cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_NONE = 0x00000000,                      // No status is set
61cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_FENCE_IS_SUBMITTED = 0x00000001,        // Fence has been submitted
62cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_VIEWPORT_BOUND = 0x00000002,            // Viewport state object has been bound
63cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_RASTER_BOUND = 0x00000004,              // Viewport state object has been bound
64cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_COLOR_BLEND_BOUND = 0x00000008,         // Viewport state object has been bound
65cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_DEPTH_STENCIL_BOUND = 0x00000010,       // Viewport state object has been bound
66cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_GPU_MEM_MAPPED = 0x00000020,            // Memory object is currently mapped
67cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_COMMAND_BUFFER_SECONDARY = 0x00000040,  // Command Buffer is of type SECONDARY
68cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski    OBJSTATUS_CUSTOM_ALLOCATOR = 0x00000080,          // Allocated with custom allocator
696cb97f9b4cb894c01e9efbc065ef11fc9f6221b6Mark Lobodzinski};
70acab8885d3e8c1fdcbfb8ebf9c52168148da63b5Tobin Ehlis
712faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski// Object and state information structure
72da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinskistruct ObjTrackState {
7354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    uint64_t handle;               // Object handle (new)
7454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    VulkanObjectType object_type;  // Object type identifier
7554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    ObjectStatusFlags status;      // Object state
7654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    uint64_t parent_object;        // Parent object
776cb97f9b4cb894c01e9efbc065ef11fc9f6221b6Mark Lobodzinski};
78e1d3f0c689c3697d2e8b316fef899d7c7cb75faeMark Lobodzinski
792faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski// Track Queue information
80da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinskistruct ObjTrackQueueInfo {
812faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    uint32_t queue_node_index;
822faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    VkQueue queue;
8373bb657499347bd40990c742af60e63bb03426f3Cody Northrop};
8414305ad4363dd22e47118a76bc89376e5b291645Mark Lobodzinski
852faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski// Layer name string to be logged with validation messages.
862faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinskiconst char LayerName[] = "ObjectTracker";
872faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski
88da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinskitypedef std::unordered_map<uint64_t, ObjTrackState *> object_map_type;
89c90f49426aa0ce60a0c381ebc3bef68da91f67a2Mark Lobodzinski
902faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinskistruct layer_data {
912faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    VkInstance instance;
922faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    VkPhysicalDevice physical_device;
93dc87a3ff47dee440b96bdfb385d90d2e271188d9Mark Lobodzinski
94b8a5f6bc08c0c75977f64e212bf6b81432556f3aMark Lobodzinski    uint64_t num_objects[kVulkanObjectTypeMax + 1];
952faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    uint64_t num_total_objects;
9661d505ea40b189b7ae63f311e2f13210eef219d2Mark Lobodzinski
972faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    debug_report_data *report_data;
982faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    std::vector<VkDebugReportCallbackEXT> logging_callback;
992faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    // The following are for keeping track of the temporary callbacks that can
1002faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    // be used in vkCreateInstance and vkDestroyInstance:
1012faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    uint32_t num_tmp_callbacks;
1022faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    VkDebugReportCallbackCreateInfoEXT *tmp_dbg_create_infos;
1032faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    VkDebugReportCallbackEXT *tmp_callbacks;
104de4f1108f0a360ea02bfa0cc5e0fa0df8cf35927Jon Ashburn
1052faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    std::vector<VkQueueFamilyProperties> queue_family_properties;
10614305ad4363dd22e47118a76bc89376e5b291645Mark Lobodzinski
107da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinski    // Vector of unordered_maps per object type to hold ObjTrackState info
1085c4c68c37fbd5e01b931fb47ff2ba31c896bcbeeTobin Ehlis    std::vector<object_map_type> object_map;
1092faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    // Special-case map for swapchain images
110da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinski    std::unordered_map<uint64_t, ObjTrackState *> swapchainImageMap;
1112faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    // Map of queue information structures, one per queue
112da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinski    std::unordered_map<VkQueue, ObjTrackQueueInfo *> queue_info_map;
11314305ad4363dd22e47118a76bc89376e5b291645Mark Lobodzinski
1147b0f9d703b1f9b2a05f52ec6778941216e7598a3Tobin Ehlis    VkLayerDispatchTable dispatch_table;
1152faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    // Default constructor
1162faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski    layer_data()
117cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski        : instance(nullptr),
118cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          physical_device(nullptr),
119cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          num_objects{},
120cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          num_total_objects(0),
121cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          report_data(nullptr),
122cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          num_tmp_callbacks(0),
123cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          tmp_dbg_create_infos(nullptr),
124cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          tmp_callbacks(nullptr),
125cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          object_map{},
126cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski          dispatch_table{} {
127b8a5f6bc08c0c75977f64e212bf6b81432556f3aMark Lobodzinski        object_map.resize(kVulkanObjectTypeMax + 1);
1285c4c68c37fbd5e01b931fb47ff2ba31c896bcbeeTobin Ehlis    }
1296cb97f9b4cb894c01e9efbc065ef11fc9f6221b6Mark Lobodzinski};
13014305ad4363dd22e47118a76bc89376e5b291645Mark Lobodzinski
13154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern std::unordered_map<void *, layer_data *> layer_data_map;
13254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern device_table_map ot_device_table_map;
13354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern instance_table_map ot_instance_table_map;
13454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern std::mutex global_lock;
13554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern uint64_t object_track_index;
13654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern uint32_t loader_layer_if_version;
13754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskiextern const std::unordered_map<std::string, void *> name_to_funcptr_map;
1382faa21475b11e094bb4a82cb7d370b9da1609623Mark Lobodzinski
13954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid DeviceReportUndestroyedObjects(VkDevice device, VulkanObjectType object_type, enum UNIQUE_VALIDATION_ERROR_CODE error_code);
14054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid CreateQueue(VkDevice device, VkQueue vkObj);
14154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid AddQueueInfo(VkDevice device, uint32_t queue_node_index, VkQueue queue);
14254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid ValidateQueueFlags(VkQueue queue, const char *function);
14354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid AllocateCommandBuffer(VkDevice device, const VkCommandPool command_pool, const VkCommandBuffer command_buffer,
14454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                           VkCommandBufferLevel level);
14554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid AllocateDescriptorSet(VkDevice device, VkDescriptorPool descriptor_pool, VkDescriptorSet descriptor_set);
14654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid CreateSwapchainImageObject(VkDevice dispatchable_object, VkImage swapchain_image, VkSwapchainKHR swapchain);
147da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinskivoid ReportUndestroyedObjects(VkDevice device, UNIQUE_VALIDATION_ERROR_CODE error_code);
148040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinskibool ValidateDeviceObject(uint64_t device_handle, enum UNIQUE_VALIDATION_ERROR_CODE invalid_handle_code,
149040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinski                          enum UNIQUE_VALIDATION_ERROR_CODE wrong_device_code);
15054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
15154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskitemplate <typename T1, typename T2>
15254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskibool ValidateObject(T1 dispatchable_object, T2 object, VulkanObjectType object_type, bool null_allowed,
15354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    enum UNIQUE_VALIDATION_ERROR_CODE invalid_handle_code, enum UNIQUE_VALIDATION_ERROR_CODE wrong_device_code) {
15454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    if (null_allowed && (object == VK_NULL_HANDLE)) {
15554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        return false;
15654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    }
15754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    auto object_handle = HandleToUint64(object);
158040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinski
159040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinski    if (object_type == kVulkanObjectTypeDevice) {
160040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinski        return ValidateDeviceObject(object_handle, invalid_handle_code, wrong_device_code);
161040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinski    }
162040ab669b8b9a0bcd49a55d9405b1bec72c572b3Mark Lobodzinski
16354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    VkDebugReportObjectTypeEXT debug_object_type = get_debug_report_enum[object_type];
16454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
16554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(dispatchable_object), layer_data_map);
16654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    // Look for object in device object map
16754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    if (device_data->object_map[object_type].find(object_handle) == device_data->object_map[object_type].end()) {
16854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        // If object is an image, also look for it in the swapchain image map
16954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        if ((object_type != kVulkanObjectTypeImage) ||
17054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            (device_data->swapchainImageMap.find(object_handle) == device_data->swapchainImageMap.end())) {
17154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            // Object not found, look for it in other device object maps
17254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            for (auto other_device_data : layer_data_map) {
17354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                if (other_device_data.second != device_data) {
17454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    if (other_device_data.second->object_map[object_type].find(object_handle) !=
17554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                            other_device_data.second->object_map[object_type].end() ||
17654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        (object_type == kVulkanObjectTypeImage && other_device_data.second->swapchainImageMap.find(object_handle) !=
17754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                                                                      other_device_data.second->swapchainImageMap.end())) {
17854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        // Object found on other device, report an error if object has a device parent error code
179ffadaf34580ea434addcaf710016382b34a4e71fMark Lobodzinski                        if ((wrong_device_code != VALIDATION_ERROR_UNDEFINED) && (object_type != kVulkanObjectTypeSurfaceKHR)) {
18054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                            return log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, debug_object_type,
18154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                                           object_handle, __LINE__, wrong_device_code, LayerName,
18254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                                           "Object 0x%" PRIxLEAST64
18354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                                           " was not created, allocated or retrieved from the correct device. %s",
18454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                                           object_handle, validation_error_map[wrong_device_code]);
18554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        } else {
18654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                            return false;
18754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        }
18854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    }
18954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                }
19054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            }
19154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            // Report an error if object was not found anywhere
19254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            return log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, debug_object_type, object_handle, __LINE__,
19354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                           invalid_handle_code, LayerName, "Invalid %s Object 0x%" PRIxLEAST64 ". %s", object_string[object_type],
19454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                           object_handle, validation_error_map[invalid_handle_code]);
19554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        }
19654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    }
19754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    return false;
19854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski}
19954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
20054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskitemplate <typename T1, typename T2>
20154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid CreateObject(T1 dispatchable_object, T2 object, VulkanObjectType object_type, const VkAllocationCallbacks *pAllocator) {
20254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    layer_data *instance_data = GetLayerDataPtr(get_dispatch_key(dispatchable_object), layer_data_map);
20354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
20454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    auto object_handle = HandleToUint64(object);
20554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    bool custom_allocator = pAllocator != nullptr;
20654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
20754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    if (!instance_data->object_map[object_type].count(object_handle)) {
20854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        VkDebugReportObjectTypeEXT debug_object_type = get_debug_report_enum[object_type];
20954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        log_msg(instance_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, debug_object_type, object_handle, __LINE__,
21054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                OBJTRACK_NONE, LayerName, "OBJ[0x%" PRIxLEAST64 "] : CREATE %s object 0x%" PRIxLEAST64, object_track_index++,
21154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                object_string[object_type], object_handle);
21254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
213da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinski        ObjTrackState *pNewObjNode = new ObjTrackState;
21454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        pNewObjNode->object_type = object_type;
21554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        pNewObjNode->status = custom_allocator ? OBJSTATUS_CUSTOM_ALLOCATOR : OBJSTATUS_NONE;
21654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        pNewObjNode->handle = object_handle;
21754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
21854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        instance_data->object_map[object_type][object_handle] = pNewObjNode;
21954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        instance_data->num_objects[object_type]++;
22054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        instance_data->num_total_objects++;
22154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    }
22254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski}
22354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
22454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskitemplate <typename T1, typename T2>
22554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinskivoid DestroyObject(T1 dispatchable_object, T2 object, VulkanObjectType object_type, const VkAllocationCallbacks *pAllocator,
22654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                   enum UNIQUE_VALIDATION_ERROR_CODE expected_custom_allocator_code,
22754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                   enum UNIQUE_VALIDATION_ERROR_CODE expected_default_allocator_code) {
22854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    layer_data *device_data = GetLayerDataPtr(get_dispatch_key(dispatchable_object), layer_data_map);
22954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
23054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    auto object_handle = HandleToUint64(object);
23154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    bool custom_allocator = pAllocator != nullptr;
23254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    VkDebugReportObjectTypeEXT debug_object_type = get_debug_report_enum[object_type];
23354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
23454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    if (object_handle != VK_NULL_HANDLE) {
23554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        auto item = device_data->object_map[object_type].find(object_handle);
23654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        if (item != device_data->object_map[object_type].end()) {
237da749ff6870f075c25543313c2a2bcabfeb3e605Mark Lobodzinski            ObjTrackState *pNode = item->second;
23854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            assert(device_data->num_total_objects > 0);
23954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            device_data->num_total_objects--;
24054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            assert(device_data->num_objects[pNode->object_type] > 0);
24154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            device_data->num_objects[pNode->object_type]--;
24254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
24354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            log_msg(device_data->report_data, VK_DEBUG_REPORT_INFORMATION_BIT_EXT, debug_object_type, object_handle, __LINE__,
24454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    OBJTRACK_NONE, LayerName,
24554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    "OBJ_STAT Destroy %s obj 0x%" PRIxLEAST64 " (%" PRIu64 " total objs remain & %" PRIu64 " %s objs).",
24654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    object_string[object_type], HandleToUint64(object), device_data->num_total_objects,
24754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    device_data->num_objects[pNode->object_type], object_string[object_type]);
24854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
24954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            auto allocated_with_custom = (pNode->status & OBJSTATUS_CUSTOM_ALLOCATOR) ? true : false;
25054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            if (allocated_with_custom && !custom_allocator && expected_custom_allocator_code != VALIDATION_ERROR_UNDEFINED) {
25154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                // This check only verifies that custom allocation callbacks were provided to both Create and Destroy calls,
25254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                // it cannot verify that these allocation callbacks are compatible with each other.
25354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, debug_object_type, object_handle, __LINE__,
25454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        expected_custom_allocator_code, LayerName,
25554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        "Custom allocator not specified while destroying %s obj 0x%" PRIxLEAST64 " but specified at creation. %s",
25654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        object_string[object_type], object_handle, validation_error_map[expected_custom_allocator_code]);
25754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            } else if (!allocated_with_custom && custom_allocator &&
25854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                       expected_default_allocator_code != VALIDATION_ERROR_UNDEFINED) {
25954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, debug_object_type, object_handle, __LINE__,
26054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        expected_default_allocator_code, LayerName,
26154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        "Custom allocator specified while destroying %s obj 0x%" PRIxLEAST64 " but not specified at creation. %s",
26254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                        object_string[object_type], object_handle, validation_error_map[expected_default_allocator_code]);
26354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            }
26454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski
26554ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            delete pNode;
26654ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            device_data->object_map[object_type].erase(item);
26754ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        } else {
26854ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski            log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_UNKNOWN_EXT, object_handle,
26954ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    __LINE__, OBJTRACK_UNKNOWN_OBJECT, LayerName,
27054ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    "Unable to remove %s obj 0x%" PRIxLEAST64 ". Was it created? Has it already been destroyed?",
27154ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski                    object_string[object_type], object_handle);
27254ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski        }
27354ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski    }
27454ccc4c2675072b5eb7fb23693d955d9501ddd58Mark Lobodzinski}
275d11c4ee2bd2a5672093d76630d895e824ee1a571Mark Lobodzinski
276cc7c305c82f6443c324165edb7af59f60fc87eebMark Lobodzinski}  // namespace object_tracker
277