vk: Preliminary support for debug markers

This commit is contained in:
kd-11 2023-05-16 02:49:44 +03:00 committed by kd-11
parent bd09dc8ea8
commit d894ccb4ea
5 changed files with 221 additions and 0 deletions

View File

@ -98,6 +98,14 @@ namespace vk
g_last_completed_event = std::max(event_id, g_last_completed_event.load()); g_last_completed_event = std::max(event_id, g_last_completed_event.load());
} }
void print_debug_markers()
{
for (const auto marker : g_resource_manager.gather_debug_markers())
{
marker->dump();
}
}
static constexpr f32 size_in_GiB(u64 size) static constexpr f32 size_in_GiB(u64 size)
{ {
return size / (1024.f * 1024.f * 1024.f); return size / (1024.f * 1024.f * 1024.f);

View File

@ -57,6 +57,7 @@ namespace vk
u64 eid; u64 eid;
const vk::render_device* m_device; const vk::render_device* m_device;
std::vector<disposable_t> m_disposables; std::vector<disposable_t> m_disposables;
std::vector<std::unique_ptr<device_debug_marker>> m_debug_markers;
eid_scope_t(u64 _eid): eid_scope_t(u64 _eid):
eid(_eid), m_device(g_render_device) eid(_eid), m_device(g_render_device)
@ -72,11 +73,13 @@ namespace vk
std::swap(eid, other.eid); std::swap(eid, other.eid);
std::swap(m_device, other.m_device); std::swap(m_device, other.m_device);
std::swap(m_disposables, other.m_disposables); std::swap(m_disposables, other.m_disposables);
std::swap(m_debug_markers, other.m_debug_markers);
} }
void discard() void discard()
{ {
m_disposables.clear(); m_disposables.clear();
m_debug_markers.clear();
} }
}; };
@ -187,6 +190,13 @@ namespace vk
get_current_eid_scope().m_disposables.emplace_back(std::move(disposable)); get_current_eid_scope().m_disposables.emplace_back(std::move(disposable));
} }
inline void dispose(std::unique_ptr<vk::device_debug_marker>& object)
{
// Special case as we may need to read these out.
// FIXME: We can manage these markers better and remove this exception.
get_current_eid_scope().m_debug_markers.emplace_back(std::move(object));
}
template<typename T> template<typename T>
inline void dispose(std::unique_ptr<T>& object) inline void dispose(std::unique_ptr<T>& object)
{ {
@ -221,6 +231,19 @@ namespace vk
} }
void trim(); void trim();
std::vector<const device_debug_marker*> gather_debug_markers() const
{
std::vector<const device_debug_marker*> result;
for (const auto& scope : m_eid_map)
{
for (const auto& item : scope.m_debug_markers)
{
result.push_back(item.get());
}
}
return result;
}
}; };
struct vmm_allocation_t struct vmm_allocation_t

View File

