Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 10 additions & 10 deletions layersvt/debug_marker/debug_marker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,12 +151,12 @@ void DebugMarker::PreDestroyInstance(VkInstance instance, const VkAllocationCall
void DebugMarker::PreDestroyDevice(VkDevice device, const VkAllocationCallbacks* pAllocator) {
(void)pAllocator;
uint64_t dev_handle = (uint64_t)device;
std::vector<DebugObjectName> removed_names;
std::vector<DebugObjectKey> removed_objects;
{
std::lock_guard<std::mutex> lock(mutex_);
for (auto it = debug_object_names_.begin(); it != debug_object_names_.end();) {
if (it->second.vk_device == dev_handle) {
removed_names.push_back(std::move(it->second));
if (it->first.vk_device == dev_handle) {
removed_objects.push_back(it->first);
it = debug_object_names_.erase(it);
} else {
++it;
Expand All @@ -166,7 +166,7 @@ void DebugMarker::PreDestroyDevice(VkDevice device, const VkAllocationCallbacks*
// Tell trace consumers that the objects of this device are unnamed from here on. The packets are
// emitted after mutex_ is released, because the session start observer takes mutex_ from the tracing
// thread (EmitAllDebugMarkers). The device is still alive here, so its handles cannot be reused yet.
for (const auto& removed : removed_names) {
for (const auto& removed : removed_objects) {
EmitDebugObjectNamePacket(removed.vk_device, removed.object_type, removed.handle, std::string());
}
}
Expand All @@ -180,30 +180,30 @@ void DebugMarker::SetDebugObjectName(uint64_t device, int32_t type, uint64_t han
std::lock_guard<std::mutex> lock(mutex_);

std::string name_str = name;
debug_object_names_[std::make_tuple(device, type, handle)] = DebugObjectName(device, type, handle, name_str);
debug_object_names_[{device, type, handle}] = name_str;
EmitDebugObjectNamePacket(device, type, handle, name_str);
}

void DebugMarker::RemoveDebugObjectName(uint64_t device, int32_t type, uint64_t handle) {
std::lock_guard<std::mutex> lock(mutex_);
if (debug_object_names_.erase(std::make_tuple(device, type, handle)) == 0) return;
if (debug_object_names_.erase({device, type, handle}) == 0) return;
// An empty name tells trace consumers the object is unnamed from here on.
EmitDebugObjectNamePacket(device, type, handle, std::string());
}

void DebugMarker::EmitAllDebugMarkers() {
std::lock_guard<std::mutex> lock(mutex_);
for (const auto& entry : debug_object_names_) {
const auto& marker = entry.second;
EmitDebugObjectNamePacket(marker.vk_device, marker.object_type, marker.handle, marker.name);
const DebugObjectKey& key = entry.first;
EmitDebugObjectNamePacket(key.vk_device, key.object_type, key.handle, entry.second);
}
}

std::optional<std::string> DebugMarker::GetDebugObjectName(uint64_t device, int32_t type, uint64_t handle) const {
std::lock_guard<std::mutex> lock(mutex_);
auto it = debug_object_names_.find(std::make_tuple(device, type, handle));
auto it = debug_object_names_.find({device, type, handle});
if (it == debug_object_names_.end()) return std::nullopt;
return it->second.name;
return it->second;
}

VkResult DebugMarker::CreateEmulatedMessenger(VkInstance instance, const VkDebugUtilsMessengerCreateInfoEXT* pCreateInfo,
Expand Down
22 changes: 14 additions & 8 deletions layersvt/debug_marker/debug_marker.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
#include <map>
#include <optional>
#include <string>
#include <tuple>
#include <unordered_map>
#include <vector>

#include "common/layer_base.h"
Expand Down Expand Up @@ -119,23 +119,29 @@ class DebugMarker : public layersvt::LayerBase {
PFN_vkVoidFunction GetLayerDeviceCommand(VkDevice device, const char* name) override;

private:
struct DebugObjectName {
struct DebugObjectKey {
uint64_t vk_device;
int32_t object_type;
uint64_t handle;
std::string name;

DebugObjectName() = default;
DebugObjectName(uint64_t dev, int32_t type, uint64_t h, const std::string& n)
: vk_device(dev), object_type(type), handle(h), name(n) {}
bool operator==(const DebugObjectKey& other) const = default;

struct Hash {
size_t operator()(const DebugObjectKey& key) const noexcept {
size_t h1 = std::hash<uint64_t>{}(key.vk_device);
size_t h2 = std::hash<int32_t>{}(key.object_type);
size_t h3 = std::hash<uint64_t>{}(key.handle);
return h1 ^ (h2 << 1) ^ (h3 << 2);
}
};
};

mutable std::mutex mutex_;
/**
* @brief Maps (vk_device, object_type, object_handle) to its debug name information.
* @brief Maps (vk_device, object_type, object_handle) to its debug name.
* Non-dispatchable handles are not guaranteed to be unique across object types or devices.
*/
std::map<std::tuple<uint64_t, int32_t, uint64_t>, DebugObjectName> debug_object_names_;
std::unordered_map<DebugObjectKey, std::string, DebugObjectKey::Hash> debug_object_names_;

struct EmulatedMessenger {
VkInstance instance;
Expand Down
8 changes: 4 additions & 4 deletions layersvt/test/test_debugmarker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,20 +159,20 @@ TEST_F(DebugMarkerTests, PreDestroyDeviceCleanupTest) {
});

DebugMarker::Get().SetDebugObjectName((uint64_t)dev1, VK_OBJECT_TYPE_BUFFER, 0x1111, "Buffer1");
DebugMarker::Get().SetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x2222, "Buffer2");
DebugMarker::Get().SetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x1111, "Buffer2");

EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev1, VK_OBJECT_TYPE_BUFFER, 0x1111), "Buffer1");
EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x2222), "Buffer2");
EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x1111), "Buffer2");

// Destroy dev1 - should remove Buffer1 but keep Buffer2
layersvt::LayerBaseTestPeer::DestroyDevice(dev1, nullptr);

EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev1, VK_OBJECT_TYPE_BUFFER, 0x1111), std::nullopt);
EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x2222), "Buffer2");
EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x1111), "Buffer2");

// Destroy dev2 - should remove Buffer2
layersvt::LayerBaseTestPeer::DestroyDevice(dev2, nullptr);
EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x2222), std::nullopt);
EXPECT_EQ(DebugMarker::Get().GetDebugObjectName((uint64_t)dev2, VK_OBJECT_TYPE_BUFFER, 0x1111), std::nullopt);
}

TEST_F(DebugMarkerTests, NullOrEmptyNameRemovesNameTest) {
Expand Down