blob: 948cc9c57d2b724d50690d3b02b36588698b707d [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.
Jeremy Hayes9cc31582015-06-18 10:12:39 -06005 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -07006 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and/or associated documentation files (the "Materials"), to
8 * deal in the Materials without restriction, including without limitation the
9 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
10 * sell copies of the Materials, and to permit persons to whom the Materials
11 * are furnished to do so, subject to the following conditions:
Jeremy Hayes9cc31582015-06-18 10:12:39 -060012 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070013 * The above copyright notice(s) and this permission notice shall be included
14 * in all copies or substantial portions of the Materials.
Jeremy Hayes9cc31582015-06-18 10:12:39 -060015 *
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070016 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Jeremy Hayes9cc31582015-06-18 10:12:39 -060017 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Mark Lobodzinski6eda00a2016-02-02 15:55:36 -070018 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 *
20 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
21 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
22 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR THE
23 * USE OR OTHER DEALINGS IN THE MATERIALS
Courtney Goeltzenleuchter05559522015-10-30 11:14:30 -060024 *
25 * Author: Jeremy Hayes <jeremy@lunarg.com>
26 * Author: Mark Lobodzinski <mark@lunarg.com>
27 * Author: Mike Stroyan <mike@LunarG.com>
28 * Author: Tobin Ehlis <tobin@lunarg.com>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060029 */
30
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060031#include <inttypes.h>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060032#include <stdio.h>
33#include <stdlib.h>
34#include <string.h>
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060035#include <assert.h>
36#include <vector>
Jeremy Hayes9cc31582015-06-18 10:12:39 -060037#include <unordered_map>
Tobin Ehlisad8c4462015-09-21 15:20:28 -060038#include <memory>
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060039using namespace std;
Jeremy Hayes9cc31582015-06-18 10:12:39 -060040
Tobin Ehlisb835d1b2015-07-03 10:34:49 -060041#include "vk_loader_platform.h"
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060042#include "vk_dispatch_table_helper.h"
43#include "vk_struct_string_helper_cpp.h"
Jeremy Hayes9cc31582015-06-18 10:12:39 -060044#include "vk_enum_validate_helper.h"
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060045#include "image.h"
46#include "vk_layer_config.h"
47#include "vk_layer_extension_utils.h"
Tobin Ehlisa0cb02e2015-07-03 10:15:26 -060048#include "vk_layer_table.h"
49#include "vk_layer_data.h"
Courtney Goeltzenleuchter426e1872015-07-07 11:18:30 -060050#include "vk_layer_extension_utils.h"
Mike Stroyana3082432015-09-25 13:39:21 -060051#include "vk_layer_utils.h"
Courtney Goeltzenleuchter8f8367e2015-10-07 08:38:30 -060052#include "vk_layer_logging.h"
Jeremy Hayes9cc31582015-06-18 10:12:39 -060053
Tobin Ehlisad8c4462015-09-21 15:20:28 -060054using namespace std;
55
Cody Northrop55443ef2015-09-28 15:09:32 -060056struct layer_data {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070057 debug_report_data *report_data;
58 vector<VkDebugReportCallbackEXT> logging_callback;
59 VkLayerDispatchTable* device_dispatch_table;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -070060 VkLayerInstanceDispatchTable *instance_dispatch_table;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070061 VkPhysicalDevice physicalDevice;
62 VkPhysicalDeviceProperties physicalDeviceProperties;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -070063
Chia-I Wue2fc5522015-10-26 20:04:44 +080064 unordered_map<VkImage, IMAGE_STATE> imageMap;
Cody Northrop55443ef2015-09-28 15:09:32 -060065
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070066 layer_data() :
67 report_data(nullptr),
68 device_dispatch_table(nullptr),
69 instance_dispatch_table(nullptr),
70 physicalDevice(0),
71 physicalDeviceProperties()
72 {};
Cody Northrop55443ef2015-09-28 15:09:32 -060073};
Jeremy Hayes9cc31582015-06-18 10:12:39 -060074
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070075static unordered_map<void*, layer_data*> layer_data_map;
Jeremy Hayes9cc31582015-06-18 10:12:39 -060076
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070077static void InitImage(layer_data *data, const VkAllocationCallbacks *pAllocator)
78{
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070079 VkDebugReportCallbackEXT callback;
Jeremy Hayes9cc31582015-06-18 10:12:39 -060080 uint32_t report_flags = getLayerOptionFlags("ImageReportFlags", 0);
81
82 uint32_t debug_action = 0;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070083 getLayerOptionEnum("ImageDebugAction", (uint32_t *) &debug_action);
84 if(debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
85 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -060086 FILE *log_output = NULL;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070087 const char* option_str = getLayerOption("ImageLogFilename");
Tobin Ehlisb1df55e2015-09-15 09:55:54 -060088 log_output = getLayerLogOutput(option_str, "Image");
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070089 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -070090 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -070091 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -070092 dbgInfo.pfnCallback = log_callback;
93 dbgInfo.pUserData = log_output;
94 dbgInfo.flags = report_flags;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -070095 layer_create_msg_callback(data->report_data, &dbgInfo, pAllocator, &callback);
Courtney Goeltzenleuchterffcdd8b2015-10-05 15:59:11 -060096 data->logging_callback.push_back(callback);
97 }
98
99 if (debug_action & VK_DBG_LAYER_ACTION_DEBUG_OUTPUT) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700100 VkDebugReportCallbackCreateInfoEXT dbgInfo;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700101 memset(&dbgInfo, 0, sizeof(dbgInfo));
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700102 dbgInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700103 dbgInfo.pfnCallback = win32_debug_output_msg;
104 dbgInfo.flags = report_flags;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700105 layer_create_msg_callback(data->report_data, &dbgInfo, pAllocator, &callback);
Courtney Goeltzenleuchterffcdd8b2015-10-05 15:59:11 -0600106 data->logging_callback.push_back(callback);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600107 }
108}
109
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700110VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDebugReportCallbackEXT(
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700111 VkInstance instance,
112 const VkDebugReportCallbackCreateInfoEXT* pCreateInfo,
113 const VkAllocationCallbacks* pAllocator,
114 VkDebugReportCallbackEXT* pMsgCallback)
115{
116 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
117 VkResult res = my_data->instance_dispatch_table->CreateDebugReportCallbackEXT(instance, pCreateInfo, pAllocator, pMsgCallback);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600118 if (res == VK_SUCCESS) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700119 res = layer_create_msg_callback(my_data->report_data, pCreateInfo, pAllocator, pMsgCallback);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600120 }
121 return res;
122}
123
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700124VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDebugReportCallbackEXT(
125 VkInstance instance,
126 VkDebugReportCallbackEXT msgCallback,
127 const VkAllocationCallbacks* pAllocator)
128{
129 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
130 my_data->instance_dispatch_table->DestroyDebugReportCallbackEXT(instance, msgCallback, pAllocator);
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700131 layer_destroy_msg_callback(my_data->report_data, msgCallback, pAllocator);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600132}
133
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700134VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDebugReportMessageEXT(
135 VkInstance instance,
136 VkDebugReportFlagsEXT flags,
137 VkDebugReportObjectTypeEXT objType,
138 uint64_t object,
139 size_t location,
140 int32_t msgCode,
141 const char* pLayerPrefix,
142 const char* pMsg)
143{
144 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
145 my_data->instance_dispatch_table->DebugReportMessageEXT(instance, flags, objType, object, location, msgCode, pLayerPrefix, pMsg);
Courtney Goeltzenleuchterf0de7242015-12-01 14:10:55 -0700146}
147
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700148VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkInstance* pInstance)
149{
150 VkLayerInstanceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600151
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700152 assert(chain_info->u.pLayerInfo);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700153 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
154 PFN_vkCreateInstance fpCreateInstance = (PFN_vkCreateInstance) fpGetInstanceProcAddr(NULL, "vkCreateInstance");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700155 if (fpCreateInstance == NULL) {
156 return VK_ERROR_INITIALIZATION_FAILED;
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600157 }
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700158
159 // Advance the link info for the next element on the chain
160 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
161
162 VkResult result = fpCreateInstance(pCreateInfo, pAllocator, pInstance);
163 if (result != VK_SUCCESS)
164 return result;
165
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700166 layer_data *my_data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700167 my_data->instance_dispatch_table = new VkLayerInstanceDispatchTable;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700168 layer_init_instance_dispatch_table(*pInstance, my_data->instance_dispatch_table, fpGetInstanceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700169
170 my_data->report_data = debug_report_create_instance(
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700171 my_data->instance_dispatch_table,
172 *pInstance,
173 pCreateInfo->enabledExtensionCount,
174 pCreateInfo->ppEnabledExtensionNames);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700175
176 InitImage(my_data, pAllocator);
177
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600178 return result;
179}
180
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700181VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance, const VkAllocationCallbacks* pAllocator)
182{
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600183 // Grab the key before the instance is destroyed.
184 dispatch_key key = get_dispatch_key(instance);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600185 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
186 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Chia-I Wuf7458c52015-10-26 21:10:41 +0800187 pTable->DestroyInstance(instance, pAllocator);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600188
189 // Clean up logging callback, if any
Courtney Goeltzenleuchterffcdd8b2015-10-05 15:59:11 -0600190 while (my_data->logging_callback.size() > 0) {
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700191 VkDebugReportCallbackEXT callback = my_data->logging_callback.back();
Courtney Goeltzenleuchter05854bf2015-11-30 12:13:14 -0700192 layer_destroy_msg_callback(my_data->report_data, callback, pAllocator);
Courtney Goeltzenleuchterffcdd8b2015-10-05 15:59:11 -0600193 my_data->logging_callback.pop_back();
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600194 }
195
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600196 layer_debug_report_destroy_instance(my_data->report_data);
197 delete my_data->instance_dispatch_table;
198 layer_data_map.erase(key);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700199
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600200}
201
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700202VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkDevice* pDevice)
203{
204 VkLayerDeviceCreateInfo *chain_info = get_chain_info(pCreateInfo, VK_LAYER_LINK_INFO);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700205
206 assert(chain_info->u.pLayerInfo);
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700207 PFN_vkGetInstanceProcAddr fpGetInstanceProcAddr = chain_info->u.pLayerInfo->pfnNextGetInstanceProcAddr;
208 PFN_vkGetDeviceProcAddr fpGetDeviceProcAddr = chain_info->u.pLayerInfo->pfnNextGetDeviceProcAddr;
209 PFN_vkCreateDevice fpCreateDevice = (PFN_vkCreateDevice) fpGetInstanceProcAddr(NULL, "vkCreateDevice");
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700210 if (fpCreateDevice == NULL) {
211 return VK_ERROR_INITIALIZATION_FAILED;
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600212 }
213
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700214 // Advance the link info for the next element on the chain
215 chain_info->u.pLayerInfo = chain_info->u.pLayerInfo->pNext;
216
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700217 VkResult result = fpCreateDevice(physicalDevice, pCreateInfo, pAllocator, pDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700218 if (result != VK_SUCCESS) {
219 return result;
220 }
221
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700222 layer_data *my_instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
223 layer_data *my_device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700224
225 // Setup device dispatch table
226 my_device_data->device_dispatch_table = new VkLayerDispatchTable;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700227 layer_init_device_dispatch_table(*pDevice, my_device_data->device_dispatch_table, fpGetDeviceProcAddr);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700228
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700229 my_device_data->report_data = layer_debug_report_create_device(my_instance_data->report_data, *pDevice);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -0700230 my_device_data->physicalDevice = physicalDevice;
231
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700232 my_instance_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, &(my_device_data->physicalDeviceProperties));
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700233
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600234 return result;
235}
236
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700237VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator)
238{
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600239 dispatch_key key = get_dispatch_key(device);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600240 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
Chia-I Wuf7458c52015-10-26 21:10:41 +0800241 my_data->device_dispatch_table->DestroyDevice(device, pAllocator);
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -0600242 delete my_data->device_dispatch_table;
243 layer_data_map.erase(key);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600244}
245
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -0700246static const VkExtensionProperties instance_extensions[] = {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700247 {
248 VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
249 VK_EXT_DEBUG_REPORT_SPEC_VERSION
250 }
251};
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600252
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700253VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
254 const char *pLayerName,
255 uint32_t *pCount,
256 VkExtensionProperties* pProperties)
257{
258 return util_GetExtensionProperties(1, instance_extensions, pCount, pProperties);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600259}
260
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700261static const VkLayerProperties pc_global_layers[] = {
262 {
263 "VK_LAYER_LUNARG_image",
264 VK_API_VERSION,
265 VK_MAKE_VERSION(0, 1, 0),
266 "Validation layer: image",
267 }
268};
Courtney Goeltzenleuchter52857662015-12-01 14:08:28 -0700269
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700270VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceLayerProperties(
271 uint32_t *pCount,
272 VkLayerProperties* pProperties)
273{
Courtney Goeltzenleuchter426e1872015-07-07 11:18:30 -0600274 return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers),
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700275 pc_global_layers,
276 pCount, pProperties);
Tony Barbour59a47322015-06-24 16:06:58 -0600277}
278
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700279VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceExtensionProperties(
280 VkPhysicalDevice physicalDevice,
281 const char* pLayerName,
282 uint32_t* pCount,
283 VkExtensionProperties* pProperties)
284{
Jon Ashburn751c4842015-11-02 17:37:20 -0700285 // Image does not have any physical device extensions
286 if (pLayerName == NULL) {
287 dispatch_key key = get_dispatch_key(physicalDevice);
288 layer_data *my_data = get_my_data_ptr(key, layer_data_map);
289 VkLayerInstanceDispatchTable *pTable = my_data->instance_dispatch_table;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700290 return pTable->EnumerateDeviceExtensionProperties(
291 physicalDevice,
292 NULL,
293 pCount,
294 pProperties);
Jon Ashburn751c4842015-11-02 17:37:20 -0700295 } else {
296 return util_GetExtensionProperties(0, NULL, pCount, pProperties);
297 }
Courtney Goeltzenleuchter426e1872015-07-07 11:18:30 -0600298}
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600299
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700300VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
301 VkPhysicalDevice physicalDevice,
302 uint32_t* pCount,
303 VkLayerProperties* pProperties)
304{
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600305 // ParamChecker's physical device layers are the same as global
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700306 return util_GetLayerProperties(ARRAY_SIZE(pc_global_layers), pc_global_layers,
307 pCount, pProperties);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600308}
309
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600310// Start of the Image layer proper
311
312// Returns TRUE if a format is a depth-compatible format
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700313bool is_depth_format(VkFormat format)
314{
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600315 bool result = VK_FALSE;
316 switch (format) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700317 case VK_FORMAT_D16_UNORM:
318 case VK_FORMAT_X8_D24_UNORM_PACK32:
319 case VK_FORMAT_D32_SFLOAT:
320 case VK_FORMAT_S8_UINT:
321 case VK_FORMAT_D16_UNORM_S8_UINT:
322 case VK_FORMAT_D24_UNORM_S8_UINT:
323 case VK_FORMAT_D32_SFLOAT_S8_UINT:
324 result = VK_TRUE;
325 break;
326 default:
327 break;
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600328 }
329 return result;
330}
331
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700332static inline uint32_t validate_VkImageLayoutKHR(VkImageLayout input_value)
333{
Mark Lobodzinski601ed152015-11-10 11:01:32 -0700334 return ((validate_VkImageLayout(input_value) == 1) ||
Ian Elliott05846062015-11-20 14:13:17 -0700335 (input_value == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR));
Mark Lobodzinski601ed152015-11-10 11:01:32 -0700336}
337
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700338VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImage* pImage)
339{
340 VkBool32 skipCall = VK_FALSE;
341 VkResult result = VK_ERROR_VALIDATION_FAILED_EXT;
Michael Lentine0a369f62016-02-03 16:51:46 -0600342 VkImageFormatProperties ImageFormatProperties;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700343
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700344 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
345 VkPhysicalDevice physicalDevice = device_data->physicalDevice;
346 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700347
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700348 if (pCreateInfo->format != VK_FORMAT_UNDEFINED)
349 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600350 VkFormatProperties properties;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700351 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceFormatProperties(
Chris Forbesbc0bb772015-06-21 22:55:02 +1200352 device_data->physicalDevice, pCreateInfo->format, &properties);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600353
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700354 if ((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
355 {
356 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
357 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
358 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", str);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600359 }
360 }
361
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700362 // Internal call to get format info. Still goes through layers, could potentially go directly to ICD.
363 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceImageFormatProperties(
364 physicalDevice, pCreateInfo->format, pCreateInfo->imageType, pCreateInfo->tiling,
365 pCreateInfo->usage, pCreateInfo->flags, &ImageFormatProperties);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600366
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700367 VkDeviceSize imageGranularity = device_data->physicalDeviceProperties.limits.bufferImageGranularity;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700368 imageGranularity = imageGranularity == 1 ? 0 : imageGranularity;
369
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700370 if ((pCreateInfo->extent.depth > ImageFormatProperties.maxExtent.depth) ||
371 (pCreateInfo->extent.width > ImageFormatProperties.maxExtent.width) ||
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700372 (pCreateInfo->extent.height > ImageFormatProperties.maxExtent.height)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700373 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)pImage, __LINE__,
374 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
375 "CreateImage extents exceed allowable limits for format: "
376 "Width = %d Height = %d Depth = %d: Limits for Width = %d Height = %d Depth = %d for format %s.",
377 pCreateInfo->extent.width, pCreateInfo->extent.height, pCreateInfo->extent.depth,
378 ImageFormatProperties.maxExtent.width, ImageFormatProperties.maxExtent.height, ImageFormatProperties.maxExtent.depth,
379 string_VkFormat(pCreateInfo->format));
380
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700381 }
382
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700383 uint64_t totalSize = ((uint64_t)pCreateInfo->extent.width *
384 (uint64_t)pCreateInfo->extent.height *
385 (uint64_t)pCreateInfo->extent.depth *
386 (uint64_t)pCreateInfo->arrayLayers *
387 (uint64_t)pCreateInfo->samples *
388 (uint64_t)vk_format_get_size(pCreateInfo->format) +
389 (uint64_t)imageGranularity ) & ~(uint64_t)imageGranularity;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700390
391 if (totalSize > ImageFormatProperties.maxResourceSize) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700392 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)pImage, __LINE__,
393 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
394 "CreateImage resource size exceeds allowable maximum "
395 "Image resource size = %#" PRIxLEAST64 ", maximum resource size = %#" PRIxLEAST64 " ",
396 totalSize, ImageFormatProperties.maxResourceSize);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700397 }
398
399 if (pCreateInfo->mipLevels > ImageFormatProperties.maxMipLevels) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700400 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)pImage, __LINE__,
401 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
402 "CreateImage mipLevels=%d exceeds allowable maximum supported by format of %d",
403 pCreateInfo->mipLevels, ImageFormatProperties.maxMipLevels);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700404 }
405
406 if (pCreateInfo->arrayLayers > ImageFormatProperties.maxArrayLayers) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700407 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)pImage, __LINE__,
408 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
409 "CreateImage arrayLayers=%d exceeds allowable maximum supported by format of %d",
410 pCreateInfo->arrayLayers, ImageFormatProperties.maxArrayLayers);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700411 }
412
413 if ((pCreateInfo->samples & ImageFormatProperties.sampleCounts) == 0) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700414 skipCall |= log_msg(phy_dev_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, (uint64_t)pImage, __LINE__,
415 IMAGE_INVALID_FORMAT_LIMITS_VIOLATION, "Image",
416 "CreateImage samples %s is not supported by format 0x%.8X",
417 string_VkSampleCountFlagBits(pCreateInfo->samples), ImageFormatProperties.sampleCounts);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700418 }
419
420 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700421 result = device_data->device_dispatch_table->CreateImage(device, pCreateInfo, pAllocator, pImage);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -0700422 }
423 if (result == VK_SUCCESS) {
Chia-I Wue2fc5522015-10-26 20:04:44 +0800424 device_data->imageMap[*pImage] = IMAGE_STATE(pCreateInfo);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600425 }
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600426 return result;
427}
428
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700429VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device, VkImage image, const VkAllocationCallbacks* pAllocator)
430{
431 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wue2fc5522015-10-26 20:04:44 +0800432 device_data->imageMap.erase(image);
Chia-I Wuf7458c52015-10-26 21:10:41 +0800433 device_data->device_dispatch_table->DestroyImage(device, image, pAllocator);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600434}
435
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700436VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkRenderPass* pRenderPass)
437{
438 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Tobin Ehlisdea00952015-09-22 08:40:52 -0600439 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700440 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
441 {
442 if(pCreateInfo->pAttachments[i].format != VK_FORMAT_UNDEFINED)
443 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600444 VkFormatProperties properties;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700445 get_my_data_ptr(get_dispatch_key(my_data->physicalDevice), layer_data_map)->instance_dispatch_table->GetPhysicalDeviceFormatProperties(
446 my_data->physicalDevice, pCreateInfo->pAttachments[i].format, &properties);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600447
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700448 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
449 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600450 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700451 ss << "vkCreateRenderPass parameter, VkFormat in pCreateInfo->pAttachments[" << i << "], contains unsupported format";
452 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
453 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_FORMAT_UNSUPPORTED, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600454 }
455 }
456 }
457
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700458 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
459 {
460 if(!validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].initialLayout) ||
461 !validate_VkImageLayoutKHR(pCreateInfo->pAttachments[i].finalLayout))
462 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600463 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700464 ss << "vkCreateRenderPass parameter, VkImageLayout in pCreateInfo->pAttachments[" << i << "], is unrecognized";
465 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
466 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600467 }
468 }
469
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700470 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
471 {
472 if(!validate_VkAttachmentLoadOp(pCreateInfo->pAttachments[i].loadOp))
473 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600474 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700475 ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
476 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
477 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600478 }
479 }
480
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700481 for(uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
482 {
483 if(!validate_VkAttachmentStoreOp(pCreateInfo->pAttachments[i].storeOp))
484 {
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600485 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700486 ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp in pCreateInfo->pAttachments[" << i << "], is unrecognized";
487 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid
488 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_RENDERPASS_INVALID_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600489 }
490 }
491
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600492 // Any depth buffers specified as attachments?
493 bool depthFormatPresent = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700494 for (uint32_t i = 0; i < pCreateInfo->attachmentCount; ++i)
495 {
496 depthFormatPresent |= is_depth_format(pCreateInfo->pAttachments[i].format);
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600497 }
498
499 if (depthFormatPresent == VK_FALSE) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700500 // No depth attachment is present, validate that subpasses set depthStencilAttachment to VK_ATTACHMENT_UNUSED;
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600501 for (uint32_t i = 0; i < pCreateInfo->subpassCount; i++) {
Chia-I Wu1efb7e52015-10-26 17:32:47 +0800502 if (pCreateInfo->pSubpasses[i].pDepthStencilAttachment &&
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700503 pCreateInfo->pSubpasses[i].pDepthStencilAttachment->attachment != VK_ATTACHMENT_UNUSED) {
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600504 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700505 ss << "vkCreateRenderPass has no depth/stencil attachment, yet subpass[" << i << "] has VkSubpassDescription::depthStencilAttachment value that is not VK_ATTACHMENT_UNUSED";
506 skipCall |= log_msg(my_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_RENDERPASS_INVALID_DS_ATTACHMENT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600507 }
508 }
509 }
Tobin Ehlisdea00952015-09-22 08:40:52 -0600510 if (skipCall)
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700511 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinski2fd634c2015-07-29 09:21:22 -0600512
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700513 VkResult result = my_data->device_dispatch_table->CreateRenderPass(device, pCreateInfo, pAllocator, pRenderPass);
Jeremy Hayes9cc31582015-06-18 10:12:39 -0600514
515 return result;
516}
517
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700518VK_LAYER_EXPORT VKAPI_ATTR VkResult VKAPI_CALL vkCreateImageView(VkDevice device, const VkImageViewCreateInfo* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkImageView* pView)
519{
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600520 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700521 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Chia-I Wue2fc5522015-10-26 20:04:44 +0800522 auto imageEntry = device_data->imageMap.find(pCreateInfo->image);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600523 if (imageEntry != device_data->imageMap.end()) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700524 if (pCreateInfo->subresourceRange.baseMipLevel >= imageEntry->second.mipLevels) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600525 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700526 ss << "vkCreateImageView called with baseMipLevel " << pCreateInfo->subresourceRange.baseMipLevel
527 << " for image " << pCreateInfo->image << " that only has " << imageEntry->second.mipLevels << " mip levels.";
528 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600529 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700530 if (pCreateInfo->subresourceRange.baseArrayLayer >= imageEntry->second.arraySize) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600531 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700532 ss << "vkCreateImageView called with baseArrayLayer " << pCreateInfo->subresourceRange.baseArrayLayer << " for image "
533 << pCreateInfo->image << " that only has " << imageEntry->second.arraySize << " mip levels.";
534 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600535 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800536 if (!pCreateInfo->subresourceRange.levelCount) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600537 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700538 ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.levelCount.";
539 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600540 }
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800541 if (!pCreateInfo->subresourceRange.layerCount) {
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600542 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700543 ss << "vkCreateImageView called with 0 in pCreateInfo->subresourceRange.layerCount.";
544 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__, IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600545 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600546
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700547 VkImageCreateFlags imageFlags = imageEntry->second.flags;
548 VkFormat imageFormat = imageEntry->second.format;
549 VkFormat ivciFormat = pCreateInfo->format;
550 VkImageAspectFlags aspectMask = pCreateInfo->subresourceRange.aspectMask;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600551
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700552 // Validate VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT state
Mark Lobodzinski1e638c62016-01-11 16:50:30 -0700553 if (imageFlags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700554 // Format MUST be compatible (in the same format compatibility class) as the format the image was created with
555 if (vk_format_get_compatibility_class(imageFormat) != vk_format_get_compatibility_class(ivciFormat)) {
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700556 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700557 ss << "vkCreateImageView(): ImageView format " << string_VkFormat(ivciFormat) << " is not in the same format compatibility class as image (" <<
558 (uint64_t)pCreateInfo->image << ") format " << string_VkFormat(imageFormat) << ". Images created with the VK_IMAGE_CREATE_MUTABLE_FORMAT BIT " <<
559 "can support ImageViews with differing formats but they must be in the same compatibility class.";
560 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700561 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
562 }
563 } else {
564 // Format MUST be IDENTICAL to the format the image was created with
565 if (imageFormat != ivciFormat) {
566 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700567 ss << "vkCreateImageView() format " << string_VkFormat(ivciFormat) << " differs from image " << (uint64_t)pCreateInfo->image << " format " <<
568 string_VkFormat(imageFormat) << ". Formats MUST be IDENTICAL unless VK_IMAGE_CREATE_MUTABLE_FORMAT BIT was set on image creation.";
569 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0, 0, __LINE__,
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700570 IMAGE_VIEW_CREATE_ERROR, "IMAGE", "%s", ss.str().c_str());
571 }
572 }
573
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700574 // Validate correct image aspect bits for desired formats and format consistency
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600575 if (vk_format_is_color(imageFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700576 if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600577 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700578 ss << "vkCreateImageView: Color image formats must have the VK_IMAGE_ASPECT_COLOR_BIT set";
579 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
580 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600581 }
582 if ((aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) != aspectMask) {
583 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700584 ss << "vkCreateImageView: Color image formats must have ONLY the VK_IMAGE_ASPECT_COLOR_BIT set";
585 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
586 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600587 }
588 if (VK_FALSE == vk_format_is_color(ivciFormat)) {
589 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700590 ss << "vkCreateImageView: The image view's format can differ from the parent image's format, but both must be "
591 << "color formats. ImageFormat is " << string_VkFormat(imageFormat) << " ImageViewFormat is " << string_VkFormat(ivciFormat);
592 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
593 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600594 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700595 // TODO: Uncompressed formats are compatible if they occupy they same number of bits per pixel.
596 // Compressed formats are compatible if the only difference between them is the numerical type of
597 // the uncompressed pixels (e.g. signed vs. unsigned, or sRGB vs. UNORM encoding).
598 } else if (vk_format_is_depth_and_stencil(imageFormat)) {
599 if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) == 0) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600600 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700601 ss << "vkCreateImageView: Depth/stencil image formats must have at least one of VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT set";
602 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
603 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600604 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700605 if ((aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT)) != aspectMask) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600606 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700607 ss << "vkCreateImageView: Combination depth/stencil image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT and VK_IMAGE_ASPECT_STENCIL_BIT set";
608 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
609 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600610 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700611 } else if (vk_format_is_depth_only(imageFormat)) {
612 if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600613 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700614 ss << "vkCreateImageView: Depth-only image formats must have the VK_IMAGE_ASPECT_DEPTH_BIT set";
615 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
616 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600617 }
618 if ((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != aspectMask) {
619 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700620 ss << "vkCreateImageView: Depth-only image formats can have only the VK_IMAGE_ASPECT_DEPTH_BIT set";
621 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
622 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600623 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700624 } else if (vk_format_is_stencil_only(imageFormat)) {
625 if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600626 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700627 ss << "vkCreateImageView: Stencil-only image formats must have the VK_IMAGE_ASPECT_STENCIL_BIT set";
628 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
629 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600630 }
631 if ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != aspectMask) {
632 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700633 ss << "vkCreateImageView: Stencil-only image formats can have only the VK_IMAGE_ASPECT_STENCIL_BIT set";
634 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
635 (uint64_t)pCreateInfo->image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600636 }
637 }
638 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600639
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700640 if (skipCall) {
Courtney Goeltzenleuchter52fee652015-12-10 16:41:22 -0700641 return VK_ERROR_VALIDATION_FAILED_EXT;
Mark Lobodzinskiadaac9d2016-01-08 11:07:56 -0700642 }
Tobin Ehlisdea00952015-09-22 08:40:52 -0600643
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700644 VkResult result = device_data->device_dispatch_table->CreateImageView(device, pCreateInfo, pAllocator, pView);
Tobin Ehlisad8c4462015-09-21 15:20:28 -0600645 return result;
646}
647
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700648VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(
649 VkCommandBuffer commandBuffer,
650 VkImage image,
651 VkImageLayout imageLayout,
652 const VkClearColorValue *pColor,
653 uint32_t rangeCount,
654 const VkImageSubresourceRange *pRanges)
655{
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600656 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700657 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600658 // For each range, image aspect must be color only
659 for (uint32_t i = 0; i < rangeCount; i++) {
660 if (pRanges[i].aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700661 char const str[] = "vkCmdClearColorImage aspectMasks for all subresource ranges must be set to VK_IMAGE_ASPECT_COLOR_BIT";
662 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
663 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600664 }
665 }
666
667 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700668 device_data->device_dispatch_table->CmdClearColorImage(commandBuffer, image, imageLayout,
669 pColor, rangeCount, pRanges);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600670 }
671}
672
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700673VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdClearDepthStencilImage(
674 VkCommandBuffer commandBuffer,
675 VkImage image,
676 VkImageLayout imageLayout,
677 const VkClearDepthStencilValue *pDepthStencil,
678 uint32_t rangeCount,
679 const VkImageSubresourceRange *pRanges)
680{
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600681 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700682 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600683 // For each range, Image aspect must be depth or stencil or both
684 for (uint32_t i = 0; i < rangeCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700685 if (((pRanges[i].aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
686 ((pRanges[i].aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT))
687 {
688 char const str[] = "vkCmdClearDepthStencilImage aspectMasks for all subresource ranges must be "
689 "set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
690 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
691 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600692 }
693 }
694
695 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700696 device_data->device_dispatch_table->CmdClearDepthStencilImage(commandBuffer,
697 image, imageLayout, pDepthStencil, rangeCount, pRanges);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600698 }
699}
700
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700701VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(
702 VkCommandBuffer commandBuffer,
703 VkImage srcImage,
704 VkImageLayout srcImageLayout,
705 VkImage dstImage,
706 VkImageLayout dstImageLayout,
707 uint32_t regionCount,
708 const VkImageCopy *pRegions)
709{
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600710 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700711 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Chia-I Wue2fc5522015-10-26 20:04:44 +0800712 auto srcImageEntry = device_data->imageMap.find(srcImage);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800713 auto dstImageEntry = device_data->imageMap.find(dstImage);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600714
Jeremy Hayes148bab22015-10-28 13:01:39 -0600715 // For each region, src and dst number of layers should not be zero
716 // For each region, src and dst number of layers must match
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600717 // For each region, src aspect mask must match dest aspect mask
718 // For each region, color aspects cannot be mixed with depth/stencil aspects
719 for (uint32_t i = 0; i < regionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700720 if(pRegions[i].srcSubresource.layerCount == 0)
721 {
722 char const str[] = "vkCmdCopyImage: number of layers in source subresource is zero";
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700723 // TODO: Verify against Valid Use section of spec
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700724 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
725 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600726 }
727
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700728 if(pRegions[i].dstSubresource.layerCount == 0)
729 {
730 char const str[] = "vkCmdCopyImage: number of layers in destination subresource is zero";
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -0700731 // TODO: Verify against Valid Use section of spec
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700732 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
733 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600734 }
735
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700736 if(pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount)
737 {
738 char const str[] = "vkCmdCopyImage: number of layers in source and destination subresources must match";
739 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
740 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600741 }
742
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700743 if (pRegions[i].srcSubresource.aspectMask != pRegions[i].dstSubresource.aspectMask) {
744 char const str[] = "vkCmdCopyImage: Src and dest aspectMasks for each region must match";
745 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
746 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600747 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700748 if ((pRegions[i].srcSubresource.aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) &&
749 (pRegions[i].srcSubresource.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT))) {
750 char const str[] = "vkCmdCopyImage aspectMask cannot specify both COLOR and DEPTH/STENCIL aspects";
751 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
752 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600753 }
754 }
755
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700756 if ((srcImageEntry != device_data->imageMap.end())
757 && (dstImageEntry != device_data->imageMap.end())) {
758 if (srcImageEntry->second.imageType != dstImageEntry->second.imageType) {
759 char const str[] = "vkCmdCopyImage called with unmatched source and dest image types.";
760 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
761 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -0600762 }
763 // Check that format is same size or exact stencil/depth
Tobin Ehlisd923d152015-09-25 14:49:43 -0600764 if (is_depth_format(srcImageEntry->second.format)) {
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800765 if (srcImageEntry->second.format != dstImageEntry->second.format) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700766 char const str[] = "vkCmdCopyImage called with unmatched source and dest image depth/stencil formats.";
767 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
768 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -0600769 }
770 } else {
Tobin Ehlisd923d152015-09-25 14:49:43 -0600771 size_t srcSize = vk_format_get_size(srcImageEntry->second.format);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800772 size_t destSize = vk_format_get_size(dstImageEntry->second.format);
Mike Stroyana3082432015-09-25 13:39:21 -0600773 if (srcSize != destSize) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700774 char const str[] = "vkCmdCopyImage called with unmatched source and dest image format sizes.";
775 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
776 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -0600777 }
778 }
779 }
780
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600781 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700782 device_data->device_dispatch_table->CmdCopyImage(commandBuffer, srcImage,
783 srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600784 }
785}
786
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700787VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(
788 VkCommandBuffer commandBuffer,
789 uint32_t attachmentCount,
790 const VkClearAttachment* pAttachments,
791 uint32_t rectCount,
792 const VkClearRect* pRects)
793{
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600794 VkBool32 skipCall = VK_FALSE;
795 VkImageAspectFlags aspectMask;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700796 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600797 for (uint32_t i = 0; i < attachmentCount; i++) {
798 aspectMask = pAttachments[i].aspectMask;
799 if (aspectMask & VK_IMAGE_ASPECT_COLOR_BIT) {
800 if (aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700801 // VK_IMAGE_ASPECT_COLOR_BIT is not the only bit set for this attachment
802 char const str[] = "vkCmdClearAttachments aspectMask [%d] must set only VK_IMAGE_ASPECT_COLOR_BIT of a color attachment.";
803 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
804 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600805 }
806 } else {
807 // Image aspect must be depth or stencil or both
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700808 if (((aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT) != VK_IMAGE_ASPECT_DEPTH_BIT) &&
809 ((aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT) != VK_IMAGE_ASPECT_STENCIL_BIT))
810 {
811 char const str[] = "vkCmdClearAttachments aspectMask [%d] must be set to VK_IMAGE_ASPECT_DEPTH_BIT and/or VK_IMAGE_ASPECT_STENCIL_BIT";
812 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
813 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str, i);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600814 }
815 }
816 }
817
818 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700819 device_data->device_dispatch_table->CmdClearAttachments(commandBuffer,
820 attachmentCount, pAttachments, rectCount, pRects);
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -0600821 }
822}
823
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700824VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(
825 VkCommandBuffer commandBuffer,
826 VkImage srcImage,
827 VkImageLayout srcImageLayout,
828 VkBuffer dstBuffer,
829 uint32_t regionCount,
830 const VkBufferImageCopy *pRegions)
831{
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600832 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700833 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
834 // For each region, the number of layers in the image subresource should not be zero
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600835 // Image aspect must be ONE OF color, depth, stencil
836 for (uint32_t i = 0; i < regionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700837 if(pRegions[i].imageSubresource.layerCount == 0)
838 {
839 char const str[] = "vkCmdCopyImageToBuffer: number of layers in image subresource is zero";
840 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
841 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
842 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600843 }
844
Chia-I Wuab83a0e2015-10-27 19:00:15 +0800845 VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
846 if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) &&
847 (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
848 (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700849 char const str[] = "vkCmdCopyImageToBuffer: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
850 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
851 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600852 }
853 }
854
855 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700856 device_data->device_dispatch_table->CmdCopyImageToBuffer(commandBuffer,
857 srcImage, srcImageLayout, dstBuffer, regionCount, pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600858 }
859}
860
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700861VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(
862 VkCommandBuffer commandBuffer,
863 VkBuffer srcBuffer,
864 VkImage dstImage,
865 VkImageLayout dstImageLayout,
866 uint32_t regionCount,
867 const VkBufferImageCopy *pRegions)
868{
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600869 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700870 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
871 // For each region, the number of layers in the image subresource should not be zero
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600872 // Image aspect must be ONE OF color, depth, stencil
873 for (uint32_t i = 0; i < regionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700874 if(pRegions[i].imageSubresource.layerCount == 0)
875 {
876 char const str[] = "vkCmdCopyBufferToImage: number of layers in image subresource is zero";
877 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
878 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
879 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600880 }
881
Chia-I Wuab83a0e2015-10-27 19:00:15 +0800882 VkImageAspectFlags aspectMask = pRegions[i].imageSubresource.aspectMask;
883 if ((aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) &&
884 (aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
885 (aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700886 char const str[] = "vkCmdCopyBufferToImage: aspectMasks for each region must specify only COLOR or DEPTH or STENCIL";
887 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
888 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600889 }
890 }
891
892 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700893 device_data->device_dispatch_table->CmdCopyBufferToImage(commandBuffer,
894 srcBuffer, dstImage, dstImageLayout, regionCount, pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -0600895 }
896}
897
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700898VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(
899 VkCommandBuffer commandBuffer,
900 VkImage srcImage,
901 VkImageLayout srcImageLayout,
902 VkImage dstImage,
903 VkImageLayout dstImageLayout,
904 uint32_t regionCount,
905 const VkImageBlit *pRegions,
906 VkFilter filter)
907{
908 VkBool32 skipCall = VK_FALSE;
909 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600910
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700911 auto srcImageEntry = device_data->imageMap.find(srcImage);
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800912 auto dstImageEntry = device_data->imageMap.find(dstImage);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600913
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700914 if ((srcImageEntry != device_data->imageMap.end()) &&
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800915 (dstImageEntry != device_data->imageMap.end())) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600916
Tobin Ehlisd923d152015-09-25 14:49:43 -0600917 VkFormat srcFormat = srcImageEntry->second.format;
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800918 VkFormat dstFormat = dstImageEntry->second.format;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600919
920 // Validate consistency for signed and unsigned formats
921 if ((vk_format_is_sint(srcFormat) && !vk_format_is_sint(dstFormat)) ||
922 (vk_format_is_uint(srcFormat) && !vk_format_is_uint(dstFormat))) {
923 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700924 ss << "vkCmdBlitImage: If one of srcImage and dstImage images has signed/unsigned integer format, "
925 << "the other one must also have signed/unsigned integer format. "
926 << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
927 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
928 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600929 }
930
931 // Validate aspect bits and formats for depth/stencil images
932 if (vk_format_is_depth_or_stencil(srcFormat) ||
933 vk_format_is_depth_or_stencil(dstFormat)) {
934 if (srcFormat != dstFormat) {
935 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700936 ss << "vkCmdBlitImage: If one of srcImage and dstImage images has a format of depth, stencil or depth "
937 << "stencil, the other one must have exactly the same format. "
938 << "Source format is " << string_VkFormat(srcFormat) << " Destination format is " << string_VkFormat(dstFormat);
939 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
940 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FORMAT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600941 }
942
943 for (uint32_t i = 0; i < regionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700944 if(pRegions[i].srcSubresource.layerCount == 0)
945 {
946 char const str[] = "vkCmdBlitImage: number of layers in source subresource is zero";
947 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
948 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
949 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600950 }
951
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700952 if(pRegions[i].dstSubresource.layerCount == 0)
953 {
954 char const str[] = "vkCmdBlitImage: number of layers in destination subresource is zero";
955 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
956 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
957 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600958 }
959
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700960 if(pRegions[i].srcSubresource.layerCount != pRegions[i].dstSubresource.layerCount)
961 {
962 char const str[] = "vkCmdBlitImage: number of layers in source and destination subresources must match";
963 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
964 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -0600965 }
966
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700967 VkImageAspectFlags srcAspect = pRegions[i].srcSubresource.aspectMask;
968 VkImageAspectFlags dstAspect = pRegions[i].dstSubresource.aspectMask;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600969
970 if (srcAspect != dstAspect) {
971 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700972 ss << "vkCmdBlitImage: Image aspects of depth/stencil images should match";
973 // TODO: Verify against Valid Use section of spec, if this case yields undefined results, then it's an error
974 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
975 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600976 }
977 if (vk_format_is_depth_and_stencil(srcFormat)) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700978 if ((srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) && (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600979 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700980 ss << "vkCmdBlitImage: Combination depth/stencil image formats must have only one of VK_IMAGE_ASPECT_DEPTH_BIT "
981 << "and VK_IMAGE_ASPECT_STENCIL_BIT set in srcImage and dstImage";
982 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
983 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600984 }
985 } else if (vk_format_is_stencil_only(srcFormat)) {
986 if (srcAspect != VK_IMAGE_ASPECT_STENCIL_BIT) {
987 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700988 ss << "vkCmdBlitImage: Stencil-only image formats must have only the VK_IMAGE_ASPECT_STENCIL_BIT "
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800989 << "set in both the srcImage and dstImage";
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700990 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
991 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -0600992 }
993 } else if (vk_format_is_depth_only(srcFormat)) {
994 if (srcAspect != VK_IMAGE_ASPECT_DEPTH_BIT) {
995 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700996 ss << "vkCmdBlitImage: Depth-only image formats must have only the VK_IMAGE_ASPECT_DEPTH "
Chia-I Wu3432a0c2015-10-27 18:04:07 +0800997 << "set in both the srcImage and dstImage";
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -0700998 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
999 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001000 }
1001 }
1002 }
1003 }
1004
1005 // Validate filter
1006 if (vk_format_is_depth_or_stencil(srcFormat) ||
1007 vk_format_is_int(srcFormat)) {
Chia-I Wub99df442015-10-26 16:49:32 +08001008 if (filter != VK_FILTER_NEAREST) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001009 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001010 ss << "vkCmdBlitImage: If the format of srcImage is a depth, stencil, depth stencil or integer-based format "
Chia-I Wub99df442015-10-26 16:49:32 +08001011 << "then filter must be VK_FILTER_NEAREST.";
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001012 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1013 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_FILTER, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001014 }
1015 }
1016 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001017
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001018 device_data->device_dispatch_table->CmdBlitImage(commandBuffer, srcImage,
1019 srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions, filter);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001020}
1021
Jeremy Hayes01b38892015-11-17 18:19:55 -07001022VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdPipelineBarrier(
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001023 VkCommandBuffer commandBuffer,
1024 VkPipelineStageFlags srcStageMask,
1025 VkPipelineStageFlags dstStageMask,
1026 VkDependencyFlags dependencyFlags,
1027 uint32_t memoryBarrierCount,
1028 const VkMemoryBarrier *pMemoryBarriers,
1029 uint32_t bufferMemoryBarrierCount,
1030 const VkBufferMemoryBarrier *pBufferMemoryBarriers,
1031 uint32_t imageMemoryBarrierCount,
1032 const VkImageMemoryBarrier *pImageMemoryBarriers)
1033{
Jeremy Hayes01b38892015-11-17 18:19:55 -07001034 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001035 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Jeremy Hayes01b38892015-11-17 18:19:55 -07001036
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001037 for (uint32_t i = 0; i < imageMemoryBarrierCount; ++i)
1038 {
1039 VkImageMemoryBarrier const*const barrier = (VkImageMemoryBarrier const*const) &pImageMemoryBarriers[i];
1040 if (barrier->sType == VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER)
1041 {
1042 if (barrier->subresourceRange.layerCount == 0)
1043 {
Jeremy Hayes01b38892015-11-17 18:19:55 -07001044 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001045 ss << "vkCmdPipelineBarrier called with 0 in ppMemoryBarriers[" << i << "]->subresourceRange.layerCount.";
1046 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, (VkDebugReportObjectTypeEXT)0,
1047 0, __LINE__, IMAGE_INVALID_IMAGE_RESOURCE, "IMAGE", "%s", ss.str().c_str());
Jeremy Hayes01b38892015-11-17 18:19:55 -07001048 }
1049 }
1050 }
1051
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001052 if (skipCall)
1053 {
Jeremy Hayes01b38892015-11-17 18:19:55 -07001054 return;
1055 }
1056
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001057 device_data->device_dispatch_table->CmdPipelineBarrier(commandBuffer, srcStageMask, dstStageMask, dependencyFlags,
1058 memoryBarrierCount, pMemoryBarriers,
1059 bufferMemoryBarrierCount, pBufferMemoryBarriers,
1060 imageMemoryBarrierCount, pImageMemoryBarriers);
Jeremy Hayes01b38892015-11-17 18:19:55 -07001061}
1062
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001063VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(
1064 VkCommandBuffer commandBuffer,
1065 VkImage srcImage,
1066 VkImageLayout srcImageLayout,
1067 VkImage dstImage,
1068 VkImageLayout dstImageLayout,
1069 uint32_t regionCount,
1070 const VkImageResolve *pRegions)
1071{
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001072 VkBool32 skipCall = VK_FALSE;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001073 layer_data *device_data = get_my_data_ptr(get_dispatch_key(commandBuffer), layer_data_map);
Chia-I Wue2fc5522015-10-26 20:04:44 +08001074 auto srcImageEntry = device_data->imageMap.find(srcImage);
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001075 auto dstImageEntry = device_data->imageMap.find(dstImage);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001076
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001077 // For each region, the number of layers in the image subresource should not be zero
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001078 // For each region, src and dest image aspect must be color only
1079 for (uint32_t i = 0; i < regionCount; i++) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001080 if(pRegions[i].srcSubresource.layerCount == 0)
1081 {
1082 char const str[] = "vkCmdResolveImage: number of layers in source subresource is zero";
1083 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
1084 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1085 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001086 }
1087
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001088 if(pRegions[i].dstSubresource.layerCount == 0)
1089 {
1090 char const str[] = "vkCmdResolveImage: number of layers in destination subresource is zero";
Courtney Goeltzenleuchter7415d5a2015-12-09 15:48:16 -07001091
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001092 // TODO: Verify against Valid Use section of spec. Generally if something yield an undefined result, it's invalid/error
1093 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_WARN_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1094 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_ASPECT, "IMAGE", str);
Jeremy Hayes148bab22015-10-28 13:01:39 -06001095 }
1096
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001097 if ((pRegions[i].srcSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) ||
1098 (pRegions[i].dstSubresource.aspectMask != VK_IMAGE_ASPECT_COLOR_BIT)) {
1099 char const str[] = "vkCmdResolveImage: src and dest aspectMasks for each region must specify only VK_IMAGE_ASPECT_COLOR_BIT";
1100 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1101 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", str);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001102 }
1103 }
1104
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001105 if ((srcImageEntry != device_data->imageMap.end()) &&
Chia-I Wu3432a0c2015-10-27 18:04:07 +08001106 (dstImageEntry != device_data->imageMap.end())) {
1107 if (srcImageEntry->second.format != dstImageEntry->second.format) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001108 char const str[] = "vkCmdResolveImage called with unmatched source and dest formats.";
1109 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1110 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_FORMAT, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001111 }
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001112 if (srcImageEntry->second.imageType != dstImageEntry->second.imageType) {
1113 char const str[] = "vkCmdResolveImage called with unmatched source and dest image types.";
1114 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1115 (uint64_t)commandBuffer, __LINE__, IMAGE_MISMATCHED_IMAGE_TYPE, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001116 }
Chia-I Wu5c17c962015-10-31 00:31:16 +08001117 if (srcImageEntry->second.samples == VK_SAMPLE_COUNT_1_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001118 char const str[] = "vkCmdResolveImage called with source sample count less than 2.";
1119 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1120 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001121 }
Chia-I Wu5c17c962015-10-31 00:31:16 +08001122 if (dstImageEntry->second.samples != VK_SAMPLE_COUNT_1_BIT) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001123 char const str[] = "vkCmdResolveImage called with dest sample count greater than 1.";
1124 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT,
1125 (uint64_t)commandBuffer, __LINE__, IMAGE_INVALID_RESOLVE_SAMPLES, "IMAGE", str);
Mike Stroyana3082432015-09-25 13:39:21 -06001126 }
1127 }
1128
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001129 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001130 device_data->device_dispatch_table->CmdResolveImage(commandBuffer, srcImage,
1131 srcImageLayout, dstImage, dstImageLayout, regionCount, pRegions);
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001132 }
1133}
1134
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001135VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetImageSubresourceLayout(
1136 VkDevice device,
1137 VkImage image,
1138 const VkImageSubresource *pSubresource,
1139 VkSubresourceLayout *pLayout)
1140{
1141 VkBool32 skipCall = VK_FALSE;
1142 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
1143 VkFormat format;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001144
Chia-I Wue2fc5522015-10-26 20:04:44 +08001145 auto imageEntry = device_data->imageMap.find(image);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001146
1147 // Validate that image aspects match formats
1148 if (imageEntry != device_data->imageMap.end()) {
Tobin Ehlisd923d152015-09-25 14:49:43 -06001149 format = imageEntry->second.format;
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001150 if (vk_format_is_color(format)) {
Chia-I Wu52b07e72015-10-27 19:55:05 +08001151 if (pSubresource->aspectMask != VK_IMAGE_ASPECT_COLOR_BIT) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001152 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001153 ss << "vkGetImageSubresourceLayout: For color formats, the aspectMask field of VkImageSubresource must be VK_IMAGE_ASPECT_COLOR.";
1154 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
1155 (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001156 }
1157 } else if (vk_format_is_depth_or_stencil(format)) {
Chia-I Wu52b07e72015-10-27 19:55:05 +08001158 if ((pSubresource->aspectMask != VK_IMAGE_ASPECT_DEPTH_BIT) &&
1159 (pSubresource->aspectMask != VK_IMAGE_ASPECT_STENCIL_BIT)) {
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001160 std::stringstream ss;
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001161 ss << "vkGetImageSubresourceLayout: For depth/stencil formats, the aspectMask selects either the depth or stencil image aspectMask.";
1162 skipCall |= log_msg(device_data->report_data, VK_DEBUG_REPORT_ERROR_BIT_EXT, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT,
1163 (uint64_t)image, __LINE__, IMAGE_INVALID_IMAGE_ASPECT, "IMAGE", "%s", ss.str().c_str());
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001164 }
1165 }
1166 }
1167
1168 if (VK_FALSE == skipCall) {
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001169 device_data->device_dispatch_table->GetImageSubresourceLayout(device,
1170 image, pSubresource, pLayout);
Mark Lobodzinskidc86b852015-10-23 14:20:31 -06001171 }
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001172}
1173
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001174VK_LAYER_EXPORT VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(VkPhysicalDevice physicalDevice, VkPhysicalDeviceProperties* pProperties)
1175{
1176 layer_data *phy_dev_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
1177 phy_dev_data->instance_dispatch_table->GetPhysicalDeviceProperties(physicalDevice, pProperties);
Mark Lobodzinskid5a23822015-11-12 15:14:35 -07001178}
1179
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001180VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device, const char* funcName)
1181{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001182 if (!strcmp(funcName, "vkGetDeviceProcAddr"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001183 return (PFN_vkVoidFunction) vkGetDeviceProcAddr;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001184 if (!strcmp(funcName, "vkDestroyDevice"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001185 return (PFN_vkVoidFunction) vkDestroyDevice;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001186 if (!strcmp(funcName, "vkCreateImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001187 return (PFN_vkVoidFunction) vkCreateImage;
Mark Lobodzinski46fc3dd2015-10-29 12:58:33 -06001188 if (!strcmp(funcName, "vkDestroyImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001189 return (PFN_vkVoidFunction) vkDestroyImage;
Tobin Ehliscde08892015-09-22 10:11:37 -06001190 if (!strcmp(funcName, "vkCreateImageView"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001191 return (PFN_vkVoidFunction) vkCreateImageView;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001192 if (!strcmp(funcName, "vkCreateRenderPass"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001193 return (PFN_vkVoidFunction) vkCreateRenderPass;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001194 if (!strcmp(funcName, "vkCmdClearColorImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001195 return (PFN_vkVoidFunction) vkCmdClearColorImage;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001196 if (!strcmp(funcName, "vkCmdClearDepthStencilImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001197 return (PFN_vkVoidFunction) vkCmdClearDepthStencilImage;
Courtney Goeltzenleuchterc9323e02015-10-15 16:51:05 -06001198 if (!strcmp(funcName, "vkCmdClearAttachments"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001199 return (PFN_vkVoidFunction) vkCmdClearAttachments;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001200 if (!strcmp(funcName, "vkCmdCopyImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001201 return (PFN_vkVoidFunction) vkCmdCopyImage;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001202 if (!strcmp(funcName, "vkCmdCopyImageToBuffer"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001203 return (PFN_vkVoidFunction) vkCmdCopyImageToBuffer;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001204 if (!strcmp(funcName, "vkCmdCopyBufferToImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001205 return (PFN_vkVoidFunction) vkCmdCopyBufferToImage;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001206 if (!strcmp(funcName, "vkCmdBlitImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001207 return (PFN_vkVoidFunction) vkCmdBlitImage;
Jeremy Hayes01b38892015-11-17 18:19:55 -07001208 if (!strcmp(funcName, "vkCmdPipelineBarrier"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001209 return (PFN_vkVoidFunction) vkCmdPipelineBarrier;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001210 if (!strcmp(funcName, "vkCmdResolveImage"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001211 return (PFN_vkVoidFunction) vkCmdResolveImage;
Mark Lobodzinskia5eabe72015-10-05 17:16:05 -06001212 if (!strcmp(funcName, "vkGetImageSubresourceLayout"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001213 return (PFN_vkVoidFunction) vkGetImageSubresourceLayout;
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -06001214
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001215 if (device == NULL) {
1216 return NULL;
1217 }
1218
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001219 layer_data *my_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001220
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001221 VkLayerDispatchTable* pTable = my_data->device_dispatch_table;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001222 {
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -06001223 if (pTable->GetDeviceProcAddr == NULL)
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001224 return NULL;
Tobin Ehlisb74f6ab2015-10-29 14:19:18 -06001225 return pTable->GetDeviceProcAddr(device, funcName);
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001226 }
1227}
1228
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001229VK_LAYER_EXPORT VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
1230{
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001231 if (!strcmp(funcName, "vkGetInstanceProcAddr"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001232 return (PFN_vkVoidFunction) vkGetInstanceProcAddr;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001233 if (!strcmp(funcName, "vkCreateInstance"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001234 return (PFN_vkVoidFunction) vkCreateInstance;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001235 if (!strcmp(funcName, "vkDestroyInstance"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001236 return (PFN_vkVoidFunction) vkDestroyInstance;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001237 if (!strcmp(funcName, "vkCreateDevice"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001238 return (PFN_vkVoidFunction) vkCreateDevice;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001239 if (!strcmp(funcName, "vkEnumerateInstanceLayerProperties"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001240 return (PFN_vkVoidFunction) vkEnumerateInstanceLayerProperties;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001241 if (!strcmp(funcName, "vkEnumerateInstanceExtensionProperties"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001242 return (PFN_vkVoidFunction) vkEnumerateInstanceExtensionProperties;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001243 if (!strcmp(funcName, "vkEnumerateDeviceLayerProperties"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001244 return (PFN_vkVoidFunction) vkEnumerateDeviceLayerProperties;
Courtney Goeltzenleuchter35985f62015-09-14 17:22:16 -06001245 if (!strcmp(funcName, "vkEnumerateDeviceExtensionProperties"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001246 return (PFN_vkVoidFunction) vkEnumerateDeviceExtensionProperties;
Mark Lobodzinskid5a23822015-11-12 15:14:35 -07001247 if (!strcmp(funcName, "vkGetPhysicalDeviceProperties"))
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001248 return (PFN_vkVoidFunction) vkGetPhysicalDeviceProperties;
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001249
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001250 if (instance == NULL) {
1251 return NULL;
1252 }
1253
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001254 layer_data *my_data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001255
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001256 PFN_vkVoidFunction fptr = debug_report_get_instance_proc_addr(my_data->report_data, funcName);
1257 if(fptr)
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001258 return fptr;
1259
Mark Lobodzinski1ed594e2016-02-03 09:57:14 -07001260 VkLayerInstanceDispatchTable* pTable = my_data->instance_dispatch_table;
Courtney Goeltzenleuchter00150eb2016-01-08 12:18:43 -07001261 if (pTable->GetInstanceProcAddr == NULL)
1262 return NULL;
1263 return pTable->GetInstanceProcAddr(instance, funcName);
Jeremy Hayes9cc31582015-06-18 10:12:39 -06001264}