~sircmpwn/xrgears

ref: 7c503767ced2ca3450233e4447bbf057aaac6f79 xrgears/vitamin-k/render/vikDebug.hpp -rw-r--r-- 11.8 KiB
7c503767 — Lubosz Sarnecki xrgears: Use struct initializers. 2 years ago
                                                                                
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
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
 /*
 * vitamin-k
 *
 * Copyright 2016 Sascha Willems - www.saschawillems.de
 * Copyright 2017-2018 Collabora Ltd.
 *
 * Authors: Lubosz Sarnecki <lubosz.sarnecki@collabora.com>
 * SPDX-License-Identifier: MIT
 */

#pragma once

#include <math.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>

#include <vulkan/vulkan.h>

#define GLM_FORCE_RADIANS
#define GLM_FORCE_DEPTH_ZERO_TO_ONE
#include <glm/glm.hpp>

#include <string>
#include <cstring>
#include <fstream>
#include <vector>
#include <sstream>

namespace vik {
namespace debug {
// Default validation layers
// On desktop the LunarG loaders exposes a meta layer that contains all layers
static int32_t validationLayerCount = 1;
static const char *validationLayerNames[] = {
  "VK_LAYER_LUNARG_standard_validation"
};

static PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback = VK_NULL_HANDLE;
static PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback = VK_NULL_HANDLE;
static PFN_vkDebugReportMessageEXT dbgBreakCallback = VK_NULL_HANDLE;

static VkDebugReportCallbackEXT msgCallback;

// Default debug callback
static VkBool32 messageCallback(
    VkDebugReportFlagsEXT flags,
    VkDebugReportObjectTypeEXT objType,
    uint64_t srcObject,
    size_t location,
    int32_t msgCode,
    const char* pLayerPrefix,
    const char* pMsg,
    void* pUserData) {
  // Select prefix depending on flags passed to the callback
  // Note that multiple flags may be set for a single validation message
  std::string prefix("");

  // Error that may result in undefined behaviour
  if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
    prefix += "ERROR:";
  // Warnings may hint at unexpected / non-spec API usage
  if (flags & VK_DEBUG_REPORT_WARNING_BIT_EXT)
    prefix += "WARNING:";
  // May indicate sub-optimal usage of the API
  if (flags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT)
    prefix += "PERFORMANCE:";
  // Informal messages that may become handy during debugging
  if (flags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT)
    prefix += "INFO:";
  // Diagnostic info from the Vulkan loader and layers
  // Usually not helpful in terms of API usage, but may help to debug layer and loader problems
  if (flags & VK_DEBUG_REPORT_DEBUG_BIT_EXT)
    prefix += "DEBUG:";

  // Display message to default output (console/logcat)
  std::stringstream debugMessage;
  debugMessage << prefix << " [" << pLayerPrefix << "] Code " << msgCode << " : " << pMsg;

  if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT)
    std::cerr << debugMessage.str() << "\n";
  else
    std::cout << debugMessage.str() << "\n";

  fflush(stdout);

  // The return value of this callback controls wether the Vulkan call that caused
  // the validation message will be aborted or not
  // We return VK_FALSE as we DON'T want Vulkan calls that cause a validation message
  // (and return a VkResult) to abort
  // If you instead want to have calls abort, pass in VK_TRUE and the function will
  // return VK_ERROR_VALIDATION_FAILED_EXT
  return VK_FALSE;
}

// Load debug function pointers and set debug callback
// if callBack is NULL, default message callback will be used
static void setupDebugging(VkInstance instance, VkDebugReportFlagsEXT flags, VkDebugReportCallbackEXT callBack) {
  CreateDebugReportCallback = reinterpret_cast<PFN_vkCreateDebugReportCallbackEXT>(vkGetInstanceProcAddr(instance, "vkCreateDebugReportCallbackEXT"));
  DestroyDebugReportCallback = reinterpret_cast<PFN_vkDestroyDebugReportCallbackEXT>(vkGetInstanceProcAddr(instance, "vkDestroyDebugReportCallbackEXT"));
  dbgBreakCallback = reinterpret_cast<PFN_vkDebugReportMessageEXT>(vkGetInstanceProcAddr(instance, "vkDebugReportMessageEXT"));

  VkDebugReportCallbackCreateInfoEXT dbgCreateInfo = {};
  dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT;
  dbgCreateInfo.pfnCallback = (PFN_vkDebugReportCallbackEXT)messageCallback;
  dbgCreateInfo.flags = flags;

  VkResult err = CreateDebugReportCallback(
        instance,
        &dbgCreateInfo,
        nullptr,
        (callBack != VK_NULL_HANDLE) ? &callBack : &msgCallback);
  assert(!err);
}

// Clear debug callback
static void freeDebugCallback(VkInstance instance) {
  if (msgCallback != VK_NULL_HANDLE)
    DestroyDebugReportCallback(instance, msgCallback, nullptr);
}
}  // namespace debug

