Home | History | Annotate | Download | only in layers
      1 /* Copyright (c) 2015-2016 The Khronos Group Inc.
      2  * Copyright (c) 2015-2016 Valve Corporation
      3  * Copyright (c) 2015-2016 LunarG, Inc.
      4  * Copyright (c) 2015-2016 Google, Inc.
      5  *
      6  * Licensed under the Apache License, Version 2.0 (the "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  *
     18  * Author: Tobin Ehlis <tobin (at) lunarg.com>
     19  */
     20 #include <assert.h>
     21 #include <unordered_map>
     22 #include "vk_dispatch_table_helper.h"
     23 #include "vulkan/vk_layer.h"
     24 #include "vk_layer_table.h"
     25 static device_table_map tableMap;
     26 static instance_table_map tableInstanceMap;
     27 
     28 // Map lookup must be thread safe
     29 VkLayerDispatchTable *device_dispatch_table(void *object) {
     30     dispatch_key key = get_dispatch_key(object);
     31     device_table_map::const_iterator it = tableMap.find((void *)key);
     32     assert(it != tableMap.end() && "Not able to find device dispatch entry");
     33     return it->second;
     34 }
     35 
     36 VkLayerInstanceDispatchTable *instance_dispatch_table(void *object) {
     37     dispatch_key key = get_dispatch_key(object);
     38     instance_table_map::const_iterator it = tableInstanceMap.find((void *)key);
     39     assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry");
     40     return it->second;
     41 }
     42 
     43 void destroy_dispatch_table(device_table_map &map, dispatch_key key) {
     44     device_table_map::const_iterator it = map.find((void *)key);
     45     if (it != map.end()) {
     46         delete it->second;
     47         map.erase(it);
     48     }
     49 }
     50 
     51 void destroy_dispatch_table(instance_table_map &map, dispatch_key key) {
     52     instance_table_map::const_iterator it = map.find((void *)key);
     53     if (it != map.end()) {
     54         delete it->second;
     55         map.erase(it);
     56     }
     57 }
     58 
     59 void destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); }
     60 
     61 void destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); }
     62 
     63 VkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) {
     64     dispatch_key key = get_dispatch_key(object);
     65     device_table_map::const_iterator it = map.find((void *)key);
     66     assert(it != map.end() && "Not able to find device dispatch entry");
     67     return it->second;
     68 }
     69 
     70 VkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) {
     71     dispatch_key key = get_dispatch_key(object);
     72     instance_table_map::const_iterator it = map.find((void *)key);
     73     assert(it != map.end() && "Not able to find instance dispatch entry");
     74     return it->second;
     75 }
     76 
     77 VkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
     78     VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
     79     while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
     80         chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
     81     }
     82     assert(chain_info != NULL);
     83     return chain_info;
     84 }
     85 
     86 VkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
     87     VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
     88     while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
     89         chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
     90     }
     91     assert(chain_info != NULL);
     92     return chain_info;
     93 }
     94 
     95 /* Various dispatchable objects will use the same underlying dispatch table if they
     96  * are created from that "parent" object. Thus use pointer to dispatch table
     97  * as the key to these table maps.
     98  *    Instance -> PhysicalDevice
     99  *    Device -> CommandBuffer or Queue
    100  * If use the object themselves as key to map then implies Create entrypoints have to be intercepted
    101  * and a new key inserted into map */
    102 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) {
    103     VkLayerInstanceDispatchTable *pTable;
    104     dispatch_key key = get_dispatch_key(instance);
    105     instance_table_map::const_iterator it = map.find((void *)key);
    106 
    107     if (it == map.end()) {
    108         pTable = new VkLayerInstanceDispatchTable;
    109         map[(void *)key] = pTable;
    110     } else {
    111         return it->second;
    112     }
    113 
    114     layer_init_instance_dispatch_table(instance, pTable, gpa);
    115 
    116     // Setup func pointers that are required but not externally exposed.  These won't be added to the instance dispatch table by
    117     // default.
    118     pTable->GetPhysicalDeviceProcAddr = (PFN_GetPhysicalDeviceProcAddr)gpa(instance, "vk_layerGetPhysicalDeviceProcAddr");
    119 
    120     return pTable;
    121 }
    122 
    123 VkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) {
    124     return initInstanceTable(instance, gpa, tableInstanceMap);
    125 }
    126 
    127 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) {
    128     VkLayerDispatchTable *pTable;
    129     dispatch_key key = get_dispatch_key(device);
    130     device_table_map::const_iterator it = map.find((void *)key);
    131 
    132     if (it == map.end()) {
    133         pTable = new VkLayerDispatchTable;
    134         map[(void *)key] = pTable;
    135     } else {
    136         return it->second;
    137     }
    138 
    139     layer_init_device_dispatch_table(device, pTable, gpa);
    140 
    141     return pTable;
    142 }
    143 
    144 VkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) {
    145     return initDeviceTable(device, gpa, tableMap);
    146 }
    147