mirror of https://github.com/RPCS3/rpcs3.git
vk: Preliminary support for debug markers
This commit is contained in:
parent
bd09dc8ea8
commit
d894ccb4ea
|
@ -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);
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue