1af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter/*
2af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Copyright (c) 2015-2016 Valve Corporation
3af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Copyright (c) 2015-2016 LunarG, Inc.
4af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter *
5af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Licensed under the Apache License, Version 2.0 (the "License");
6af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * you may not use this file except in compliance with the License.
7af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * You may obtain a copy of the License at
8af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter *
9af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter *     http://www.apache.org/licenses/LICENSE-2.0
10af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter *
11af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Unless required by applicable law or agreed to in writing, software
12af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * distributed under the License is distributed on an "AS IS" BASIS,
13af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * See the License for the specific language governing permissions and
15af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * limitations under the License.
16af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter *
17af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter * Author: Jeremy Hayes <jeremy@lunarg.com>
18af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter */
19af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
20af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include <cassert>
21af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include <iostream>
22af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include <unordered_map>
23af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
24af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include "vk_dispatch_table_helper.h"
25af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include "vk_layer_data.h"
26af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter#include "vk_layer_extension_utils.h"
27af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
28af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchternamespace test
29af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
30af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
31af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchterstruct layer_data {
32af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    VkInstance instance;
33af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    VkLayerInstanceDispatchTable *instance_dispatch_table;
34af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
35af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    layer_data() : instance(VK_NULL_HANDLE), instance_dispatch_table(nullptr) {};
36af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter};
37af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
38af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchterstatic std::unordered_map<void *, layer_data *> layer_data_map;
39af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
40af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVKAPI_ATTR VkResult VKAPI_CALL CreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator,
41af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter		VkInstance* pInstance)
42af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
43af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
44af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    assert(chain_info != nullptr);
45af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
46af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    assert(chain_info->u.pLayerInfo != nullptr);
47af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
48af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    assert(fpGetInstanceProcAddr != nullptr);
49af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
50af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
51af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    if (fpCreateInstance == nullptr)
52af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    {
53af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        return VK_ERROR_INITIALIZATION_FAILED;
54af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    }
55af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
56af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
57af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
58af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    if (result != VK_SUCCESS)
59af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    {
60af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        return result;
61af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    }
62af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
63af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    layer_data *instance_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
64af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    instance_data->instance = *pInstance;
65af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    instance_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
66af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    layer_init_instance_dispatch_table(*pInstance, instance_data->instance_dispatch_table, fpGetInstanceProcAddr);
67af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
68af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    // Marker for testing.
69af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    std::cout << "VK_LAYER_LUNARG_test: CreateInstance" << '\n';
70af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
71af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    return result;
72af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
73af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
74af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVKAPI_ATTR void VKAPI_CALL DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator)
75af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
76af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    dispatch_key key = get_dispatch_key(instance);
77af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    layer_data *instance_data = get_my_data_ptr(key, layer_data_map);
78af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    instance_data->instance_dispatch_table->DestroyInstance(instance, pAllocator);
79af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
80af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    delete instance_data->instance_dispatch_table;
81af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    layer_data_map.erase(key);
82af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
83af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    // Marker for testing.
84af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    std::cout << "VK_LAYER_LUNARG_test: DestroyInstance" << '\n';
85af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
86af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
87af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL GetInstanceProcAddr(VkInstance instance, const char* funcName)
88af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
89af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    // Return the functions that are intercepted by this layer.
90af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    static const struct
91af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    {
92af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        const char *name;
93af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        PFN_vkVoidFunction proc;
94af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    } core_instance_commands[] =
95af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    {
96af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
97af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
98af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) }
99af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    };
100af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
101af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++)
102af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    {
103af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        if (!strcmp(core_instance_commands[i].name, funcName))
104af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        {
105af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter            return core_instance_commands[i].proc;
106af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        }
107af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    }
108af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
109af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    // Only call down the chain for Vulkan commands that this layer does not intercept.
110af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    layer_data *instance_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
111af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    VkLayerInstanceDispatchTable *pTable = instance_data->instance_dispatch_table;
112af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    if (pTable->GetInstanceProcAddr == nullptr)
113af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    {
114af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter        return nullptr;
115af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    }
116af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
117af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    return pTable->GetInstanceProcAddr(instance, funcName);
118af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
119af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
120af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
121af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
122af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
123af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
124af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    return test::GetInstanceProcAddr(instance, funcName);
125af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
126af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
127af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char *funcName)
128af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
129af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    return nullptr;
130af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
131af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
132af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties)
133af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
134af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    return VK_ERROR_LAYER_NOT_PRESENT;
135af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
136af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter
137af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney GoeltzenleuchterVK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties)
138af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter{
139af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter    return VK_ERROR_LAYER_NOT_PRESENT;
140af4d398afbd91e28926089c5b8b4423d7a740ad5Courtney Goeltzenleuchter}
141