Vulkan: Implement debug markers
Covers both GL_KHR_debug and GL_EXT_debug_marker.
Debug markers are used to specify events or hierarchically categorize a
set of commands within the command buffer. When debugging, this allows
for quicker navigation to the draw calls of interest, and otherwise
provides context to debug output.
Bug: angleproject:2853
Change-Id: Id65e11fc877d9e70b6fd0fae7f0bbbcb1164bf10
Reviewed-on: https://chromium-review.googlesource.com/c/1403956
Commit-Queue: Shahbaz Youssefi <syoussefi@chromium.org>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
diff --git a/src/libANGLE/renderer/vulkan/CommandGraph.cpp b/src/libANGLE/renderer/vulkan/CommandGraph.cpp
index 2aef407..5f6892b 100644
--- a/src/libANGLE/renderer/vulkan/CommandGraph.cpp
+++ b/src/libANGLE/renderer/vulkan/CommandGraph.cpp
@@ -85,11 +85,45 @@
UNREACHABLE();
return "FenceSync";
}
+ case CommandGraphResourceType::DebugMarker:
+ switch (function)
+ {
+ case CommandGraphNodeFunction::InsertDebugMarker:
+ return "InsertDebugMarker";
+ case CommandGraphNodeFunction::PushDebugMarker:
+ return "PushDebugMarker";
+ case CommandGraphNodeFunction::PopDebugMarker:
+ return "PopDebugMarker";
+ default:
+ UNREACHABLE();
+ return "DebugMarker";
+ }
default:
UNREACHABLE();
return "";
}
}
+
+void MakeDebugUtilsLabel(GLenum source, const char *marker, VkDebugUtilsLabelEXT *label)
+{
+ static constexpr angle::ColorF kLabelColors[6] = {
+ angle::ColorF(1.0f, 0.5f, 0.5f, 1.0f), // DEBUG_SOURCE_API
+ angle::ColorF(0.5f, 1.0f, 0.5f, 1.0f), // DEBUG_SOURCE_WINDOW_SYSTEM
+ angle::ColorF(0.5f, 0.5f, 1.0f, 1.0f), // DEBUG_SOURCE_SHADER_COMPILER
+ angle::ColorF(0.7f, 0.7f, 0.7f, 1.0f), // DEBUG_SOURCE_THIRD_PARTY
+ angle::ColorF(0.5f, 0.8f, 0.9f, 1.0f), // DEBUG_SOURCE_APPLICATION
+ angle::ColorF(0.9f, 0.8f, 0.5f, 1.0f), // DEBUG_SOURCE_OTHER
+ };
+
+ int colorIndex = source - GL_DEBUG_SOURCE_API;
+ ASSERT(colorIndex >= 0 && static_cast<size_t>(colorIndex) < ArraySize(kLabelColors));
+
+ label->sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT;
+ label->pNext = nullptr;
+ label->pLabelName = marker;
+ kLabelColors[colorIndex].writeData(label->color);
+}
+
} // anonymous namespace
// CommandGraphResource implementation.
@@ -356,6 +390,14 @@
mFenceSyncEvent = event.getHandle();
}
+void CommandGraphNode::setDebugMarker(GLenum source, std::string &&marker)
+{
+ ASSERT(mFunction == CommandGraphNodeFunction::InsertDebugMarker ||
+ mFunction == CommandGraphNodeFunction::PushDebugMarker);
+ mDebugMarkerSource = source;
+ mDebugMarker = std::move(marker);
+}
+
// Do not call this in anything but testing code, since it's slow.
bool CommandGraphNode::isChildOf(CommandGraphNode *parent)
{
@@ -499,6 +541,39 @@
break;
+ case CommandGraphNodeFunction::InsertDebugMarker:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+
+ if (vkCmdInsertDebugUtilsLabelEXT)
+ {
+ VkDebugUtilsLabelEXT label;
+ MakeDebugUtilsLabel(mDebugMarkerSource, mDebugMarker.c_str(), &label);
+
+ vkCmdInsertDebugUtilsLabelEXT(primaryCommandBuffer->getHandle(), &label);
+ }
+ break;
+
+ case CommandGraphNodeFunction::PushDebugMarker:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+
+ if (vkCmdBeginDebugUtilsLabelEXT)
+ {
+ VkDebugUtilsLabelEXT label;
+ MakeDebugUtilsLabel(mDebugMarkerSource, mDebugMarker.c_str(), &label);
+
+ vkCmdBeginDebugUtilsLabelEXT(primaryCommandBuffer->getHandle(), &label);
+ }
+ break;
+
+ case CommandGraphNodeFunction::PopDebugMarker:
+ ASSERT(!mOutsideRenderPassCommands.valid() && !mInsideRenderPassCommands.valid());
+
+ if (vkCmdEndDebugUtilsLabelEXT)
+ {
+ vkCmdEndDebugUtilsLabelEXT(primaryCommandBuffer->getHandle());
+ }
+ break;
+
default:
UNREACHABLE();
}
@@ -712,6 +787,26 @@
newNode->setFenceSync(event);
}
+void CommandGraph::insertDebugMarker(GLenum source, std::string &&marker)
+{
+ CommandGraphNode *newNode = allocateBarrierNode(CommandGraphResourceType::DebugMarker,
+ CommandGraphNodeFunction::InsertDebugMarker);
+ newNode->setDebugMarker(source, std::move(marker));
+}
+
+void CommandGraph::pushDebugMarker(GLenum source, std::string &&marker)
+{
+ CommandGraphNode *newNode = allocateBarrierNode(CommandGraphResourceType::DebugMarker,
+ CommandGraphNodeFunction::PushDebugMarker);
+ newNode->setDebugMarker(source, std::move(marker));
+}
+
+void CommandGraph::popDebugMarker()
+{
+ allocateBarrierNode(CommandGraphResourceType::DebugMarker,
+ CommandGraphNodeFunction::PopDebugMarker);
+}
+
// Dumps the command graph into a dot file that works with graphviz.
void CommandGraph::dumpGraphDotFile(std::ostream &out) const
{
@@ -739,38 +834,53 @@
std::stringstream strstr;
strstr << GetResourceTypeName(node->getResourceTypeForDiagnostics(), node->getFunction());
- strstr << " ";
- auto it = objectIDMap.find(node->getResourceIDForDiagnostics());
- if (it != objectIDMap.end())
+ if (node->getResourceTypeForDiagnostics() == CommandGraphResourceType::DebugMarker)
{
- strstr << it->second;
+ // For debug markers, use the string from the debug marker itself.
+ if (node->getFunction() != CommandGraphNodeFunction::PopDebugMarker)
+ {
+ strstr << " " << node->getDebugMarker();
+ }
}
else
{
- int id = 0;
+ strstr << " ";
- switch (node->getResourceTypeForDiagnostics())
+ // Otherwise assign each object an ID, so all the nodes of the same object have the same
+ // label.
+ ASSERT(node->getResourceIDForDiagnostics() != 0);
+ auto it = objectIDMap.find(node->getResourceIDForDiagnostics());
+ if (it != objectIDMap.end())
{
- case CommandGraphResourceType::Buffer:
- id = bufferIDCounter++;
- break;
- case CommandGraphResourceType::Framebuffer:
- id = framebufferIDCounter++;
- break;
- case CommandGraphResourceType::Image:
- id = imageIDCounter++;
- break;
- case CommandGraphResourceType::Query:
- id = queryIDCounter++;
- break;
- default:
- UNREACHABLE();
- break;
+ strstr << it->second;
}
+ else
+ {
+ int id = 0;
- objectIDMap[node->getResourceIDForDiagnostics()] = id;
- strstr << id;
+ switch (node->getResourceTypeForDiagnostics())
+ {
+ case CommandGraphResourceType::Buffer:
+ id = bufferIDCounter++;
+ break;
+ case CommandGraphResourceType::Framebuffer:
+ id = framebufferIDCounter++;
+ break;
+ case CommandGraphResourceType::Image:
+ id = imageIDCounter++;
+ break;
+ case CommandGraphResourceType::Query:
+ id = queryIDCounter++;
+ break;
+ default:
+ UNREACHABLE();
+ break;
+ }
+
+ objectIDMap[node->getResourceIDForDiagnostics()] = id;
+ strstr << id;
+ }
}
const std::string &label = strstr.str();