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