1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_GraphicsSystem.cpp
4 
5   Copyright (C)2009-2011 Nintendo/HAL Laboratory, Inc.  All rights reserved.
6 
7   These coded instructions, statements, and computer programs contain proprietary
8   information of Nintendo and/or its licensed developers and are protected by
9   national and international copyright laws. They may not be disclosed to third
10   parties or copied or duplicated in any form, in whole or in part, without the
11   prior written consent of Nintendo.
12 
13   The content herein is highly confidential and should be handled accordingly.
14 
15   $Revision: 31311 $
16  *---------------------------------------------------------------------------*/
17 
18 #include <nw/demo/demo_GraphicsSystem.h>
19 
20 #include <nw/demo/demo_DisplayBufferSwapper.h>
21 #include <nw/demo/demo_Memory.h>
22 #include <nw/demo/demo_Utility.h>
23 #include <nw/demo/demo_DebugUtility.h>
24 #include <nw/demo/demo_GraphicsDrawing.h>
25 #include <nw/demo/demo_CameraController.h>
26 #include <nw/demo/demo_GraphicsMemoryAllocator.h>
27 
28 #include <nw/gfx/gfx_IRenderTarget.h>
29 #include <nw/gfx/gfx_RenderContext.h>
30 #include <nw/gfx/gfx_RenderElement.h>
31 #include <nw/gfx/gfx_MeshRenderer.h>
32 #include <nw/gfx/gfx_ShaderProgram.h>
33 #include <nw/gfx/gfx_SceneNode.h>
34 #include <nw/gfx/gfx_UserRenderNode.h>
35 #include <nw/gfx/gfx_Model.h>
36 #include <nw/gfx/gfx_FragmentLight.h>
37 #include <nw/gfx/gfx_SceneTraverser.h>
38 #include <nw/gfx/gfx_SceneContext.h>
39 #include <nw/gfx/gfx_WorldMatrixUpdater.h>
40 #include <nw/gfx/gfx_SkeletonUpdater.h>
41 #include <nw/gfx/gfx_SceneUpdater.h>
42 #include <nw/gfx/gfx_SceneInitializer.h>
43 #include <nw/gfx/gfx_Camera.h>
44 #include <nw/gfx/gfx_Fog.h>
45 #include <nw/gfx/gfx_IMaterialIdGenerator.h>
46 #include <nw/gfx/gfx_CommandUtil.h>
47 #include <nw/gfx/gfx_ParticleUtil.h>
48 
49 #include <nw/ut/ut_Color.h>
50 #include <nw/ut/ut_Foreach.h>
51 
52 #include <nw/dev.h>
53 
54 #include <nn/fs.h>
55 #include <nn/fnd.h>
56 #include <nn/gx.h>
57 
58 //! このマクロを有効にすると、ログ出力にレンダーキューのソート後の状態をレポートします。
59 //#define REPORT_RENDER_QUEUE_ENABLED
60 
61 //! このマクロを有効にすると、半透明以外の深度ソートを省略するようになります。
62 #define SORT_DEPTH_OF_TRANSLUCENT_MESH_ENABLED
63 
64 namespace nw
65 {
66 namespace demo
67 {
68 
69 const float RenderSystem::LoadMeterDescription::NANO_TO_MILLI = 1.0f / (1000.0f * 1000.0f);
70 const float RenderSystem::LoadMeterDescription::MILLI_TO_RATE = 1.0f / (1000.0f / 60.0f);
71 
72 namespace
73 {
74     GraphicsMemoryAllocator s_GraphicsMemoryAllocator;
75     nw::demo::DemoAllocator* s_DeviceAllocator;
76 }
77 
78 //----------------------------------------
AllocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,GLsizei size)79 void* AllocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, GLsizei size)
80 {
81 
82     void* buffer = s_GraphicsMemoryAllocator.Allocate(area, aim, id, size);
83 
84     // NOTE: GL の管理領域を nw::gfx に設定する必要がなくなり、このコードは不要となりました。
85 #if 0
86     if (s_GetGlSystemFlag)
87     {
88         if (size == nw::gfx::GlSystem::SHADER_MANAGER_BUFFER_SIZE)
89         {
90             nw::gfx::GlSystem::SetGlShManager( buffer );
91         }
92     }
93 #endif
94 
95     return buffer;
96 }
97 
98 //----------------------------------------
DeallocateGraphicsMemory(GLenum area,GLenum aim,GLuint id,void * addr)99 void DeallocateGraphicsMemory(GLenum area, GLenum aim, GLuint id, void* addr)
100 {
101     s_GraphicsMemoryAllocator.Deallocate(area, aim, id, addr);
102 }
103 
104 //----------------------------------------
105 RenderSystem*
Create(os::IAllocator * allocator,const Description & description)106 RenderSystem::Create(
107     os::IAllocator* allocator,
108     const Description& description
109 )
110 {
111     void* memory = allocator->Alloc(sizeof(RenderSystem));
112     RenderSystem* renderSystem = new(memory) RenderSystem();
113 
114     renderSystem->m_RenderContext = gfx::RenderContext::Builder()
115         .Create(allocator);
116 
117     renderSystem->m_PostRenderCallback = ut::Signal1<void, const gfx::Camera*>::CreateVariableSizeSignal(allocator);
118     renderSystem->m_PostRightRenderCallback = ut::Signal1<void, const gfx::Camera*>::CreateVariableSizeSignal(allocator);
119 
120 #ifdef SORT_DEPTH_OF_TRANSLUCENT_MESH_ENABLED
121     // 半透明以外のメッシュで深度情報の量子化を行わなくするための
122     // レンダーキー・ファクトリクラスを生成します。
123     renderSystem->m_PriorMaterialRenderKeyFactory =
124         gfx::CreatePriorMaterialAndZeroDepthRenderKeyFactory(allocator);
125 #else
126     renderSystem->m_PriorMaterialRenderKeyFactory =
127         gfx::CreatePriorMaterialRenderKeyFactory(allocator);
128 #endif
129 
130     renderSystem->m_PriorDepthRenderKeyFactory =
131         gfx::CreatePriorDepthReverseDepthRenderKeyFactory(allocator);
132 
133     renderSystem->m_RenderQueue = gfx::RenderQueue::Builder()
134         .MaxRenderElements(256)
135         .Create(allocator);
136 
137     renderSystem->m_RenderQueue->Reset(
138         renderSystem->m_PriorMaterialRenderKeyFactory,
139         renderSystem->m_PriorDepthRenderKeyFactory,
140         renderSystem->m_PriorMaterialRenderKeyFactory,
141         renderSystem->m_PriorMaterialRenderKeyFactory);
142 
143     renderSystem->m_MeshRenderer = gfx::MeshRenderer::Create(allocator);
144     renderSystem->m_MeshRenderer->SetRenderContext(renderSystem->m_RenderContext);
145 
146 
147     if (nngxInitialize(AllocateGraphicsMemory, DeallocateGraphicsMemory) == GL_FALSE)
148     {
149         NW_FATAL_ERROR("nngxInitialize failed.\n");
150     }
151 
152     // コマンドリスト
153     nw::demo::CommandListSwapper::Description swapperDescription;
154     swapperDescription.commandListCount = description.commandListCount;
155     swapperDescription.bufferSize = description.commandBufferSize;
156     swapperDescription.requestCount = description.commandRequestCount;
157     swapperDescription.reusableBufferSize = description.reusableCommandBufferSize;
158     swapperDescription.reusableRequestCount = description.reusableCommandRequestCount;
159     swapperDescription.maxGpuProfilingEntryCount = description.maxGpuProfilingEntryCount;
160     renderSystem->m_CommandListSwapper =
161         nw::demo::CommandListSwapper::Create(allocator, swapperDescription);
162 
163     NW_POINTER_ASSERT(renderSystem->m_CommandListSwapper);
164 
165     renderSystem->m_CommandListSwapper->Bind();
166     renderSystem->m_CommandListSwapper->RunAsync();
167 
168     nngxStartLcdDisplay();
169 
170 
171     renderSystem->m_UpperSwapper = DisplayBufferSwapper::Builder()
172         .BufferDescription(description.upperScreenDescription)
173         .BufferCount(description.displayBufferCount)
174         .Create(allocator);
175 
176     renderSystem->m_LowerSwapper = DisplayBufferSwapper::Builder()
177         .BufferDescription(description.lowerScreenDescription)
178         .BufferCount(description.displayBufferCount)
179         .Create(allocator);
180 
181     nngxSetDisplayMode(description.upperScreenMode);
182 
183     // ステレオモードの場合は上画面のディスプレイバッファを追加で生成する
184     if (description.upperScreenMode == UPPER_SCREEN_MODE_STEREO)
185     {
186         nw::demo::DisplayBufferSwapper::Description extensionScreenDescription;
187         extensionScreenDescription.screenKind = nw::demo::EXTENSION_SCREEN;
188         extensionScreenDescription.width  = description.upperScreenDescription.width;
189         extensionScreenDescription.height = description.upperScreenDescription.height;
190         extensionScreenDescription.transferMode = description.upperScreenDescription.transferMode;
191 
192         renderSystem->m_ExtensionSwapper = DisplayBufferSwapper::Builder()
193             .BufferDescription(extensionScreenDescription)
194             .BufferCount(description.displayBufferCount)
195             .Create(allocator);
196 
197         // ステレオカメラを生成する
198         void* cameraMemory = allocator->Alloc(sizeof(nn::ulcd::CTR::StereoCamera));
199         nn::ulcd::CTR::StereoCamera* stereoCamera = new(cameraMemory) nn::ulcd::CTR::StereoCamera();
200         stereoCamera->Initialize();
201         renderSystem->m_StereoCamera = stereoCamera;
202     }
203 
204     NW_GL_ASSERT();
205 
206     renderSystem->m_Allocator = allocator;
207 
208     return renderSystem;
209 }
210 
211 //----------------------------------------
212 void
LoadSkyModel(const wchar_t * fileName)213 RenderSystem::LoadSkyModel(const wchar_t* fileName)
214 {
215     ResourceSet* resourceSet = Utility::LoadResources(m_Resources, fileName, m_Allocator);
216 
217     resourceSet->resource.ForeachTexture(nw::gfx::TextureLocationFlagSetter(NN_GX_MEM_VRAMA | GL_NO_COPY_FCRAM_DMP));
218     resourceSet->resource.ForeachIndexStream(nw::gfx::IndexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
219     resourceSet->resource.ForeachVertexStream(nw::gfx::VertexStreamLocationFlagSetter(NN_GX_MEM_VRAMB | GL_NO_COPY_FCRAM_DMP));
220 
221     nw::gfx::Result result = resourceSet->resource.Setup(m_Allocator);
222     if (result.IsFailure())
223     {
224         NW_FATAL_ERROR("Fail to set up model. A result code is 0x%x", result.GetCode());
225     }
226 
227     // モデルのインスタンスを生成します。
228     nw::gfx::ResModelArray models = resourceSet->resource.GetModels();
229     nw::gfx::SceneNode* node = nw::demo::Utility::CreateSceneNode(
230         m_Allocator,
231         *(models.begin()),
232         false
233     );
234 
235     nw::gfx::Model* model = nw::ut::DynamicCast<nw::gfx::Model*>(node);
236     NW_NULL_ASSERT(model);
237 
238     m_SkyModel = model;
239 }
240 
241 //----------------------------------------
242 void
Destroy()243 RenderSystem::Destroy()
244 {
245     os::IAllocator* allocator = this->m_Allocator;
246 
247     nngxStopCmdlist();
248     nngxWaitCmdlistDone();
249 
250     gfx::SafeDestroy(this->m_SkyModel);
251     nw::demo::SafeCleanupResources(m_Resources);
252     m_Resources.clear();
253 
254     if (this->m_StereoCamera)
255     {
256         m_StereoCamera->Finalize();
257         allocator->Free(m_StereoCamera);
258     }
259 
260     gfx::SafeDestroy(this->m_ExtensionSwapper);
261 
262     gfx::SafeDestroy(this->m_LowerSwapper);
263     gfx::SafeDestroy(this->m_UpperSwapper);
264     gfx::SafeDestroy(this->m_MeshRenderer);
265     gfx::SafeDestroy(this->m_RenderQueue);
266     gfx::SafeDestroy(this->m_PriorMaterialRenderKeyFactory);
267     gfx::SafeDestroy(this->m_PriorDepthRenderKeyFactory);
268     gfx::SafeDestroy(this->m_PostRightRenderCallback);
269     gfx::SafeDestroy(this->m_PostRenderCallback);
270     gfx::SafeDestroy(this->m_RenderContext);
271     gfx::SafeDestroy(this->m_CommandListSwapper);
272 
273     // VSync のタイミングで nngxFinalize() を呼び出すと止まりが発生することがあるため、
274     // 直前で VSync を待ちます。
275     nngxWaitVSync(NN_GX_DISPLAY_BOTH);
276 
277     nngxFinalize();
278     // TODO: グラフィックスメモリアロケーターのデアロケータを実装する
279     s_GraphicsMemoryAllocator.Finalize();
280     NW_GL_ASSERT();
281 
282     void* memory = static_cast<void*>(this);
283     this->~RenderSystem();
284 
285     allocator->Free(memory);
286 }
287 
288 //----------------------------------------
289 void
SetRenderTarget(gfx::IRenderTarget * renderTarget)290 RenderSystem::SetRenderTarget(gfx::IRenderTarget* renderTarget)
291 {
292     gfx::RenderContext* renderContext = this->GetRenderContext();
293     renderContext->SetRenderTarget(renderTarget);
294 }
295 
296 //----------------------------------------
297 void
SetRenderSortMode(gfx::ISceneUpdater::RenderSortMode renderSortMode)298 RenderSystem::SetRenderSortMode(gfx::ISceneUpdater::RenderSortMode renderSortMode)
299 {
300     this->m_RenderSortMode = renderSortMode;
301 
302     gfx::SafeDestroy(this->m_PriorDepthRenderKeyFactory);
303     if (this->m_RenderSortMode == gfx::ISceneUpdater::OPAQUE_MESH_BASE_AND_TRANSLUCENT_MODEL_BASE_SORT)
304     {
305         this->m_PriorDepthRenderKeyFactory =
306             gfx::CreateTopPriorDepthReverseDepthRenderKeyFactory(this->m_Allocator);
307     }
308     else
309     {
310         this->m_PriorDepthRenderKeyFactory =
311             gfx::CreatePriorDepthReverseDepthRenderKeyFactory(this->m_Allocator);
312     }
313 
314     NW_NULL_ASSERT(this->m_PriorDepthRenderKeyFactory);
315 }
316 
317 //----------------------------------------
318 struct RenderSceneInternalFunctor
319 : public std::unary_function<gfx::RenderElement&, void>
320 {
321     gfx::RenderContext* m_RenderContext;
322     gfx::MeshRenderer* m_MeshRenderer;
323 
RenderSceneInternalFunctornw::demo::RenderSceneInternalFunctor324     RenderSceneInternalFunctor(gfx::RenderContext* renderContext, gfx::MeshRenderer* meshRenderer)
325     : m_RenderContext(renderContext), m_MeshRenderer(meshRenderer)
326     {
327         NW_NULL_ASSERT(renderContext);
328         NW_NULL_ASSERT(meshRenderer);
329     }
330 
operator ()nw::demo::RenderSceneInternalFunctor331     void operator()(gfx::RenderElement& element)
332     {
333         if (element.IsCommand())
334         {
335             gfx::RenderCommand* command = element.GetCommand();
336             NW_NULL_ASSERT(command);
337             command->Invoke(this->m_RenderContext);
338         }
339         else
340         {
341             gfx::ResMesh mesh = element.GetMesh();
342             gfx::Model* model = element.GetModel();
343             model->PreRenderSignal()(model, mesh, this->m_RenderContext);
344             this->m_MeshRenderer->RenderMesh(mesh, model);
345             model->PostRenderSignal()(model, mesh, this->m_RenderContext);
346         }
347         NW_GL_ASSERT();
348     }
349 };
350 
351 //----------------------------------------
352 void
SetSceneEnvironmentSettings(SceneSystem * sceneSystem,ut::MoveArray<gfx::SceneEnvironmentSetting * > * sceneEnvironmentSettings)353 RenderSystem::SetSceneEnvironmentSettings(
354     SceneSystem* sceneSystem,
355     ut::MoveArray<gfx::SceneEnvironmentSetting*>* sceneEnvironmentSettings
356 )
357 {
358     gfx::RenderContext* renderContext = this->GetRenderContext();
359     gfx::SceneContext* sceneContext = sceneSystem->GetSceneContext();
360     gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
361 
362     ut::MoveArray<gfx::SceneEnvironmentSetting*>::iterator end = sceneEnvironmentSettings->end();
363     for (ut::MoveArray<gfx::SceneEnvironmentSetting*>::iterator sceneEnvironmentSetting = sceneEnvironmentSettings->begin();
364         sceneEnvironmentSetting != end;
365         ++sceneEnvironmentSetting)
366     {
367         (*sceneEnvironmentSetting)->ResolveReference(*sceneContext);
368         sceneEnvironment.ApplyFrom(**sceneEnvironmentSetting);
369     }
370 }
371 
372 //----------------------------------------
373 void
SetEnvironment(SceneSystem * sceneSystem)374 RenderSystem::SetEnvironment(
375     SceneSystem* sceneSystem
376 )
377 {
378     NW_PROFILE("RenderSystem::SetEnvironment");
379 
380     gfx::RenderContext* renderContext = this->GetRenderContext();
381     gfx::SceneContext* sceneContext = sceneSystem->GetSceneContext();
382     gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
383 
384     if (sceneContext->GetAmbientLightsBegin() != sceneContext->GetAmbientLightsEnd())
385     {
386         sceneEnvironment.SetAmbientLight(*sceneContext->GetAmbientLightsBegin());
387     }
388 
389     if (sceneContext->GetHemiSphereLightsBegin() != sceneContext->GetHemiSphereLightsEnd())
390     {
391         sceneEnvironment.SetHemiSphereLight(*sceneContext->GetHemiSphereLightsBegin());
392     }
393 
394     std::for_each(
395         sceneContext->GetFragmentLightsBegin(),
396         sceneContext->GetFragmentLightsEnd(),
397         std::bind1st(std::mem_fun(&gfx::SceneEnvironment::SetFragmentLight), &sceneEnvironment));
398 
399     std::for_each(
400         sceneContext->GetVertexLightsBegin(),
401         sceneContext->GetVertexLightsEnd(),
402         std::bind1st(std::mem_fun(&gfx::SceneEnvironment::SetVertexLight), &sceneEnvironment));
403 
404     if (sceneContext->GetFogBegin() != sceneContext->GetFogEnd())
405     {
406         sceneEnvironment.SetFog(0, *sceneContext->GetFogBegin());
407     }
408 }
409 
410 //----------------------------------------
411 void
SubmitView(SceneSystem * sceneSystem)412 RenderSystem::SubmitView(
413     SceneSystem* sceneSystem
414 )
415 {
416     NW_PROFILE("RenderSystem::SubmitView");
417 
418     nw::gfx::Camera* camera = this->GetRenderContext()->GetActiveCamera();
419     gfx::SceneContext* sceneContext = sceneSystem->GetSceneContext();
420 
421     //----------------------------------------
422     // フォグを更新します。
423     std::for_each(sceneContext->GetFogBegin(), sceneContext->GetFogEnd(), gfx::Fog::UpdateFunctor(camera));
424 
425     //----------------------------------------
426     // カメラに依存する処理と、描画要素をレンダーキューに積みます。
427 
428     #ifdef SORT_DEPTH_OF_TRANSLUCENT_MESH_ENABLED
429     // RenderQueue::Reset の引数に true を指定すると、ソート用キーをキャッシュする最適化機能が
430     // 有効になります。
431     // 半透明以外のソート用キーのみキャッシュされるようになります。
432     this->m_RenderQueue->Reset(true);
433 
434     // 半透明メッシュの深度のみ計算して、半透明メッシュのみ深度によるソートがされるようになります。
435     // 深度計算の処理負荷の低減を期待できます。
436     sceneSystem->GetSceneUpdater()->SetDepthSortMode(gfx::ISceneUpdater::SORT_DEPTH_OF_TRANSLUCENT_MESH);
437     #else
438     this->m_RenderQueue->Reset();
439 
440     // すべてのメッシュの深度を計算して、深度によってもソートされるようになります。
441     // 不透明物体等を手前から描画することで、GPUのフィル負荷の低減を期待できます。
442     sceneSystem->GetSceneUpdater()->SetDepthSortMode(gfx::ISceneUpdater::SORT_DEPTH_OF_ALL_MESH);
443     #endif
444 
445     sceneSystem->GetSceneUpdater()->SubmitView(
446         this->m_RenderQueue,
447         sceneContext,
448         *camera,
449         0,
450         1,
451         this->m_RenderSortMode);
452 
453     //----------------------------------------
454     // シーンコンテキスト中から、ユーザ定義による描画ノードを取得して、
455     // それが持つレンダーコマンドをレンダーキューに追加します。
456     {
457         nw::gfx::UserRenderNodeArray::const_iterator begin = sceneContext->GetUserRenderNodesBegin();
458         nw::gfx::UserRenderNodeArray::const_iterator end   = sceneContext->GetUserRenderNodesEnd();
459 
460         for ( nw::gfx::UserRenderNodeArray::const_iterator node = begin; node != end; ++node )
461         {
462             nw::gfx::UserRenderNode* userRenderNode             = (*node);
463             nw::gfx::UserRenderCommand* userRenderCommand       = userRenderNode->GetUserRenderCommand();
464             gfx::ResMaterial::TranslucencyKind translucencyKind = userRenderNode->GetTranslucencyKind();
465             u8 priority                                         = userRenderNode->GetPriority();
466             u8 layerId                                          = userRenderNode->GetLayerId();
467 
468             EnqueueRenderCommand( userRenderCommand,
469                 translucencyKind,
470                 priority,
471                 layerId );
472         }
473     }
474 
475     //----------------------------------------
476     // レンダーキューをソートします。
477     // RenderElementCompare() やレンダーキーファクトリーをカスタマイズすることで
478     // 描画順を変更することができます。
479     // 詳しくは最適化TIPSを参照してください。
480     std::sort(
481         this->m_RenderQueue->Begin(),
482         this->m_RenderQueue->End(),
483         gfx::RenderElementCompare());
484 
485 #ifdef REPORT_RENDER_QUEUE_ENABLED
486     // レンダーキューのソート後の状態をレポートします。
487     // リリース版ではなにも表示されなくなっています。
488     std::for_each(
489         this->m_RenderQueue->Begin(),
490         this->m_RenderQueue->End(),
491         gfx::RenderQueue::ReportFunctor());
492 #endif
493 }
494 
495 //----------------------------------------
496 void
RenderScene(gfx::Camera * camera,s32 screenKind,bool isCommandCacheDump)497 RenderSystem::RenderScene(
498     gfx::Camera* camera,
499     s32 screenKind,
500     bool isCommandCacheDump
501 )
502 {
503     NW_PROFILE("RenderSystem::RenderScene");
504 
505     gfx::RenderContext* renderContext = this->GetRenderContext();
506     gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
507 
508     NW_GL_ASSERT();
509 
510     // GPU処理時間計測開始
511     int profilingId = m_CommandListSwapper->AddGpuProfilingStartPoint(true);
512     NW_ASSERT(profilingId >= 0);
513     int cmdBufferSize = m_CommandListSwapper->GetCommandBufferSize();
514 
515     renderContext->SetCameraMatrix(camera);
516 
517     if (m_SkyModel != NULL)
518     {
519         this->ClearBySkyModel(camera);
520     }
521     else
522     {
523         this->ClearBuffer(nw::ut::FloatColor(0.5f, 0.5f, 0.5f, 1.0f));
524     }
525 
526     if (isCommandCacheDump)
527     {
528         nw::gfx::internal::CommandCacheBuilder builder;
529         builder.Begin();
530 
531         std::for_each(
532             this->m_RenderQueue->Begin(),
533             this->m_RenderQueue->End(),
534             RenderSceneInternalFunctor(renderContext, this->m_MeshRenderer));
535 
536         builder.End();
537         builder.Report();
538     }
539     else
540     {
541         std::for_each(
542             this->m_RenderQueue->Begin(),
543             this->m_RenderQueue->End(),
544             RenderSceneInternalFunctor(renderContext, this->m_MeshRenderer));
545     }
546 
547     m_LoadMeterDescription.drawCommandBufferSize =
548         m_CommandListSwapper->GetCommandBufferSize() - cmdBufferSize;
549     m_CumulativeLoadMeterDescription.drawCommandBufferSize =
550         m_CommandListSwapper->GetCommandBufferSize() - cmdBufferSize;
551 
552     (*m_PostRenderCallback)(camera);
553 
554     // GPU処理時間計測終了
555     nngxSplitDrawCmdlist();
556 
557     m_CommandListSwapper->SetGpuProfilingEndPoint(profilingId);
558 
559     TransferBuffer(screenKind);
560 }
561 
562 //----------------------------------------
563 void
RenderStereoScene(gfx::Camera * leftCamera,gfx::Camera * rightCamera,bool isCommandCacheDump)564 RenderSystem::RenderStereoScene(
565     gfx::Camera* leftCamera,
566     gfx::Camera* rightCamera,
567     bool isCommandCacheDump
568 )
569 {
570     NW_PROFILE("RenderSystem::RenderStereoScene");
571 
572     gfx::RenderContext* renderContext = this->GetRenderContext();
573     gfx::SceneEnvironment& sceneEnvironment = renderContext->GetSceneEnvironment();
574 
575     //----------------------------------------
576     // 再利用するためのコマンドを作成し、保存します。
577     //
578     // ベースカメラを元にしたシーンを描画します。
579     m_CommandListSwapper->StartCommandSave();
580     int cmdBufferSize = m_CommandListSwapper->GetCommandBufferSize();
581 
582     if (m_SkyModel != NULL)
583     {
584         this->ClearBySkyModel(renderContext->GetActiveCamera());
585     }
586     else
587     {
588         this->ClearBuffer(nw::ut::FloatColor(0.5f, 0.5f, 0.5f, 1.0f));
589     }
590 
591     if (isCommandCacheDump)
592     {
593         nw::gfx::internal::CommandCacheBuilder builder;
594         builder.Begin();
595 
596         std::for_each(
597             this->m_RenderQueue->Begin(),
598             this->m_RenderQueue->End(),
599             RenderSceneInternalFunctor(renderContext, this->m_MeshRenderer));
600 
601         builder.End();
602         builder.Report();
603     }
604     else
605     {
606         std::for_each(
607             this->m_RenderQueue->Begin(),
608             this->m_RenderQueue->End(),
609             RenderSceneInternalFunctor(renderContext, this->m_MeshRenderer));
610     }
611 
612     m_LoadMeterDescription.drawCommandBufferSize =
613         m_CommandListSwapper->GetCommandBufferSize() - cmdBufferSize;
614 
615     m_CommandListSwapper->EndCommandSave();
616 
617     //----------------------------------------
618     // 左目用と右目用に保存したコマンドを再利用します。
619 
620     // GPU処理時間計測開始
621     int profilerLeft = m_CommandListSwapper->AddGpuProfilingStartPoint(true);
622     NW_ASSERT(profilerLeft >= 0);
623 
624     // 左目用
625     renderContext->SetCameraMatrix(leftCamera);
626     m_CommandListSwapper->ReuseCommand(false);
627 
628     (*m_PostRenderCallback)(leftCamera);
629 
630     // GPU処理時間計測終了
631     m_CommandListSwapper->SetGpuProfilingEndPoint(profilerLeft);
632 
633     TransferBuffer(UPPER_SCREEN);
634     NW_GL_ASSERT();
635 
636     // GPU処理時間計測開始
637     int profilerRight = m_CommandListSwapper->AddGpuProfilingStartPoint(true);
638     NW_ASSERT(profilerRight >= 0);
639 
640     // 右目用
641     renderContext->SetCameraMatrix(rightCamera);
642     m_CommandListSwapper->ReuseCommand(false);
643 
644     (*m_PostRightRenderCallback)(rightCamera);
645 
646     // GPU処理時間計測終了
647     m_CommandListSwapper->SetGpuProfilingEndPoint(profilerRight);
648 
649     TransferBuffer(EXTENSION_SCREEN);
650     NW_GL_ASSERT();
651 }
652 
653 //----------------------------------------
654 void
ClearBuffer(nw::ut::FloatColor clearColor)655 RenderSystem::ClearBuffer( nw::ut::FloatColor clearColor )
656 {
657     if (!nw::demo::DebugUtility::IsCpuProfilingMode())
658     {
659         this->SuspendLoadMeter();
660 
661         this->m_RenderContext->ClearBuffer(
662             GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT,
663             clearColor,
664             1.0f);
665         NW_GL_ASSERT();
666 
667         this->ResumeLoadMeter();
668     }
669 }
670 
671 //----------------------------------------
672 void
ClearBySkyModel(const gfx::Camera * camera)673 RenderSystem::ClearBySkyModel(const gfx::Camera* camera)
674 {
675     NW_NULL_ASSERT(camera);
676 
677     if (m_SkyModel != NULL)
678     {
679 #ifdef NW_GFX_MODEL_TRANSLATE_OFFSET_ENABLED
680         math::VEC3 translate = camera->WorldMatrix().GetColumn(3) - this->GetRenderContext()->ModelTranslateOffset();
681 #else
682         math::VEC3 translate = camera->WorldMatrix().GetColumn(3);
683 #endif
684         m_SkyModel->WorldMatrix()._03 = translate.x;
685         m_SkyModel->WorldMatrix()._13 = translate.y;
686         m_SkyModel->WorldMatrix()._23 = translate.z;
687 
688         // Far の半分まで SkyModel を拡大します。
689         float scale = (camera->GetFar() / 2.0f);
690         m_SkyModel->WorldMatrix()._00 = scale;
691         m_SkyModel->WorldMatrix()._11 = scale;
692         m_SkyModel->WorldMatrix()._22 = scale;
693 
694         gfx::ResMeshArray meshArray = m_SkyModel->GetResMeshes();
695         gfx::ResMeshArray::iterator endMesh = meshArray.end();
696         for (gfx::ResMeshArray::iterator iter = meshArray.begin();
697             iter != endMesh;
698             ++iter)
699         {
700             this->m_MeshRenderer->RenderMesh(*iter, m_SkyModel);
701         }
702     }
703 }
704 
705 //----------------------------------------
706 void
TransferBuffer(s32 screenKind)707 RenderSystem::TransferBuffer(
708     s32 screenKind
709 )
710 {
711     gfx::RenderContext* renderContext = this->GetRenderContext();
712 
713     // コマンドリストが多重化されている場合、
714     // ディスプレイバッファへの転送するタイミングが変わるため、
715     // 転送先のディスプレイバッファを変更する必要があります。
716     // 詳細は PresentBuffer() のコメントを参照してください。
717 
718     bool isMultiCommandList = m_CommandListSwapper->GetListCount() > 1;
719 
720     if (screenKind & UPPER_SCREEN)
721     {
722         this->m_UpperSwapper->MakeTransferBufferCommand(
723             renderContext->GetRenderTarget(),
724             isMultiCommandList);
725     }
726 
727     if (screenKind & LOWER_SCREEN)
728     {
729         this->m_LowerSwapper->MakeTransferBufferCommand(
730             renderContext->GetRenderTarget(),
731             isMultiCommandList);
732     }
733 
734     if (screenKind & EXTENSION_SCREEN)
735     {
736         this->m_ExtensionSwapper->MakeTransferBufferCommand(
737             renderContext->GetRenderTarget(),
738             isMultiCommandList);
739     }
740 }
741 
742 //----------------------------------------
743 void
WaitCommandList()744 RenderSystem::WaitCommandList()
745 {
746     this->SuspendLoadMeter();
747 
748     NW_PROFILE("RenderSystem::WaitCommandList");
749 
750     nn::os::Tick startTick = nn::os::Tick::GetSystemCurrent();
751 
752     m_CommandListSwapper->WaitDone();
753 
754     s64 span = static_cast<nn::os::Tick>(nn::os::Tick::GetSystemCurrent() - startTick).ToTimeSpan().GetNanoSeconds();
755     m_LoadMeterDescription.cumulativeWaitTime +=
756         static_cast<float>(span) * LoadMeterDescription::NANO_TO_MILLI;
757 
758     this->ResumeLoadMeter();
759 }
760 
761 //----------------------------------------
762 void
RunCommandList()763 RenderSystem::RunCommandList()
764 {
765     m_CommandListSwapper->RunAsync();
766 }
767 
768 //----------------------------------------
769 void
SwapCommandList()770 RenderSystem::SwapCommandList()
771 {
772     m_CommandListSwapper->Swap();
773     m_CommandListSwapper->Bind();
774 }
775 
776 //----------------------------------------
777 void
WaitVSync(s32 screenKind)778 RenderSystem::WaitVSync(s32 screenKind)
779 {
780     NW_MAX_ASSERT(screenKind, (int)BOTH_SCREENS);
781 
782     GLenum display;
783     if (screenKind & (UPPER_SCREEN | LOWER_SCREEN)) { display = NN_GX_DISPLAY_BOTH; }
784     else if (screenKind & UPPER_SCREEN) { display = NN_GX_DISPLAY0; }
785     else if (screenKind & LOWER_SCREEN) { display = NN_GX_DISPLAY1; }
786 
787 
788     EndLoadMeter();
789 
790     {
791         NW_PROFILE("WaitVSync");
792         nngxWaitVSync(display);
793     }
794 
795     BeginLoadMeter();
796 }
797 
798 //----------------------------------------
799 void
SwapBuffer(s32 screenKind)800 RenderSystem::SwapBuffer(
801     s32 screenKind
802 )
803 {
804     GLenum display;
805     if ((screenKind & NORMAL_SCREENS) == NORMAL_SCREENS)
806     {
807         this->m_UpperSwapper->ActivateBuffer();
808         this->m_LowerSwapper->ActivateBuffer();
809 
810         if (screenKind & EXTENSION_SCREEN)
811         {
812             this->m_ExtensionSwapper->ActivateBuffer();
813         }
814 
815         display = NN_GX_DISPLAY_BOTH;
816     }
817     else if (screenKind & UPPER_SCREEN)
818     {
819         this->m_UpperSwapper->ActivateBuffer();
820 
821         if (screenKind & EXTENSION_SCREEN)
822         {
823             this->m_ExtensionSwapper->ActivateBuffer();
824         }
825 
826         display = NN_GX_DISPLAY0;
827     }
828     else if (screenKind & LOWER_SCREEN)
829     {
830         this->m_LowerSwapper->ActivateBuffer();
831 
832         display = NN_GX_DISPLAY1;
833     }
834 
835     nngxSwapBuffers(display);
836     glBindFramebuffer(GL_FRAMEBUFFER, 0);
837 }
838 
839 //----------------------------------------
840 void
PresentBuffer(s32 screenKind)841 RenderSystem::PresentBuffer(s32 screenKind)
842 {
843     // コマンドリストが多重化されているかどうかで、
844     // 転送するディスプレイバッファを変更したり、
845     // コマンドリスト終了待ちのタイミングを変えたりする必要があります。
846     // これらを正しく行わない場合、テアリングなどが発生することがあります。
847     if (m_CommandListSwapper->GetListCount() > 1)
848     {
849         // コマンドリストが多重化されている場合、
850         // この関数が呼ばれるまでに蓄積されたコマンドが実行( RunCommandList() )されるのは
851         // VSync とディスプレイバッファのスワップが行われた後になります。
852         //
853         // レンダーバッファからディスプレイバッファへの転送もコマンドとして蓄積され、
854         // 同じくディスプレイバッファのスワップ後に実行されます。
855         // そのため、この関数内で呼ばれるSwapBuffer()により表示されるディスプレイバッファへの転送をしてしまうと、
856         // 表示中のディスプレイバッファへの転送が実行され、テアリングが発生します。
857         //
858         // これを解決するため、ディスプレイバッファへの転送コマンドを蓄積する場合、
859         // その時点を基準に2回ディスプレイバッファのスワップが行われたときに
860         // 表示されるバッファへ転送する必要があります。
861         // DisplayBufferSwapper::MakeTransferBufferCommand() の第2引数にtrueを指定することで、
862         // 内部的にこのような転送先の調整が行われます。
863         WaitCommandList();
864         SwapBuffer(screenKind);
865         WaitVSync(screenKind);
866         RunCommandList();
867         SwapCommandList();
868     }
869     else
870     {
871         RunCommandList();
872         WaitCommandList();
873         SwapBuffer(screenKind);
874         WaitVSync(screenKind);
875     }
876 }
877 
878 //----------------------------------------
879 void
CalcStereoCamera(gfx::Camera * leftCamera,gfx::Camera * rightCamera,gfx::Camera * baseCamera,f32 depthLevel,f32 depthRange)880 RenderSystem::CalcStereoCamera(
881     gfx::Camera* leftCamera,
882     gfx::Camera* rightCamera,
883     gfx::Camera* baseCamera,
884     f32 depthLevel,
885     f32 depthRange)
886 {
887     NW_NULL_ASSERT(leftCamera);
888     NW_NULL_ASSERT(rightCamera);
889     NW_NULL_ASSERT(baseCamera);
890     nn::math::MTX44& projOriginal = baseCamera->ProjectionMatrix();
891     nn::math::MTX34& viewOriginal = baseCamera->ViewMatrix();
892     nn::math::MTX44& projL = leftCamera->ProjectionMatrix();
893     nn::math::MTX34& viewL = leftCamera->ViewMatrix();
894     nn::math::MTX44& projR = rightCamera->ProjectionMatrix();
895     nn::math::MTX34& viewR = rightCamera->ViewMatrix();
896 
897     // Orthoカメラをステレオ表示する場合は自分で絵を用意しなければいけません。
898     if (baseCamera->GetResCamera().GetProjectionType() == gfx::ResCamera::PROJTYPE_ORTHO)
899     {
900         // 現在はOrthoカメラのステレオ表示には未対応です。
901         math::MTX44Copy(&projL, &projOriginal);
902         math::MTX34Copy(&viewL, &viewOriginal);
903         math::MTX44Copy(&projR, &projOriginal);
904         math::MTX34Copy(&viewR, &viewOriginal);
905 
906         // CalculateMatrices(....)で画面にあわせての回転を行っているので、
907         // Orthoの場合はpivotを設定します。
908         baseCamera->GetProjectionUpdater()->SetPivotDirection(math::PIVOT_UPSIDE_TO_TOP);
909         leftCamera->GetProjectionUpdater()->SetPivotDirection(math::PIVOT_UPSIDE_TO_TOP);
910         rightCamera->GetProjectionUpdater()->SetPivotDirection(math::PIVOT_UPSIDE_TO_TOP);
911     }
912     else
913     {
914         m_StereoCamera->CalculateMatrices(
915             &projL,
916             &viewL,
917             &projR,
918             &viewR,
919             &projOriginal,
920             &viewOriginal,
921             depthLevel,
922             depthRange,
923             false);
924     }
925 }
926 
927 //----------------------------------------
928 void
BeginLoadMeter()929 RenderSystem::BeginLoadMeter()
930 {
931     m_LoadMeterDescription.startTick = nn::os::Tick::GetSystemCurrent();
932     m_LoadMeterDescription.drawCommandBufferSize = 0;
933 }
934 
935 //----------------------------------------
936 void
EndLoadMeter()937 RenderSystem::EndLoadMeter()
938 {
939     nn::os::Tick endTick = nn::os::Tick::GetSystemCurrent();
940 
941     s64 span = static_cast<nn::os::Tick>(endTick - m_LoadMeterDescription.startTick).ToTimeSpan().GetNanoSeconds();
942 
943     float currentTime         = static_cast<float>(span) * LoadMeterDescription::NANO_TO_MILLI;
944     float currentGpuTime      = static_cast<float>(this->m_CommandListSwapper->GetGpuProfilingTotalCostTime());
945 
946     m_LoadMeterDescription.cumulativeTime += currentTime;
947     m_LoadMeterDescription.cumulativeGpuTime += currentGpuTime;
948 
949     m_CumulativeLoadMeterDescription.cumulativeTime += currentTime;
950     m_CumulativeLoadMeterDescription.cumulativeGpuTime += currentGpuTime;
951 
952     m_CumulativeLoadMeterDescription.drawCommandBufferSize = m_LoadMeterDescription.drawCommandBufferSize;
953 
954     ++m_LoadMeterDescription.callCount;
955     ++m_CumulativeLoadMeterDescription.callCount;
956 }
957 
958 //----------------------------------------
959 void
CalcLoadMeter()960 RenderSystem::CalcLoadMeter()
961 {
962     float callCount = static_cast<float>(m_LoadMeterDescription.callCount);
963     m_LoadMeterDescription.loadTime = m_LoadMeterDescription.cumulativeTime / callCount;
964     m_LoadMeterDescription.loadGpuTime = m_LoadMeterDescription.cumulativeGpuTime / callCount;
965     m_LoadMeterDescription.waitTime = m_LoadMeterDescription.cumulativeWaitTime / callCount;
966     m_LoadMeterDescription.cumulativeTime = 0.0f;
967     m_LoadMeterDescription.cumulativeGpuTime = 0.0f;
968     m_LoadMeterDescription.cumulativeWaitTime = 0.0f;
969     m_LoadMeterDescription.callCount = 0;
970 }
971 
972 //----------------------------------------
973 void
SuspendLoadMeter()974 RenderSystem::SuspendLoadMeter()
975 {
976     nn::os::Tick endTick = nn::os::Tick::GetSystemCurrent();
977 
978     s64 span = static_cast<nn::os::Tick>(endTick - m_LoadMeterDescription.startTick).ToTimeSpan().GetNanoSeconds();
979     m_LoadMeterDescription.cumulativeTime +=
980         static_cast<float>(span) * LoadMeterDescription::NANO_TO_MILLI;
981     m_CumulativeLoadMeterDescription.cumulativeTime +=
982         static_cast<float>(span) * LoadMeterDescription::NANO_TO_MILLI;
983 
984     m_LoadMeterDescription.startTick = 0;
985 }
986 
987 //----------------------------------------
988 void
ResumeLoadMeter()989 RenderSystem::ResumeLoadMeter()
990 {
991     m_LoadMeterDescription.startTick = nn::os::Tick::GetSystemCurrent();
992 }
993 
994 //----------------------------------------
995 void
ResetCumulativeLoadMeter()996 RenderSystem::ResetCumulativeLoadMeter()
997 {
998     m_CumulativeLoadMeterDescription.cumulativeTime = 0.0f;
999     m_CumulativeLoadMeterDescription.cumulativeGpuTime = 0.0f;
1000     m_CumulativeLoadMeterDescription.cumulativeWaitTime = 0.0f;
1001     m_CumulativeLoadMeterDescription.callCount = 0;
1002 }
1003 
1004 
1005 //----------------------------------------
1006 SceneSystem*
Create(os::IAllocator * allocator,const Description & description)1007 SceneSystem::Create(
1008     os::IAllocator* allocator,
1009     const Description& description
1010 )
1011 {
1012     void* memory = allocator->Alloc(sizeof(SceneSystem));
1013     SceneSystem* sceneSystem = new(memory) SceneSystem();
1014 
1015     sceneSystem->m_SceneContext = gfx::SceneContext::Builder()
1016         .MaxSceneNodes(description.maxSceneNodes)
1017         .MaxModels(description.maxModels)
1018         .MaxSkeletalModels(description.maxSkeletalModels)
1019         .MaxCameras(description.maxCameras)
1020         .MaxLights(description.maxLights)
1021         .MaxFragmentLights(description.maxFragmentLights)
1022         .MaxVertexLights(description.maxVertexLights)
1023         .MaxHemiSphereLights(description.maxHemiSphereLights)
1024         .MaxAmbientLights(description.maxAmbientLights)
1025         .MaxFogs(description.maxFogs)
1026         .MaxParticleSets(description.maxParticleSets)
1027         .MaxParticleEmitters(description.maxParticleEmitters)
1028         .MaxParticleModels(description.maxParticleModels)
1029         .MaxUserRenderNodes(description.maxUserRenderNodes)
1030         .IsFixedSizeMemory(description.isFixedSizeMemory)
1031         .Create(allocator);
1032 
1033     sceneSystem->m_SceneTraverser = gfx::SceneTraverser::Builder()
1034         .Create(allocator);
1035 
1036     gfx::WorldMatrixUpdater* worldMatrixUpdater = gfx::WorldMatrixUpdater::Builder()
1037         .Create(allocator);
1038 
1039     gfx::SkeletonUpdater* skeletonUpdater = gfx::SkeletonUpdater::Builder()
1040         .Create(allocator);
1041 
1042     sceneSystem->m_SceneUpdater = gfx::SceneUpdater::Builder()
1043         .WorldMatrixUpdaterPtr(worldMatrixUpdater)
1044         .SkeletonUpdaterPtr(skeletonUpdater)
1045         .Create(allocator);
1046 
1047     nw::gfx::IMaterialIdGenerator* materialIdGenerator =
1048         nw::gfx::SortingMaterialIdGenerator::Builder()
1049         .IsFixedSizeMemory(description.isFixedSizeMemory)
1050         .MaxMaterials(description.maxMaterials)
1051         .Create(allocator);
1052 
1053     sceneSystem->m_SceneInitializer = gfx::SceneInitializer::Builder()
1054         .MaterialIdGenerator(materialIdGenerator)
1055         .Create(allocator);
1056 
1057     sceneSystem->m_CameraController = CameraController::Builder()
1058         .Create(allocator);
1059 
1060     NW_GL_ASSERT();
1061 
1062     sceneSystem->m_Allocator = allocator;
1063 
1064     return sceneSystem;
1065 }
1066 
1067 //----------------------------------------
1068 void
Destroy()1069 SceneSystem::Destroy()
1070 {
1071     gfx::SafeDestroy(this->m_SceneInitializer);
1072     gfx::SafeDestroy(this->m_SceneTraverser);
1073     gfx::SafeDestroy(this->m_SceneUpdater);
1074     gfx::SafeDestroy(this->m_SceneContext);
1075 
1076     gfx::SafeDestroy(this->m_CameraController);
1077 
1078     os::IAllocator* allocator = this->m_Allocator;
1079 
1080     void* memory = static_cast<void*>(this);
1081     this->~SceneSystem();
1082     allocator->Free(memory);
1083 }
1084 
1085 //----------------------------------------
1086 void
InitializeScene(gfx::SceneNode * sceneRoot)1087 SceneSystem::InitializeScene(gfx::SceneNode* sceneRoot)
1088 {
1089     this->m_SceneInitializer->Begin();
1090     sceneRoot->Accept(this->m_SceneInitializer);
1091     this->m_SceneInitializer->End();
1092 
1093     TraverseScene(sceneRoot);
1094 }
1095 
1096 //----------------------------------------
1097 void
TraverseScene(gfx::SceneNode * sceneRoot)1098 SceneSystem::TraverseScene(gfx::SceneNode* sceneRoot)
1099 {
1100     this->m_SceneTraverser->Begin(this->m_SceneContext);
1101     sceneRoot->Accept(this->m_SceneTraverser);
1102     this->m_SceneTraverser->End();
1103 
1104     // パーティクルセットの依存順でソートする
1105     std::sort(
1106         this->m_SceneContext->GetParticleSetBegin(),
1107         this->m_SceneContext->GetParticleSetEnd(),
1108         gfx::ParticleSetCompare());
1109 }
1110 
1111 //----------------------------------------
1112 void
UpdateScene()1113 SceneSystem::UpdateScene()
1114 {
1115     NW_PROFILE("SceneSystem::UpdateScene");
1116 
1117     this->m_SceneUpdater->UpdateAll(this->m_SceneContext);
1118 }
1119 
1120 
1121 //----------------------------------------
1122 void
FinalizeGraphicsSystem()1123 FinalizeGraphicsSystem()
1124 {
1125     s_GraphicsMemoryAllocator.Finalize();
1126 
1127     nw::demo::FinalizeDemoAllocator(s_DeviceAllocator);
1128 }
1129 
1130 //----------------------------------------
1131 void
InitializeGraphicsSystem(nw::demo::DemoAllocator * deviceAllocator)1132 InitializeGraphicsSystem(nw::demo::DemoAllocator* deviceAllocator)
1133 {
1134     s_DeviceAllocator = deviceAllocator;
1135 
1136     nn::os::Initialize();
1137     nn::fs::Initialize();
1138 
1139     // メインメモリとデバイスメモリを初期化します。
1140     // メインメモリはユーザーが自由にアクセスできる領域となり、
1141     // デバイスメモリはGPUがアクセスするFCRAM上の領域となります。
1142     nw::demo::InitializeDemoMemory();
1143 
1144     nw::demo::InitializeDemoAllocator(s_DeviceAllocator, nw::demo::DEMO_MEMORY_SIZE, nn::os::ALLOCATE_OPTION_LINEAR);
1145 
1146     // デバイスメモリを用いるグラフィックスメモリアロケータを初期化します。
1147     s_GraphicsMemoryAllocator.Initialize(s_DeviceAllocator);
1148 
1149     const int MAX_FILE = 256;
1150     const int MAX_DIRECTORY = 16;
1151 
1152     s32 workingMemorySize = nn::fs::GetRomRequiredMemorySize(MAX_FILE, MAX_DIRECTORY);
1153     void* workingMemory = Alloc(workingMemorySize);
1154     nn::Result result = nn::fs::MountRom(MAX_FILE, MAX_DIRECTORY, workingMemory, workingMemorySize);
1155 
1156     NW_ASSERT(result.IsSuccess());
1157 }
1158 
1159 } // namespace demo
1160 } // namespace nw
1161