App.cpp 9.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433
  1. // Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <anki/core/App.h>
  6. #include <anki/misc/ConfigSet.h>
  7. #include <anki/util/Logger.h>
  8. #include <anki/util/File.h>
  9. #include <anki/util/Filesystem.h>
  10. #include <anki/util/System.h>
  11. #include <anki/util/ThreadPool.h>
  12. #include <anki/util/ThreadHive.h>
  13. #include <anki/core/Trace.h>
  14. #include <anki/core/NativeWindow.h>
  15. #include <anki/input/Input.h>
  16. #include <anki/scene/SceneGraph.h>
  17. #include <anki/resource/ResourceManager.h>
  18. #include <anki/physics/PhysicsWorld.h>
  19. #include <anki/renderer/MainRenderer.h>
  20. #include <anki/script/ScriptManager.h>
  21. #include <anki/resource/ResourceFilesystem.h>
  22. #include <anki/resource/AsyncLoader.h>
  23. #include <anki/core/StagingGpuMemoryManager.h>
  24. #if ANKI_OS == ANKI_OS_ANDROID
  25. #include <android_native_app_glue.h>
  26. #endif
  27. namespace anki
  28. {
  29. #if ANKI_OS == ANKI_OS_ANDROID
  30. /// The one and only android hack
  31. android_app* gAndroidApp = nullptr;
  32. #endif
  33. App::App()
  34. {
  35. }
  36. App::~App()
  37. {
  38. cleanup();
  39. }
  40. void App::cleanup()
  41. {
  42. if(m_script)
  43. {
  44. m_heapAlloc.deleteInstance(m_script);
  45. m_script = nullptr;
  46. }
  47. if(m_scene)
  48. {
  49. m_heapAlloc.deleteInstance(m_scene);
  50. m_scene = nullptr;
  51. }
  52. if(m_renderer)
  53. {
  54. m_heapAlloc.deleteInstance(m_renderer);
  55. m_renderer = nullptr;
  56. }
  57. if(m_resources)
  58. {
  59. m_heapAlloc.deleteInstance(m_resources);
  60. m_resources = nullptr;
  61. }
  62. if(m_resourceFs)
  63. {
  64. m_heapAlloc.deleteInstance(m_resourceFs);
  65. m_resourceFs = nullptr;
  66. }
  67. if(m_physics)
  68. {
  69. m_heapAlloc.deleteInstance(m_physics);
  70. m_physics = nullptr;
  71. }
  72. if(m_stagingMem)
  73. {
  74. m_heapAlloc.deleteInstance(m_stagingMem);
  75. m_stagingMem = nullptr;
  76. }
  77. if(m_gr)
  78. {
  79. GrManager::deleteInstance(m_gr);
  80. m_gr = nullptr;
  81. }
  82. if(m_threadpool)
  83. {
  84. m_heapAlloc.deleteInstance(m_threadpool);
  85. m_threadpool = nullptr;
  86. }
  87. if(m_threadHive)
  88. {
  89. m_heapAlloc.deleteInstance(m_threadHive);
  90. m_threadHive = nullptr;
  91. }
  92. if(m_input)
  93. {
  94. m_heapAlloc.deleteInstance(m_input);
  95. m_input = nullptr;
  96. }
  97. if(m_window)
  98. {
  99. m_heapAlloc.deleteInstance(m_window);
  100. m_window = nullptr;
  101. }
  102. m_settingsDir.destroy(m_heapAlloc);
  103. m_cacheDir.destroy(m_heapAlloc);
  104. #if ANKI_ENABLE_TRACE
  105. TraceManagerSingleton::destroy();
  106. #endif
  107. }
  108. Error App::init(const ConfigSet& config, AllocAlignedCallback allocCb, void* allocCbUserData)
  109. {
  110. Error err = initInternal(config, allocCb, allocCbUserData);
  111. if(err)
  112. {
  113. cleanup();
  114. ANKI_CORE_LOGE("App initialization failed");
  115. }
  116. return err;
  117. }
  118. Error App::initInternal(const ConfigSet& config_, AllocAlignedCallback allocCb, void* allocCbUserData)
  119. {
  120. m_allocCb = allocCb;
  121. m_allocCbData = allocCbUserData;
  122. m_heapAlloc = HeapAllocator<U8>(allocCb, allocCbUserData);
  123. ConfigSet config = config_;
  124. ANKI_CHECK(initDirs(config));
  125. // Print a message
  126. const char* buildType =
  127. #if ANKI_OPTIMIZE
  128. "optimized, "
  129. #else
  130. "NOT optimized, "
  131. #endif
  132. #if ANKI_DEBUG_SYMBOLS
  133. "dbg symbols, "
  134. #else
  135. "NO dbg symbols, "
  136. #endif
  137. #if ANKI_EXTRA_CHECKS
  138. "extra checks";
  139. #else
  140. "NO extra checks";
  141. #endif
  142. ANKI_CORE_LOGI("Initializing application ("
  143. "version %u.%u, "
  144. "%s, "
  145. "compiler %s, "
  146. "build date %s, "
  147. "commit %s)",
  148. ANKI_VERSION_MAJOR,
  149. ANKI_VERSION_MINOR,
  150. buildType,
  151. ANKI_COMPILER_STR,
  152. __DATE__,
  153. ANKI_REVISION);
  154. m_timerTick = 1.0 / 60.0; // in sec. 1.0 / period
  155. // Check SIMD support
  156. #if ANKI_SIMD == ANKI_SIMD_SSE && ANKI_COMPILER != ANKI_COMPILER_MSVC
  157. if(!__builtin_cpu_supports("sse4.2"))
  158. {
  159. ANKI_CORE_LOGF(
  160. "AnKi is built with sse4.2 support but your CPU doesn't support it. Try bulding without SSE support");
  161. }
  162. #endif
  163. #if ANKI_ENABLE_TRACE
  164. ANKI_CHECK(TraceManagerSingleton::get().create(m_heapAlloc, m_settingsDir.toCString()));
  165. #endif
  166. ANKI_CORE_LOGI("Number of main threads: %u", U(config.getNumber("core.mainThreadCount")));
  167. //
  168. // Window
  169. //
  170. NativeWindowInitInfo nwinit;
  171. nwinit.m_width = config.getNumber("width");
  172. nwinit.m_height = config.getNumber("height");
  173. nwinit.m_depthBits = 0;
  174. nwinit.m_stencilBits = 0;
  175. nwinit.m_fullscreenDesktopRez = config.getNumber("window.fullscreenDesktopResolution");
  176. m_window = m_heapAlloc.newInstance<NativeWindow>();
  177. ANKI_CHECK(m_window->init(nwinit, m_heapAlloc));
  178. //
  179. // Input
  180. //
  181. m_input = m_heapAlloc.newInstance<Input>();
  182. ANKI_CHECK(m_input->init(m_window));
  183. //
  184. // ThreadPool
  185. //
  186. m_threadpool = m_heapAlloc.newInstance<ThreadPool>(config.getNumber("core.mainThreadCount"));
  187. m_threadHive = m_heapAlloc.newInstance<ThreadHive>(config.getNumber("core.mainThreadCount"), m_heapAlloc);
  188. //
  189. // Graphics API
  190. //
  191. GrManagerInitInfo grInit;
  192. grInit.m_allocCallback = m_allocCb;
  193. grInit.m_allocCallbackUserData = m_allocCbData;
  194. grInit.m_cacheDirectory = m_cacheDir.toCString();
  195. grInit.m_config = &config;
  196. grInit.m_window = m_window;
  197. ANKI_CHECK(GrManager::newInstance(grInit, m_gr));
  198. //
  199. // Staging mem
  200. //
  201. m_stagingMem = m_heapAlloc.newInstance<StagingGpuMemoryManager>();
  202. ANKI_CHECK(m_stagingMem->init(m_gr, config));
  203. //
  204. // Physics
  205. //
  206. m_physics = m_heapAlloc.newInstance<PhysicsWorld>();
  207. ANKI_CHECK(m_physics->create(m_allocCb, m_allocCbData));
  208. //
  209. // Resource FS
  210. //
  211. m_resourceFs = m_heapAlloc.newInstance<ResourceFilesystem>(m_heapAlloc);
  212. ANKI_CHECK(m_resourceFs->init(config, m_cacheDir.toCString()));
  213. //
  214. // Resources
  215. //
  216. ResourceManagerInitInfo rinit;
  217. rinit.m_gr = m_gr;
  218. rinit.m_physics = m_physics;
  219. rinit.m_resourceFs = m_resourceFs;
  220. rinit.m_config = &config;
  221. rinit.m_cacheDir = m_cacheDir.toCString();
  222. rinit.m_allocCallback = m_allocCb;
  223. rinit.m_allocCallbackData = m_allocCbData;
  224. m_resources = m_heapAlloc.newInstance<ResourceManager>();
  225. ANKI_CHECK(m_resources->init(rinit));
  226. //
  227. // Renderer
  228. //
  229. if(nwinit.m_fullscreenDesktopRez)
  230. {
  231. config.set("width", m_window->getWidth());
  232. config.set("height", m_window->getHeight());
  233. }
  234. m_renderer = m_heapAlloc.newInstance<MainRenderer>();
  235. ANKI_CHECK(m_renderer->init(
  236. m_threadpool, m_resources, m_gr, m_stagingMem, m_allocCb, m_allocCbData, config, &m_globalTimestamp));
  237. //
  238. // Scene
  239. //
  240. m_scene = m_heapAlloc.newInstance<SceneGraph>();
  241. ANKI_CHECK(m_scene->init(m_allocCb,
  242. m_allocCbData,
  243. m_threadpool,
  244. m_threadHive,
  245. m_resources,
  246. m_stagingMem,
  247. m_input,
  248. &m_globalTimestamp,
  249. config));
  250. //
  251. // Script
  252. //
  253. m_script = m_heapAlloc.newInstance<ScriptManager>();
  254. ANKI_CHECK(m_script->init(m_allocCb, m_allocCbData, m_scene, m_renderer));
  255. ANKI_CORE_LOGI("Application initialized");
  256. return Error::NONE;
  257. }
  258. Error App::initDirs(const ConfigSet& cfg)
  259. {
  260. #if ANKI_OS != ANKI_OS_ANDROID
  261. // Settings path
  262. StringAuto home(m_heapAlloc);
  263. ANKI_CHECK(getHomeDirectory(m_heapAlloc, home));
  264. m_settingsDir.sprintf(m_heapAlloc, "%s/.anki", &home[0]);
  265. if(!directoryExists(m_settingsDir.toCString()))
  266. {
  267. ANKI_CORE_LOGI("Creating settings dir \"%s\"", &m_settingsDir[0]);
  268. ANKI_CHECK(createDirectory(m_settingsDir.toCString()));
  269. }
  270. else
  271. {
  272. ANKI_CORE_LOGI("Using settings dir \"%s\"", &m_settingsDir[0]);
  273. }
  274. // Cache
  275. m_cacheDir.sprintf(m_heapAlloc, "%s/cache", &m_settingsDir[0]);
  276. const Bool cacheDirExists = directoryExists(m_cacheDir.toCString());
  277. if(cfg.getNumber("clearCaches") && cacheDirExists)
  278. {
  279. ANKI_CORE_LOGI("Will delete the cache dir and start fresh: %s", &m_cacheDir[0]);
  280. ANKI_CHECK(removeDirectory(m_cacheDir.toCString()));
  281. ANKI_CHECK(createDirectory(m_cacheDir.toCString()));
  282. }
  283. else if(!cacheDirExists)
  284. {
  285. ANKI_CORE_LOGI("Will create cache dir: %s", &m_cacheDir[0]);
  286. ANKI_CHECK(createDirectory(m_cacheDir.toCString()));
  287. }
  288. #else
  289. // ANKI_ASSERT(gAndroidApp);
  290. // ANativeActivity* activity = gAndroidApp->activity;
  291. // Settings path
  292. // settingsDir = String(activity->internalDataDir, alloc);
  293. settingsDir = String("/sdcard/.anki/");
  294. if(!directoryExists(settingsDir.c_str()))
  295. {
  296. createDirectory(settingsDir.c_str());
  297. }
  298. // Cache
  299. cacheDir = settingsDir + "/cache";
  300. if(directoryExists(cacheDir.c_str()))
  301. {
  302. removeDirectory(cacheDir.c_str());
  303. }
  304. createDirectory(cacheDir.c_str());
  305. #endif
  306. return Error::NONE;
  307. }
  308. Error App::mainLoop()
  309. {
  310. ANKI_CORE_LOGI("Entering main loop");
  311. Bool quit = false;
  312. Second prevUpdateTime = HighRezTimer::getCurrentTime();
  313. Second crntTime = prevUpdateTime;
  314. while(!quit)
  315. {
  316. ANKI_TRACE_START_FRAME();
  317. HighRezTimer timer;
  318. timer.start();
  319. prevUpdateTime = crntTime;
  320. crntTime = HighRezTimer::getCurrentTime();
  321. m_gr->beginFrame();
  322. // Update
  323. ANKI_CHECK(m_input->handleEvents());
  324. // User update
  325. ANKI_CHECK(userMainLoop(quit));
  326. ANKI_CHECK(m_scene->update(prevUpdateTime, crntTime));
  327. RenderQueue rqueue;
  328. m_scene->doVisibilityTests(rqueue);
  329. ANKI_CHECK(m_renderer->render(rqueue));
  330. // Pause and sync async loader. That will force all tasks before the pause to finish in this frame.
  331. m_resources->getAsyncLoader().pause();
  332. m_gr->swapBuffers();
  333. m_stagingMem->endFrame();
  334. // Update the trace info with some async loader stats
  335. U64 asyncTaskCount = m_resources->getAsyncLoader().getCompletedTaskCount();
  336. ANKI_TRACE_INC_COUNTER(RESOURCE_ASYNC_TASKS, asyncTaskCount - m_resourceCompletedAsyncTaskCount);
  337. m_resourceCompletedAsyncTaskCount = asyncTaskCount;
  338. // Now resume the loader
  339. m_resources->getAsyncLoader().resume();
  340. // Sleep
  341. timer.stop();
  342. if(timer.getElapsedTime() < m_timerTick)
  343. {
  344. ANKI_TRACE_SCOPED_EVENT(TIMER_TICK_SLEEP);
  345. HighRezTimer::sleep(m_timerTick - timer.getElapsedTime());
  346. }
  347. ++m_globalTimestamp;
  348. ANKI_TRACE_STOP_FRAME();
  349. }
  350. return Error::NONE;
  351. }
  352. } // end namespace anki