1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
|
#ifndef WITH_VALIDATION
#define WITH_VALIDATION
#endif
#include <assert.h>
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <vulkan/vulkan.h>
#include "eprintf.h"
#include "nelem.h"
#include "validation.h"
static const char *vlayers[] = {
"VK_LAYER_LUNARG_standard_validation",
};
static const char *vexts[] = {
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
};
// callback: Validation callback
static VKAPI_ATTR VkBool32 VKAPI_CALL callback(
VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT type,
uint64_t obj, size_t location, int32_t code, const char
*prefix, const char *msg, void *data)
{
(void)flags; (void)type; (void)obj; (void)location;
(void)code; (void)prefix; (void)data;
weprintf("Validation: %s", msg);
return VK_FALSE;
}
// havelayers: Check if all required validation layers are supported
static bool havelayers(void)
{
VkLayerProperties *instlrp;
uint32_t ninstlrp;
static enum { UNK, NO, YES } have = UNK;
if (have != UNK) return have == YES;
have = NO;
vkEnumerateInstanceLayerProperties(&ninstlrp, NULL);
instlrp = emalloc(ninstlrp * sizeof *instlrp);
vkEnumerateInstanceLayerProperties(&ninstlrp, instlrp);
for (size_t vl = 0; vl < NELEM(vlayers); vl++) {
for (uint32_t il = 0; il < ninstlrp; il++)
if (strcmp(vlayers[vl], instlrp[il].layerName) == 0)
goto next;
goto fail_layers;
next: ;
}
have = YES;
fail_layers: free(instlrp);
return have == YES;
}
// validation_info: Append validation layers and extension
void validation_info(struct strlist *layers, struct strlist *exts)
{
if (havelayers() && layers != NULL)
sl_append(layers, vlayers, NELEM(vlayers));
if (exts != NULL) sl_append(exts, vexts, NELEM(vexts));
}
// validation_createcb: Create the validation callback
void *validation_createcb(VkInstance inst)
{
VkDebugReportCallbackCreateInfoEXT rccinf;
PFN_vkCreateDebugReportCallbackEXT func;
VkDebugReportCallbackEXT *cb;
func = (PFN_vkCreateDebugReportCallbackEXT)
vkGetInstanceProcAddr(inst, "vkCreateDebugReportCallbackEXT");
if (func == NULL)
eprintf("Validation: Could not create callback: Failed to get constructor");
rccinf = (VkDebugReportCallbackCreateInfoEXT){
.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT,
.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT,
.pfnCallback = callback,
};
cb = emalloc(sizeof *cb);
if (func(inst, &rccinf, NULL, cb) != VK_SUCCESS)
eprintf("Validation: Could not create callback: Constructor");
return cb;
}
// validation_destroycb: Destroy the validation callback
void validation_destroycb(VkInstance inst, void *_cb)
{
PFN_vkDestroyDebugReportCallbackEXT func;
VkDebugReportCallbackEXT *cb = _cb;
assert(cb != NULL);
func = (PFN_vkDestroyDebugReportCallbackEXT)
vkGetInstanceProcAddr(inst, "vkDestroyDebugReportCallbackEXT");
if (func == NULL)
eprintf("Validation: Could not destroy callback: Failed to get destructor");
func(inst, *cb, NULL);
free(cb);
}
|