@@ -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
52118XrResult 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