// Setup and functions for the VK_EXT_debug_marker_extension
// Extension spec can be found at https://github.com/KhronosGroup/Vulkan-Docs/blob/1.0-VK_EXT_debug_marker/doc/specs/vulkan/appendices/VK_EXT_debug_marker.txt
// Note that the extension will only be present if run from an offline debugging application
// The actual check for extension presence and enabling it on the device is done in the example base class
// See VulkanExampleBase::createInstance and VulkanExampleBase::createDevice (base/vulkanexamplebase.cpp)
namespace debugmarker {
// Set to true if function pointer for the debug marker are available
static bool active = false;

static PFN_vkDebugMarkerSetObjectTagEXT pfnDebugMarkerSetObjectTag = VK_NULL_HANDLE;
static PFN_vkDebugMarkerSetObjectNameEXT pfnDebugMarkerSetObjectName = VK_NULL_HANDLE;
static PFN_vkCmdDebugMarkerBeginEXT pfnCmdDebugMarkerBegin = VK_NULL_HANDLE;
static PFN_vkCmdDebugMarkerEndEXT pfnCmdDebugMarkerEnd = VK_NULL_HANDLE;
static PFN_vkCmdDebugMarkerInsertEXT pfnCmdDebugMarkerInsert = VK_NULL_HANDLE;

// Get function pointers for the debug report extensions from the device
static void setup(VkDevice device) {
  pfnDebugMarkerSetObjectTag = reinterpret_cast<PFN_vkDebugMarkerSetObjectTagEXT>(vkGetDeviceProcAddr(device, "vkDebugMarkerSetObjectTagEXT"));
  pfnDebugMarkerSetObjectName = reinterpret_cast<PFN_vkDebugMarkerSetObjectNameEXT>(vkGetDeviceProcAddr(device, "vkDebugMarkerSetObjectNameEXT"));
  pfnCmdDebugMarkerBegin = reinterpret_cast<PFN_vkCmdDebugMarkerBeginEXT>(vkGetDeviceProcAddr(device, "vkCmdDebugMarkerBeginEXT"));
  pfnCmdDebugMarkerEnd = reinterpret_cast<PFN_vkCmdDebugMarkerEndEXT>(vkGetDeviceProcAddr(device, "vkCmdDebugMarkerEndEXT"));
  pfnCmdDebugMarkerInsert = reinterpret_cast<PFN_vkCmdDebugMarkerInsertEXT>(vkGetDeviceProcAddr(device, "vkCmdDebugMarkerInsertEXT"));

  // Set flag if at least one function pointer is present
  active = (pfnDebugMarkerSetObjectName != VK_NULL_HANDLE);
}

// Sets the debug name of an object
// All Objects in Vulkan are represented by their 64-bit handles which are passed into this function
// along with the object type
/*
static void setObjectName(VkDevice device, uint64_t object, VkDebugReportObjectTypeEXT objectType, const char *name) {
  // Check for valid function pointer (may not be present if not running in a debugging application)
  if (pfnDebugMarkerSetObjectName) {
    VkDebugMarkerObjectNameInfoEXT nameInfo = {};
    nameInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_NAME_INFO_EXT;
    nameInfo.objectType = objectType;
    nameInfo.object = object;
    nameInfo.pObjectName = name;
    pfnDebugMarkerSetObjectName(device, &nameInfo);
  }
}
// Set the tag for an object
static void setObjectTag(VkDevice device, uint64_t object, VkDebugReportObjectTypeEXT objectType, uint64_t name, size_t tagSize, const void* tag) {
  // Check for valid function pointer (may not be present if not running in a debugging application)
  if (pfnDebugMarkerSetObjectTag) {
    VkDebugMarkerObjectTagInfoEXT tagInfo = {};
    tagInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_OBJECT_TAG_INFO_EXT;
    tagInfo.objectType = objectType;
    tagInfo.object = object;
    tagInfo.tagName = name;
    tagInfo.tagSize = tagSize;
    tagInfo.pTag = tag;
    pfnDebugMarkerSetObjectTag(device, &tagInfo);
  }
}
*/

// Start a new debug marker region
static void beginRegion(VkCommandBuffer cmdbuffer, const char* pMarkerName, glm::vec4 color) {
  // Check for valid function pointer (may not be present if not running in a debugging application)
  if (pfnCmdDebugMarkerBegin) {
    VkDebugMarkerMarkerInfoEXT markerInfo = {};
    markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
    memcpy(markerInfo.color, &color[0], sizeof(float) * 4);
    markerInfo.pMarkerName = pMarkerName;
    pfnCmdDebugMarkerBegin(cmdbuffer, &markerInfo);
  }
}
/*
// Insert a new debug marker into the command buffer
static void insert(VkCommandBuffer cmdbuffer, std::string markerName, glm::vec4 color) {
  // Check for valid function pointer (may not be present if not running in a debugging application)
  if (pfnCmdDebugMarkerInsert) {
    VkDebugMarkerMarkerInfoEXT markerInfo = {};
    markerInfo.sType = VK_STRUCTURE_TYPE_DEBUG_MARKER_MARKER_INFO_EXT;
    memcpy(markerInfo.color, &color[0], sizeof(float) * 4);
    markerInfo.pMarkerName = markerName.c_str();
    pfnCmdDebugMarkerInsert(cmdbuffer, &markerInfo);
  }
}
*/
// End the current debug marker region
static void endRegion(VkCommandBuffer cmdBuffer) {
  // Check for valid function (may not be present if not runnin in a debugging application)
  if (pfnCmdDebugMarkerEnd)
    pfnCmdDebugMarkerEnd(cmdBuffer);
}

// Object specific naming functions
/*
static void setCommandBufferName(VkDevice device, VkCommandBuffer cmdBuffer, const char * name) {
  setObjectName(device, (uint64_t)cmdBuffer, VK_DEBUG_REPORT_OBJECT_TYPE_COMMAND_BUFFER_EXT, name);
}

static void setQueueName(VkDevice device, VkQueue queue, const char * name) {
  setObjectName(device, (uint64_t)queue, VK_DEBUG_REPORT_OBJECT_TYPE_QUEUE_EXT, name);
}

static void setImageName(VkDevice device, VkImage image, const char * name) {
  setObjectName(device, (uint64_t)image, VK_DEBUG_REPORT_OBJECT_TYPE_IMAGE_EXT, name);
}

static void setSamplerName(VkDevice device, VkSampler sampler, const char * name) {
  setObjectName(device, (uint64_t)sampler, VK_DEBUG_REPORT_OBJECT_TYPE_SAMPLER_EXT, name);
}

static void setBufferName(VkDevice device, VkBuffer buffer, const char * name) {
  setObjectName(device, (uint64_t)buffer, VK_DEBUG_REPORT_OBJECT_TYPE_BUFFER_EXT, name);
}

static void setDeviceMemoryName(VkDevice device, VkDeviceMemory memory, const char * name) {
  setObjectName(device, (uint64_t)memory, VK_DEBUG_REPORT_OBJECT_TYPE_DEVICE_MEMORY_EXT, name);
}

static void setShaderModuleName(VkDevice device, VkShaderModule shaderModule, const char * name) {
  setObjectName(device, (uint64_t)shaderModule, VK_DEBUG_REPORT_OBJECT_TYPE_SHADER_MODULE_EXT, name);
}

static void setPipelineName(VkDevice device, VkPipeline pipeline, const char * name) {
  setObjectName(device, (uint64_t)pipeline, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_EXT, name);
}

static void setPipelineLayoutName(VkDevice device, VkPipelineLayout pipelineLayout, const char * name) {
  setObjectName(device, (uint64_t)pipelineLayout, VK_DEBUG_REPORT_OBJECT_TYPE_PIPELINE_LAYOUT_EXT, name);
}

static void setRenderPassName(VkDevice device, VkRenderPass renderPass, const char * name) {
  setObjectName(device, (uint64_t)renderPass, VK_DEBUG_REPORT_OBJECT_TYPE_RENDER_PASS_EXT, name);
}

static void setFramebufferName(VkDevice device, VkFramebuffer framebuffer, const char * name) {
  setObjectName(device, (uint64_t)framebuffer, VK_DEBUG_REPORT_OBJECT_TYPE_FRAMEBUFFER_EXT, name);
}

static void setDescriptorSetLayoutName(VkDevice device, VkDescriptorSetLayout descriptorSetLayout, const char * name) {
  setObjectName(device, (uint64_t)descriptorSetLayout, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_LAYOUT_EXT, name);
}

static void setDescriptorSetName(VkDevice device, VkDescriptorSet descriptorSet, const char * name) {
  setObjectName(device, (uint64_t)descriptorSet, VK_DEBUG_REPORT_OBJECT_TYPE_DESCRIPTOR_SET_EXT, name);
}

static void setSemaphoreName(VkDevice device, VkSemaphore semaphore, const char * name) {
  setObjectName(device, (uint64_t)semaphore, VK_DEBUG_REPORT_OBJECT_TYPE_SEMAPHORE_EXT, name);
}

static void setFenceName(VkDevice device, VkFence fence, const char * name) {
  setObjectName(device, (uint64_t)fence, VK_DEBUG_REPORT_OBJECT_TYPE_FENCE_EXT, name);
}

static void setEventName(VkDevice device, VkEvent _event, const char * name) {
  setObjectName(device, (uint64_t)_event, VK_DEBUG_REPORT_OBJECT_TYPE_EVENT_EXT, name);
}
*/
}  // namespace debugmarker
}  // namespace vik