summaryrefslogtreecommitdiffstats
path: root/validation.c
blob: cfe258a823d7993b574b18f4f9948907af052da2 (plain)
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);
}