1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File: ParticleNodeCombinationDemo.cpp
4
5 Copyright (C)2009-2010 Nintendo Co., Ltd./HAL Laboratory, Inc. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Revision: 25056 $
14 *---------------------------------------------------------------------------*/
15
16 #define NW_DEBUG_CHECK_MEMORY_LEAK
17
18 #include <nn/os.h>
19 #include <nn/fs.h>
20
21 #include <nw/types.h>
22 #include <nw/demo.h>
23 #include <nw/dev.h>
24 #include <nw/gfx.h>
25 #include <nw/ut.h>
26
27 namespace
28 {
29
30 //----------------------------------------
31 // メモリ関係
32
33 // デバイスメモリを確保するためのアロケータです。
34 nw::demo::DemoAllocator s_DeviceAllocator;
35 nw::demo::DemoAllocator s_ParticleAllocator;
36
37 //----------------------------------------
38 // ファイル名の定義です。
39 const wchar_t* SKY_SPHERE_FILE_NAME = NW_DEMO_FILE_PATH(L"SkySphere.bcmdl");
40
41 //----------------------------------------
42 // 描画関係
43 const int RENDER_TARGET_COUNT = 1;
44 typedef nw::ut::FixedSizeArray<nw::gfx::IRenderTarget*, RENDER_TARGET_COUNT> RenderTargetArray;
45
46 RenderTargetArray s_RenderTargets;
47 nw::demo::SceneSystem* s_SceneSystem = NULL;
48 nw::demo::RenderSystem* s_RenderSystem = NULL;
49 nw::gfx::ParticleContext* s_ParticleContext = NULL;
50
51 nw::demo::GraphicsDrawing s_GraphicsDrawing;
52
53 //----------------------------------------
54 // リソース関係
55 nw::demo::ResourceArray s_Resources;
56
57 //----------------------------------------
58 // シーン関係
59 nw::gfx::SceneNode* s_SceneRoot = NULL;
60 s32 s_FrameCount = 0;
61 nw::gfx::Camera* s_BaseCamera = NULL;
62 nw::gfx::Camera* s_LeftCamera = NULL;
63 nw::gfx::Camera* s_RightCamera = NULL;
64 const f32 s_fNearPlane = 0.1f;
65
66 const s32 s_BaseCameraIndex = 0;
67
68 //----------------------------------------
69 // パーティクル関係
70 nw::gfx::ParticleSceneUpdater* s_ParticleSceneUpdater = NULL;
71
72 nw::demo::FlushCache* s_FlushCache;
73
74 /*!--------------------------------------------------------------------------*
75 @brief グラフィックス関連の初期化を行います。
76 *---------------------------------------------------------------------------*/
77 void
InitializeGraphics()78 InitializeGraphics()
79 {
80 nw::gfx::CommandCacheManager::SetAllocator( &s_DeviceAllocator );
81
82 // renderDescriptionへステレオの設定を行います。
83 nw::demo::RenderSystem::Description renderDescription;
84
85 renderDescription.reusableCommandBufferSize = 0x100000;
86 renderDescription.reusableCommandRequestCount = 512;
87 renderDescription.upperScreenMode = nw::demo::UPPER_SCREEN_MODE_STEREO;
88
89 s_RenderSystem = nw::demo::RenderSystem::Create(&s_DeviceAllocator, renderDescription);
90
91 s_GraphicsDrawing.SetScreenSize(
92 renderDescription.lowerScreenDescription.width,
93 renderDescription.lowerScreenDescription.height
94 );
95
96 nw::demo::Utility::InitializeGraphicsDrawing(&s_DeviceAllocator, s_GraphicsDrawing);
97
98 s_RenderTargets.push_back(
99 nw::demo::Utility::CreateUpperScreenBuffer(&s_DeviceAllocator, renderDescription)
100 );
101 NW_ASSERT(!s_RenderTargets.empty());
102 s_RenderSystem->GetRenderContext()->SetRenderTarget(s_RenderTargets.front());
103
104 // sceneDescriptionへの標準的な設定はコンストラクタで行われています。
105 nw::demo::SceneSystem::Description sceneDescription;
106 s_SceneSystem = nw::demo::SceneSystem::Create(&s_DeviceAllocator, sceneDescription);
107
108 s_ParticleContext = nw::gfx::ParticleContext::Builder()
109 .MaxEmission(1000)
110 .Create(&s_DeviceAllocator);
111
112 s_ParticleSceneUpdater = nw::gfx::ParticleSceneUpdater::Builder()
113 .Create(&s_DeviceAllocator);
114
115 // デモ用の最遠景モデルをレンダリングシステムに設定します。
116 // gfx のデモでは glClear などを用いずに背景で塗りつぶしを行います。
117 s_RenderSystem->LoadSkyModel(SKY_SPHERE_FILE_NAME);
118
119 NW_GL_ASSERT();
120 }
121
122 /*!--------------------------------------------------------------------------*
123 @brief グラフィックス関連の後始末をします。
124 *---------------------------------------------------------------------------*/
125 void
TerminateGraphics()126 TerminateGraphics()
127 {
128 nw::gfx::SafeDestroy(s_LeftCamera);
129
130 nw::gfx::SafeDestroy(s_RightCamera);
131
132 nw::gfx::SafeDestroy(s_ParticleSceneUpdater);
133
134 nw::gfx::SafeDestroy(s_ParticleContext);
135
136 nw::gfx::SafeDestroy(s_SceneSystem);
137
138 nw::gfx::SafeDestroyAll(s_RenderTargets);
139
140 s_GraphicsDrawing.Finalize();
141
142 nw::gfx::SafeDestroy(s_RenderSystem);
143
144 NW_GL_ASSERT();
145 }
146
147 /*!--------------------------------------------------------------------------*
148 @brief ルートノード関連の構築をします。
149 *---------------------------------------------------------------------------*/
150 void
BuildRootNodes()151 BuildRootNodes()
152 {
153 NW_ASSERT(s_SceneRoot == NULL);
154 s_SceneRoot = nw::gfx::TransformNode::DynamicBuilder()
155 .IsFixedSizeMemory(false)
156 .Create(&s_DeviceAllocator);
157 NW_NULL_ASSERT(s_SceneRoot);
158 }
159
160 /*!--------------------------------------------------------------------------*
161 @brief カメラ関連の構築をします。
162 *---------------------------------------------------------------------------*/
163 void
BuildCameras()164 BuildCameras()
165 {
166 nw::demo::Utility::CreateStereoCameras(
167 &s_BaseCamera,
168 &s_LeftCamera,
169 &s_RightCamera,
170 &s_DeviceAllocator,
171 nw::math::VEC3(0.0f, 13.0f, 70.f),
172 nw::math::VEC3(0.0f, 13.0f, 0.0f),
173 s_fNearPlane
174 );
175
176 s_SceneRoot->AttachChild(s_BaseCamera);
177 s_SceneSystem->GetCameraController()->Register(s_BaseCamera);
178 }
179
180
181 /*!--------------------------------------------------------------------------*
182 @brief シーンを初期化します。
183 *---------------------------------------------------------------------------*/
184 void
InitializeScenes()185 InitializeScenes()
186 {
187 BuildRootNodes();
188
189 BuildCameras();
190
191 // シーンツリーを巡回して初期化を行います。
192 s_SceneSystem->InitializeScene(s_SceneRoot);
193 s_SceneSystem->UpdateScene();
194
195 // カメラを設定します。
196 nw::gfx::SceneEnvironment& sceneEnvironment = s_RenderSystem->GetSceneEnvironment();
197 sceneEnvironment.SetCamera(s_BaseCameraIndex, s_BaseCamera);
198 nw::demo::Utility::SetCameraAspectRatio(s_BaseCamera, s_RenderTargets[0]);
199
200 NW_GL_ASSERT();
201
202 s_FrameCount = 0;
203 }
204
205 /*!--------------------------------------------------------------------------*
206 @brief シーン関連の後始末をします。
207 *---------------------------------------------------------------------------*/
208 void
TerminateScenes()209 TerminateScenes()
210 {
211 nw::gfx::SafeDestroyBranch(s_SceneRoot);
212 nw::demo::SafeCleanupResources(s_Resources);
213
214 NW_GL_ASSERT();
215
216 s_Resources.clear();
217 }
218
219 /*!--------------------------------------------------------------------------*
220 @brief シーンを更新します。
221 *---------------------------------------------------------------------------*/
222 void
UpdateScene()223 UpdateScene()
224 {
225 NW_ASSERT(0 < s_RenderTargets.size());
226
227 s_SceneSystem->GetCameraController()->Update();
228
229 s_SceneSystem->UpdateScene();
230
231 s_BaseCamera->UpdateCameraMatrix();
232
233 NW_NULL_ASSERT(s_ParticleSceneUpdater);
234 s_ParticleSceneUpdater->UpdateNode(
235 s_SceneSystem->GetSceneContext(),
236 s_ParticleContext);
237
238 s_RenderSystem->CalcStereoCamera(s_LeftCamera, s_RightCamera, s_BaseCamera, s_fNearPlane + 5.0f);
239
240 s_FrameCount++;
241
242 s_FlushCache->Execute();
243 }
244
245 /*!--------------------------------------------------------------------------*
246 @brief 負荷表示やテスト機能の処理をおこないます。
247 *---------------------------------------------------------------------------*/
248 void
ReportDemo()249 ReportDemo()
250 {
251 NW_PROFILE("ReportDemo");
252
253 // 負荷表示からはこれらの負荷は除きます。
254 s_RenderSystem->SuspendLoadMeter();
255
256 nw::demo::DebugUtility::CalcLoadMeter(s_RenderSystem);
257
258 s_GraphicsDrawing.BeginDrawingShape();
259
260 nw::demo::DebugUtility::DrawLoadMeter(
261 s_RenderSystem,
262 &s_GraphicsDrawing
263 );
264
265 s_GraphicsDrawing.EndDrawingShape();
266
267 s_GraphicsDrawing.BeginDrawingString();
268
269 nw::demo::DebugUtility::DrawLoadMeterText(
270 s_RenderSystem,
271 &s_GraphicsDrawing
272 );
273
274 s_GraphicsDrawing.EndDrawingString();
275
276 s_RenderSystem->ResumeLoadMeter();
277 }
278
279
280
281
282 //----------------------------------------
283 // デモ固有の変数
284
285 // パーティクルエフェクトクラス
286 nw::demo::ParticleEffect* s_ParticleEffect = NULL;
287
288 // 配置数
289 #define DEMO_FIRE_DRAW_NUM (5)
290
291 // パーティクルハンドルクラス
292 nw::demo::ParticleHandle* s_PaticleHandle5M5E[DEMO_FIRE_DRAW_NUM];
293 nw::demo::ParticleHandle* s_PaticleHandle1M5E = NULL;
294 nw::demo::ParticleHandle* s_PaticleHandle1M1E = NULL;
295
296 // カウンタ
297 u32 s_Count = 0;
298
299 // アニメーションステート
300 enum
301 {
302 DEMO_ASSORTMENT_STATE_5MODEL_5EMITTER = 0,
303 DEMO_ASSORTMENT_STATE_1MODEL_5EMITTER = 1,
304 DEMO_ASSORTMENT_STATE_1MODEL_1EMITTER = 2,
305 DEMO_ASSORTMENT_STATE_MAX = 3
306 };
307 u32 s_AnimationState = DEMO_ASSORTMENT_STATE_5MODEL_5EMITTER;
308
309 // ロードするエフェクトファイル
310 const wchar_t* EFFECT_RESOURCE_FILE = NW_DEMO_FILE_PATH(L"fire_particle_mem5.bcptl");
311
312 // ロードするエフェクトシェーダファイル
313 const wchar_t* SHADER_RESOURCE_FILE_NAME = NW_DEMO_FILE_PATH(L"nwgfx_ParticleDefaultShader.bcsdr");
314
315
316 /*!--------------------------------------------------------------------------*
317 @brief ParticleNodeCombinationDemoの初期化を行います。
318 *---------------------------------------------------------------------------*/
319 void
InitializeParticleNodeCombinationDemo()320 InitializeParticleNodeCombinationDemo()
321 {
322 // 以下のパーティクルモデル/エミッタ組み合わせを用いて、
323 // 炎エフェクトを画面に5つ表示するデモです。
324 // 5 ParticleModel - 5 ParticleEmitter(5M5E)
325 // 配置等の扱いは容易ですが、メモリ・処理速度面で不利です。
326 //
327 // 1 ParticleModel - 5 ParticleEmitter(1M5E)
328 // 自由度が低くなりますが、処理速度やメモリ使用量で有利です。
329 //
330 // 1 ParticleModel - 1 ParticleEmitter(1M1E)
331 // 自由度が低くなりますが、処理速度やメモリ使用量で有利です。
332 // また、この手法は放出間隔が1フレームのデータにしか適用できません。
333 // メモリ面では(1M1E)、速度面では(1M5E)の方が有利です。
334
335 s_AnimationState = DEMO_ASSORTMENT_STATE_5MODEL_5EMITTER;
336 s_Count = 0;
337 s_ParticleEffect = NULL;
338
339 // シェーダバイナリをロードします。
340 nw::demo::ParticleEffect::InitializeShaderBinary(SHADER_RESOURCE_FILE_NAME, &s_DeviceAllocator);
341
342 // パーティクルエフェクトクラスを生成します。
343 s_ParticleEffect = nw::demo::ParticleEffect::Create(&s_DeviceAllocator, &s_DeviceAllocator, false, s_ParticleContext);
344
345 // エフェクトデータをロードしてセットアップします。
346 nw::demo::ResourceSet* resourceSet = nw::demo::Utility::LoadResources(s_Resources, EFFECT_RESOURCE_FILE, &s_DeviceAllocator);
347
348 // リソースのセットアップを行います。
349 s_ParticleEffect->Setup(resourceSet->resource, false);
350
351 // ParticleEffectにリソースをセットします。
352 s_ParticleEffect->Register(resourceSet->resource);
353 s_ParticleEffect->AddPool(6);
354
355 // (5M5E)の準備を行います。
356 for (s32 i = 0; i < DEMO_FIRE_DRAW_NUM; ++i)
357 {
358 s_PaticleHandle5M5E[i] = s_ParticleEffect->LeaseInstance();
359 if (s_PaticleHandle5M5E[i])
360 {
361 s_PaticleHandle5M5E[i]->SetTranslate(10.0f * (i - 2), 0.f, 0.f);
362 }
363
364 // シーンに追加します。
365 s_SceneRoot->AttachChild(s_PaticleHandle5M5E[i]);
366 }
367
368 // (1M5E)の準備を行います。
369 s_PaticleHandle1M5E = s_ParticleEffect->CreateMultiEmitterParticleHandle( DEMO_FIRE_DRAW_NUM );
370 if (s_PaticleHandle1M5E)
371 {
372 for (s32 i = 0; i < s_PaticleHandle1M5E->GetParticleEmitterSize(); ++i)
373 {
374 s_PaticleHandle1M5E->GetParticleEmitter(i)->Transform().SetTranslate(10.0f * (i - 2), 0.f, 0.f);
375 }
376 }
377
378 // (1M1E)の準備を行います。
379 s_PaticleHandle1M1E = s_ParticleEffect->LeaseInstance();
380 s_PaticleHandle1M1E->SetTranslate(0.f, 0.f, 0.f);
381 s_SceneRoot->AttachChild(s_PaticleHandle1M1E);
382
383 // シーンを更新します。
384 s_SceneSystem->InitializeScene(s_SceneRoot);
385 s_SceneSystem->UpdateScene();
386 }
387
388 /*!--------------------------------------------------------------------------*
389 @brief ParticleNodeCombinationDemoの定期処理です。
390 *---------------------------------------------------------------------------*/
391 void
UpdateParticleNodeCombinationDemo()392 UpdateParticleNodeCombinationDemo()
393 {
394 ++s_Count;
395
396 // 600フレームごとに組み合わせパターンを変更します。
397 if ( s_Count%600 == 0 )
398 {
399 s_Count = 0;
400
401 switch(s_AnimationState)
402 {
403 case DEMO_ASSORTMENT_STATE_5MODEL_5EMITTER:
404 {
405 // (5M5E)ノードをデタッチします。
406 for (u32 i = 0; i < DEMO_FIRE_DRAW_NUM; ++i)
407 {
408 s_SceneRoot->DetachChild(s_PaticleHandle5M5E[i]);
409 }
410
411 // (1M5E)ノードをアタッチします。
412 s_SceneRoot->AttachChild(s_PaticleHandle1M5E);
413
414 // シーンを更新します。
415 s_SceneSystem->InitializeScene(s_SceneRoot);
416 s_SceneSystem->UpdateScene();
417
418 s_AnimationState = DEMO_ASSORTMENT_STATE_1MODEL_5EMITTER;
419 }
420 break;
421
422 case DEMO_ASSORTMENT_STATE_1MODEL_5EMITTER:
423 {
424 // (1M5E)ノードをデタッチします。
425 s_SceneRoot->DetachChild(s_PaticleHandle1M5E);
426
427 // (1M1E)ノードをアタッチします。
428 s_SceneRoot->AttachChild(s_PaticleHandle1M1E);
429
430 // シーンを更新します。
431 s_SceneSystem->InitializeScene(s_SceneRoot);
432 s_SceneSystem->UpdateScene();
433
434 s_AnimationState = DEMO_ASSORTMENT_STATE_1MODEL_1EMITTER;
435 }
436 break;
437
438 case DEMO_ASSORTMENT_STATE_1MODEL_1EMITTER:
439 {
440 // (1M1E)ノードをデタッチします。
441 s_SceneRoot->DetachChild(s_PaticleHandle1M1E);
442
443 // (5M5E)ノードをアタッチします。
444 for (u32 i = 0; i < DEMO_FIRE_DRAW_NUM; ++i)
445 {
446 s_SceneRoot->AttachChild(s_PaticleHandle5M5E[i]);
447 }
448
449 // シーンを更新します。
450 s_SceneSystem->InitializeScene(s_SceneRoot);
451 s_SceneSystem->UpdateScene();
452
453 s_AnimationState = DEMO_ASSORTMENT_STATE_5MODEL_5EMITTER;
454 }
455 break;
456
457 default:
458 break;
459 }
460 }
461
462 // (1M1E)の場合は、毎フレーム放出位置の変更と放出処理を行う必要があります。
463 // 放出処理の後、Reset処理を行うので、放出間隔1フレーム以外の値を
464 // 指定しているデータにおいても、毎フレーム放出を行ってしまうので注意が必要です。
465 if( s_AnimationState == DEMO_ASSORTMENT_STATE_1MODEL_1EMITTER )
466 {
467 nw::gfx::ParticleEmitter* emitter = s_PaticleHandle1M1E->GetParticleEmitter(0);
468 if (emitter)
469 {
470 for (s32 i = 0; i < DEMO_FIRE_DRAW_NUM; ++i)
471 {
472 // 放出位置を設定します。
473 emitter->WorldMatrix().SetupTranslate(nn::math::VEC3(nw::math::VEC3(10.0f * (i - 2), 0.f, 0.f)));
474
475 // 放出処理を行い、リセットを行います。
476 emitter->UpdateParticleFrame();
477 emitter->Emission(s_ParticleContext);
478 emitter->Reset();
479 }
480 }
481 }
482 }
483
484 /*!--------------------------------------------------------------------------*
485 @brief ParticleNodeCombinationDemoのスクリーンデバッグ表示です。
486 *---------------------------------------------------------------------------*/
487 void
ReportParticleNodeCombinationDemo()488 ReportParticleNodeCombinationDemo()
489 {
490 s_GraphicsDrawing.DrawString(10, 10, "Counter : %d\n", (600 - s_Count) );
491
492 switch(s_AnimationState)
493 {
494 case DEMO_ASSORTMENT_STATE_5MODEL_5EMITTER:
495 {
496 s_GraphicsDrawing.DrawString(10, 22, "Particle Model Num : 5\n" );
497 s_GraphicsDrawing.DrawString(10, 34, "Particle Emitter Num : 5\n" );
498 }
499 break;
500
501 case DEMO_ASSORTMENT_STATE_1MODEL_5EMITTER:
502 {
503 s_GraphicsDrawing.DrawString(10, 22, "Particle Model Num : 1\n" );
504 s_GraphicsDrawing.DrawString(10, 34, "Particle Emitter Num : 5\n" );
505 }
506 break;
507
508 case DEMO_ASSORTMENT_STATE_1MODEL_1EMITTER:
509 {
510 s_GraphicsDrawing.DrawString(10, 22, "Particle Model Num : 1\n" );
511 s_GraphicsDrawing.DrawString(10, 34, "Particle Emitter Num : 1\n" );
512 }
513 break;
514 }
515 }
516
517 /*!--------------------------------------------------------------------------*
518 @brief ParticleNodeCombinationDemoの終了処理を行います。
519 *---------------------------------------------------------------------------*/
520 void
TerminateParticleNodeCombinationDemo()521 TerminateParticleNodeCombinationDemo()
522 {
523 // s_ParticleEffect->DestroyParticleHandle(s_PaticleHandle1M1E);
524 nw::demo::ParticleNode* prevTarget = s_ParticleEffect->GetActiveEffect(0);
525 while (prevTarget != NULL)
526 {
527 s_ParticleEffect->ReleaseInstance(prevTarget);
528 prevTarget = s_ParticleEffect->GetActiveEffect(0);
529 }
530
531 // CreateMultiEmitterParticleHandle で生成したので、ハンドルの破棄が必要です。
532 s_ParticleEffect->DestroyParticleHandle(s_PaticleHandle1M5E);
533
534 s_ParticleEffect->FreePool();
535
536 nw::ut::SafeDestroy(s_ParticleEffect);
537
538 // ロードしたパーティクルシェーダを破棄します。
539 nw::demo::ParticleEffect::FinalizeShaderBinary();
540 }
541
542
543
544
545 /*!--------------------------------------------------------------------------*
546 @brief シーンをデモンストレーションします。
547 *---------------------------------------------------------------------------*/
548 void
DemoScene()549 DemoScene()
550 {
551 NW_ASSERT(!s_RenderTargets.empty());
552
553 nw::gfx::RenderContext* renderContext = s_RenderSystem->GetRenderContext();
554
555 InitializeScenes();
556
557 // ParticleNodeCombinationDemoの初期化処理です。
558 InitializeParticleNodeCombinationDemo();
559
560 bool isContinuing = true;
561
562 while ( isContinuing )
563 {
564 nw::demo::DebugUtility::AdvanceAutoTestFrame();
565
566 nw::demo::PadFactory::GetPad()->Update();
567
568
569 // ParticleNodeCombinationDemoの定期処理です。
570 UpdateParticleNodeCombinationDemo();
571
572 UpdateScene();
573
574 renderContext->SetActiveCamera(s_BaseCameraIndex);
575 s_RenderSystem->SubmitView(s_SceneSystem);
576
577 s_RenderSystem->SetRenderTarget(s_RenderTargets[0]);
578 s_RenderSystem->RenderStereoScene(s_LeftCamera, s_RightCamera);
579
580 s_RenderSystem->ClearBySkyModel(s_BaseCamera);
581 ReportDemo();
582
583 // ParticleNodeCombinationDemoのレポートを表示します。
584 ReportParticleNodeCombinationDemo();
585
586 s_RenderSystem->TransferBuffer(nw::demo::LOWER_SCREEN);
587
588 s_RenderSystem->PresentBuffer(nw::demo::UPPER_SCREEN | nw::demo::LOWER_SCREEN | nw::demo::EXTENSION_SCREEN);
589
590 renderContext->ResetState();
591
592 if (nw::demo::Utility::IsTerminating())
593 {
594 isContinuing = false;
595 }
596 }
597
598 // ParticleNodeCombinationDemoの終了処理です。
599 TerminateParticleNodeCombinationDemo();
600
601 TerminateScenes();
602 }
603
604 } // namespace
605
606 /*!--------------------------------------------------------------------------*
607 @brief メイン関数です。
608 *---------------------------------------------------------------------------*/
609 void
nnMain()610 nnMain()
611 {
612 nw::demo::InitializeGraphicsSystem(&s_DeviceAllocator);
613 nw::demo::InitializeDemoAllocator(&s_ParticleAllocator, nw::demo::DEMO_PARTICLE_MEMORY_SIZE);
614
615 nw::demo::PadFactory::Initialize(&s_DeviceAllocator);
616
617 NW_DEMO_TEST_LOOP(&s_DeviceAllocator, &s_ParticleAllocator, &s_RenderSystem)
618 {
619 InitializeGraphics();
620
621 s_FlushCache = nw::demo::FlushCache::Create(&s_DeviceAllocator);
622
623 DemoScene();
624
625 nw::ut::SafeDestroy(s_FlushCache);
626
627 TerminateGraphics();
628 }
629
630 nw::demo::PadFactory::Finalize();
631
632 nw::demo::FinalizeDemoAllocator(&s_ParticleAllocator);
633
634 nw::demo::FinalizeGraphicsSystem();
635 }
636