1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
|
// Copyright (c) 2017-2022, The Khronos Group Inc.
// Copyright (c) 2017-2019 Valve Corporation
// Copyright (c) 2017-2019 LunarG, Inc.
// Copyright (c) 2019 Collabora, Ltd.
//
// SPDX-License-Identifier: Apache-2.0 OR MIT
//
// Initial Authors: Mark Young <marky@lunarg.com>, Ryan Pavlik <ryan.pavlik@collabora.com
//
/*!
* @file
*
* The core of an XR_EXT_debug_utils implementation, used/shared by the loader and several SDK layers.
*/
#pragma once
#include "hex_and_handles.h"
#include <openxr/openxr.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <vector>
struct XrSdkGenericObject {
//! Type-erased handle value
uint64_t handle;
//! Kind of object this handle refers to
XrObjectType type;
/// Un-erase the type of the handle and get it properly typed again.
///
/// Note: Does not check the type before doing it!
template <typename HandleType>
HandleType& GetTypedHandle() {
return TreatIntegerAsHandle<HandleType&>(handle);
}
//! @overload
template <typename HandleType>
HandleType const& GetTypedHandle() const {
return TreatIntegerAsHandle<HandleType&>(handle);
}
//! Create from a typed handle and object type
template <typename T>
XrSdkGenericObject(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
//! Create from an untyped handle value (integer) and object type
XrSdkGenericObject(uint64_t h, XrObjectType t) : handle(h), type(t) {}
};
struct XrSdkLogObjectInfo {
//! Type-erased handle value
uint64_t handle;
//! Kind of object this handle refers to
XrObjectType type;
//! To be assigned by the application - not part of this object's identity
std::string name;
/// Un-erase the type of the handle and get it properly typed again.
///
/// Note: Does not check the type before doing it!
template <typename HandleType>
HandleType& GetTypedHandle() {
return TreatIntegerAsHandle<HandleType&>(handle);
}
//! @overload
template <typename HandleType>
HandleType const& GetTypedHandle() const {
return TreatIntegerAsHandle<HandleType&>(handle);
}
XrSdkLogObjectInfo() = default;
//! Create from a typed handle and object type
template <typename T>
XrSdkLogObjectInfo(T h, XrObjectType t) : handle(MakeHandleGeneric(h)), type(t) {}
//! Create from an untyped handle value (integer) and object type
XrSdkLogObjectInfo(uint64_t h, XrObjectType t) : handle(h), type(t) {}
//! Create from an untyped handle value (integer), object type, and name
XrSdkLogObjectInfo(uint64_t h, XrObjectType t, const char* n) : handle(h), type(t), name(n == nullptr ? "" : n) {}
std::string ToString() const;
};
//! True if the two object infos have the same handle value and handle type
static inline bool Equivalent(XrSdkLogObjectInfo const& a, XrSdkLogObjectInfo const& b) {
return a.handle == b.handle && a.type == b.type;
}
//! @overload
static inline bool Equivalent(XrDebugUtilsObjectNameInfoEXT const& a, XrSdkLogObjectInfo const& b) {
return a.objectHandle == b.handle && a.objectType == b.type;
}
//! @overload
static inline bool Equivalent(XrSdkLogObjectInfo const& a, XrDebugUtilsObjectNameInfoEXT const& b) { return Equivalent(b, a); }
/// Object info registered with calls to xrSetDebugUtilsObjectNameEXT
class ObjectInfoCollection {
public:
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
void RemoveObject(uint64_t object_handle, XrObjectType object_type);
//! Find the stored object info, if any, matching handle and type.
//! Return nullptr if not found.
XrSdkLogObjectInfo const* LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info) const;
//! Find the stored object info, if any, matching handle and type.
//! Return nullptr if not found.
XrSdkLogObjectInfo* LookUpStoredObjectInfo(XrSdkLogObjectInfo const& info);
//! Find the stored object info, if any.
//! Return nullptr if not found.
XrSdkLogObjectInfo const* LookUpStoredObjectInfo(uint64_t handle, XrObjectType type) const {
return LookUpStoredObjectInfo({handle, type});
}
//! Find the object name, if any, and update debug utils info accordingly.
//! Return true if found and updated.
bool LookUpObjectName(XrDebugUtilsObjectNameInfoEXT& info) const;
//! Find the object name, if any, and update logging info accordingly.
//! Return true if found and updated.
bool LookUpObjectName(XrSdkLogObjectInfo& info) const;
//! Is the collection empty?
bool Empty() const { return object_info_.empty(); }
private:
// Object names that have been set for given objects
std::vector<XrSdkLogObjectInfo> object_info_;
};
struct XrSdkSessionLabel;
using XrSdkSessionLabelPtr = std::unique_ptr<XrSdkSessionLabel>;
using XrSdkSessionLabelList = std::vector<XrSdkSessionLabelPtr>;
struct XrSdkSessionLabel {
static XrSdkSessionLabelPtr make(const XrDebugUtilsLabelEXT& label_info, bool individual);
std::string label_name;
XrDebugUtilsLabelEXT debug_utils_label;
bool is_individual_label;
private:
XrSdkSessionLabel(const XrDebugUtilsLabelEXT& label_info, bool individual);
};
/// The metadata for a collection of objects. Must persist unmodified during the entire debug messenger call!
struct NamesAndLabels {
NamesAndLabels() = default;
NamesAndLabels(std::vector<XrSdkLogObjectInfo> obj, std::vector<XrDebugUtilsLabelEXT> lab);
/// C++ structure owning the data (strings) backing the objects vector.
std::vector<XrSdkLogObjectInfo> sdk_objects;
std::vector<XrDebugUtilsObjectNameInfoEXT> objects;
std::vector<XrDebugUtilsLabelEXT> labels;
/// Populate the debug utils callback data structure.
void PopulateCallbackData(XrDebugUtilsMessengerCallbackDataEXT& data) const;
// XrDebugUtilsMessengerCallbackDataEXT MakeCallbackData() const;
};
struct AugmentedCallbackData {
std::vector<XrDebugUtilsLabelEXT> labels;
std::vector<XrDebugUtilsObjectNameInfoEXT> new_objects;
XrDebugUtilsMessengerCallbackDataEXT modified_data;
const XrDebugUtilsMessengerCallbackDataEXT* exported_data;
};
/// Tracks all the data (handle names and session labels) required to fully augment XR_EXT_debug_utils-related calls.
class DebugUtilsData {
public:
DebugUtilsData() = default;
DebugUtilsData(const DebugUtilsData&) = delete;
DebugUtilsData& operator=(const DebugUtilsData&) = delete;
bool Empty() const { return object_info_.Empty() && session_labels_.empty(); }
//! Core of implementation for xrSetDebugUtilsObjectNameEXT
void AddObjectName(uint64_t object_handle, XrObjectType object_type, const std::string& object_name);
/// Core of implementation for xrSessionBeginDebugUtilsLabelRegionEXT
void BeginLabelRegion(XrSession session, const XrDebugUtilsLabelEXT& label_info);
/// Core of implementation for xrSessionEndDebugUtilsLabelRegionEXT
void EndLabelRegion(XrSession session);
/// Core of implementation for xrSessionInsertDebugUtilsLabelEXT
void InsertLabel(XrSession session, const XrDebugUtilsLabelEXT& label_info);
/// Removes all labels associated with a session - call in xrDestroySession and xrDestroyInstance (for all child sessions)
void DeleteSessionLabels(XrSession session);
/// Retrieve labels for the given session, if any, and push them in reverse order on the vector.
void LookUpSessionLabels(XrSession session, std::vector<XrDebugUtilsLabelEXT>& labels) const;
/// Removes all data related to this object - including session labels if it's a session.
///
/// Does not take care of handling child objects - you must do this yourself.
void DeleteObject(uint64_t object_handle, XrObjectType object_type);
/// Given the collection of objects, populate their names and list of labels
NamesAndLabels PopulateNamesAndLabels(std::vector<XrSdkLogObjectInfo> objects) const;
void WrapCallbackData(AugmentedCallbackData* aug_data,
const XrDebugUtilsMessengerCallbackDataEXT* provided_callback_data) const;
private:
void RemoveIndividualLabel(XrSdkSessionLabelList& label_vec);
XrSdkSessionLabelList* GetSessionLabelList(XrSession session);
XrSdkSessionLabelList& GetOrCreateSessionLabelList(XrSession session);
// Session labels: one vector of them per session.
std::unordered_map<XrSession, std::unique_ptr<XrSdkSessionLabelList>> session_labels_;
// Names for objects.
ObjectInfoCollection object_info_;
};
|