Path: blob/master/thirdparty/openxr/src/common/object_info.cpp
9903 views
// Copyright (c) 2017-2025 The Khronos Group Inc.1// Copyright (c) 2017-2019 Valve Corporation2// Copyright (c) 2017-2019 LunarG, Inc.3// Copyright (c) 2019 Collabora, Ltd.4//5// SPDX-License-Identifier: Apache-2.0 OR MIT6//7// Initial Authors: Mark Young <[email protected]>8// Rylie Pavlik <[email protected]>9// Dave Houlton <[email protected]>10//1112#include "object_info.h"1314#include "extra_algorithms.h"15#include "hex_and_handles.h"1617#include <openxr/openxr.h>1819#include <algorithm>20#include <iterator>21#include <memory>22#include <sstream>23#include <string>24#include <vector>2526#include "memory.h"2728std::string XrSdkLogObjectInfo::ToString() const {29std::ostringstream oss;30oss << Uint64ToHexString(handle);31if (!name.empty()) {32oss << " (" << name << ")";33}34return oss.str();35}3637void ObjectInfoCollection::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {38// If name is empty, we should erase it39if (object_name.empty()) {40RemoveObject(object_handle, object_type);41return;42}4344// Otherwise, add it or update the name45XrSdkLogObjectInfo new_obj = {object_handle, object_type};4647// If it already exists, update the name48auto lookup_info = LookUpStoredObjectInfo(new_obj);49if (lookup_info != nullptr) {50lookup_info->name = object_name;51return;52}5354// It doesn't exist, so add a new info block55new_obj.name = object_name;56object_info_.push_back(new_obj);57}5859void ObjectInfoCollection::RemoveObject(uint64_t object_handle, XrObjectType object_type) {60vector_remove_if_and_erase(61object_info_, [=](XrSdkLogObjectInfo const& info) { return info.handle == object_handle && info.type == object_type; });62}6364XrSdkLogObjectInfo const* ObjectInfoCollection::LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) const {65auto e = object_info_.end();66auto it = std::find_if(object_info_.begin(), e, [&](XrSdkLogObjectInfo const& stored) { return Equivalent(stored, info); });67if (it != e) {68return &(*it);69}70return nullptr;71}7273XrSdkLogObjectInfo* ObjectInfoCollection::LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) {74auto e = object_info_.end();75auto it = std::find_if(object_info_.begin(), e, [&](XrSdkLogObjectInfo const& stored) { return Equivalent(stored, info); });76if (it != e) {77return &(*it);78}79return nullptr;80}8182bool ObjectInfoCollection::LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const {83auto info_lookup = LookUpStoredObjectInfo(info.objectHandle, info.objectType);84if (info_lookup != nullptr) {85info.objectName = info_lookup->name.c_str();86return true;87}88return false;89}9091bool ObjectInfoCollection::LookUpObjectName(XrSdkLogObjectInfo& info) const {92auto info_lookup = LookUpStoredObjectInfo(info);93if (info_lookup != nullptr) {94info.name = info_lookup->name;95return true;96}97return false;98}99100static std::vector<XrDebugUtilsObjectNameInfoEXT> PopulateObjectNameInfo(std::vector<XrSdkLogObjectInfo> const& obj) {101std::vector<XrDebugUtilsObjectNameInfoEXT> ret;102ret.reserve(obj.size());103std::transform(obj.begin(), obj.end(), std::back_inserter(ret), [](XrSdkLogObjectInfo const& info) {104return XrDebugUtilsObjectNameInfoEXT{XR_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, nullptr, info.type, info.handle,105info.name.c_str()};106});107return ret;108}109110NamesAndLabels::NamesAndLabels(std::vector<XrSdkLogObjectInfo> obj, std::vector<XrDebugUtilsLabelEXT> lab)111: sdk_objects(std::move(obj)), objects(PopulateObjectNameInfo(sdk_objects)), labels(std::move(lab)) {}112113void NamesAndLabels::PopulateCallbackData(XrDebugUtilsMessengerCallbackDataEXT& callback_data) const {114callback_data.objects = objects.empty() ? nullptr : const_cast<XrDebugUtilsObjectNameInfoEXT*>(objects.data());115callback_data.objectCount = static_cast<uint32_t>(objects.size());116callback_data.sessionLabels = labels.empty() ? nullptr : const_cast<XrDebugUtilsLabelEXT*>(labels.data());117callback_data.sessionLabelCount = static_cast<uint32_t>(labels.size());118}119120void DebugUtilsData::LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const {121auto session_label_iterator = session_labels_.find(session);122if (session_label_iterator != session_labels_.end()) {123auto& XrSdkSessionLabels = *session_label_iterator->second;124// Copy the debug utils labels in reverse order in the the labels vector.125std::transform(XrSdkSessionLabels.rbegin(), XrSdkSessionLabels.rend(), std::back_inserter(labels),126[](XrSdkSessionLabelPtr const& label) { return label->debug_utils_label; });127}128}129130XrSdkSessionLabel::XrSdkSessionLabel(const XrDebugUtilsLabelEXT& label_info, bool individual)131: label_name(label_info.labelName), debug_utils_label(label_info), is_individual_label(individual) {132// Update the c string pointer to the one we hold.133debug_utils_label.labelName = label_name.c_str();134// Zero out the next pointer to avoid a dangling pointer135debug_utils_label.next = nullptr;136}137138XrSdkSessionLabelPtr XrSdkSessionLabel::make(const XrDebugUtilsLabelEXT& label_info, bool individual) {139XrSdkSessionLabelPtr ret(new XrSdkSessionLabel(label_info, individual));140return ret;141}142void DebugUtilsData::AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name) {143object_info_.AddObjectName(object_handle, object_type, object_name);144}145146// We always want to remove the old individual label before we do anything else.147// So, do that in its own method148void DebugUtilsData::RemoveIndividualLabel(XrSdkSessionLabelList& label_vec) {149if (!label_vec.empty() && label_vec.back()->is_individual_label) {150label_vec.pop_back();151}152}153154XrSdkSessionLabelList* DebugUtilsData::GetSessionLabelList(XrSession session) {155auto session_label_iterator = session_labels_.find(session);156if (session_label_iterator == session_labels_.end()) {157return nullptr;158}159return session_label_iterator->second.get();160}161162XrSdkSessionLabelList& DebugUtilsData::GetOrCreateSessionLabelList(XrSession session) {163XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);164if (vec_ptr == nullptr) {165std::unique_ptr<XrSdkSessionLabelList> vec(new XrSdkSessionLabelList);166vec_ptr = vec.get();167session_labels_[session] = std::move(vec);168}169return *vec_ptr;170}171172void DebugUtilsData::BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT& label_info) {173auto& vec = GetOrCreateSessionLabelList(session);174175// Individual labels do not stay around in the transition into a new label region176RemoveIndividualLabel(vec);177178// Start the new label region179vec.emplace_back(XrSdkSessionLabel::make(label_info, false));180}181182void DebugUtilsData::EndLabelRegion(XrSession session) {183XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);184if (vec_ptr == nullptr) {185return;186}187188// Individual labels do not stay around in the transition out of label region189RemoveIndividualLabel(*vec_ptr);190191// Remove the last label region192if (!vec_ptr->empty()) {193vec_ptr->pop_back();194}195}196197void DebugUtilsData::InsertLabel(XrSession session, const XrDebugUtilsLabelEXT& label_info) {198auto& vec = GetOrCreateSessionLabelList(session);199200// Remove any individual layer that might already be there201RemoveIndividualLabel(vec);202203// Insert a new individual label204vec.emplace_back(XrSdkSessionLabel::make(label_info, true));205}206207void DebugUtilsData::DeleteObject(uint64_t object_handle, XrObjectType object_type) {208object_info_.RemoveObject(object_handle, object_type);209210if (object_type == XR_OBJECT_TYPE_SESSION) {211auto session = TreatIntegerAsHandle<XrSession>(object_handle);212XrSdkSessionLabelList* vec_ptr = GetSessionLabelList(session);213if (vec_ptr != nullptr) {214session_labels_.erase(session);215}216}217}218219void DebugUtilsData::DeleteSessionLabels(XrSession session) { session_labels_.erase(session); }220221NamesAndLabels DebugUtilsData::PopulateNamesAndLabels(std::vector<XrSdkLogObjectInfo> objects) const {222std::vector<XrDebugUtilsLabelEXT> labels;223for (auto& obj : objects) {224// Check for any names that have been associated with the objects and set them up here225object_info_.LookUpObjectName(obj);226// If this is a session, see if there are any labels associated with it for us to add227// to the callback content.228if (XR_OBJECT_TYPE_SESSION == obj.type) {229LookUpSessionLabels(obj.GetTypedHandle<XrSession>(), labels);230}231}232233return {objects, labels};234}235236void DebugUtilsData::WrapCallbackData(AugmentedCallbackData* aug_data,237const XrDebugUtilsMessengerCallbackDataEXT* callback_data) const {238// If there's nothing to add, just return the original data as the augmented copy239aug_data->exported_data = callback_data;240if (object_info_.Empty() || callback_data->objectCount == 0) {241return;242}243244// Inspect each of the callback objects245bool name_found = false;246for (uint32_t obj = 0; obj < callback_data->objectCount; ++obj) {247auto& current_obj = callback_data->objects[obj];248name_found |= (nullptr != object_info_.LookUpStoredObjectInfo(current_obj.objectHandle, current_obj.objectType));249250// If this is a session, record any labels associated with it251if (XR_OBJECT_TYPE_SESSION == current_obj.objectType) {252XrSession session = TreatIntegerAsHandle<XrSession>(current_obj.objectHandle);253LookUpSessionLabels(session, aug_data->labels);254}255}256257// If we found nothing to add, return the original data258if (!name_found && aug_data->labels.empty()) {259return;260}261262// Found additional data - modify an internal copy and return that as the exported data263memcpy(&aug_data->modified_data, callback_data, sizeof(XrDebugUtilsMessengerCallbackDataEXT));264aug_data->new_objects.assign(callback_data->objects, callback_data->objects + callback_data->objectCount);265266// Record (overwrite) the names of all incoming objects provided in our internal list267for (auto& obj : aug_data->new_objects) {268object_info_.LookUpObjectName(obj);269}270271// Update local copy & point export to it272aug_data->modified_data.objects = aug_data->new_objects.data();273aug_data->modified_data.sessionLabelCount = static_cast<uint32_t>(aug_data->labels.size());274aug_data->modified_data.sessionLabels = aug_data->labels.empty() ? nullptr : aug_data->labels.data();275aug_data->exported_data = &aug_data->modified_data;276return;277}278279280