blob: 374911b4446f6012afa56be6688b7a8eff102175 [file] [log] [blame]
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07001/* 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.
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -06005 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -06006 * 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
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -06009 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060010 * http://www.apache.org/licenses/LICENSE-2.0
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060011 *
Jon Ashburn3ebf1252016-04-19 11:30:31 -060012 * 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.
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060017 *
18 * Author: Mark Lobodzinski <mark@lunarg.com>
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070019 * Author: Mike Stroyan <mike@LunarG.com>
20 * Author: Tobin Ehlis <tobin@lunarg.com>
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060021 */
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unordered_map>
27#include <memory>
28
29#include "vk_loader_platform.h"
30#include "vk_dispatch_table_helper.h"
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060031#if defined(__GNUC__)
32#pragma GCC diagnostic ignored "-Wwrite-strings"
33#endif
34#if defined(__GNUC__)
35#pragma GCC diagnostic warning "-Wwrite-strings"
36#endif
37#include "vk_struct_size_helper.h"
38#include "device_limits.h"
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -070039#include "vulkan/vk_layer.h"
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060040#include "vk_layer_config.h"
Michael Lentine5d8ad0a2016-01-28 15:03:46 -060041#include "vk_enum_validate_helper.h"
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060042#include "vk_layer_table.h"
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060043#include "vk_layer_data.h"
44#include "vk_layer_logging.h"
45#include "vk_layer_extension_utils.h"
Mark Lobodzinski6f2274e2015-09-22 09:33:21 -060046#include "vk_layer_utils.h"
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060047
Chia-I Wu080cb7a2016-04-28 11:27:46 +080048namespace device_limits {
49
Tobin Ehlis9da65002015-09-24 15:25:16 -060050// This struct will be stored in a map hashed by the dispatchable object
Cody Northrop55443ef2015-09-28 15:09:32 -060051struct layer_data {
Chia-I Wu50c4ad92016-04-28 16:04:15 +080052 VkInstance instance;
53
Jon Ashburn5484e0c2016-03-08 17:48:44 -070054 debug_report_data *report_data;
55 std::vector<VkDebugReportCallbackEXT> logging_callback;
56 VkLayerDispatchTable *device_dispatch_table;
57 VkLayerInstanceDispatchTable *instance_dispatch_table;
Tobin Ehlis9da65002015-09-24 15:25:16 -060058 // Track state of each instance
Jon Ashburn5484e0c2016-03-08 17:48:44 -070059 unique_ptr<INSTANCE_STATE> instanceState;
60 unique_ptr<PHYSICAL_DEVICE_STATE> physicalDeviceState;
61 VkPhysicalDeviceFeatures actualPhysicalDeviceFeatures;
62 VkPhysicalDeviceFeatures requestedPhysicalDeviceFeatures;
Mark Lobodzinski941aea92016-01-13 10:23:15 -070063
Tobin Ehlis1cb7f572015-10-06 09:09:24 -060064 // Track physical device per logical device
65 VkPhysicalDevice physicalDevice;
Dustin Gravesa97c3942016-03-31 18:01:37 -060066 VkPhysicalDeviceProperties physicalDeviceProperties;
Tobin Ehlis9da65002015-09-24 15:25:16 -060067 // Vector indices correspond to queueFamilyIndex
68 vector<unique_ptr<VkQueueFamilyProperties>> queueFamilyProperties;
Cody Northrop55443ef2015-09-28 15:09:32 -060069
Jon Ashburn5484e0c2016-03-08 17:48:44 -070070 layer_data()
71 : report_data(nullptr), device_dispatch_table(nullptr), instance_dispatch_table(nullptr), instanceState(nullptr),
72 physicalDeviceState(nullptr), actualPhysicalDeviceFeatures(), requestedPhysicalDeviceFeatures(), physicalDevice(){};
Cody Northrop55443ef2015-09-28 15:09:32 -060073};
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060074
Tobin Ehlis1cb7f572015-10-06 09:09:24 -060075static unordered_map<void *, layer_data *> layer_data_map;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060076
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070077// TODO : This can be much smarter, using separate locks for separate global data
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060078static int globalLockInitialized = 0;
79static loader_platform_thread_mutex globalLock;
80
Jon Ashburn5484e0c2016-03-08 17:48:44 -070081static void init_device_limits(layer_data *my_data, const VkAllocationCallbacks *pAllocator) {
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060082
Mark Lobodzinski1079e1b2016-03-15 14:21:59 -060083 layer_debug_actions(my_data->report_data, my_data->logging_callback, pAllocator, "lunarg_device_limits");
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060084
Jon Ashburn5484e0c2016-03-08 17:48:44 -070085 if (!globalLockInitialized) {
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -060086 // TODO/TBD: Need to delete this mutex sometime. How??? One
87 // suggestion is to call this during vkCreateInstance(), and then we
88 // can clean it up during vkDestroyInstance(). However, that requires
89 // that the layer have per-instance locks. We need to come back and
90 // address this soon.
91 loader_platform_thread_create_mutex(&globalLock);
92 globalLockInitialized = 1;
93 }
94}
Courtney Goeltzenleuchter20c35012015-11-30 12:14:06 -070095
Jon Ashburn5484e0c2016-03-08 17:48:44 -070096static const VkExtensionProperties instance_extensions[] = {{VK_EXT_DEBUG_REPORT_EXTENSION_NAME, VK_EXT_DEBUG_REPORT_SPEC_VERSION}};
Courtney Goeltzenleuchter20c35012015-11-30 12:14:06 -070097
Chia-I Wucc0aa7a2016-04-28 14:12:27 +080098static const VkLayerProperties global_layer = {
Jon Ashburndc9111c2016-03-22 12:57:13 -060099 "VK_LAYER_LUNARG_device_limits", VK_LAYER_API_VERSION, 1, "LunarG Validation Layer",
Chia-I Wucc0aa7a2016-04-28 14:12:27 +0800100};
Tobin Ehlisfd3843f2015-09-29 12:26:00 -0600101
Chia-I Wu99860202016-04-28 14:01:30 +0800102VKAPI_ATTR VkResult VKAPI_CALL
103CreateInstance(const VkInstanceCreateInfo *pCreateInfo, const VkAllocationCallbacks *pAllocator, VkInstance *pInstance) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700104 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600105
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700106 assert(chain_info->u.pLayerInfo);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700107 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700108 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance)fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700109 if (fpCreateInstance == NULL) {
110 return VK_ERROR_INITIALIZATION_FAILED;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600111 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700112
113 // Advance the link info for the next element on the chain
114 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
115
116 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
117 if (result != VK_SUCCESS)
118 return result;
119
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700120 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Chia-I Wu50c4ad92016-04-28 16:04:15 +0800121 my_data->instance = *pInstance;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700122 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700123 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700124
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700125 my_data->report_data = debug_report_create_instance(my_data->instance_dispatch_table, *pInstance,
126 pCreateInfo->enabledExtensionCount, pCreateInfo->ppEnabledExtensionNames);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700127
128 init_device_limits(my_data, pAllocator);
129 my_data->instanceState = unique_ptr<INSTANCE_STATE>(new INSTANCE_STATE());
130
131 return VK_SUCCESS;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600132}
133
134/* hook DestroyInstance to remove tableInstanceMap entry */
Chia-I Wu99860202016-04-28 14:01:30 +0800135VKAPI_ATTR void VKAPI_CALL
136DestroyInstance(VkInstance instance, const VkAllocationCallbacks *pAllocator) {
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600137 dispatch_key key = get_dispatch_key(instance);
Tobin Ehlis1cb7f572015-10-06 09:09:24 -0600138 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
139 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800140 pTable->DestroyInstance(instance, pAllocator);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600141
142 // Clean up logging callback, if any
Courtney Goeltzenleuchterd6fce632015-10-05 14:51:41 -0600143 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700144 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700145 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchterd6fce632015-10-05 14:51:41 -0600146 my_data->logging_callback.pop_back();
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600147 }
148
149 layer_debug_report_destroy_instance(my_data->report_data);
Tobin Ehlis1cb7f572015-10-06 09:09:24 -0600150 delete my_data->instance_dispatch_table;
151 layer_data_map.erase(key);
Tobin Ehlis0b632332015-10-07 09:38:40 -0600152 if (layer_data_map.empty()) {
153 // Release mutex when destroying last instance.
154 loader_platform_thread_delete_mutex(&globalLock);
155 globalLockInitialized = 0;
156 }
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600157}
158
Chia-I Wu99860202016-04-28 14:01:30 +0800159VKAPI_ATTR VkResult VKAPI_CALL
160EnumeratePhysicalDevices(VkInstance instance, uint32_t *pPhysicalDeviceCount, VkPhysicalDevice *pPhysicalDevices) {
Dustin Graves080069b2016-04-05 13:48:15 -0600161 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700162 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600163 if (my_data->instanceState) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700164 // For this instance, flag when vkEnumeratePhysicalDevices goes to QUERY_COUNT and then QUERY_DETAILS
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600165 if (NULL == pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700166 my_data->instanceState->vkEnumeratePhysicalDevicesState = QUERY_COUNT;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600167 } else {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700168 if (UNCALLED == my_data->instanceState->vkEnumeratePhysicalDevicesState) {
169 // Flag error here, shouldn't be calling this without having queried count
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700170 skipCall |=
171 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0,
172 __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
173 "Invalid call sequence to vkEnumeratePhysicalDevices() w/ non-NULL pPhysicalDevices. You should first "
174 "call vkEnumeratePhysicalDevices() w/ NULL pPhysicalDevices to query pPhysicalDeviceCount.");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700175 } // TODO : Could also flag a warning if re-calling this function in QUERY_DETAILS state
176 else if (my_data->instanceState->physicalDevicesCount != *pPhysicalDeviceCount) {
177 // TODO: Having actual count match count from app is not a requirement, so this can be a warning
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700178 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
179 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
180 "Call to vkEnumeratePhysicalDevices() w/ pPhysicalDeviceCount value %u, but actual count "
181 "supported by this instance is %u.",
182 *pPhysicalDeviceCount, my_data->instanceState->physicalDevicesCount);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600183 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700184 my_data->instanceState->vkEnumeratePhysicalDevicesState = QUERY_DETAILS;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600185 }
Tobin Ehlis9da65002015-09-24 15:25:16 -0600186 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700187 return VK_ERROR_VALIDATION_FAILED_EXT;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700188 VkResult result =
189 my_data->instance_dispatch_table->EnumeratePhysicalDevices(instance, pPhysicalDeviceCount, pPhysicalDevices);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600190 if (NULL == pPhysicalDevices) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700191 my_data->instanceState->physicalDevicesCount = *pPhysicalDeviceCount;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600192 } else { // Save physical devices
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700193 for (uint32_t i = 0; i < *pPhysicalDeviceCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700194 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(pPhysicalDevices[i]), layer_data_map);
195 phy_dev_data->physicalDeviceState = unique_ptr<PHYSICAL_DEVICE_STATE>(new PHYSICAL_DEVICE_STATE());
Tobin Ehlis9da65002015-09-24 15:25:16 -0600196 // Init actual features for each physical device
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700197 my_data->instance_dispatch_table->GetPhysicalDeviceFeatures(pPhysicalDevices[i],
198 &(phy_dev_data->actualPhysicalDeviceFeatures));
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600199 }
200 }
201 return result;
202 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700203 log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_INSTANCE_EXT, 0, __LINE__,
Mark Muelleraab36502016-05-03 13:17:29 -0600204 DEVLIMITS_INVALID_INSTANCE, "DL", "Invalid instance (0x%" PRIxLEAST64 ") passed into vkEnumeratePhysicalDevices().",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700205 (uint64_t)instance);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600206 }
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700207 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600208}
209
Chia-I Wu99860202016-04-28 14:01:30 +0800210VKAPI_ATTR void VKAPI_CALL
211GetPhysicalDeviceFeatures(VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700212 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
213 phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceFeaturesState = QUERY_DETAILS;
214 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFeatures(physicalDevice, pFeatures);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600215}
216
Chia-I Wu99860202016-04-28 14:01:30 +0800217VKAPI_ATTR void VKAPI_CALL
218GetPhysicalDeviceFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700219 get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
220 ->instance_dispatch_table->GetPhysicalDeviceFormatProperties(physicalDevice, format, pFormatProperties);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600221}
222
Chia-I Wu99860202016-04-28 14:01:30 +0800223VKAPI_ATTR VkResult VKAPI_CALL
224GetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type, VkImageTiling tiling,
225 VkImageUsageFlags usage, VkImageCreateFlags flags,
226 VkImageFormatProperties *pImageFormatProperties) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700227 return get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
228 ->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(physicalDevice, format, type, tiling, usage, flags,
229 pImageFormatProperties);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600230}
231
Chia-I Wu99860202016-04-28 14:01:30 +0800232VKAPI_ATTR void VKAPI_CALL
233GetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties *pProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700234 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
235 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600236}
237
Chia-I Wu99860202016-04-28 14:01:30 +0800238VKAPI_ATTR void VKAPI_CALL
239GetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount,
240 VkQueueFamilyProperties *pQueueFamilyProperties) {
Dustin Graves080069b2016-04-05 13:48:15 -0600241 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700242 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600243 if (phy_dev_data->physicalDeviceState) {
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600244 if (NULL == pQueueFamilyProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700245 phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_COUNT;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600246 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700247 // Verify that for each physical device, this function is called first with NULL pQueueFamilyProperties ptr in order to
248 // get count
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700249 if (UNCALLED == phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700250 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
251 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
252 "Invalid call sequence to vkGetPhysicalDeviceQueueFamilyProperties() w/ non-NULL "
253 "pQueueFamilyProperties. You should first call vkGetPhysicalDeviceQueueFamilyProperties() w/ "
254 "NULL pQueueFamilyProperties to query pCount.");
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600255 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700256 // Then verify that pCount that is passed in on second call matches what was returned
257 if (phy_dev_data->physicalDeviceState->queueFamilyPropertiesCount != *pCount) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700258
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700259 // TODO: this is not a requirement of the Valid Usage section for vkGetPhysicalDeviceQueueFamilyProperties, so
260 // provide as warning
261 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
262 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_COUNT_MISMATCH, "DL",
263 "Call to vkGetPhysicalDeviceQueueFamilyProperties() w/ pCount value %u, but actual count "
264 "supported by this physicalDevice is %u.",
265 *pCount, phy_dev_data->physicalDeviceState->queueFamilyPropertiesCount);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600266 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700267 phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState = QUERY_DETAILS;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600268 }
Tobin Ehlis9da65002015-09-24 15:25:16 -0600269 if (skipCall)
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600270 return;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700271 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceQueueFamilyProperties(physicalDevice, pCount,
272 pQueueFamilyProperties);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600273 if (NULL == pQueueFamilyProperties) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700274 phy_dev_data->physicalDeviceState->queueFamilyPropertiesCount = *pCount;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600275 } else { // Save queue family properties
Tobin Ehlis9da65002015-09-24 15:25:16 -0600276 phy_dev_data->queueFamilyProperties.reserve(*pCount);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700277 for (uint32_t i = 0; i < *pCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700278 phy_dev_data->queueFamilyProperties.emplace_back(new VkQueueFamilyProperties(pQueueFamilyProperties[i]));
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600279 }
280 }
Courtney Goeltzenleuchter06d89472015-10-20 16:40:38 -0600281 return;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600282 } else {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700283 log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
284 __LINE__, DEVLIMITS_INVALID_PHYSICAL_DEVICE, "DL",
Mark Muelleraab36502016-05-03 13:17:29 -0600285 "Invalid physicalDevice (0x%" PRIxLEAST64 ") passed into vkGetPhysicalDeviceQueueFamilyProperties().",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700286 (uint64_t)physicalDevice);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600287 }
288}
289
Chia-I Wu99860202016-04-28 14:01:30 +0800290VKAPI_ATTR void VKAPI_CALL
291GetPhysicalDeviceMemoryProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700292 get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
293 ->instance_dispatch_table->GetPhysicalDeviceMemoryProperties(physicalDevice, pMemoryProperties);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600294}
295
Chia-I Wu99860202016-04-28 14:01:30 +0800296VKAPI_ATTR void VKAPI_CALL
297GetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice, VkFormat format, VkImageType type,
298 VkSampleCountFlagBits samples, VkImageUsageFlags usage, VkImageTiling tiling,
299 uint32_t *pNumProperties, VkSparseImageFormatProperties *pProperties) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700300 get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map)
301 ->instance_dispatch_table->GetPhysicalDeviceSparseImageFormatProperties(physicalDevice, format, type, samples, usage,
302 tiling, pNumProperties, pProperties);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600303}
304
Chia-I Wu99860202016-04-28 14:01:30 +0800305VKAPI_ATTR void VKAPI_CALL
306CmdSetViewport(VkCommandBuffer commandBuffer, uint32_t firstViewport, uint32_t viewportCount, const VkViewport *pViewports) {
Dustin Graves080069b2016-04-05 13:48:15 -0600307 bool skipCall = false;
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -0600308 /* TODO: Verify viewportCount < maxViewports from VkPhysicalDeviceLimits */
Dustin Graves080069b2016-04-05 13:48:15 -0600309 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700310 layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
311 my_data->device_dispatch_table->CmdSetViewport(commandBuffer, firstViewport, viewportCount, pViewports);
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -0600312 }
313}
314
Chia-I Wu99860202016-04-28 14:01:30 +0800315VKAPI_ATTR void VKAPI_CALL
316CmdSetScissor(VkCommandBuffer commandBuffer, uint32_t firstScissor, uint32_t scissorCount, const VkRect2D *pScissors) {
Dustin Graves080069b2016-04-05 13:48:15 -0600317 bool skipCall = false;
Courtney Goeltzenleuchter078f8172015-09-21 11:44:06 -0600318 /* TODO: Verify scissorCount < maxViewports from VkPhysicalDeviceLimits */
319 /* TODO: viewportCount and scissorCount must match at draw time */
Dustin Graves080069b2016-04-05 13:48:15 -0600320 if (!skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700321 layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
322 my_data->device_dispatch_table->CmdSetScissor(commandBuffer, firstScissor, scissorCount, pScissors);
Courtney Goeltzenleuchter49c73082015-09-17 15:06:17 -0600323 }
324}
325
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700326// Verify that features have been queried and verify that requested features are available
Dustin Graves080069b2016-04-05 13:48:15 -0600327static bool validate_features_request(layer_data *phy_dev_data) {
328 bool skipCall = false;
Tobin Ehlis9da65002015-09-24 15:25:16 -0600329 // Verify that all of the requested features are available
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700330 // Get ptrs into actual and requested structs and if requested is 1 but actual is 0, request is invalid
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700331 VkBool32 *actual = (VkBool32 *)&(phy_dev_data->actualPhysicalDeviceFeatures);
332 VkBool32 *requested = (VkBool32 *)&(phy_dev_data->requestedPhysicalDeviceFeatures);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700333 // TODO : This is a nice, compact way to loop through struct, but a bad way to report issues
334 // Need to provide the struct member name with the issue. To do that seems like we'll
335 // have to loop through each struct member which should be done w/ codegen to keep in synch.
Tobin Ehlis9da65002015-09-24 15:25:16 -0600336 uint32_t errors = 0;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700337 uint32_t totalBools = sizeof(VkPhysicalDeviceFeatures) / sizeof(VkBool32);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600338 for (uint32_t i = 0; i < totalBools; i++) {
339 if (requested[i] > actual[i]) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700340 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
341 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED,
342 "DL", "While calling vkCreateDevice(), requesting feature #%u in VkPhysicalDeviceFeatures struct, "
343 "which is not available on this device.",
344 i);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600345 errors++;
346 }
347 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700348 if (errors && (UNCALLED == phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceFeaturesState)) {
Tobin Ehlis9da65002015-09-24 15:25:16 -0600349 // If user didn't request features, notify them that they should
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700350 // TODO: Verify this against the spec. I believe this is an invalid use of the API and should return an error
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700351 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
352 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_FEATURE_REQUESTED, "DL",
353 "You requested features that are unavailable on this device. You should first query feature "
354 "availability by calling vkGetPhysicalDeviceFeatures().");
Tobin Ehlis9da65002015-09-24 15:25:16 -0600355 }
Tobin Ehlis72b27cc2015-09-29 11:22:37 -0600356 return skipCall;
Tobin Ehlis9da65002015-09-24 15:25:16 -0600357}
358
Chia-I Wu99860202016-04-28 14:01:30 +0800359VKAPI_ATTR VkResult VKAPI_CALL
360CreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
361 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice) {
Dustin Graves080069b2016-04-05 13:48:15 -0600362 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700363 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
Tobin Ehlis54a6c182015-09-22 14:00:58 -0600364 // First check is app has actually requested queueFamilyProperties
Tobin Ehlis9da65002015-09-24 15:25:16 -0600365 if (!phy_dev_data->physicalDeviceState) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700366 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
367 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_MUST_QUERY_COUNT, "DL",
368 "Invalid call to vkCreateDevice() w/o first calling vkEnumeratePhysicalDevices().");
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700369 } else if (QUERY_DETAILS != phy_dev_data->physicalDeviceState->vkGetPhysicalDeviceQueueFamilyPropertiesState) {
370 // TODO: This is not called out as an invalid use in the spec so make more informative recommendation.
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700371 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_WARNING_BIT_EXT,
372 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
373 "DL", "Call to vkCreateDevice() w/o first calling vkGetPhysicalDeviceQueueFamilyProperties().");
Tobin Ehlis54a6c182015-09-22 14:00:58 -0600374 } else {
375 // Check that the requested queue properties are valid
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700376 for (uint32_t i = 0; i < pCreateInfo->queueCreateInfoCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700377 uint32_t requestedIndex = pCreateInfo->pQueueCreateInfos[i].queueFamilyIndex;
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700378 if (phy_dev_data->queueFamilyProperties.size() <=
379 requestedIndex) { // requested index is out of bounds for this physical device
380 skipCall |= log_msg(
381 phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0,
382 __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL",
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700383 "Invalid queue create request in vkCreateDevice(). Invalid queueFamilyIndex %u requested.", requestedIndex);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700384 } else if (pCreateInfo->pQueueCreateInfos[i].queueCount >
385 phy_dev_data->queueFamilyProperties[requestedIndex]->queueCount) {
386 skipCall |=
387 log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
388 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
389 "DL", "Invalid queue create request in vkCreateDevice(). QueueFamilyIndex %u only has %u queues, but "
390 "requested queueCount is %u.",
391 requestedIndex, phy_dev_data->queueFamilyProperties[requestedIndex]->queueCount,
392 pCreateInfo->pQueueCreateInfos[i].queueCount);
Tobin Ehlis54a6c182015-09-22 14:00:58 -0600393 }
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600394 }
395 }
Tobin Ehlis9da65002015-09-24 15:25:16 -0600396 // Check that any requested features are available
397 if (pCreateInfo->pEnabledFeatures) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700398 phy_dev_data->requestedPhysicalDeviceFeatures = *(pCreateInfo->pEnabledFeatures);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600399 skipCall |= validate_features_request(phy_dev_data);
400 }
401 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700402 return VK_ERROR_VALIDATION_FAILED_EXT;
Tobin Ehlis9da65002015-09-24 15:25:16 -0600403
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700404 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Mark Lobodzinski941aea92016-01-13 10:23:15 -0700405
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700406 assert(chain_info->u.pLayerInfo);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700407 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
408 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
Chia-I Wu50c4ad92016-04-28 16:04:15 +0800409 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice)fpGetInstanceProcAddr(phy_dev_data->instance, "vkCreateDevice");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700410 if (fpCreateDevice == NULL) {
411 return VK_ERROR_INITIALIZATION_FAILED;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600412 }
Mark Lobodzinski941aea92016-01-13 10:23:15 -0700413
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700414 // Advance the link info for the next element on the chain
415 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
416
417 VkResult result = fpCreateDevice(gpu, pCreateInfo, pAllocator, pDevice);
418 if (result != VK_SUCCESS) {
419 return result;
420 }
421
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700422 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700423 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700424 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
Dustin Gravesa97c3942016-03-31 18:01:37 -0600425 my_device_data->report_data = layer_debug_report_create_device(phy_dev_data->report_data, *pDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700426 my_device_data->physicalDevice = gpu;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700427
428 // Get physical device properties for this device
Dustin Gravesa97c3942016-03-31 18:01:37 -0600429 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(gpu, &(my_device_data->physicalDeviceProperties));
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600430 return result;
431}
432
Chia-I Wu99860202016-04-28 14:01:30 +0800433VKAPI_ATTR void VKAPI_CALL
434DestroyDevice(VkDevice device, const VkAllocationCallbacks *pAllocator) {
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600435 // Free device lifetime allocations
436 dispatch_key key = get_dispatch_key(device);
Tobin Ehlis1cb7f572015-10-06 09:09:24 -0600437 layer_data *my_device_data = get_my_data_ptr(key, layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +0800438 my_device_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Tobin Ehlis1cb7f572015-10-06 09:09:24 -0600439 delete my_device_data->device_dispatch_table;
440 layer_data_map.erase(key);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600441}
442
Chia-I Wu99860202016-04-28 14:01:30 +0800443VKAPI_ATTR VkResult VKAPI_CALL
444CreateRenderPass(VkDevice device, const VkRenderPassCreateInfo *pCreateInfo,
445 const VkAllocationCallbacks *pAllocator,
446 VkRenderPass *pRenderPass) {
Michael Lentine20e4c192016-04-06 17:40:22 -0500447 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
448 bool skip_call = false;
449 uint32_t max_color_attachments = dev_data->physicalDeviceProperties.limits.maxColorAttachments;
450 for (uint32_t i = 0; i < pCreateInfo->subpassCount; ++i) {
451 if (pCreateInfo->pSubpasses[i].colorAttachmentCount > max_color_attachments) {
452 skip_call |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_EXT,
453 reinterpret_cast<uint64_t>(device), __LINE__, DEVLIMITS_INVALID_ATTACHMENT_COUNT, "DL",
454 "Cannot create a render pass with %d color attachments. Max is %d.",
455 pCreateInfo->pSubpasses[i].colorAttachmentCount, max_color_attachments);
456 }
457 }
458 if (skip_call) {
459 return VK_ERROR_VALIDATION_FAILED_EXT;
460 }
461 return dev_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
462}
463
Chia-I Wu99860202016-04-28 14:01:30 +0800464VKAPI_ATTR VkResult VKAPI_CALL
465CreateCommandPool(VkDevice device, const VkCommandPoolCreateInfo *pCreateInfo,
466 const VkAllocationCallbacks *pAllocator,
467 VkCommandPool *pCommandPool) {
Tobin Ehlis9da65002015-09-24 15:25:16 -0600468 // TODO : Verify that requested QueueFamilyIndex for this pool exists
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700469 VkResult result = get_my_data_ptr(get_dispatch_key(device), layer_data_map)
470 ->device_dispatch_table->CreateCommandPool(device, pCreateInfo, pAllocator, pCommandPool);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600471 return result;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600472}
473
Chia-I Wu99860202016-04-28 14:01:30 +0800474VKAPI_ATTR void VKAPI_CALL
475DestroyCommandPool(VkDevice device, VkCommandPool commandPool, const VkAllocationCallbacks *pAllocator) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700476 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
477 ->device_dispatch_table->DestroyCommandPool(device, commandPool, pAllocator);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600478}
479
Chia-I Wu99860202016-04-28 14:01:30 +0800480VKAPI_ATTR VkResult VKAPI_CALL
481ResetCommandPool(VkDevice device, VkCommandPool commandPool, VkCommandPoolResetFlags flags) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700482 VkResult result = get_my_data_ptr(get_dispatch_key(device), layer_data_map)
483 ->device_dispatch_table->ResetCommandPool(device, commandPool, flags);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600484 return result;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600485}
486
Chia-I Wu99860202016-04-28 14:01:30 +0800487VKAPI_ATTR VkResult VKAPI_CALL
488AllocateCommandBuffers(VkDevice device, const VkCommandBufferAllocateInfo *pCreateInfo, VkCommandBuffer *pCommandBuffer) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700489 VkResult result = get_my_data_ptr(get_dispatch_key(device), layer_data_map)
490 ->device_dispatch_table->AllocateCommandBuffers(device, pCreateInfo, pCommandBuffer);
Tobin Ehlis9da65002015-09-24 15:25:16 -0600491 return result;
492}
Mark Lobodzinskifbb130e2015-10-06 11:59:54 -0600493
Chia-I Wu99860202016-04-28 14:01:30 +0800494VKAPI_ATTR void VKAPI_CALL
495FreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t count, const VkCommandBuffer *pCommandBuffers) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700496 get_my_data_ptr(get_dispatch_key(device), layer_data_map)
497 ->device_dispatch_table->FreeCommandBuffers(device, commandPool, count, pCommandBuffers);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600498}
499
Chia-I Wu99860202016-04-28 14:01:30 +0800500VKAPI_ATTR VkResult VKAPI_CALL
501BeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo) {
Michael Lentine09853ef2016-01-28 14:20:46 -0600502 bool skipCall = false;
503 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Tony Barboure24b8e32016-03-25 13:04:20 -0600504 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(dev_data->physicalDevice), layer_data_map);
Michael Lentine09853ef2016-01-28 14:20:46 -0600505 const VkCommandBufferInheritanceInfo *pInfo = pBeginInfo->pInheritanceInfo;
Tony Barboure24b8e32016-03-25 13:04:20 -0600506 if (phy_dev_data->actualPhysicalDeviceFeatures.inheritedQueries == VK_FALSE && pInfo && pInfo->occlusionQueryEnable != VK_FALSE) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700507 skipCall |= log_msg(
508 dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
509 reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DEVLIMITS_INVALID_INHERITED_QUERY, "DL",
510 "Cannot set inherited occlusionQueryEnable in vkBeginCommandBuffer() when device does not support inheritedQueries.");
Michael Lentine09853ef2016-01-28 14:20:46 -0600511 }
Tony Barboure24b8e32016-03-25 13:04:20 -0600512 if (phy_dev_data->actualPhysicalDeviceFeatures.inheritedQueries != VK_FALSE && pInfo && pInfo->occlusionQueryEnable != VK_FALSE &&
Michael Lentine5d8ad0a2016-01-28 15:03:46 -0600513 !validate_VkQueryControlFlagBits(VkQueryControlFlagBits(pInfo->queryFlags))) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700514 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
515 reinterpret_cast<uint64_t>(commandBuffer), __LINE__, DEVLIMITS_INVALID_INHERITED_QUERY, "DL",
516 "Cannot enable in occlusion queries in vkBeginCommandBuffer() and set queryFlags to %d which is not a "
517 "valid combination of VkQueryControlFlagBits.",
Michael Lentine5d8ad0a2016-01-28 15:03:46 -0600518 pInfo->queryFlags);
519 }
Michael Lentine0a369f62016-02-03 16:51:46 -0600520 VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine09853ef2016-01-28 14:20:46 -0600521 if (!skipCall)
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700522 result = dev_data->device_dispatch_table->BeginCommandBuffer(commandBuffer, pBeginInfo);
Michael Lentine0a369f62016-02-03 16:51:46 -0600523 return result;
Michael Lentine09853ef2016-01-28 14:20:46 -0600524}
525
Chia-I Wu99860202016-04-28 14:01:30 +0800526VKAPI_ATTR void VKAPI_CALL
527GetDeviceQueue(VkDevice device, uint32_t queueFamilyIndex, uint32_t queueIndex, VkQueue *pQueue) {
Dustin Graves080069b2016-04-05 13:48:15 -0600528 bool skipCall = false;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700529 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlis1cb7f572015-10-06 09:09:24 -0600530 VkPhysicalDevice gpu = dev_data->physicalDevice;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700531 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(gpu), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700532 if (queueFamilyIndex >=
533 phy_dev_data->queueFamilyProperties.size()) { // requested index is out of bounds for this physical device
534 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
535 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__, DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST,
536 "DL", "Invalid queueFamilyIndex %u requested in vkGetDeviceQueue().", queueFamilyIndex);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700537 } else if (queueIndex >= phy_dev_data->queueFamilyProperties[queueFamilyIndex]->queueCount) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700538 skipCall |= log_msg(
539 phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
540 DEVLIMITS_INVALID_QUEUE_CREATE_REQUEST, "DL",
541 "Invalid queue request in vkGetDeviceQueue(). QueueFamilyIndex %u only has %u queues, but requested queueIndex is %u.",
542 queueFamilyIndex, phy_dev_data->queueFamilyProperties[queueFamilyIndex]->queueCount, queueIndex);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600543 }
Dustin Graves080069b2016-04-05 13:48:15 -0600544 if (!skipCall)
545 dev_data->device_dispatch_table->GetDeviceQueue(device, queueFamilyIndex, queueIndex, pQueue);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600546}
547
Chia-I Wu99860202016-04-28 14:01:30 +0800548VKAPI_ATTR void VKAPI_CALL
549UpdateDescriptorSets(VkDevice device, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700550 uint32_t descriptorCopyCount, const VkCopyDescriptorSet *pDescriptorCopies) {
551 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Dustin Graves080069b2016-04-05 13:48:15 -0600552 bool skipCall = false;
Mark Lobodzinski941aea92016-01-13 10:23:15 -0700553
Mark Youngee3f3a22016-01-25 12:18:32 -0700554 for (uint32_t i = 0; i < descriptorWriteCount; i++) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700555 if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER) ||
556 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC)) {
Dustin Gravesa97c3942016-03-31 18:01:37 -0600557 VkDeviceSize uniformAlignment = dev_data->physicalDeviceProperties.limits.minUniformBufferOffsetAlignment;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700558 for (uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) {
559 if (vk_safe_modulo(pDescriptorWrites[i].pBufferInfo[j].offset, uniformAlignment) != 0) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700560 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
561 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
562 DEVLIMITS_INVALID_UNIFORM_BUFFER_OFFSET, "DL",
Mark Muelleraab36502016-05-03 13:17:29 -0600563 "vkUpdateDescriptorSets(): pDescriptorWrites[%d].pBufferInfo[%d].offset (0x%" PRIxLEAST64
564 ") must be a multiple of device limit minUniformBufferOffsetAlignment 0x%" PRIxLEAST64,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700565 i, j, pDescriptorWrites[i].pBufferInfo[j].offset, uniformAlignment);
Mark Lobodzinski941aea92016-01-13 10:23:15 -0700566 }
567 }
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700568 } else if ((pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER) ||
569 (pDescriptorWrites[i].descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC)) {
Dustin Gravesa97c3942016-03-31 18:01:37 -0600570 VkDeviceSize storageAlignment = dev_data->physicalDeviceProperties.limits.minStorageBufferOffsetAlignment;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700571 for (uint32_t j = 0; j < pDescriptorWrites[i].descriptorCount; j++) {
572 if (vk_safe_modulo(pDescriptorWrites[i].pBufferInfo[j].offset, storageAlignment) != 0) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700573 skipCall |= log_msg(dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT,
574 VK_DEBUG_REPORT_OBJECT_TYPE_PHYSICAL_DEVICE_EXT, 0, __LINE__,
575 DEVLIMITS_INVALID_STORAGE_BUFFER_OFFSET, "DL",
Mark Muelleraab36502016-05-03 13:17:29 -0600576 "vkUpdateDescriptorSets(): pDescriptorWrites[%d].pBufferInfo[%d].offset (0x%" PRIxLEAST64
577 ") must be a multiple of device limit minStorageBufferOffsetAlignment 0x%" PRIxLEAST64,
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700578 i, j, pDescriptorWrites[i].pBufferInfo[j].offset, storageAlignment);
Mark Lobodzinski941aea92016-01-13 10:23:15 -0700579 }
580 }
581 }
582 }
Dustin Graves080069b2016-04-05 13:48:15 -0600583 if (!skipCall) {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700584 dev_data->device_dispatch_table->UpdateDescriptorSets(device, descriptorWriteCount, pDescriptorWrites, descriptorCopyCount,
585 pDescriptorCopies);
Mark Lobodzinski941aea92016-01-13 10:23:15 -0700586 }
587}
588
Chia-I Wu99860202016-04-28 14:01:30 +0800589VKAPI_ATTR void VKAPI_CALL
590CmdUpdateBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer,
591 VkDeviceSize dstOffset, VkDeviceSize dataSize, const uint32_t *pData) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700592 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mike Stroyana3082432015-09-25 13:39:21 -0600593
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700594 // dstOffset is the byte offset into the buffer to start updating and must be a multiple of 4.
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800595 if (dstOffset & 3) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700596 layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Chris Forbes45501682016-04-07 12:00:33 +1200597 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
598 DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700599 "vkCmdUpdateBuffer parameter, VkDeviceSize dstOffset, is not a multiple of 4")) {
Mike Stroyana3082432015-09-25 13:39:21 -0600600 return;
601 }
602 }
603
604 // dataSize is the number of bytes to update, which must be a multiple of 4.
605 if (dataSize & 3) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700606 layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Chris Forbes45501682016-04-07 12:00:33 +1200607 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
608 DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700609 "vkCmdUpdateBuffer parameter, VkDeviceSize dataSize, is not a multiple of 4")) {
Mike Stroyana3082432015-09-25 13:39:21 -0600610 return;
611 }
612 }
613
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700614 dev_data->device_dispatch_table->CmdUpdateBuffer(commandBuffer, dstBuffer, dstOffset, dataSize, pData);
Mike Stroyana3082432015-09-25 13:39:21 -0600615}
616
Chia-I Wu99860202016-04-28 14:01:30 +0800617VKAPI_ATTR void VKAPI_CALL
618CmdFillBuffer(VkCommandBuffer commandBuffer, VkBuffer dstBuffer, VkDeviceSize dstOffset, VkDeviceSize size, uint32_t data) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700619 layer_data *dev_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mike Stroyana3082432015-09-25 13:39:21 -0600620
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700621 // dstOffset is the byte offset into the buffer to start filling and must be a multiple of 4.
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800622 if (dstOffset & 3) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700623 layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Chris Forbes45501682016-04-07 12:00:33 +1200624 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
625 DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700626 "vkCmdFillBuffer parameter, VkDeviceSize dstOffset, is not a multiple of 4")) {
Mike Stroyana3082432015-09-25 13:39:21 -0600627 return;
628 }
629 }
630
Chia-I Wu2bfb33c2015-10-26 17:24:52 +0800631 // size is the number of bytes to fill, which must be a multiple of 4.
632 if (size & 3) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700633 layer_data *my_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Chris Forbes45501682016-04-07 12:00:33 +1200634 if (log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VkDebugReportObjectTypeEXT(0), 0, __LINE__,
635 DEVLIMITS_INVALID_BUFFER_UPDATE_ALIGNMENT, "DL",
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700636 "vkCmdFillBuffer parameter, VkDeviceSize size, is not a multiple of 4")) {
Mike Stroyana3082432015-09-25 13:39:21 -0600637 return;
638 }
639 }
640
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700641 dev_data->device_dispatch_table->CmdFillBuffer(commandBuffer, dstBuffer, dstOffset, size, data);
Mike Stroyana3082432015-09-25 13:39:21 -0600642}
643
Chia-I Wu99860202016-04-28 14:01:30 +0800644VKAPI_ATTR VkResult VKAPI_CALL
645CreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
646 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700647 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
648 VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600649 if (VK_SUCCESS == res) {
Mark Lobodzinski97c4d512016-05-19 15:27:18 -0600650 res = layer_create_msg_callback(my_data->report_data, false, pCreateInfo, pAllocator, pMsgCallback);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600651 }
652 return res;
653}
654
Chia-I Wu99860202016-04-28 14:01:30 +0800655VKAPI_ATTR void VKAPI_CALL
656DestroyDebugReportCallbackEXT(VkInstance instance,
657 VkDebugReportCallbackEXT msgCallback,
658 const VkAllocationCallbacks *pAllocator) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700659 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
660 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700661 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600662}
663
Chia-I Wu99860202016-04-28 14:01:30 +0800664VKAPI_ATTR void VKAPI_CALL
665DebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
666 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700667 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700668 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix,
669 pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700670}
671
Chia-I Wu99860202016-04-28 14:01:30 +0800672VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wub02600c2016-05-20 07:11:22 +0800673EnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
674 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
675}
676
677VKAPI_ATTR VkResult VKAPI_CALL
678EnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
679 return util_GetLayerProperties(1, &global_layer, pCount, pProperties);
680}
681
682VKAPI_ATTR VkResult VKAPI_CALL
683EnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
684 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
685 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
686
687 return VK_ERROR_LAYER_NOT_PRESENT;
688}
689
690VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu99860202016-04-28 14:01:30 +0800691EnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
692 const char *pLayerName, uint32_t *pCount,
693 VkExtensionProperties *pProperties) {
Chia-I Wuc83c0832016-04-28 14:21:13 +0800694 if (pLayerName && !strcmp(pLayerName, global_layer.layerName))
Chia-I Wu16489ac2016-04-28 11:21:49 +0800695 return util_GetExtensionProperties(0, nullptr, pCount, pProperties);
Chia-I Wuc83c0832016-04-28 14:21:13 +0800696
697 assert(physicalDevice);
698
699 dispatch_key key = get_dispatch_key(physicalDevice);
700 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
701 return my_data->instance_dispatch_table->EnumerateDeviceExtensionProperties(physicalDevice, pLayerName, pCount, pProperties);
Chia-I Wu16489ac2016-04-28 11:21:49 +0800702}
703
Chia-I Wuafe42442016-04-28 14:38:57 +0800704static PFN_vkVoidFunction
Chia-I Wu2b8c6e62016-04-28 14:38:57 +0800705intercept_core_instance_command(const char *name);
706
707static PFN_vkVoidFunction
Chia-I Wuafe42442016-04-28 14:38:57 +0800708intercept_core_device_command(const char *name);
709
Chia-I Wu99860202016-04-28 14:01:30 +0800710VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
711GetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wuafe42442016-04-28 14:38:57 +0800712 PFN_vkVoidFunction proc = intercept_core_device_command(funcName);
713 if (proc)
714 return proc;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600715
Chia-I Wuafe42442016-04-28 14:38:57 +0800716 assert(dev);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700717
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700718 layer_data *my_data = get_my_data_ptr(get_dispatch_key(dev), layer_data_map);
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700719 VkLayerDispatchTable *pTable = my_data->device_dispatch_table;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600720 {
721 if (pTable->GetDeviceProcAddr == NULL)
722 return NULL;
723 return pTable->GetDeviceProcAddr(dev, funcName);
724 }
725}
726
Chia-I Wu99860202016-04-28 14:01:30 +0800727VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL
728GetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu2b8c6e62016-04-28 14:38:57 +0800729 PFN_vkVoidFunction proc = intercept_core_instance_command(funcName);
Chia-I Wu79d1c8d2016-04-28 15:16:59 +0800730 if (!proc)
731 intercept_core_device_command(funcName);
Chia-I Wu2b8c6e62016-04-28 14:38:57 +0800732 if (proc)
733 return proc;
734
Tobin Ehlis1cb7f572015-10-06 09:09:24 -0600735 layer_data *my_data;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600736
Chia-I Wu79d1c8d2016-04-28 15:16:59 +0800737 assert(instance);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700738 my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
739
Chia-I Wu79d1c8d2016-04-28 15:16:59 +0800740 proc = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
741 if (proc)
742 return proc;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600743
744 {
Jon Ashburn5484e0c2016-03-08 17:48:44 -0700745 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Tobin Ehlisb5fc4fb2015-09-03 09:50:06 -0600746 if (pTable->GetInstanceProcAddr == NULL)
747 return NULL;
748 return pTable->GetInstanceProcAddr(instance, funcName);
749 }
750}
Chia-I Wu16489ac2016-04-28 11:21:49 +0800751
Chia-I Wuafe42442016-04-28 14:38:57 +0800752static PFN_vkVoidFunction
Chia-I Wu2b8c6e62016-04-28 14:38:57 +0800753intercept_core_instance_command(const char *name) {
754 static const struct {
755 const char *name;
756 PFN_vkVoidFunction proc;
757 } core_instance_commands[] = {
758 { "vkGetInstanceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetInstanceProcAddr) },
759 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
760 { "vkCreateInstance", reinterpret_cast<PFN_vkVoidFunction>(CreateInstance) },
761 { "vkDestroyInstance", reinterpret_cast<PFN_vkVoidFunction>(DestroyInstance) },
762 { "vkCreateDevice", reinterpret_cast<PFN_vkVoidFunction>(CreateDevice) },
763 { "vkEnumeratePhysicalDevices", reinterpret_cast<PFN_vkVoidFunction>(EnumeratePhysicalDevices) },
764 { "vkGetPhysicalDeviceFeatures", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFeatures) },
765 { "vkGetPhysicalDeviceFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceFormatProperties) },
766 { "vkGetPhysicalDeviceImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceImageFormatProperties) },
767 { "vkGetPhysicalDeviceProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceProperties) },
768 { "vkGetPhysicalDeviceQueueFamilyProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceQueueFamilyProperties) },
769 { "vkGetPhysicalDeviceMemoryProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceMemoryProperties) },
770 { "vkGetPhysicalDeviceSparseImageFormatProperties", reinterpret_cast<PFN_vkVoidFunction>(GetPhysicalDeviceSparseImageFormatProperties) },
Chia-I Wub02600c2016-05-20 07:11:22 +0800771 { "vkEnumerateInstanceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceLayerProperties) },
772 { "vkEnumerateDeviceLayerProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceLayerProperties) },
773 { "vkEnumerateInstanceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateInstanceExtensionProperties) },
Chia-I Wudfe8e6c2016-04-28 15:17:27 +0800774 { "vkEnumerateDeviceExtensionProperties", reinterpret_cast<PFN_vkVoidFunction>(EnumerateDeviceExtensionProperties) },
Chia-I Wu2b8c6e62016-04-28 14:38:57 +0800775 };
776
777 for (size_t i = 0; i < ARRAY_SIZE(core_instance_commands); i++) {
778 if (!strcmp(core_instance_commands[i].name, name))
779 return core_instance_commands[i].proc;
780 }
781
782 return nullptr;
783}
784
785static PFN_vkVoidFunction
Chia-I Wuafe42442016-04-28 14:38:57 +0800786intercept_core_device_command(const char *name) {
787 static const struct {
788 const char *name;
789 PFN_vkVoidFunction proc;
790 } core_device_commands[] = {
791 { "vkGetDeviceProcAddr", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceProcAddr) },
792 { "vkDestroyDevice", reinterpret_cast<PFN_vkVoidFunction>(DestroyDevice) },
793 { "vkGetDeviceQueue", reinterpret_cast<PFN_vkVoidFunction>(GetDeviceQueue) },
794 { "vkCreateRenderPass", reinterpret_cast<PFN_vkVoidFunction>(CreateRenderPass) },
795 { "vkCreateCommandPool", reinterpret_cast<PFN_vkVoidFunction>(CreateCommandPool) },
796 { "vkDestroyCommandPool", reinterpret_cast<PFN_vkVoidFunction>(DestroyCommandPool) },
797 { "vkResetCommandPool", reinterpret_cast<PFN_vkVoidFunction>(ResetCommandPool) },
798 { "vkAllocateCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(AllocateCommandBuffers) },
799 { "vkFreeCommandBuffers", reinterpret_cast<PFN_vkVoidFunction>(FreeCommandBuffers) },
800 { "vkBeginCommandBuffer", reinterpret_cast<PFN_vkVoidFunction>(BeginCommandBuffer) },
801 { "vkCmdUpdateBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdUpdateBuffer) },
802 { "vkUpdateDescriptorSets", reinterpret_cast<PFN_vkVoidFunction>(UpdateDescriptorSets) },
803 { "vkCmdFillBuffer", reinterpret_cast<PFN_vkVoidFunction>(CmdFillBuffer) },
Chia-I Wufa5e51c2016-04-28 14:44:08 +0800804 { "vkCmdSetScissor", reinterpret_cast<PFN_vkVoidFunction>(CmdSetScissor) },
805 { "vkCmdSetViewport", reinterpret_cast<PFN_vkVoidFunction>(CmdSetViewport) },
Chia-I Wuafe42442016-04-28 14:38:57 +0800806 };
807
808 for (size_t i = 0; i < ARRAY_SIZE(core_device_commands); i++) {
809 if (!strcmp(core_device_commands[i].name, name))
810 return core_device_commands[i].proc;
811 }
812
813 return nullptr;
814}
815
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800816} // namespace device_limits
817
818// vk_layer_logging.h expects these to be defined
819
Chia-I Wu99860202016-04-28 14:01:30 +0800820VKAPI_ATTR VkResult VKAPI_CALL
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800821vkCreateDebugReportCallbackEXT(VkInstance instance, const VkDebugReportCallbackCreateInfoEXT *pCreateInfo,
822 const VkAllocationCallbacks *pAllocator, VkDebugReportCallbackEXT *pMsgCallback) {
Chia-I Wu99860202016-04-28 14:01:30 +0800823 return device_limits::CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800824}
825
Chia-I Wu99860202016-04-28 14:01:30 +0800826VKAPI_ATTR void VKAPI_CALL
827vkDestroyDebugReportCallbackEXT(VkInstance instance,
828 VkDebugReportCallbackEXT msgCallback,
829 const VkAllocationCallbacks *pAllocator) {
830 device_limits::DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800831}
832
Chia-I Wu99860202016-04-28 14:01:30 +0800833VKAPI_ATTR void VKAPI_CALL
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800834vkDebugReportMessageEXT(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objType, uint64_t object,
835 size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg) {
Chia-I Wu99860202016-04-28 14:01:30 +0800836 device_limits::DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800837}
838
Chia-I Wub02600c2016-05-20 07:11:22 +0800839// loader-layer interface v0, just wrappers since there is only a layer
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800840
Chia-I Wu16489ac2016-04-28 11:21:49 +0800841VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
842vkEnumerateInstanceLayerProperties(uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +0800843 return device_limits::EnumerateInstanceLayerProperties(pCount, pProperties);
Chia-I Wu16489ac2016-04-28 11:21:49 +0800844}
845
846VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
847vkEnumerateDeviceLayerProperties(VkPhysicalDevice physicalDevice, uint32_t *pCount, VkLayerProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +0800848 // the layer command handles VK_NULL_HANDLE just fine internally
849 assert(physicalDevice == VK_NULL_HANDLE);
850 return device_limits::EnumerateDeviceLayerProperties(VK_NULL_HANDLE, pCount, pProperties);
Chia-I Wu16489ac2016-04-28 11:21:49 +0800851}
852
853VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL
854vkEnumerateInstanceExtensionProperties(const char *pLayerName, uint32_t *pCount, VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +0800855 return device_limits::EnumerateInstanceExtensionProperties(pLayerName, pCount, pProperties);
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800856}
857
858VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physicalDevice,
859 const char *pLayerName, uint32_t *pCount,
860 VkExtensionProperties *pProperties) {
Chia-I Wub02600c2016-05-20 07:11:22 +0800861 // the layer command handles VK_NULL_HANDLE just fine internally
862 assert(physicalDevice == VK_NULL_HANDLE);
Chia-I Wuc83c0832016-04-28 14:21:13 +0800863 return device_limits::EnumerateDeviceExtensionProperties(VK_NULL_HANDLE, pLayerName, pCount, pProperties);
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800864}
865
866VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice dev, const char *funcName) {
Chia-I Wu99860202016-04-28 14:01:30 +0800867 return device_limits::GetDeviceProcAddr(dev, funcName);
Chia-I Wu080cb7a2016-04-28 11:27:46 +0800868}
869
870VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char *funcName) {
Chia-I Wu99860202016-04-28 14:01:30 +0800871 return device_limits::GetInstanceProcAddr(instance, funcName);
Chia-I Wu16489ac2016-04-28 11:21:49 +0800872}