@ -7,6 +7,8 @@
namespace vk namespace vk
{ {
extern void print_debug_markers();
void die_with_error(VkResult error_code, std::string message, void die_with_error(VkResult error_code, std::string message,
const char* file, const char* file,
const char* func, const char* func,
@ -103,6 +105,8 @@ namespace vk
{ {
default: default:
case 0: case 0:
print_debug_markers();
if (!message.empty()) message += "\n\n"; if (!message.empty()) message += "\n\n";
fmt::throw_exception("%sAssertion Failed! Vulkan API call failed with unrecoverable error: %s%s", message, error_message, src_loc{line, col, file, func}); fmt::throw_exception("%sAssertion Failed! Vulkan API call failed with unrecoverable error: %s%s", message, error_message, src_loc{line, col, file, func});
case 1: case 1:

View File

@ -10,6 +10,9 @@
#include "util/sysinfo.hpp" #include "util/sysinfo.hpp"
#include "util/asm.hpp" #include "util/asm.hpp"
// FIXME: namespace pollution
#include "../VKResourceManager.h"
namespace vk namespace vk
{ {
fence::fence(VkDevice dev) fence::fence(VkDevice dev)
@ -169,6 +172,135 @@ namespace vk
} }
} }
device_marker_pool::device_marker_pool(const vk::render_device& dev, u32 count)
: pdev(&dev), m_count(count)
{}
std::tuple<VkBuffer, u64, volatile u32*> device_marker_pool::allocate()
{
if (!m_buffer || m_offset >= m_count)
{
create_impl();
}
const auto out_offset = m_offset;
m_offset ++;
return { m_buffer->value, out_offset * 4, m_mapped + out_offset };
}
void device_marker_pool::create_impl()
{
if (m_buffer)
{
m_buffer->unmap();
vk::get_resource_manager()->dispose(m_buffer);
}
m_buffer = std::make_unique<buffer>
(
*pdev,
m_count * 4,
pdev->get_memory_mapping().host_visible_coherent,
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT,
VK_BUFFER_USAGE_TRANSFER_DST_BIT,
0,
VMM_ALLOCATION_POOL_SYSTEM
);
m_mapped = reinterpret_cast<volatile u32*>(m_buffer->map(0, VK_WHOLE_SIZE));
m_offset = 0;
}
device_debug_marker::device_debug_marker(device_marker_pool& pool, std::string message)
: m_device(*pool.pdev), m_message(std::move(message))
{
std::tie(m_buffer, m_buffer_offset, m_value) = pool.allocate();
*m_value = 0xCAFEBABE;
}
device_debug_marker::~device_debug_marker()
{
if (!m_printed)
{
dump();
}
m_value = nullptr;
}
void device_debug_marker::signal(const command_buffer& cmd, VkPipelineStageFlags stages, VkAccessFlags access)
{
insert_global_memory_barrier(cmd, stages, VK_PIPELINE_STAGE_TRANSFER_BIT, access, VK_ACCESS_TRANSFER_WRITE_BIT);
vkCmdFillBuffer(cmd, m_buffer, m_buffer_offset, 4, 0xDEADBEEF);
}
void device_debug_marker::dump()
{
if (*m_value == 0xCAFEBABE)
{
rsx_log.error("DEBUG MARKER NOT REACHED: %s", m_message);
}
m_printed = true;
}
void device_debug_marker::dump() const
{
if (*m_value == 0xCAFEBABE)
{
rsx_log.error("DEBUG MARKER NOT REACHED: %s", m_message);
}
else
{
rsx_log.error("DEBUG MARKER: %s", m_message);
}
}
// FIXME
static std::unique_ptr<device_marker_pool> g_device_marker_pool;
device_marker_pool& get_shared_marker_pool(const vk::render_device& dev)
{
if (!g_device_marker_pool)
{
g_device_marker_pool = std::make_unique<device_marker_pool>(dev, 65536);
}
return *g_device_marker_pool;
}
void device_debug_marker::insert(
const vk::render_device& dev,
const vk::command_buffer& cmd,
std::string message,
VkPipelineStageFlags stages,
VkAccessFlags access)
{
auto result = std::make_unique<device_debug_marker>(get_shared_marker_pool(dev), message);
result->signal(cmd, stages, access);
vk::get_resource_manager()->dispose(result);
}
debug_marker_scope::debug_marker_scope(const vk::command_buffer& cmd, const std::string& message)
: dev(&cmd.get_command_pool().get_owner()), cb(&cmd), message(message)
{
vk::device_debug_marker::insert(
*dev,
*cb,
fmt::format("0x%x: Enter %s", rsx::get_shared_tag(), message)
);
}
debug_marker_scope::~debug_marker_scope()
{
ensure(cb && cb->is_recording());
vk::device_debug_marker::insert(
*dev,
*cb,
fmt::format("0x%x: Exit %s", rsx::get_shared_tag(), message)
);
}
VkResult wait_for_fence(fence* pFence, u64 timeout) VkResult wait_for_fence(fence* pFence, u64 timeout)
{ {
pFence->wait_flush(); pFence->wait_flush();

View File

@ -87,6 +87,60 @@ namespace vk
operator VkSemaphore() const; operator VkSemaphore() const;
}; };
class device_marker_pool
{
std::unique_ptr<buffer> m_buffer;
volatile u32* m_mapped = nullptr;
u64 m_offset = 0;
u32 m_count = 0;
void create_impl();
public:
device_marker_pool(const vk::render_device& dev, u32 count);
std::tuple<VkBuffer, u64, volatile u32*> allocate();
const vk::render_device* pdev = nullptr;
};
class device_debug_marker
{
std::string m_message;
bool m_printed = false;
VkDevice m_device = VK_NULL_HANDLE;
VkBuffer m_buffer = VK_NULL_HANDLE;
u64 m_buffer_offset = 0;
volatile u32* m_value = nullptr;
public:
device_debug_marker(device_marker_pool& pool, std::string message);
~device_debug_marker();
device_debug_marker(const event&) = delete;
void signal(const command_buffer& cmd, VkPipelineStageFlags stages, VkAccessFlags access);
void dump();
void dump() const;
static void insert(
const vk::render_device& dev,
const vk::command_buffer& cmd,
std::string message,
VkPipelineStageFlags stages = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT,
VkAccessFlags access = VK_ACCESS_MEMORY_READ_BIT | VK_ACCESS_MEMORY_WRITE_BIT);
};
class debug_marker_scope
{
const vk::render_device* dev;
const vk::command_buffer* cb;
std::string message;
public:
debug_marker_scope(const vk::command_buffer& cmd, const std::string& text);
~debug_marker_scope();
};
VkResult wait_for_fence(fence* pFence, u64 timeout = 0ull); VkResult wait_for_fence(fence* pFence, u64 timeout = 0ull);
VkResult wait_for_event(event* pEvent, u64 timeout = 0ull); VkResult wait_for_event(event* pEvent, u64 timeout = 0ull);
} }