Home | History | Annotate | Download | only in layers
      1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
      2  * Copyright (c) 2015-2016 Valve Corporation
      3  * Copyright (c) 2015-2016 LunarG, Inc.
      4  * Copyright (c) 2015-2016 Google, Inc.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a copy
      7  * of this software and/or associated documentation files (the "Materials"), to
      8  * deal in the Materials without restriction, including without limitation the
      9  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
     10  * sell copies of the Materials, and to permit persons to whom the Materials
     11  * are furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice(s) and this permission notice shall be included
     14  * in all copies or substantial portions of the Materials.
     15  *
     16  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     17  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
     19  *
     20  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
     21  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
     22  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
     23  * USE OR OTHER DEALINGS IN THE MATERIALS
     24  *
     25  * Author: Tobin Ehlis <tobin (at) lunarg.com>
     26  */
     27 #include <assert.h>
     28 #include <unordered_map>
     29 #include "vk_dispatch_table_helper.h"
     30 #include "vulkan/vk_layer.h"
     31 #include "vk_layer_table.h"
     32 static device_table_map tableMap;
     33 static instance_table_map tableInstanceMap;
     34 
     35 #define DISPATCH_MAP_DEBUG 0
     36 
     37 // Map lookup must be thread safe
     38 VkLayerDispatchTable *device_dispatch_table(void *object) {
     39     dispatch_key key = get_dispatch_key(object);
     40     device_table_map::const_iterator it = tableMap.find((void *)key);
     41     assert(it != tableMap.end() && "Not able to find device dispatch entry");
     42     return it->second;
     43 }
     44 
     45 VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) {
     46     dispatch_key key = get_dispatch_key(object);
     47     instance_table_map::const_iterator it = tableInstanceMap.find((void *)key);
     48 #if DISPATCH_MAP_DEBUG
     49     if (it != tableInstanceMap.end()) {
     50         fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key,
     51                 it->second);
     52     } else {
     53         fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
     54     }
     55 #endif
     56     assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry");
     57     return it->second;
     58 }
     59 
     60 void destroy_dispatch_table(device_table_map &map, dispatch_key key) {
     61 #if DISPATCH_MAP_DEBUG
     62     device_table_map::const_iterator it = map.find((void *)key);
     63     if (it != map.end()) {
     64         fprintf(stderr, "destroy device dispatch_table: map: %p, key: %p, table: %p\n", &map, key, it->second);
     65     } else {
     66         fprintf(stderr, "destroy device dispatch table: map: %p, key: %p, table: UNKNOWN\n", &map, key);
     67         assert(it != map.end());
     68     }
     69 #endif
     70     map.erase(key);
     71 }
     72 
     73 void destroy_dispatch_table(instance_table_map &map, dispatch_key key) {
     74 #if DISPATCH_MAP_DEBUG
     75     instance_table_map::const_iterator it = map.find((void *)key);
     76     if (it != map.end()) {
     77         fprintf(stderr, "destroy instance dispatch_table: map: %p, key: %p, table: %p\n", &map, key, it->second);
     78     } else {
     79         fprintf(stderr, "destroy instance dispatch table: map: %p, key: %p, table: UNKNOWN\n", &map, key);
     80         assert(it != map.end());
     81     }
     82 #endif
     83     map.erase(key);
     84 }
     85 
     86 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); }
     87 
     88 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); }
     89 
     90 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) {
     91     dispatch_key key = get_dispatch_key(object);
     92     device_table_map::const_iterator it = map.find((void *)key);
     93 #if DISPATCH_MAP_DEBUG
     94     if (it != map.end()) {
     95         fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key,
     96                 it->second);
     97     } else {
     98         fprintf(stderr, "device_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
     99     }
    100 #endif
    101     assert(it != map.end() && "Not able to find device dispatch entry");
    102     return it->second;
    103 }
    104 
    105 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) {
    106     //    VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) object;
    107     dispatch_key key = get_dispatch_key(object);
    108     instance_table_map::const_iterator it = map.find((void *)key);
    109 #if DISPATCH_MAP_DEBUG
    110     if (it != map.end()) {
    111         fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: %p\n", &tableInstanceMap, object, key,
    112                 it->second);
    113     } else {
    114         fprintf(stderr, "instance_dispatch_table: map: %p, object: %p, key: %p, table: UNKNOWN\n", &tableInstanceMap, object, key);
    115     }
    116 #endif
    117     assert(it != map.end() && "Not able to find instance dispatch entry");
    118     return it->second;
    119 }
    120 
    121 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
    122     VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
    123     while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
    124         chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
    125     }
    126     assert(chain_info != NULL);
    127     return chain_info;
    128 }
    129 
    130 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
    131     VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
    132     while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
    133         chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
    134     }
    135     assert(chain_info != NULL);
    136     return chain_info;
    137 }
    138 
    139 /* Various dispatchable objects will use the same underlying dispatch table if they
    140  * are created from that "parent" object. Thus use pointer to dispatch table
    141  * as the key to these table maps.
    142  *    Instance -> PhysicalDevice
    143  *    Device -> CommandBuffer or Queue
    144  * If use the object themselves as key to map then implies Create entrypoints have to be intercepted
    145  * and a new key inserted into map */
    146 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) {
    147     VkLayerInstanceDispatchTable *pTable;
    148     dispatch_key key = get_dispatch_key(instance);
    149     instance_table_map::const_iterator it = map.find((void *)key);
    150 
    151     if (it == map.end()) {
    152         pTable = new VkLayerInstanceDispatchTable;
    153         map[(void *)key] = pTable;
    154 #if DISPATCH_MAP_DEBUG
    155         fprintf(stderr, "New, Instance: map: %p, key: %p, table: %p\n", &map, key, pTable);
    156 #endif
    157     } else {
    158 #if DISPATCH_MAP_DEBUG
    159         fprintf(stderr, "Instance: map: %p, key: %p, table: %p\n", &map, key, it->second);
    160 #endif
    161         return it->second;
    162     }
    163 
    164     layer_init_instance_dispatch_table(instance, pTable, gpa);
    165 
    166     return pTable;
    167 }
    168 
    169 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) {
    170     return initInstanceTable(instance, gpa, tableInstanceMap);
    171 }
    172 
    173 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) {
    174     VkLayerDispatchTable *pTable;
    175     dispatch_key key = get_dispatch_key(device);
    176     device_table_map::const_iterator it = map.find((void *)key);
    177 
    178     if (it == map.end()) {
    179         pTable = new VkLayerDispatchTable;
    180         map[(void *)key] = pTable;
    181 #if DISPATCH_MAP_DEBUG
    182         fprintf(stderr, "New, Device: map: %p, key: %p, table: %p\n", &map, key, pTable);
    183 #endif
    184     } else {
    185 #if DISPATCH_MAP_DEBUG
    186         fprintf(stderr, "Device: map: %p, key: %p, table: %p\n", &map, key, it->second);
    187 #endif
    188         return it->second;
    189     }
    190 
    191     layer_init_device_dispatch_table(device, pTable, gpa);
    192 
    193     return pTable;
    194 }
    195 
    196 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) {
    197     return initDeviceTable(device, gpa, tableMap);
    198 }
    199