111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Copyright (c) 2015-2016 The Khronos Group Inc.
211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 Valve Corporation
311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 LunarG, Inc.
411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Copyright (c) 2015-2016 Google, Inc.
511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Licensed under the Apache License, Version 2.0 (the "License");
711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * you may not use this file except in compliance with the License.
811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * You may obtain a copy of the License at
911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *     http://www.apache.org/licenses/LICENSE-2.0
1111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Unless required by applicable law or agreed to in writing, software
1311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * distributed under the License is distributed on an "AS IS" BASIS,
1411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * See the License for the specific language governing permissions and
1611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * limitations under the License.
1711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *
1811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * Author: Tobin Ehlis <tobin@lunarg.com>
1911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert */
2011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <assert.h>
2111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include <unordered_map>
2211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_dispatch_table_helper.h"
2311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vulkan/vk_layer.h"
2411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#include "vk_layer_table.h"
2511cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic device_table_map tableMap;
2611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertstatic instance_table_map tableInstanceMap;
2711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
2811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#define DISPATCH_MAP_DEBUG 0
2911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert// Map lookup must be thread safe
3111cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerDispatchTable *device_dispatch_table(void *object) {
3211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(object);
3311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    device_table_map::const_iterator it = tableMap.find((void *)key);
3411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(it != tableMap.end() && "Not able to find device dispatch entry");
3511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return it->second;
3611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
3711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
3811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerInstanceDispatchTable *instance_dispatch_table(void *object) {
3911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(object);
4011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    instance_table_map::const_iterator it = tableInstanceMap.find((void *)key);
4111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
4211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it != tableInstanceMap.end()) {
4311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "instance_dispatch_table: map:  0x%p, object:  0x%p, key:  0x%p, table:  0x%p\n", &tableInstanceMap, object, key,
4411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                it->second);
4511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
4611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "instance_dispatch_table: map:  0x%p, object:  0x%p, key:  0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key);
4711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
4811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
4911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(it != tableInstanceMap.end() && "Not able to find instance dispatch entry");
5011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return it->second;
5111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
5211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
5311cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid destroy_dispatch_table(device_table_map &map, dispatch_key key) {
5411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
5511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    device_table_map::const_iterator it = map.find((void *)key);
5611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it != map.end()) {
5711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "destroy device dispatch_table: map:  0x%p, key:  0x%p, table:  0x%p\n", &map, key, it->second);
5811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
5911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "destroy device dispatch table: map:  0x%p, key:  0x%p, table: UNKNOWN\n", &map, key);
6011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        assert(it != map.end());
6111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
6211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
6311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    map.erase(key);
6411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
6511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
6611cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid destroy_dispatch_table(instance_table_map &map, dispatch_key key) {
6711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
6811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    instance_table_map::const_iterator it = map.find((void *)key);
6911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it != map.end()) {
7011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "destroy instance dispatch_table: map:  0x%p, key:  0x%p, table:  0x%p\n", &map, key, it->second);
7111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
7211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "destroy instance dispatch table: map:  0x%p, key:  0x%p, table: UNKNOWN\n", &map, key);
7311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        assert(it != map.end());
7411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
7511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
7611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    map.erase(key);
7711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
7811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
7911cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid destroy_device_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableMap, key); }
8011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8111cd02dfb91661c65134cac258cf5924270e9d2Dan Albertvoid destroy_instance_dispatch_table(dispatch_key key) { destroy_dispatch_table(tableInstanceMap, key); }
8211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
8311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerDispatchTable *get_dispatch_table(device_table_map &map, void *object) {
8411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(object);
8511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    device_table_map::const_iterator it = map.find((void *)key);
8611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
8711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it != map.end()) {
8811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "device_dispatch_table: map:  0x%p, object:  0x%p, key:  0x%p, table:  0x%p\n", &tableInstanceMap, object, key,
8911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                it->second);
9011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
9111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "device_dispatch_table: map:  0x%p, object:  0x%p, key:  0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key);
9211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
9311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
9411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(it != map.end() && "Not able to find device dispatch entry");
9511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return it->second;
9611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
9711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
9811cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerInstanceDispatchTable *get_dispatch_table(instance_table_map &map, void *object) {
9911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    //    VkLayerInstanceDispatchTable *pDisp = *(VkLayerInstanceDispatchTable **) object;
10011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(object);
10111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    instance_table_map::const_iterator it = map.find((void *)key);
10211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
10311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it != map.end()) {
10411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "instance_dispatch_table: map:  0x%p, object:  0x%p, key:  0x%p, table:  0x%p\n", &tableInstanceMap, object, key,
10511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert                it->second);
10611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
10711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "instance_dispatch_table: map:  0x%p, object:  0x%p, key:  0x%p, table: UNKNOWN\n", &tableInstanceMap, object, key);
10811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
10911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
11011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(it != map.end() && "Not able to find instance dispatch entry");
11111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return it->second;
11211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
11311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
11411cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerInstanceCreateInfo *get_chain_info(const VkInstanceCreateInfo *pCreateInfo, VkLayerFunction func) {
11511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceCreateInfo *chain_info = (VkLayerInstanceCreateInfo *)pCreateInfo->pNext;
11611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_INSTANCE_CREATE_INFO && chain_info->function == func)) {
11711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        chain_info = (VkLayerInstanceCreateInfo *)chain_info->pNext;
11811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
11911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(chain_info != NULL);
12011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return chain_info;
12111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
12211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
12311cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerDeviceCreateInfo *get_chain_info(const VkDeviceCreateInfo *pCreateInfo, VkLayerFunction func) {
12411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDeviceCreateInfo *chain_info = (VkLayerDeviceCreateInfo *)pCreateInfo->pNext;
12511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    while (chain_info && !(chain_info->sType == VK_STRUCTURE_TYPE_LOADER_DEVICE_CREATE_INFO && chain_info->function == func)) {
12611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        chain_info = (VkLayerDeviceCreateInfo *)chain_info->pNext;
12711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
12811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    assert(chain_info != NULL);
12911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return chain_info;
13011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
13111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
13211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert/* Various dispatchable objects will use the same underlying dispatch table if they
13311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * are created from that "parent" object. Thus use pointer to dispatch table
13411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * as the key to these table maps.
13511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    Instance -> PhysicalDevice
13611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert *    Device -> CommandBuffer or Queue
13711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * If use the object themselves as key to map then implies Create entrypoints have to be intercepted
13811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert * and a new key inserted into map */
13911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa, instance_table_map &map) {
14011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerInstanceDispatchTable *pTable;
14111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(instance);
14211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    instance_table_map::const_iterator it = map.find((void *)key);
14311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
14411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it == map.end()) {
14511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pTable = new VkLayerInstanceDispatchTable;
14611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        map[(void *)key] = pTable;
14711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
14811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "New, Instance: map:  0x%p, key:  0x%p, table:  0x%p\n", &map, key, pTable);
14911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
15011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
15111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
15211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "Instance: map:  0x%p, key:  0x%p, table:  0x%p\n", &map, key, it->second);
15311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
15411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return it->second;
15511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
15611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_init_instance_dispatch_table(instance, pTable, gpa);
15811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
15911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return pTable;
16011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
16111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16211cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerInstanceDispatchTable *initInstanceTable(VkInstance instance, const PFN_vkGetInstanceProcAddr gpa) {
16311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return initInstanceTable(instance, gpa, tableInstanceMap);
16411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
16511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
16611cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa, device_table_map &map) {
16711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    VkLayerDispatchTable *pTable;
16811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    dispatch_key key = get_dispatch_key(device);
16911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    device_table_map::const_iterator it = map.find((void *)key);
17011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
17111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    if (it == map.end()) {
17211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        pTable = new VkLayerDispatchTable;
17311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        map[(void *)key] = pTable;
17411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
17511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "New, Device: map:  0x%p, key:  0x%p, table:  0x%p\n", &map, key, pTable);
17611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
17711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    } else {
17811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#if DISPATCH_MAP_DEBUG
17911cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        fprintf(stderr, "Device: map:  0x%p, key:  0x%p, table:  0x%p\n", &map, key, it->second);
18011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert#endif
18111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert        return it->second;
18211cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    }
18311cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18411cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    layer_init_device_dispatch_table(device, pTable, gpa);
18511cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18611cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return pTable;
18711cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
18811cd02dfb91661c65134cac258cf5924270e9d2Dan Albert
18911cd02dfb91661c65134cac258cf5924270e9d2Dan AlbertVkLayerDispatchTable *initDeviceTable(VkDevice device, const PFN_vkGetDeviceProcAddr gpa) {
19011cd02dfb91661c65134cac258cf5924270e9d2Dan Albert    return initDeviceTable(device, gpa, tableMap);
19111cd02dfb91661c65134cac258cf5924270e9d2Dan Albert}
192