Skip to content

Commit 52a7d3f

Browse files
committed
loader: Filter out enabled extensions that are provided only by the loader.
Code is intended to be somewhat re-usable in other layers.
1 parent 0ef57de commit 52a7d3f

1 file changed

Lines changed: 84 additions & 2 deletions

File tree

src/loader/loader_instance.cpp

Lines changed: 84 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,72 @@ const std::array<XrExtensionProperties, 1>& LoaderInstance::LoaderSpecificExtens
4848
return extensions;
4949
}
5050

51+
namespace {
52+
class InstanceCreateInfoManager {
53+
public:
54+
explicit InstanceCreateInfoManager(const XrInstanceCreateInfo* info) : original_create_info(info), modified_create_info(*info) {
55+
Reset();
56+
}
57+
58+
// Reset the "modified" state to match the original state.
59+
void Reset() {
60+
enabled_extensions_cstr.clear();
61+
enabled_extensions_cstr.reserve(original_create_info->enabledExtensionCount);
62+
63+
for (uint32_t i = 0; i < original_create_info->enabledExtensionCount; ++i) {
64+
enabled_extensions_cstr.push_back(original_create_info->enabledExtensionNames[i]);
65+
}
66+
Update();
67+
}
68+
69+
// Remove extensions named in the parameter and return a pointer to the current state.
70+
const XrInstanceCreateInfo* FilterOutExtensions(const std::vector<const char*>& extensions_to_skip) {
71+
if (enabled_extensions_cstr.empty()) {
72+
return &modified_create_info;
73+
}
74+
if (extensions_to_skip.empty()) {
75+
return &modified_create_info;
76+
}
77+
auto b = enabled_extensions_cstr.begin();
78+
auto e = enabled_extensions_cstr.end();
79+
auto shouldSkipExtension = [&](const char* extensionInQuestion) {
80+
auto it = std::find_if(b, e, [&](const char* extension) { return strcmp(extensionInQuestion, extension) == 0; });
81+
return it != extensions_to_skip.end();
82+
};
83+
vector_remove_if_and_erase(enabled_extensions_cstr, shouldSkipExtension);
84+
return Update();
85+
}
86+
// Remove the extension named in the parameter and return a pointer to the current state.
87+
const XrInstanceCreateInfo* FilterOutExtension(const char* extension_to_skip) {
88+
if (enabled_extensions_cstr.empty()) {
89+
return &modified_create_info;
90+
}
91+
auto b = enabled_extensions_cstr.begin();
92+
auto e = enabled_extensions_cstr.end();
93+
auto it = std::find_if(b, e, [&](const char* extension) { return strcmp(extension_to_skip, extension) == 0; });
94+
if (it != e) {
95+
// Just that one element goes away
96+
enabled_extensions_cstr.erase(it);
97+
}
98+
return Update();
99+
}
100+
101+
// Get the current modified XrInstanceCreateInfo
102+
const XrInstanceCreateInfo* Get() const { return &modified_create_info; }
103+
104+
private:
105+
const XrInstanceCreateInfo* Update() {
106+
modified_create_info.enabledExtensionCount = static_cast<uint32_t>(enabled_extensions_cstr.size());
107+
modified_create_info.enabledExtensionNames = enabled_extensions_cstr.empty() ? nullptr : enabled_extensions_cstr.data();
108+
return &modified_create_info;
109+
}
110+
const XrInstanceCreateInfo* original_create_info;
111+
112+
XrInstanceCreateInfo modified_create_info;
113+
std::vector<const char*> enabled_extensions_cstr;
114+
};
115+
} // namespace
116+
51117
// Factory method
52118
XrResult LoaderInstance::CreateInstance(std::vector<std::unique_ptr<ApiLayerInterface>>&& api_layer_interfaces,
53119
const XrInstanceCreateInfo* info, XrInstance* instance) {
@@ -62,6 +128,20 @@ XrResult LoaderInstance::CreateInstance(std::vector<std::unique_ptr<ApiLayerInte
62128
std::unique_ptr<LoaderInstance> loader_instance(new LoaderInstance(std::move(api_layer_interfaces)));
63129
*instance = reinterpret_cast<XrInstance>(loader_instance.get());
64130

131+
// Remove the loader-supported-extensions (debug utils), if it's in the list of enabled extensions but not supported by
132+
// the runtime.
133+
InstanceCreateInfoManager create_info_manager{info};
134+
const XrInstanceCreateInfo* modified_create_info = info;
135+
if (info->enabledExtensionCount > 0) {
136+
std::vector<const char*> extensions_to_skip;
137+
for (const auto& ext : LoaderInstance::LoaderSpecificExtensions()) {
138+
if (!RuntimeInterface::GetRuntime().SupportsExtension(ext.extensionName)) {
139+
extensions_to_skip.emplace_back(ext.extensionName);
140+
}
141+
}
142+
modified_create_info = create_info_manager.FilterOutExtensions(extensions_to_skip);
143+
}
144+
65145
// Only start the xrCreateApiLayerInstance stack if we have layers.
66146
std::vector<std::unique_ptr<ApiLayerInterface>>& layer_interfaces = loader_instance->LayerInterfaces();
67147
if (!layer_interfaces.empty()) {
@@ -110,10 +190,12 @@ XrResult LoaderInstance::CreateInstance(std::vector<std::unique_ptr<ApiLayerInte
110190
api_layer_ci.loaderInstance = reinterpret_cast<void*>(loader_instance.get());
111191
api_layer_ci.settings_file_location[0] = '\0';
112192
api_layer_ci.nextInfo = next_info_list.get();
113-
last_error = topmost_cali_fp(info, &api_layer_ci, instance);
193+
//! @todo do we filter our create info extension list here?
194+
//! Think that actually each layer might need to filter...
195+
last_error = topmost_cali_fp(modified_create_info, &api_layer_ci, instance);
114196

115197
} else {
116-
last_error = topmost_ci_fp(info, instance);
198+
last_error = topmost_ci_fp(modified_create_info, instance);
117199
}
118200

119201
if (XR_SUCCEEDED(last_error)) {

0 commit comments

Comments
 (0)