Commit a4e06ca0 by Ben Clayton

Vulkan: Add debugging of the command buffer.

Add a debugger context and server to vk::Device, along with a getter for acquiring the debugger context. Generate a synthetic file containing all the Vulkan commands in the command buffer, and allow the debugger to single line step over these. All of this is no-op unless ENABLE_VK_DEBUGGER is defined at compile time, and the VK_DEBUGGER_PORT env var is set at run time. Bug: b/145351270 Change-Id: I8bea398a6c08d4cb23d76172dbca2a08ae109a6d Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/38913 Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: 's avatarNicolas Capens <nicolascapens@google.com> Tested-by: 's avatarBen Clayton <bclayton@google.com>
parent 45a4d0f3
...@@ -15,14 +15,14 @@ ...@@ -15,14 +15,14 @@
#ifndef VK_DEBUG_VALUE_HPP_ #ifndef VK_DEBUG_VALUE_HPP_
#define VK_DEBUG_VALUE_HPP_ #define VK_DEBUG_VALUE_HPP_
#include "Type.hpp"
#include <memory> #include <memory>
#include <string> #include <string>
namespace vk { namespace vk {
namespace dbg { namespace dbg {
class Type;
// FormatFlags holds settings used to serialize a Value to a string. // FormatFlags holds settings used to serialize a Value to a string.
struct FormatFlags struct FormatFlags
{ {
......
...@@ -25,6 +25,12 @@ ...@@ -25,6 +25,12 @@
#include "VkRenderPass.hpp" #include "VkRenderPass.hpp"
#include "Device/Renderer.hpp" #include "Device/Renderer.hpp"
#include "./Debug/Context.hpp"
#include "./Debug/File.hpp"
#include "./Debug/Thread.hpp"
#include "marl/defer.h"
#include <cstring> #include <cstring>
class vk::CommandBuffer::Command class vk::CommandBuffer::Command
...@@ -1281,8 +1287,9 @@ private: ...@@ -1281,8 +1287,9 @@ private:
namespace vk { namespace vk {
CommandBuffer::CommandBuffer(VkCommandBufferLevel pLevel) CommandBuffer::CommandBuffer(Device *device, VkCommandBufferLevel pLevel)
: level(pLevel) : device(device)
, level(pLevel)
{ {
// FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
commands = new std::vector<std::unique_ptr<Command>>(); commands = new std::vector<std::unique_ptr<Command>>();
...@@ -1329,6 +1336,19 @@ VkResult CommandBuffer::end() ...@@ -1329,6 +1336,19 @@ VkResult CommandBuffer::end()
state = EXECUTABLE; state = EXECUTABLE;
#ifdef ENABLE_VK_DEBUGGER
auto debuggerContext = device->getDebuggerContext();
if(debuggerContext)
{
std::string source;
for(auto &command : *commands)
{
source += command->description() + "\n";
}
debuggerFile = debuggerContext->lock().createVirtualFile("VkCommandBuffer", source.c_str());
}
#endif // ENABLE_VK_DEBUGGER
return VK_SUCCESS; return VK_SUCCESS;
} }
...@@ -1745,8 +1765,30 @@ void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState) ...@@ -1745,8 +1765,30 @@ void CommandBuffer::submit(CommandBuffer::ExecutionState &executionState)
// Perform recorded work // Perform recorded work
state = PENDING; state = PENDING;
#ifdef ENABLE_VK_DEBUGGER
std::shared_ptr<vk::dbg::Thread> debuggerThread;
auto debuggerContext = device->getDebuggerContext();
if(debuggerContext)
{
auto lock = debuggerContext->lock();
debuggerThread = lock.currentThread();
debuggerThread->setName("vkQueue processor");
debuggerThread->enter(lock, debuggerFile, "vkCommandBuffer::submit");
lock.unlock();
}
defer(if(debuggerThread) { debuggerThread->exit(); });
int line = 1;
#endif // ENABLE_VK_DEBUGGER
for(auto &command : *commands) for(auto &command : *commands)
{ {
#ifdef ENABLE_VK_DEBUGGER
if(debuggerThread)
{
debuggerThread->update({ line++, debuggerFile });
}
#endif // ENABLE_VK_DEBUGGER
command->play(executionState); command->play(executionState);
} }
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "VkObject.hpp" #include "VkObject.hpp"
#include "Device/Color.hpp" #include "Device/Color.hpp"
#include "Device/Context.hpp" #include "Device/Context.hpp"
#include <memory> #include <memory>
#include <vector> #include <vector>
...@@ -33,6 +34,11 @@ class TaskEvents; ...@@ -33,6 +34,11 @@ class TaskEvents;
namespace vk { namespace vk {
namespace dbg {
class File;
} // namespace dbg
class Device;
class Buffer; class Buffer;
class Event; class Event;
class Framebuffer; class Framebuffer;
...@@ -47,7 +53,7 @@ class CommandBuffer ...@@ -47,7 +53,7 @@ class CommandBuffer
public: public:
static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; } static constexpr VkSystemAllocationScope GetAllocationScope() { return VK_SYSTEM_ALLOCATION_SCOPE_OBJECT; }
CommandBuffer(VkCommandBufferLevel pLevel); CommandBuffer(Device *device, VkCommandBufferLevel pLevel);
static inline CommandBuffer *Cast(VkCommandBuffer object) static inline CommandBuffer *Cast(VkCommandBuffer object)
{ {
...@@ -201,11 +207,17 @@ private: ...@@ -201,11 +207,17 @@ private:
PENDING, PENDING,
INVALID INVALID
}; };
Device *const device;
State state = INITIAL; State state = INITIAL;
VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; VkCommandBufferLevel level = VK_COMMAND_BUFFER_LEVEL_PRIMARY;
// FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations // FIXME (b/119409619): replace this vector by an allocator so we can control all memory allocations
std::vector<std::unique_ptr<Command>> *commands; std::vector<std::unique_ptr<Command>> *commands;
#ifdef ENABLE_VK_DEBUGGER
std::shared_ptr<vk::dbg::File> debuggerFile;
#endif // ENABLE_VK_DEBUGGER
}; };
using DispatchableCommandBuffer = DispatchableObject<CommandBuffer, VkCommandBuffer>; using DispatchableCommandBuffer = DispatchableObject<CommandBuffer, VkCommandBuffer>;
......
...@@ -46,7 +46,7 @@ size_t CommandPool::ComputeRequiredAllocationSize(const VkCommandPoolCreateInfo ...@@ -46,7 +46,7 @@ size_t CommandPool::ComputeRequiredAllocationSize(const VkCommandPoolCreateInfo
return 0; return 0;
} }
VkResult CommandPool::allocateCommandBuffers(VkCommandBufferLevel level, uint32_t commandBufferCount, VkCommandBuffer *pCommandBuffers) VkResult CommandPool::allocateCommandBuffers(Device *device, VkCommandBufferLevel level, uint32_t commandBufferCount, VkCommandBuffer *pCommandBuffers)
{ {
for(uint32_t i = 0; i < commandBufferCount; i++) for(uint32_t i = 0; i < commandBufferCount; i++)
{ {
...@@ -54,7 +54,7 @@ VkResult CommandPool::allocateCommandBuffers(VkCommandBufferLevel level, uint32_ ...@@ -54,7 +54,7 @@ VkResult CommandPool::allocateCommandBuffers(VkCommandBufferLevel level, uint32_
void *deviceMemory = vk::allocate(sizeof(DispatchableCommandBuffer), REQUIRED_MEMORY_ALIGNMENT, void *deviceMemory = vk::allocate(sizeof(DispatchableCommandBuffer), REQUIRED_MEMORY_ALIGNMENT,
DEVICE_MEMORY, DispatchableCommandBuffer::GetAllocationScope()); DEVICE_MEMORY, DispatchableCommandBuffer::GetAllocationScope());
ASSERT(deviceMemory); ASSERT(deviceMemory);
DispatchableCommandBuffer *commandBuffer = new(deviceMemory) DispatchableCommandBuffer(level); DispatchableCommandBuffer *commandBuffer = new(deviceMemory) DispatchableCommandBuffer(device, level);
if(commandBuffer) if(commandBuffer)
{ {
pCommandBuffers[i] = *commandBuffer; pCommandBuffers[i] = *commandBuffer;
......
...@@ -16,10 +16,13 @@ ...@@ -16,10 +16,13 @@
#define VK_COMMAND_POOL_HPP_ #define VK_COMMAND_POOL_HPP_
#include "VkObject.hpp" #include "VkObject.hpp"
#include <set> #include <set>
namespace vk { namespace vk {
class Device;
class CommandPool : public Object<CommandPool, VkCommandPool> class CommandPool : public Object<CommandPool, VkCommandPool>
{ {
public: public:
...@@ -28,7 +31,7 @@ public: ...@@ -28,7 +31,7 @@ public:
static size_t ComputeRequiredAllocationSize(const VkCommandPoolCreateInfo *pCreateInfo); static size_t ComputeRequiredAllocationSize(const VkCommandPoolCreateInfo *pCreateInfo);
VkResult allocateCommandBuffers(VkCommandBufferLevel level, uint32_t commandBufferCount, VkCommandBuffer *pCommandBuffers); VkResult allocateCommandBuffers(Device *device, VkCommandBufferLevel level, uint32_t commandBufferCount, VkCommandBuffer *pCommandBuffers);
void freeCommandBuffers(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers); void freeCommandBuffers(uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers);
VkResult reset(VkCommandPoolResetFlags flags); VkResult reset(VkCommandPoolResetFlags flags);
void trim(VkCommandPoolTrimFlags flags); void trim(VkCommandPoolTrimFlags flags);
......
...@@ -19,6 +19,8 @@ ...@@ -19,6 +19,8 @@
#include "VkDescriptorSetLayout.hpp" #include "VkDescriptorSetLayout.hpp"
#include "VkFence.hpp" #include "VkFence.hpp"
#include "VkQueue.hpp" #include "VkQueue.hpp"
#include "Debug/Context.hpp"
#include "Debug/Server.hpp"
#include "Device/Blitter.hpp" #include "Device/Blitter.hpp"
#include <chrono> #include <chrono>
...@@ -97,6 +99,18 @@ Device::Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice ...@@ -97,6 +99,18 @@ Device::Device(const VkDeviceCreateInfo *pCreateInfo, void *mem, PhysicalDevice
// FIXME (b/119409619): use an allocator here so we can control all memory allocations // FIXME (b/119409619): use an allocator here so we can control all memory allocations
blitter.reset(new sw::Blitter()); blitter.reset(new sw::Blitter());
samplingRoutineCache.reset(new SamplingRoutineCache()); samplingRoutineCache.reset(new SamplingRoutineCache());
#ifdef ENABLE_VK_DEBUGGER
static auto port = getenv("VK_DEBUGGER_PORT");
if(port)
{
// Construct the debugger context and server - this may block for a
// debugger connection, allowing breakpoints to be set before they're
// executed.
debugger.context = vk::dbg::Context::create();
debugger.server = vk::dbg::Server::create(debugger.context, atoi(port));
}
#endif // ENABLE_VK_DEBUGGER
} }
void Device::destroy(const VkAllocationCallbacks *pAllocator) void Device::destroy(const VkAllocationCallbacks *pAllocator)
......
...@@ -33,6 +33,11 @@ namespace vk { ...@@ -33,6 +33,11 @@ namespace vk {
class PhysicalDevice; class PhysicalDevice;
class Queue; class Queue;
namespace dbg {
class Context;
class Server;
} // namespace dbg
class Device class Device
{ {
public: public:
...@@ -93,6 +98,13 @@ public: ...@@ -93,6 +98,13 @@ public:
rr::Routine *findInConstCache(const SamplingRoutineCache::Key &key) const; rr::Routine *findInConstCache(const SamplingRoutineCache::Key &key) const;
void updateSamplingRoutineConstCache(); void updateSamplingRoutineConstCache();
#ifdef ENABLE_VK_DEBUGGER
std::shared_ptr<vk::dbg::Context> getDebuggerContext() const
{
return debugger.context;
}
#endif // ENABLE_VK_DEBUGGER
private: private:
PhysicalDevice *const physicalDevice = nullptr; PhysicalDevice *const physicalDevice = nullptr;
Queue *const queues = nullptr; Queue *const queues = nullptr;
...@@ -105,6 +117,14 @@ private: ...@@ -105,6 +117,14 @@ private:
ExtensionName *extensions = nullptr; ExtensionName *extensions = nullptr;
const VkPhysicalDeviceFeatures enabledFeatures = {}; const VkPhysicalDeviceFeatures enabledFeatures = {};
std::shared_ptr<marl::Scheduler> scheduler; std::shared_ptr<marl::Scheduler> scheduler;
#ifdef ENABLE_VK_DEBUGGER
struct
{
std::shared_ptr<vk::dbg::Context> context;
std::shared_ptr<vk::dbg::Server> server;
} debugger;
#endif // ENABLE_VK_DEBUGGER
}; };
using DispatchableDevice = DispatchableObject<Device, VkDevice>; using DispatchableDevice = DispatchableObject<Device, VkDevice>;
......
...@@ -1964,7 +1964,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(VkDevice device, const V ...@@ -1964,7 +1964,7 @@ VKAPI_ATTR VkResult VKAPI_CALL vkAllocateCommandBuffers(VkDevice device, const V
nextInfo = nextInfo->pNext; nextInfo = nextInfo->pNext;
} }
return vk::Cast(pAllocateInfo->commandPool)->allocateCommandBuffers(pAllocateInfo->level, pAllocateInfo->commandBufferCount, pCommandBuffers); return vk::Cast(pAllocateInfo->commandPool)->allocateCommandBuffers(vk::Cast(device), pAllocateInfo->level, pAllocateInfo->commandBufferCount, pCommandBuffers);
} }
VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers) VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device, VkCommandPool commandPool, uint32_t commandBufferCount, const VkCommandBuffer *pCommandBuffers)
......
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