Commit 3705fc41 by Ian Elliott Committed by Commit Bot

Vulkan:Add debug labels for OpenGL calls

Implement the DebugAnnotatorVk class, and plumb the EVENT macro in the GL entrypoints to save a string of call info in the vector of all GL calls in ContextVk. Then add a vkCmdBeginDebugUtilsLabelEXT() call that includes the OpenGL draw/dispatch call prior to any Vulkan Draw or Dispatch calls. Also embedded under that label add a second vkCmdBeginDebugUtilsLabelEXT() call labeled "OpenGL Commands" that includes all of the OpenGL calls leading up to the draw/dispatch. Each individual OpenGL call is then given its own vkCmdBegin/EndDebugUtilsLabelEXT() pair so that the complete sequence of GL calls leading up to a draw call is visible for each Draw. Enable the OGL->VK mapping feature by setting "angle_enable_trace = true" in GN args. Note: This will create an ANGLE APK on Android that generally won't work with games, unless launched by AGI (which provides the debug utils extension). A future version will disable these labels unless the debug utils extension is found. Bug: b/162068318 Bug: b/169243237 Change-Id: I09886f17fa9287528c12552698738ea1fe2a4b8c Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/2427557 Commit-Queue: Ian Elliott <ianelliott@google.com> Reviewed-by: 's avatarTim Van Patten <timvp@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCourtney Goeltzenleuchter <courtneygo@google.com> Reviewed-by: 's avatarShahbaz Youssefi <syoussefi@chromium.org>
parent b156a753
......@@ -81,7 +81,7 @@ std::ostream *gSwallowStream;
bool DebugAnnotationsActive()
{
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS)
#if defined(ANGLE_ENABLE_DEBUG_ANNOTATIONS) || defined(ANGLE_ENABLE_DEBUG_TRACE)
return g_debugAnnotator != nullptr && g_debugAnnotator->getStatus();
#else
return false;
......
......@@ -27,6 +27,8 @@ _vulkan_backend_sources = [
"CompilerVk.h",
"ContextVk.cpp",
"ContextVk.h",
"DebugAnnotatorVk.cpp",
"DebugAnnotatorVk.h",
"DeviceVk.cpp",
"DeviceVk.h",
"DisplayVk.cpp",
......
......@@ -302,6 +302,14 @@ vk::ResourceAccess GetStencilAccess(const gl::DepthStencilState &dsState)
// Simplify this check by returning write instead of checking the mask.
return vk::ResourceAccess::Write;
}
#if defined(ANGLE_ENABLE_DEBUG_TRACE)
# define ANGLE_WRITE_EVENT_LOG(context, commandBuffer) writeEventLog(context, commandBuffer)
# define ANGLE_END_EVENT_LOG(commandBuffer) commandBuffer->endDebugUtilsLabelEXT()
#else
# define ANGLE_WRITE_EVENT_LOG(context, commandBuffer)
# define ANGLE_END_EVENT_LOG(commandBuffer)
#endif
} // anonymous namespace
ANGLE_INLINE void ContextVk::flushDescriptorSetUpdates()
......@@ -1077,6 +1085,8 @@ angle::Result ContextVk::setupDraw(const gl::Context *context,
if (dirtyBits.none())
return angle::Result::Continue;
ANGLE_WRITE_EVENT_LOG(context, *commandBufferOut);
// Flush any relevant dirty bits.
for (size_t dirtyBit : dirtyBits)
{
......@@ -1282,6 +1292,7 @@ angle::Result ContextVk::setupDispatch(const gl::Context *context,
// The following ensures prior commands are flushed before we start processing dirty bits.
ANGLE_TRY(flushCommandsAndEndRenderPass());
*commandBufferOut = &mOutsideRenderPassCommands->getCommandBuffer();
ANGLE_WRITE_EVENT_LOG(context, *commandBufferOut);
// Create a local object to ensure we flush the descriptor updates to device when we leave this
// function
......@@ -2087,7 +2098,7 @@ angle::Result ContextVk::drawArrays(const gl::Context *context,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->draw(clampedVertexCount, first);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2107,12 +2118,15 @@ angle::Result ContextVk::drawArraysInstanced(const gl::Context *context,
gl::DrawElementsType::InvalidEnum, nullptr, &commandBuffer,
&numIndices));
commandBuffer->drawIndexedInstanced(numIndices, instances);
return angle::Result::Continue;
}
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances, first);
else
{
ANGLE_TRY(setupDraw(context, mode, first, count, instances,
gl::DrawElementsType::InvalidEnum, nullptr, mNonIndexedDirtyBitsMask,
&commandBuffer));
commandBuffer->drawInstanced(gl::GetClampedVertexCount<uint32_t>(count), instances, first);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2134,13 +2148,16 @@ angle::Result ContextVk::drawArraysInstancedBaseInstance(const gl::Context *cont
&numIndices));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(numIndices, instances, 0, 0,
baseInstance);
return angle::Result::Continue;
}
ANGLE_TRY(setupDraw(context, mode, first, count, instances, gl::DrawElementsType::InvalidEnum,
nullptr, mNonIndexedDirtyBitsMask, &commandBuffer));
commandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count), instances,
first, baseInstance);
else
{
ANGLE_TRY(setupDraw(context, mode, first, count, instances,
gl::DrawElementsType::InvalidEnum, nullptr, mNonIndexedDirtyBitsMask,
&commandBuffer));
commandBuffer->drawInstancedBaseInstance(gl::GetClampedVertexCount<uint32_t>(count),
instances, first, baseInstance);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2163,7 +2180,7 @@ angle::Result ContextVk::drawElements(const gl::Context *context,
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexed(count);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2187,7 +2204,7 @@ angle::Result ContextVk::drawElementsBaseVertex(const gl::Context *context,
ANGLE_TRY(setupIndexedDraw(context, mode, count, 1, type, indices, &commandBuffer));
commandBuffer->drawIndexedBaseVertex(count, baseVertex);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2213,6 +2230,7 @@ angle::Result ContextVk::drawElementsInstanced(const gl::Context *context,
}
commandBuffer->drawIndexedInstanced(count, instances);
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2239,6 +2257,7 @@ angle::Result ContextVk::drawElementsInstancedBaseVertex(const gl::Context *cont
}
commandBuffer->drawIndexedInstancedBaseVertex(count, instances, baseVertex);
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2260,12 +2279,14 @@ angle::Result ContextVk::drawElementsInstancedBaseVertexBaseInstance(const gl::C
setupLineLoopDraw(context, mode, 0, count, type, indices, &commandBuffer, &indexCount));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(indexCount, instances, 0,
baseVertex, baseInstance);
return angle::Result::Continue;
}
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0, baseVertex,
baseInstance);
else
{
ANGLE_TRY(setupIndexedDraw(context, mode, count, instances, type, indices, &commandBuffer));
commandBuffer->drawIndexedInstancedBaseVertexBaseInstance(count, instances, 0, baseVertex,
baseInstance);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2339,13 +2360,16 @@ angle::Result ContextVk::drawArraysIndirect(const gl::Context *context,
&dstIndirectBuf, &dstIndirectBufOffset));
commandBuffer->drawIndexedIndirect(dstIndirectBuf->getBuffer(), dstIndirectBufOffset, 1, 0);
return angle::Result::Continue;
}
else
{
ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer));
ANGLE_TRY(setupIndirectDraw(context, mode, mNonIndexedDirtyBitsMask, currentIndirectBuf,
currentIndirectBufOffset, &commandBuffer));
commandBuffer->drawIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1, 0);
commandBuffer->drawIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1,
0);
}
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2420,6 +2444,7 @@ angle::Result ContextVk::drawElementsIndirect(const gl::Context *context,
commandBuffer->drawIndexedIndirect(currentIndirectBuf->getBuffer(), currentIndirectBufOffset, 1,
0);
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -2617,6 +2642,56 @@ angle::Result ContextVk::popDebugGroup(const gl::Context *context)
return angle::Result::Continue;
}
void ContextVk::writeEventLog(const gl::Context *context, vk::CommandBuffer *commandBuffer)
{
if (mEventLog.empty())
{
return;
}
// Insert OpenGL ES commands into debug label. We create a 3-level cascade here for
// OpenGL-ES-first debugging in AGI. Here's the general outline of commands:
// -glDrawCommand
// --vkCmdBeginDebugUtilsLabelEXT() #1 for "glDrawCommand"
// --OpenGL ES Commands
// ---vkCmdBeginDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
// ---Individual OpenGL ES Commands leading up to glDrawCommand
// ----vkCmdBeginDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
// ----vkCmdEndDebugUtilsLabelEXT() #3 for each individual OpenGL ES Command
// ----...More Individual OGL Commands...
// ----Final Individual OGL command will be the same glDrawCommand shown in #1 above
// ---vkCmdEndDebugUtilsLabelEXT() #2 for "OpenGL ES Commands"
// --VK SetupDraw & Draw-related commands will be embedded here under glDraw #1
// --vkCmdEndDebugUtilsLabelEXT() #1 is called after each vkDraw* or vkDispatch* call
VkDebugUtilsLabelEXT label = {VK_STRUCTURE_TYPE_DEBUG_UTILS_LABEL_EXT,
nullptr,
mEventLog.back().c_str(),
{0.0f, 0.0f, 0.0f, 0.0f}};
// This is #1 from comment above
commandBuffer->beginDebugUtilsLabelEXT(label);
std::string oglCmds = "OpenGL ES Commands";
label.pLabelName = oglCmds.c_str();
// This is #2 from comment above
commandBuffer->beginDebugUtilsLabelEXT(label);
for (uint32_t i = 0; i < mEventLog.size(); ++i)
{
label.pLabelName = mEventLog[i].c_str();
// NOTE: We have to use a begin/end pair here because AGI does not promote the
// pLabelName from an insertDebugUtilsLabelEXT() call to the Commands panel.
// Internal bug b/169243237 is tracking this and once the insert* call shows the
// pLabelName similar to begin* call, we can switch these to insert* calls instead.
// This is #3 from comment above.
// TODO(ianelliott): Transfer the bug to a publicly-visible bug.
commandBuffer->beginDebugUtilsLabelEXT(label);
commandBuffer->endDebugUtilsLabelEXT();
}
commandBuffer->endDebugUtilsLabelEXT();
// The final end* call for #1 above is made in the ContextVk::draw* or
// ContextVk::dispatch* function calls.
mEventLog.clear();
}
bool ContextVk::isViewportFlipEnabledForDrawFBO() const
{
return mFlipViewportForDrawFramebuffer && mFlipYForCurrentSurface;
......@@ -3578,6 +3653,8 @@ angle::Result ContextVk::dispatchCompute(const gl::Context *context,
commandBuffer->dispatch(numGroupsX, numGroupsY, numGroupsZ);
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......@@ -3593,6 +3670,8 @@ angle::Result ContextVk::dispatchComputeIndirect(const gl::Context *context, GLi
commandBuffer->dispatchIndirect(buffer.getBuffer(), indirect);
ANGLE_END_EVENT_LOG(commandBuffer);
return angle::Result::Continue;
}
......
......@@ -261,6 +261,9 @@ class ContextVk : public ContextImpl, public vk::Context
const std::string &message) override;
angle::Result popDebugGroup(const gl::Context *context) override;
// Record GL API calls for debuggers
void logEvent(const char *eventString) { mEventLog.push_back(eventString); }
bool isViewportFlipEnabledForDrawFBO() const;
bool isViewportFlipEnabledForReadFBO() const;
// When the device/surface is rotated such that the surface's aspect ratio is different than
......@@ -952,6 +955,9 @@ class ContextVk : public ContextImpl, public vk::Context
bool shouldSwitchToReadOnlyDepthFeedbackLoopMode(const gl::Context *context,
gl::Texture *texture) const;
// Record GL API calls for debuggers
void writeEventLog(const gl::Context *context, vk::CommandBuffer *commandBuffer);
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mGraphicsDirtyBitHandlers;
std::array<DirtyBitHandler, DIRTY_BIT_MAX> mComputeDirtyBitHandlers;
......@@ -1149,6 +1155,9 @@ class ContextVk : public ContextImpl, public vk::Context
vk::DynamicBuffer mStagingBuffer;
std::vector<std::string> mCommandBufferDiagnostics;
// Record GL API calls for debuggers
std::vector<std::string> mEventLog;
};
ANGLE_INLINE angle::Result ContextVk::endRenderPassIfTransformFeedbackBuffer(
......
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DebugAnnotatorVk.cpp: Vulkan helpers for adding trace annotations.
//
#include "libANGLE/renderer/vulkan/DebugAnnotatorVk.h"
#include "libANGLE/Context.h"
#include "libANGLE/renderer/vulkan/ContextVk.h"
namespace rx
{
DebugAnnotatorVk::DebugAnnotatorVk() {}
DebugAnnotatorVk::~DebugAnnotatorVk() {}
void DebugAnnotatorVk::beginEvent(gl::Context *context,
const char *eventName,
const char *eventMessage)
{
angle::LoggingAnnotator::beginEvent(context, eventName, eventMessage);
if (context)
{
ContextVk *contextVk = vk::GetImpl(static_cast<gl::Context *>(context));
contextVk->logEvent(eventMessage);
}
}
void DebugAnnotatorVk::endEvent(const char *eventName)
{
angle::LoggingAnnotator::endEvent(eventName);
}
bool DebugAnnotatorVk::getStatus()
{
return true;
}
} // namespace rx
//
// Copyright 2020 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// DebugAnnotatorVk.h: Vulkan helpers for adding trace annotations.
//
#ifndef LIBANGLE_RENDERER_VULKAN_DEBUGANNOTATORVK_H_
#define LIBANGLE_RENDERER_VULKAN_DEBUGANNOTATORVK_H_
#include "libANGLE/LoggingAnnotator.h"
namespace rx
{
class DebugAnnotatorVk : public angle::LoggingAnnotator
{
public:
DebugAnnotatorVk();
~DebugAnnotatorVk() override;
void beginEvent(gl::Context *context, const char *eventName, const char *eventMessage) override;
void endEvent(const char *eventName) override;
bool getStatus() override;
// Note: To avoid any race conditions between threads, this class has no private data; all
// events are stored in ContextVk.
};
} // namespace rx
#endif // LIBANGLE_RENDERER_VULKAN_DEBUGANNOTATORVK_H_
......@@ -902,11 +902,14 @@ angle::Result RendererVk::initialize(DisplayVk *displayVk,
// Initialize the format table.
mFormatTable.initialize(this, &mNativeTextureCaps, &mNativeCaps.compressedTextureFormats);
gl::InitializeDebugAnnotations(&mAnnotator);
if (getFeatures().enableCommandProcessingThread.enabled)
{
mCommandProcessorThread =
std::thread(&CommandProcessor::processCommandProcessorTasks, &mCommandProcessor);
}
return angle::Result::Continue;
}
......
......@@ -27,6 +27,7 @@
#include "libANGLE/BlobCache.h"
#include "libANGLE/Caps.h"
#include "libANGLE/renderer/vulkan/CommandProcessor.h"
#include "libANGLE/renderer/vulkan/DebugAnnotatorVk.h"
#include "libANGLE/renderer/vulkan/QueryVk.h"
#include "libANGLE/renderer/vulkan/ResourceVk.h"
#include "libANGLE/renderer/vulkan/UtilsVk.h"
......@@ -369,6 +370,8 @@ class RendererVk : angle::NonCopyable
std::string mLastValidationMessage;
uint32_t mValidationMessageCount;
DebugAnnotatorVk mAnnotator;
// How close to VkPhysicalDeviceLimits::maxMemoryAllocationCount we allow ourselves to get
static constexpr double kPercentMaxMemoryAllocationCount = 0.3;
// How many objects to garbage collect before issuing a flush()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment