Blender V5.0
vk_debug.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
8
9#include <sstream>
10
11#include "BKE_global.hh"
12#include "CLG_log.h"
13
14#include "vk_backend.hh"
15#include "vk_context.hh"
16#include "vk_debug.hh"
17#include "vk_to_string.hh"
18
19#include "gpu_profile_report.hh"
20
21static CLG_LogRef LOG = {"gpu.vulkan"};
22
23namespace blender::gpu {
24void VKContext::debug_group_begin(const char *name, int)
25{
27
28 if (!G.profile_gpu) {
29 return;
30 }
31
32 ScopeTimings timings = {};
33 timings.name = name;
34 timings.finished = false;
35 timings.cpu_start = ScopeTimings::Clock::now();
36
37 scope_timings.append(timings);
38}
39
41{
43
44 if (!G.profile_gpu) {
45 return;
46 }
47
48 for (int i = scope_timings.size() - 1; i >= 0; i--) {
49 ScopeTimings &query = scope_timings[i];
50 if (!query.finished) {
51 query.finished = true;
52 query.cpu_end = ScopeTimings::Clock::now();
53 break;
54 }
55 if (i == 0) {
56 CLOG_ERROR(&LOG, "Profile GPU error: Extra GPU_debug_group_end() call.");
57 }
58 }
59}
60
61void VKContext::process_frame_timings()
62{
63 if (!G.profile_gpu) {
64 return;
65 }
66
67 Vector<ScopeTimings> &queries = scope_timings;
68
69 bool frame_is_valid = !queries.is_empty();
70
71 for (int i = queries.size() - 1; i >= 0; i--) {
72 if (!queries[i].finished) {
73 frame_is_valid = false;
74 CLOG_ERROR(&LOG, "Profile GPU error: Missing GPU_debug_group_end() call");
75 }
76 break;
77 }
78
79 if (!frame_is_valid) {
80 return;
81 }
82
83 for (ScopeTimings &query : queries) {
85 query.cpu_start.time_since_epoch().count(),
86 query.cpu_end.time_since_epoch().count());
87 }
88
89 queries.clear();
90}
91
98
99bool VKBackend::debug_capture_begin(const char *title)
100{
101#ifdef WITH_RENDERDOC
102 bool result = renderdoc_api_.start_frame_capture(device.instance_get(), nullptr);
103 if (result && title) {
104 renderdoc_api_.set_frame_capture_title(title);
105 }
106 return result;
107#else
108 UNUSED_VARS(title);
109 return false;
110#endif
111}
112
119
121{
122#ifdef WITH_RENDERDOC
123 renderdoc_api_.end_frame_capture(device.instance_get(), nullptr);
124#endif
125}
126
128{
129 return (void *)name;
130}
131
133{
134#ifdef WITH_RENDERDOC
135 const char *title = (const char *)scope;
136 if (StringRefNull(title) != StringRefNull(G.gpu_debug_scope_name)) {
137 return false;
138 }
140#else
141 UNUSED_VARS(scope);
142#endif
143 return false;
144}
145
147{
148#ifdef WITH_RENDERDOC
149 const char *title = (const char *)scope;
150 if (StringRefNull(title) == StringRefNull(G.gpu_debug_scope_name)) {
152 }
153#else
154 UNUSED_VARS(scope);
155#endif
156}
157
158} // namespace blender::gpu
159
160namespace blender::gpu::debug {
161
162void VKDebuggingTools::init(VkInstance vk_instance)
163{
165 init_messenger(vk_instance);
166}
167
168void VKDebuggingTools::deinit(VkInstance vk_instance)
169{
170 destroy_messenger(vk_instance);
171}
172
173void object_label(VkObjectType vk_object_type, uint64_t object_handle, const char *name)
174{
175 const VKDevice &device = VKBackend::get().device;
176 if (G.debug & G_DEBUG_GPU && device.functions.vkSetDebugUtilsObjectName && object_handle != 0) {
177 VkDebugUtilsObjectNameInfoEXT info = {};
178 info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT;
179 info.objectType = vk_object_type;
180 info.objectHandle = object_handle;
181 info.pObjectName = name;
182 device.functions.vkSetDebugUtilsObjectName(device.vk_handle(), &info);
183 }
184}
185
186} // namespace blender::gpu::debug
187
188namespace blender::gpu::debug {
189
190void VKDebuggingTools::print_labels(const VkDebugUtilsMessengerCallbackDataEXT *callback_data)
191{
192 std::stringstream ss;
193 for (uint32_t object = 0; object < callback_data->objectCount; ++object) {
194 ss << " - ObjectType[" << to_string(callback_data->pObjects[object].objectType) << "],";
195 ss << "Handle[0x" << std::hex << uintptr_t(callback_data->pObjects[object].objectHandle)
196 << "]";
197 if (callback_data->pObjects[object].pObjectName) {
198 ss << ",Name[" << callback_data->pObjects[object].pObjectName << "]";
199 }
200 ss << std::endl;
201 }
202 for (uint32_t label = 0; label < callback_data->cmdBufLabelCount; ++label) {
203 if (callback_data->pCmdBufLabels[label].pLabelName) {
204 ss << " - CommandBuffer : " << callback_data->pCmdBufLabels[label].pLabelName << std::endl;
205 }
206 }
207 for (uint32_t label = 0; label < callback_data->queueLabelCount; ++label) {
208 if (callback_data->pQueueLabels[label].pLabelName) {
209 ss << " - Queue : " << callback_data->pQueueLabels[label].pLabelName << std::endl;
210 }
211 }
212 ss << std::endl;
213 printf("%s", ss.str().c_str());
214}
215
216static VKAPI_ATTR VkBool32 VKAPI_CALL
217messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity,
218 VkDebugUtilsMessageTypeFlagsEXT /*message_type*/,
219 const VkDebugUtilsMessengerCallbackDataEXT *callback_data,
220 void *user_data)
221{
223 if (message_severity & (VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
224 VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT))
225 {
226 level = CLG_LEVEL_INFO;
227 }
228 if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT) {
229 level = CLG_LEVEL_WARN;
230 }
231 if (message_severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
232 level = CLG_LEVEL_ERROR;
233 }
234
235 const char *format = "{0x%x}% s\n %s ";
237 level,
238 format,
239 callback_data->messageIdNumber,
240 callback_data->pMessageIdName,
241 callback_data->pMessage);
242 const bool do_labels = (callback_data->objectCount + callback_data->cmdBufLabelCount +
243 callback_data->queueLabelCount) > 0;
244 const bool log_active = CLOG_CHECK(&LOG, level);
245 if (do_labels && log_active) {
246 VKDebuggingTools &debugging_tools = *reinterpret_cast<VKDebuggingTools *>(user_data);
247 debugging_tools.print_labels(callback_data);
248 }
249
250 return VK_FALSE;
251};
252
253void VKDebuggingTools::init_messenger(VkInstance vk_instance)
254{
255 if (vk_debug_utils_messenger) {
256 return;
257 }
258
259 VKDevice &device = VKBackend::get().device;
261 return;
262 }
263
264 VkDebugUtilsMessengerCreateInfoEXT create_info;
265 create_info.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_MESSENGER_CREATE_INFO_EXT;
266 create_info.pNext = nullptr;
267 create_info.flags = 0;
268 create_info.messageSeverity = VK_DEBUG_UTILS_MESSAGE_SEVERITY_INFO_BIT_EXT |
269 VK_DEBUG_UTILS_MESSAGE_SEVERITY_VERBOSE_BIT_EXT |
270 VK_DEBUG_UTILS_MESSAGE_SEVERITY_WARNING_BIT_EXT |
271 VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT;
272 create_info.messageType = VK_DEBUG_UTILS_MESSAGE_TYPE_GENERAL_BIT_EXT |
273 VK_DEBUG_UTILS_MESSAGE_TYPE_VALIDATION_BIT_EXT |
274 VK_DEBUG_UTILS_MESSAGE_TYPE_PERFORMANCE_BIT_EXT;
275 create_info.pfnUserCallback = messenger_callback;
276 create_info.pUserData = this;
278 vk_instance, &create_info, nullptr, &vk_debug_utils_messenger);
279 return;
280}
281
282void VKDebuggingTools::destroy_messenger(VkInstance vk_instance)
283{
284 if (vk_debug_utils_messenger == nullptr) {
285 return;
286 }
287
288 VKDevice &device = VKBackend::get().device;
289 device.functions.vkDestroyDebugUtilsMessenger(vk_instance, vk_debug_utils_messenger, nullptr);
290 vk_debug_utils_messenger = nullptr;
291 return;
292}
293
294}; // namespace blender::gpu::debug
@ G_DEBUG_GPU
#define UNUSED_VARS(...)
#define CLOG_ERROR(clg_ref,...)
Definition CLG_log.h:188
#define CLOG_CHECK(clg_ref, verbose_level,...)
Definition CLG_log.h:147
void CLG_logref_init(CLG_LogRef *clg_ref)
Definition clog.cc:984
CLG_Level
Definition CLG_log.h:52
@ CLG_LEVEL_ERROR
Definition CLG_log.h:56
@ CLG_LEVEL_INFO
Definition CLG_log.h:60
@ CLG_LEVEL_WARN
Definition CLG_log.h:58
#define CLOG_AT_LEVEL(clg_ref, verbose_level,...)
Definition CLG_log.h:150
unsigned long long int uint64_t
int64_t size() const
bool is_empty() const
static ProfileReport & get()
void add_group_cpu(StringRefNull name, uint64_t cpu_start, uint64_t cpu_end)
static VKBackend & get()
Definition vk_backend.hh:91
bool debug_capture_begin(const char *title)
Definition vk_debug.cc:99
void debug_group_begin(const char *, int) override
Definition vk_debug.cc:24
void debug_group_end() override
Definition vk_debug.cc:40
bool debug_capture_scope_begin(void *scope) override
Definition vk_debug.cc:132
void * debug_capture_scope_create(const char *name) override
Definition vk_debug.cc:127
bool debug_capture_begin(const char *title) override
Definition vk_debug.cc:92
const render_graph::VKRenderGraph & render_graph() const
Definition vk_context.hh:79
void debug_capture_end() override
Definition vk_debug.cc:113
void debug_capture_scope_end(void *scope) override
Definition vk_debug.cc:146
TimelineValue flush_render_graph(RenderGraphFlushFlags flags, VkPipelineStageFlags wait_dst_stage_mask=VK_PIPELINE_STAGE_NONE, VkSemaphore wait_semaphore=VK_NULL_HANDLE, VkSemaphore signal_semaphore=VK_NULL_HANDLE, VkFence signal_fence=VK_NULL_HANDLE)
PFN_vkSetDebugUtilsObjectNameEXT vkSetDebugUtilsObjectName
Definition vk_device.hh:236
VkDevice vk_handle() const
Definition vk_device.hh:311
PFN_vkCreateDebugUtilsMessengerEXT vkCreateDebugUtilsMessenger
Definition vk_device.hh:237
PFN_vkDestroyDebugUtilsMessengerEXT vkDestroyDebugUtilsMessenger
Definition vk_device.hh:238
struct blender::gpu::VKDevice::@152120360333013146246346216002113345357100126073 functions
void print_labels(const VkDebugUtilsMessengerCallbackDataEXT *callback_data)
Definition vk_debug.cc:190
void init(VkInstance vk_instance)
Definition vk_debug.cc:162
void destroy_messenger(VkInstance vk_instance)
Definition vk_debug.cc:282
void deinit(VkInstance vk_instance)
Definition vk_debug.cc:168
void init_messenger(VkInstance vk_instance)
Definition vk_debug.cc:253
void debug_group_begin(const char *name, const ColorTheme4f &color)
static const char * to_string(const Interpolation &interp)
Definition gl_shader.cc:103
#define printf(...)
format
#define LOG(level)
Definition log.h:97
#define G(x, y, z)
static ColorTheme4f get_debug_group_color(StringRefNull name)
static VKAPI_ATTR VkBool32 VKAPI_CALL messenger_callback(VkDebugUtilsMessageSeverityFlagBitsEXT message_severity, VkDebugUtilsMessageTypeFlagsEXT, const VkDebugUtilsMessengerCallbackDataEXT *callback_data, void *user_data)
Definition vk_debug.cc:217
void object_label(GLenum type, GLuint object, const char *name)
Definition gl_debug.cc:329
static CLG_LogRef LOG
const char * name
i
Definition text_draw.cc:230