@@ -25,40 +25,92 @@ class IApplicationFramework : public core::IReferenceCounted
25
25
// this is safe to call multiple times
26
26
static bool GlobalsInit ()
27
27
{
28
- #ifdef _NBL_PLATFORM_WINDOWS_
29
- #ifdef NBL_CPACK_PACKAGE_DXC_DLL_DIR
30
- #ifdef NBL_CPACK_NO_BUILD_DIRECTORY_MODULES
31
- const HRESULT dxcLoad = CSystemWin32::delayLoadDLL (" dxcompiler.dll" , { NBL_CPACK_PACKAGE_DXC_DLL_DIR });
32
- #else
33
- const HRESULT dxcLoad = CSystemWin32::delayLoadDLL (" dxcompiler.dll" , { path (_DXC_DLL_).parent_path (), NBL_CPACK_PACKAGE_DXC_DLL_DIR });
34
- #endif
28
+ // TODO: update CMake and rename "DLL" in all of those defines here to "MODULE" or "RUNTIME"
29
+
30
+ auto getEnvInstallDirectory = []()
31
+ {
32
+ const char * sdk = std::getenv (" NBL_INSTALL_DIRECTORY" );
33
+
34
+ if (sdk)
35
+ {
36
+ const auto directory = system::path (sdk);
37
+
38
+ if (std::filesystem::exists (directory))
39
+ return directory;
40
+ }
41
+
42
+ return system::path (" " );
43
+ };
44
+
45
+ constexpr struct
46
+ {
47
+ std::string_view nabla, dxc;
48
+ } module =
49
+ {
50
+ #ifdef _NBL_SHARED_BUILD_
51
+ _NABLA_DLL_NAME_
35
52
#else
36
- const HRESULT dxcLoad = CSystemWin32::delayLoadDLL ( " dxcompiler.dll " , { path (_DXC_DLL_). parent_path () });
53
+ " "
37
54
#endif
55
+ ,
56
+ " dxcompiler"
57
+ };
38
58
39
- if (FAILED (dxcLoad))
40
- return false ;
41
-
42
- #ifdef _NBL_SHARED_BUILD_
43
- // if there was no DLL next to the executable, then try from the Nabla build directory
44
- // else if nothing in the build dir, then try looking for Nabla in the CURRENT BUILD'S INSTALL DIR
45
- // and in CPack package install directory
46
-
47
- #ifdef NBL_CPACK_PACKAGE_NABLA_DLL_DIR
48
- #ifdef NBL_CPACK_NO_BUILD_DIRECTORY_MODULES
49
- const HRESULT nablaLoad = CSystemWin32::delayLoadDLL (_NABLA_DLL_NAME_, { _NABLA_INSTALL_DIR_, NBL_CPACK_PACKAGE_NABLA_DLL_DIR });
50
- #else
51
- const HRESULT nablaLoad = CSystemWin32::delayLoadDLL (_NABLA_DLL_NAME_, { _NABLA_OUTPUT_DIR_,_NABLA_INSTALL_DIR_, NBL_CPACK_PACKAGE_NABLA_DLL_DIR });
52
- #endif
53
- #else
54
- const HRESULT nablaLoad = CSystemWin32::delayLoadDLL (_NABLA_DLL_NAME_, { _NABLA_OUTPUT_DIR_,_NABLA_INSTALL_DIR_ });
55
- #endif
56
-
57
- if (FAILED (nablaLoad))
59
+ const auto sdk = getEnvInstallDirectory ();
60
+
61
+ struct
62
+ {
63
+ system::path nabla, dxc;
64
+ } install, env, build, rel;
65
+
66
+ install.nabla = std::filesystem::absolute (system::path (_NABLA_INSTALL_DIR_) / NBL_CPACK_PACKAGE_NABLA_DLL_DIR_ABS_KEY);
67
+ install.dxc = std::filesystem::absolute (system::path (_NABLA_INSTALL_DIR_) / NBL_CPACK_PACKAGE_DXC_DLL_DIR_ABS_KEY);
68
+
69
+ env.nabla = sdk / NBL_CPACK_PACKAGE_NABLA_DLL_DIR_ABS_KEY;
70
+ env.dxc = sdk / NBL_CPACK_PACKAGE_DXC_DLL_DIR_ABS_KEY;
71
+
72
+ #ifdef _NBL_SHARED_BUILD_
73
+ build.nabla = _NABLA_OUTPUT_DIR_;
74
+ #endif
75
+ build.dxc = path (_DXC_DLL_).parent_path ();
76
+
77
+ #ifdef NBL_CPACK_PACKAGE_NABLA_DLL_DIR
78
+ rel.nabla = NBL_CPACK_PACKAGE_NABLA_DLL_DIR;
79
+ #endif
80
+
81
+ #ifdef NBL_CPACK_PACKAGE_DXC_DLL_DIR
82
+ rel.dxc = NBL_CPACK_PACKAGE_DXC_DLL_DIR;
83
+ #endif
84
+
85
+ auto load = [](std::string_view moduleName, const std::vector<system::path>& searchPaths)
86
+ {
87
+ #ifdef _NBL_PLATFORM_WINDOWS_
88
+ const bool isAlreadyLoaded = GetModuleHandleA (moduleName.data ());
89
+
90
+ if (not isAlreadyLoaded)
91
+ {
92
+ const HRESULT hook = system::CSystemWin32::delayLoadDLL (moduleName.data (), searchPaths);
93
+
94
+ // ! don't be scared if you see "No symbols loaded" - you will not hit "false" in this case, the DLL will get loaded if found,
95
+ // ! proc addresses will be resolved correctly but status may scream "FAILED" due to lack of a PDB to load
96
+
97
+ if (FAILED (hook))
58
98
return false ;
59
- #endif // _NBL_SHARED_BUILD_
60
- #else
61
- // nothing else needs to be done cause we have RPath
99
+ }
100
+ #else
101
+ // nothing else needs to be done cause we have RPath
102
+ // TODO: to be checked when time comes
103
+ #endif
104
+
105
+ return true ;
106
+ };
107
+
108
+ if (not load (module .dxc , { install.dxc , env.dxc , build.dxc , rel.dxc }))
109
+ return false ;
110
+
111
+ #ifdef _NBL_SHARED_BUILD_
112
+ if (not load (module .nabla , { install.nabla , env.nabla , build.nabla , rel.nabla }))
113
+ return false ;
62
114
#endif
63
115
64
116
return true ;
@@ -70,9 +122,13 @@ class IApplicationFramework : public core::IReferenceCounted
70
122
{
71
123
path CWD = system::path (argv[0 ]).parent_path ().generic_string () + " /" ;
72
124
auto app = core::make_smart_refctd_ptr<CRTP>(CWD/" ../" ,CWD,CWD/" ../../media/" ,CWD/" ../../tmp/" );
125
+
73
126
for (auto i=0 ; i<argc; i++)
74
127
app->argv .emplace_back (argv[i]);
75
128
129
+ if (not app->isAPILoaded ())
130
+ app->onAPILoadFailure ();
131
+
76
132
if (!app->onAppInitialized (nullptr ))
77
133
return -1 ;
78
134
while (app->keepRunning ())
@@ -95,11 +151,9 @@ class IApplicationFramework : public core::IReferenceCounted
95
151
96
152
// needs to be public because of how constructor forwarding works
97
153
IApplicationFramework (const path& _localInputCWD, const path& _localOutputCWD, const path& _sharedInputCWD, const path& _sharedOutputCWD) :
98
- localInputCWD (_localInputCWD), localOutputCWD(_localOutputCWD), sharedInputCWD(_sharedInputCWD), sharedOutputCWD(_sharedOutputCWD)
99
- {
100
- const bool status = GlobalsInit ();
101
- assert (status);
102
- }
154
+ localInputCWD (_localInputCWD), localOutputCWD(_localOutputCWD), sharedInputCWD(_sharedInputCWD), sharedOutputCWD(_sharedOutputCWD), m_apiLoaded(GlobalsInit()) {}
155
+
156
+ virtual bool onAPILoadFailure () { return m_apiLoaded = false ; }
103
157
104
158
// DEPRECATED
105
159
virtual void setSystem (core::smart_refctd_ptr<ISystem>&& system) {}
@@ -112,6 +166,9 @@ class IApplicationFramework : public core::IReferenceCounted
112
166
virtual void workLoopBody () = 0;
113
167
virtual bool keepRunning () = 0;
114
168
169
+ // ! returns status of global initialization - on false you are supposed to terminate the application with non-zero code (otherwise you enter undefined behavior zone)
170
+ inline bool isAPILoaded () { return m_apiLoaded; }
171
+
115
172
protected:
116
173
// need this one for skipping the whole constructor chain
117
174
IApplicationFramework () = default ;
@@ -130,7 +187,6 @@ class IApplicationFramework : public core::IReferenceCounted
130
187
*******************************************************************
131
188
*/
132
189
133
-
134
190
/*
135
191
This is a CWD which is used for reading app-local assets.
136
192
Do NOT try writing to this path if you wan't your app to work on Android because on Android this CWD is located inside a readonly APK archive.
@@ -153,6 +209,8 @@ class IApplicationFramework : public core::IReferenceCounted
153
209
This CWD is used to output data that can be shared between apps e.g. quantization cache
154
210
*/
155
211
path sharedOutputCWD;
212
+
213
+ bool m_apiLoaded;
156
214
};
157
215
158
216
}
0 commit comments