blob: d42cf2a6be4a1bba87ee343751c4299fbb65af92 [file] [log] [blame]
Jeremy Hayesb707aa52015-06-18 10:12:39 -06001/*
2 * Vulkan
3 *
4 * Copyright (C) 2014 LunarG, Inc.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 */
24
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <iostream>
30#include <string>
31#include <sstream>
32#include <unordered_map>
33
34#include "loader_platform.h"
Tobin Ehlis2d1d9702015-07-03 09:42:57 -060035#include "vk_layer.h"
Tobin Ehlis56d204a2015-07-03 10:15:26 -060036#include "vk_layer_config.h"
Jeremy Hayesb707aa52015-06-18 10:12:39 -060037#include "vk_enum_validate_helper.h"
38#include "vk_struct_validate_helper.h"
39//The following is #included again to catch certain OS-specific functions being used:
40#include "loader_platform.h"
41
Tobin Ehlis56d204a2015-07-03 10:15:26 -060042#include "vk_layer_table.h"
43#include "vk_layer_data.h"
44#include "vk_layer_logging.h"
Jeremy Hayesb707aa52015-06-18 10:12:39 -060045
46typedef struct _layer_data {
47 debug_report_data *report_data;
48 VkDbgMsgCallback logging_callback;
Chris Forbesd7576302015-06-21 22:55:02 +120049 VkPhysicalDevice physicalDevice;
Jeremy Hayesb707aa52015-06-18 10:12:39 -060050} layer_data;
51
52static std::unordered_map<void*, layer_data*> layer_data_map;
53static device_table_map image_device_table_map;
54static instance_table_map image_instance_table_map;
55
56// "my device data"
57debug_report_data *mdd(VkObject object)
58{
59 dispatch_key key = get_dispatch_key(object);
60 layer_data *data = get_my_data_ptr(key, layer_data_map);
61#if DISPATCH_MAP_DEBUG
62 fprintf(stderr, "MDD: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
63#endif
Jeremy Hayesb707aa52015-06-18 10:12:39 -060064 return data->report_data;
65}
66
67// "my instance data"
68debug_report_data *mid(VkInstance object)
69{
70 dispatch_key key = get_dispatch_key(object);
Courtney Goeltzenleuchter07199212015-06-22 16:19:14 -060071 layer_data *data = get_my_data_ptr(key, layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -060072#if DISPATCH_MAP_DEBUG
73 fprintf(stderr, "MID: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
74#endif
Jeremy Hayesb707aa52015-06-18 10:12:39 -060075 return data->report_data;
76}
77
78static void InitImage(layer_data *data)
79{
80 uint32_t report_flags = getLayerOptionFlags("ImageReportFlags", 0);
81
82 uint32_t debug_action = 0;
83 getLayerOptionEnum("ImageDebugAction", (uint32_t *) &debug_action);
84 if(debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
85 {
86 FILE *log_output = NULL;
87 const char* option_str = getLayerOption("ImageLogFilename");
88 if(option_str)
89 {
90 log_output = fopen(option_str, "w");
91 }
92 if(log_output == NULL)
93 {
94 log_output = stdout;
95 }
96
97 layer_create_msg_callback(data->report_data, report_flags, log_callback, (void*)log_output, &data->logging_callback);
98 }
99}
100
101VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(
102 VkInstance instance,
103 VkFlags msgFlags,
104 const PFN_vkDbgMsgCallback pfnMsgCallback,
105 void* pUserData,
106 VkDbgMsgCallback* pMsgCallback)
107{
108 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
109 VkResult res = pTable->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
110 if (res == VK_SUCCESS) {
111 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
112
113 res = layer_create_msg_callback(data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
114 }
115 return res;
116}
117
118VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(
119 VkInstance instance,
120 VkDbgMsgCallback msgCallback)
121{
122 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
123 VkResult res = pTable->DbgDestroyMsgCallback(instance, msgCallback);
124
125 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
126 layer_destroy_msg_callback(data->report_data, msgCallback);
127
128 return res;
129}
130
131VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
132{
133 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, *pInstance);
134 VkResult result = pTable->CreateInstance(pCreateInfo, pInstance);
135
136 if (result == VK_SUCCESS) {
137 layer_data *data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
138 data->report_data = debug_report_create_instance(pTable, *pInstance, pCreateInfo->extensionCount,
139 pCreateInfo->pEnabledExtensions);
140
141 InitImage(data);
142 }
143
144 return result;
145}
146
147VK_LAYER_EXPORT VkResult VKAPI vkDestroyInstance(VkInstance instance)
148{
149 // Grab the key before the instance is destroyed.
150 dispatch_key key = get_dispatch_key(instance);
151 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
152 VkResult result = pTable->DestroyInstance(instance);
153
154 // Clean up logging callback, if any
155 layer_data *data = get_my_data_ptr(key, layer_data_map);
156 if(data->logging_callback)
157 {
158 layer_destroy_msg_callback(data->report_data, data->logging_callback);
159 }
160
161 layer_debug_report_destroy_instance(mid(instance));
162 layer_data_map.erase(pTable);
163
164 image_instance_table_map.erase(key);
165 assert(image_instance_table_map.size() == 0 && "Should not have any instance mappings hanging around");
166
167 return result;
168}
169
170VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice)
171{
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600172 VkLayerDispatchTable *pTable = get_dispatch_table(image_device_table_map, *pDevice);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600173 VkResult result = pTable->CreateDevice(physicalDevice, pCreateInfo, pDevice);
174 if(result == VK_SUCCESS)
175 {
176 layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
177 layer_data *device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
178 device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
Chris Forbesd7576302015-06-21 22:55:02 +1200179 device_data->physicalDevice = physicalDevice;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600180 }
181
182 return result;
183}
184
185VK_LAYER_EXPORT VkResult VKAPI vkDestroyDevice(VkDevice device)
186{
187 layer_debug_report_destroy_device(device);
188
189 dispatch_key key = get_dispatch_key(device);
190#if DISPATCH_MAP_DEBUG
191 fprintf(stderr, "Device: %p, key: %p\n", device, key);
192#endif
193
194 VkResult result = get_dispatch_table(image_device_table_map, device)->DestroyDevice(device);
195 image_device_table_map.erase(key);
196 assert(image_device_table_map.size() == 0 && "Should not have any instance mappings hanging around");
197
198 return result;
199}
200
201#define IMAGE_LAYER_EXT_ARRAY_SIZE 2
202static const VkExtensionProperties pcExts[IMAGE_LAYER_EXT_ARRAY_SIZE] = {
203 {
204 VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
205 "Image",
206 0x10,
207 "Sample layer: Image",
208 },
209 {
210 VK_STRUCTURE_TYPE_EXTENSION_PROPERTIES,
211 "Validation",
212 0x10,
213 "Sample layer: Image",
214 }
215};
Tony Barbour426b9052015-06-24 16:06:58 -0600216VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionCount(
217 uint32_t* pCount)
218{
219 *pCount = IMAGE_LAYER_EXT_ARRAY_SIZE;
220 return VK_SUCCESS;
221}
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600222
Tony Barbour426b9052015-06-24 16:06:58 -0600223VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionProperties(
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600224 uint32_t extensionIndex,
Tony Barbour426b9052015-06-24 16:06:58 -0600225 VkExtensionProperties* pProperties)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600226{
227 /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600228
Tony Barbour426b9052015-06-24 16:06:58 -0600229 if (extensionIndex >= IMAGE_LAYER_EXT_ARRAY_SIZE)
230 return VK_ERROR_INVALID_VALUE;
231 memcpy(pProperties, &pcExts[extensionIndex], sizeof(VkExtensionProperties));
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600232
233 return VK_SUCCESS;
234}
235
Tony Barbour426b9052015-06-24 16:06:58 -0600236VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionCount(
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600237 VkPhysicalDevice gpu,
Tony Barbour426b9052015-06-24 16:06:58 -0600238 uint32_t* pCount)
239{
240 *pCount = IMAGE_LAYER_EXT_ARRAY_SIZE;
241 return VK_SUCCESS;
242}
243
244VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionProperties(
245 VkPhysicalDevice gpu,
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600246 uint32_t extensionIndex,
Tony Barbour426b9052015-06-24 16:06:58 -0600247 VkExtensionProperties* pProperties)
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600248{
249 /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600250
Tony Barbour426b9052015-06-24 16:06:58 -0600251 if (extensionIndex >= IMAGE_LAYER_EXT_ARRAY_SIZE)
252 return VK_ERROR_INVALID_VALUE;
253 memcpy(pProperties, &pcExts[extensionIndex], sizeof(VkExtensionProperties));
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600254
255 return VK_SUCCESS;
256}
257
258VK_LAYER_EXPORT VkResult VKAPI vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage)
259{
260 if(pCreateInfo->format != VK_FORMAT_UNDEFINED)
261 {
Courtney Goeltzenleuchter07199212015-06-22 16:19:14 -0600262 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600263 VkFormatProperties properties;
Chris Forbesd7576302015-06-21 22:55:02 +1200264 VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatInfo(
265 device_data->physicalDevice, pCreateInfo->format, &properties);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600266 if(result != VK_SUCCESS)
267 {
268 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, cannot be validated";
269 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
270 }
271
272 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
273 {
274 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
275 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
276 }
277 }
278
279 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateImage(device, pCreateInfo, pImage);
280
281 return result;
282}
283
284VK_LAYER_EXPORT VkResult VKAPI vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass)
285{
286 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
287 {
288 if(pCreateInfo->pColorFormats[i] != VK_FORMAT_UNDEFINED)
289 {
Courtney Goeltzenleuchter07199212015-06-22 16:19:14 -0600290 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600291 VkFormatProperties properties;
Chris Forbesd7576302015-06-21 22:55:02 +1200292 VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatInfo(
293 device_data->physicalDevice, pCreateInfo->pColorFormats[i], &properties);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600294 if(result != VK_SUCCESS)
295 {
296 std::stringstream ss;
297 ss << "vkCreateRenderPass parameter, VkFormat pCreateInfo->pColorFormats[" << i << "], cannot be validated";
298 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
299 continue;
300 }
301
302 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
303 {
304 std::stringstream ss;
305 ss << "vkCreateRenderPass parameter, VkFormat pCreateInfo->pColorFormats[" << i << "], contains unsupported format";
306 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
307 }
308 }
309 }
310
311 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
312 {
313 if(!validate_VkImageLayout(pCreateInfo->pColorLayouts[i]))
314 {
315 std::stringstream ss;
316 ss << "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pColorLayouts[" << i << "], is unrecognized";
317 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
318 }
319 }
320
321 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
322 {
323 if(!validate_VkAttachmentLoadOp(pCreateInfo->pColorLoadOps[i]))
324 {
325 std::stringstream ss;
326 ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp pCreateInfo->pColorLoadOps[" << i << "], is unrecognized";
327 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
328 }
329 }
330
331 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
332 {
333 if(!validate_VkAttachmentStoreOp(pCreateInfo->pColorStoreOps[i]))
334 {
335 std::stringstream ss;
336 ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp pCreateInfo->pColorStoreOps[" << i << "], is unrecognized";
337 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
338 }
339 }
340
341 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
342 {
Chris Forbese3105972015-06-24 14:34:53 +1200343 if(!vk_validate_vkclearcolorvalue(&(pCreateInfo->pColorLoadClearValues[i])))
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600344 {
345 std::stringstream ss;
Chris Forbese3105972015-06-24 14:34:53 +1200346 ss << "vkCreateRenderPass parameter, VkClearColorValue pCreateInfo->pColorLoadClearValues[" << i << "], is invalid";
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600347 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
348 }
349 }
350
351 if(pCreateInfo->depthStencilFormat != VK_FORMAT_UNDEFINED)
352 {
Courtney Goeltzenleuchter07199212015-06-22 16:19:14 -0600353 layer_data *device_data = get_my_data_ptr(get_dispatch_key(device), layer_data_map);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600354 VkFormatProperties properties;
Chris Forbesd7576302015-06-21 22:55:02 +1200355 VkResult result = get_dispatch_table(image_instance_table_map, device_data->physicalDevice)->GetPhysicalDeviceFormatInfo(
356 device_data->physicalDevice, pCreateInfo->depthStencilFormat, &properties);
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600357 if(result != VK_SUCCESS)
358 {
359 char const str[] = "vkCreateRenderPass parameter, VkFormat pCreateInfo->depthStencilFormat, cannot be validated";
360 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
361 }
362
363 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
364 {
365 char const str[] = "vkCreateRenderPass parameter, VkFormat pCreateInfo->depthStencilFormat, contains unsupported format";
366 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
367 }
368 }
369
370 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateRenderPass(device, pCreateInfo, pRenderPass);
371
372 return result;
373}
374
375VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
376{
377 if (device == NULL) {
378 return NULL;
379 }
380
381 /* loader uses this to force layer initialization; device object is wrapped */
382 if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
383 initDeviceTable(image_device_table_map, (const VkBaseLayerObject *) device);
384 return (void*) vkGetDeviceProcAddr;
385 }
386
Courtney Goeltzenleuchterbe637992015-06-25 18:01:43 -0600387 if (!strcmp(funcName, "vkCreateDevice"))
388 return (void*) vkCreateDevice;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600389 if (!strcmp(funcName, "vkDestroyDevice"))
390 return (void*) vkDestroyDevice;
391 if (!strcmp(funcName, "vkCreateImage"))
392 return (void*) vkCreateImage;
393 if (!strcmp(funcName, "vkCreateRenderPass"))
394 return (void*) vkCreateRenderPass;
Tony Barbour426b9052015-06-24 16:06:58 -0600395 if (!strcmp(funcName, "vkGetGlobalExtensionProperties"))
396 return (void*) vkGetGlobalExtensionProperties;
397 if (!strcmp(funcName, "vkGetGlobalExtensionCount"))
398 return (void*) vkGetGlobalExtensionCount;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600399
400 {
401 if (get_dispatch_table(image_device_table_map, device)->GetDeviceProcAddr == NULL)
402 return NULL;
403 return get_dispatch_table(image_device_table_map, device)->GetDeviceProcAddr(device, funcName);
404 }
405}
406
407VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
408{
409 if (instance == NULL) {
410 return NULL;
411 }
412
413 /* loader uses this to force layer initialization; instance object is wrapped */
414 if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
415 initInstanceTable(image_instance_table_map, (const VkBaseLayerObject *) instance);
416 return (void *) vkGetInstanceProcAddr;
417 }
418
419 if (!strcmp(funcName, "vkCreateInstance"))
420 return (void*) vkCreateInstance;
421 if (!strcmp(funcName, "vkDestroyInstance"))
422 return (void *) vkDestroyInstance;
Tony Barbour426b9052015-06-24 16:06:58 -0600423 if (!strcmp(funcName, "vkGetPhysicalDeviceExtensionProperties"))
424 return (void*) vkGetPhysicalDeviceExtensionProperties;
425 if (!strcmp(funcName, "vkGetPhysicalDeviceExtensionCount"))
426 return (void*) vkGetPhysicalDeviceExtensionCount;
Jeremy Hayesb707aa52015-06-18 10:12:39 -0600427
428 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
429 void* fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
430 if(fptr)
431 return fptr;
432
433 {
434 if (get_dispatch_table(image_instance_table_map, instance)->GetInstanceProcAddr == NULL)
435 return NULL;
436 return get_dispatch_table(image_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
437 }
438}