blob: cac66a5a924b5391ec93ec1533c5891e6e66d999 [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"
35#include "vkLayer.h"
36#include "layers_config.h"
37#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
42#include "layers_table.h"
43#include "layer_data.h"
44#include "layer_logging.h"
45
46typedef struct _layer_data {
47 debug_report_data *report_data;
48 VkDbgMsgCallback logging_callback;
49} layer_data;
50
51static std::unordered_map<void*, layer_data*> layer_data_map;
52static device_table_map image_device_table_map;
53static instance_table_map image_instance_table_map;
54
55// "my device data"
56debug_report_data *mdd(VkObject object)
57{
58 dispatch_key key = get_dispatch_key(object);
59 layer_data *data = get_my_data_ptr(key, layer_data_map);
60#if DISPATCH_MAP_DEBUG
61 fprintf(stderr, "MDD: map: %p, object: %p, key: %p, data: %p\n", &layer_data_map, object, key, data);
62#endif
63 assert(data->report_data != NULL);
64 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);
71 layer_data *data = get_my_data_ptr(get_dispatch_key(object), layer_data_map);
72#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
75 assert(data->report_data != NULL);
76 return data->report_data;
77}
78
79static void InitImage(layer_data *data)
80{
81 uint32_t report_flags = getLayerOptionFlags("ImageReportFlags", 0);
82
83 uint32_t debug_action = 0;
84 getLayerOptionEnum("ImageDebugAction", (uint32_t *) &debug_action);
85 if(debug_action & VK_DBG_LAYER_ACTION_LOG_MSG)
86 {
87 FILE *log_output = NULL;
88 const char* option_str = getLayerOption("ImageLogFilename");
89 if(option_str)
90 {
91 log_output = fopen(option_str, "w");
92 }
93 if(log_output == NULL)
94 {
95 log_output = stdout;
96 }
97
98 layer_create_msg_callback(data->report_data, report_flags, log_callback, (void*)log_output, &data->logging_callback);
99 }
100}
101
102VK_LAYER_EXPORT VkResult VKAPI vkDbgCreateMsgCallback(
103 VkInstance instance,
104 VkFlags msgFlags,
105 const PFN_vkDbgMsgCallback pfnMsgCallback,
106 void* pUserData,
107 VkDbgMsgCallback* pMsgCallback)
108{
109 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
110 VkResult res = pTable->DbgCreateMsgCallback(instance, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
111 if (res == VK_SUCCESS) {
112 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
113
114 res = layer_create_msg_callback(data->report_data, msgFlags, pfnMsgCallback, pUserData, pMsgCallback);
115 }
116 return res;
117}
118
119VK_LAYER_EXPORT VkResult VKAPI vkDbgDestroyMsgCallback(
120 VkInstance instance,
121 VkDbgMsgCallback msgCallback)
122{
123 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
124 VkResult res = pTable->DbgDestroyMsgCallback(instance, msgCallback);
125
126 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
127 layer_destroy_msg_callback(data->report_data, msgCallback);
128
129 return res;
130}
131
132VK_LAYER_EXPORT VkResult VKAPI vkCreateInstance(const VkInstanceCreateInfo* pCreateInfo, VkInstance* pInstance)
133{
134 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, *pInstance);
135 VkResult result = pTable->CreateInstance(pCreateInfo, pInstance);
136
137 if (result == VK_SUCCESS) {
138 layer_data *data = get_my_data_ptr(get_dispatch_key(*pInstance), layer_data_map);
139 data->report_data = debug_report_create_instance(pTable, *pInstance, pCreateInfo->extensionCount,
140 pCreateInfo->pEnabledExtensions);
141
142 InitImage(data);
143 }
144
145 return result;
146}
147
148VK_LAYER_EXPORT VkResult VKAPI vkDestroyInstance(VkInstance instance)
149{
150 // Grab the key before the instance is destroyed.
151 dispatch_key key = get_dispatch_key(instance);
152 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, instance);
153 VkResult result = pTable->DestroyInstance(instance);
154
155 // Clean up logging callback, if any
156 layer_data *data = get_my_data_ptr(key, layer_data_map);
157 if(data->logging_callback)
158 {
159 layer_destroy_msg_callback(data->report_data, data->logging_callback);
160 }
161
162 layer_debug_report_destroy_instance(mid(instance));
163 layer_data_map.erase(pTable);
164
165 image_instance_table_map.erase(key);
166 assert(image_instance_table_map.size() == 0 && "Should not have any instance mappings hanging around");
167
168 return result;
169}
170
171VK_LAYER_EXPORT VkResult VKAPI vkCreateDevice(VkPhysicalDevice physicalDevice, const VkDeviceCreateInfo* pCreateInfo, VkDevice* pDevice)
172{
173 VkLayerInstanceDispatchTable *pTable = get_dispatch_table(image_instance_table_map, physicalDevice);
174 VkResult result = pTable->CreateDevice(physicalDevice, pCreateInfo, pDevice);
175 if(result == VK_SUCCESS)
176 {
177 layer_data *instance_data = get_my_data_ptr(get_dispatch_key(physicalDevice), layer_data_map);
178 layer_data *device_data = get_my_data_ptr(get_dispatch_key(*pDevice), layer_data_map);
179 device_data->report_data = layer_debug_report_create_device(instance_data->report_data, *pDevice);
180 }
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};
216
217VK_LAYER_EXPORT VkResult VKAPI vkGetGlobalExtensionInfo(
218 VkExtensionInfoType infoType,
219 uint32_t extensionIndex,
220 size_t* pDataSize,
221 void* pData)
222{
223 /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
224 uint32_t *count = NULL;
225
226 if (pDataSize == NULL)
227 {
228 return VK_ERROR_INVALID_POINTER;
229 }
230
231 switch (infoType) {
232 case VK_EXTENSION_INFO_TYPE_COUNT:
233 *pDataSize = sizeof(uint32_t);
234 if (pData == NULL)
235 return VK_SUCCESS;
236 count = (uint32_t *) pData;
237 *count = IMAGE_LAYER_EXT_ARRAY_SIZE;
238 break;
239 case VK_EXTENSION_INFO_TYPE_PROPERTIES:
240 *pDataSize = sizeof(VkExtensionProperties);
241 if (pData == NULL)
242 return VK_SUCCESS;
243 if (extensionIndex >= IMAGE_LAYER_EXT_ARRAY_SIZE)
244 return VK_ERROR_INVALID_VALUE;
245 memcpy((VkExtensionProperties *) pData, &pcExts[extensionIndex], sizeof(VkExtensionProperties));
246 break;
247 default:
248 return VK_ERROR_INVALID_VALUE;
249 };
250
251 return VK_SUCCESS;
252}
253
254VK_LAYER_EXPORT VkResult VKAPI vkGetPhysicalDeviceExtensionInfo(
255 VkPhysicalDevice gpu,
256 VkExtensionInfoType infoType,
257 uint32_t extensionIndex,
258 size_t* pDataSize,
259 void* pData)
260{
261 /* This entrypoint is NOT going to init it's own dispatch table since loader calls here early */
262 uint32_t *count = NULL;
263
264 if (pDataSize == NULL)
265 {
266 return VK_ERROR_INVALID_POINTER;
267 }
268
269 switch (infoType) {
270 case VK_EXTENSION_INFO_TYPE_COUNT:
271 *pDataSize = sizeof(uint32_t);
272 if (pData == NULL)
273 return VK_SUCCESS;
274 count = (uint32_t *) pData;
275 *count = IMAGE_LAYER_EXT_ARRAY_SIZE;
276 break;
277 case VK_EXTENSION_INFO_TYPE_PROPERTIES:
278 *pDataSize = sizeof(VkExtensionProperties);
279 if (pData == NULL)
280 return VK_SUCCESS;
281 if (extensionIndex >= IMAGE_LAYER_EXT_ARRAY_SIZE)
282 return VK_ERROR_INVALID_VALUE;
283 memcpy((VkExtensionProperties *) pData, &pcExts[extensionIndex], sizeof(VkExtensionProperties));
284 break;
285 default:
286 return VK_ERROR_INVALID_VALUE;
287 };
288
289 return VK_SUCCESS;
290}
291
292VK_LAYER_EXPORT VkResult VKAPI vkCreateImage(VkDevice device, const VkImageCreateInfo* pCreateInfo, VkImage* pImage)
293{
294 if(pCreateInfo->format != VK_FORMAT_UNDEFINED)
295 {
296 VkFormatProperties properties;
297 size_t size = sizeof(properties);
298 VkResult result = get_dispatch_table(image_device_table_map, device)->GetFormatInfo(device, pCreateInfo->format,
299 VK_FORMAT_INFO_TYPE_PROPERTIES, &size, &properties);
300 if(result != VK_SUCCESS)
301 {
302 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, cannot be validated";
303 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
304 }
305
306 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
307 {
308 char const str[] = "vkCreateImage parameter, VkFormat pCreateInfo->format, contains unsupported format";
309 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
310 }
311 }
312
313 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateImage(device, pCreateInfo, pImage);
314
315 return result;
316}
317
318VK_LAYER_EXPORT VkResult VKAPI vkCreateRenderPass(VkDevice device, const VkRenderPassCreateInfo* pCreateInfo, VkRenderPass* pRenderPass)
319{
320 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
321 {
322 if(pCreateInfo->pColorFormats[i] != VK_FORMAT_UNDEFINED)
323 {
324 VkFormatProperties properties;
325 size_t size = sizeof(properties);
326 VkResult result = get_dispatch_table(image_device_table_map, device)->GetFormatInfo(device, pCreateInfo->pColorFormats[i],
327 VK_FORMAT_INFO_TYPE_PROPERTIES, &size, &properties);
328 if(result != VK_SUCCESS)
329 {
330 std::stringstream ss;
331 ss << "vkCreateRenderPass parameter, VkFormat pCreateInfo->pColorFormats[" << i << "], cannot be validated";
332 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
333 continue;
334 }
335
336 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
337 {
338 std::stringstream ss;
339 ss << "vkCreateRenderPass parameter, VkFormat pCreateInfo->pColorFormats[" << i << "], contains unsupported format";
340 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
341 }
342 }
343 }
344
345 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
346 {
347 if(!validate_VkImageLayout(pCreateInfo->pColorLayouts[i]))
348 {
349 std::stringstream ss;
350 ss << "vkCreateRenderPass parameter, VkImageLayout pCreateInfo->pColorLayouts[" << i << "], is unrecognized";
351 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
352 }
353 }
354
355 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
356 {
357 if(!validate_VkAttachmentLoadOp(pCreateInfo->pColorLoadOps[i]))
358 {
359 std::stringstream ss;
360 ss << "vkCreateRenderPass parameter, VkAttachmentLoadOp pCreateInfo->pColorLoadOps[" << i << "], is unrecognized";
361 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
362 }
363 }
364
365 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
366 {
367 if(!validate_VkAttachmentStoreOp(pCreateInfo->pColorStoreOps[i]))
368 {
369 std::stringstream ss;
370 ss << "vkCreateRenderPass parameter, VkAttachmentStoreOp pCreateInfo->pColorStoreOps[" << i << "], is unrecognized";
371 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
372 }
373 }
374
375 for(uint32_t i = 0; i < pCreateInfo->colorAttachmentCount; ++i)
376 {
377 if(!vk_validate_vkclearcolor(&(pCreateInfo->pColorLoadClearValues[i])))
378 {
379 std::stringstream ss;
380 ss << "vkCreateRenderPass parameter, VkClearColor pCreateInfo->pColorLoadClearValues[" << i << "], is invalid";
381 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", ss.str().c_str());
382 }
383 }
384
385 if(pCreateInfo->depthStencilFormat != VK_FORMAT_UNDEFINED)
386 {
387 VkFormatProperties properties;
388 size_t size = sizeof(properties);
389 VkResult result = get_dispatch_table(image_device_table_map, device)->GetFormatInfo(device, pCreateInfo->depthStencilFormat,
390 VK_FORMAT_INFO_TYPE_PROPERTIES, &size, &properties);
391 if(result != VK_SUCCESS)
392 {
393 char const str[] = "vkCreateRenderPass parameter, VkFormat pCreateInfo->depthStencilFormat, cannot be validated";
394 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
395 }
396
397 if((properties.linearTilingFeatures) == 0 && (properties.optimalTilingFeatures == 0))
398 {
399 char const str[] = "vkCreateRenderPass parameter, VkFormat pCreateInfo->depthStencilFormat, contains unsupported format";
400 log_msg(mdd(device), VK_DBG_REPORT_WARN_BIT, (VkObjectType)0, NULL, 0, 1, "IMAGE", str);
401 }
402 }
403
404 VkResult result = get_dispatch_table(image_device_table_map, device)->CreateRenderPass(device, pCreateInfo, pRenderPass);
405
406 return result;
407}
408
409VK_LAYER_EXPORT void* VKAPI vkGetDeviceProcAddr(VkDevice device, const char* funcName)
410{
411 if (device == NULL) {
412 return NULL;
413 }
414
415 /* loader uses this to force layer initialization; device object is wrapped */
416 if (!strcmp(funcName, "vkGetDeviceProcAddr")) {
417 initDeviceTable(image_device_table_map, (const VkBaseLayerObject *) device);
418 return (void*) vkGetDeviceProcAddr;
419 }
420
421 if (!strcmp(funcName, "vkDestroyDevice"))
422 return (void*) vkDestroyDevice;
423 if (!strcmp(funcName, "vkCreateImage"))
424 return (void*) vkCreateImage;
425 if (!strcmp(funcName, "vkCreateRenderPass"))
426 return (void*) vkCreateRenderPass;
427
428 {
429 if (get_dispatch_table(image_device_table_map, device)->GetDeviceProcAddr == NULL)
430 return NULL;
431 return get_dispatch_table(image_device_table_map, device)->GetDeviceProcAddr(device, funcName);
432 }
433}
434
435VK_LAYER_EXPORT void* VKAPI vkGetInstanceProcAddr(VkInstance instance, const char* funcName)
436{
437 if (instance == NULL) {
438 return NULL;
439 }
440
441 /* loader uses this to force layer initialization; instance object is wrapped */
442 if (!strcmp(funcName, "vkGetInstanceProcAddr")) {
443 initInstanceTable(image_instance_table_map, (const VkBaseLayerObject *) instance);
444 return (void *) vkGetInstanceProcAddr;
445 }
446
447 if (!strcmp(funcName, "vkCreateInstance"))
448 return (void*) vkCreateInstance;
449 if (!strcmp(funcName, "vkDestroyInstance"))
450 return (void *) vkDestroyInstance;
451 if (!strcmp(funcName, "vkCreateDevice"))
452 return (void*) vkCreateDevice;
453 if (!strcmp(funcName, "vkGetGlobalExtensionInfo"))
454 return (void*) vkGetGlobalExtensionInfo;
455 if (!strcmp(funcName, "vkGetPhysicalDeviceExtensionInfo"))
456 return (void*) vkGetPhysicalDeviceExtensionInfo;
457
458 layer_data *data = get_my_data_ptr(get_dispatch_key(instance), layer_data_map);
459 void* fptr = debug_report_get_instance_proc_addr(data->report_data, funcName);
460 if(fptr)
461 return fptr;
462
463 {
464 if (get_dispatch_table(image_instance_table_map, instance)->GetInstanceProcAddr == NULL)
465 return NULL;
466 return get_dispatch_table(image_instance_table_map, instance)->GetInstanceProcAddr(instance, funcName);
467 }
468}