1 /*---------------------------------------------------------------------------*
2   Project:  NintendoWare
3   File:     demo_CommandListSwapper.h
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 #ifndef NW_DEMO_COMMANDLISTSWAPPER_H_
18 #define NW_DEMO_COMMANDLISTSWAPPER_H_
19 
20 #include <GLES2/gl2.h>
21 
22 #include <nw/ut/ut_MoveArray.h>
23 #include <nn/gx.h>
24 #include <nn/os.h>
25 
26 namespace nw
27 {
28 namespace os
29 {
30 class IAllocator;
31 }
32 
33 namespace demo
34 {
35 //---------------------------------------------------------------------------
36 //! @brief        コマンドリストとそのバッファリングを管理するクラスです。
37 //---------------------------------------------------------------------------
38 class CommandListSwapper
39 {
40     NW_DISALLOW_COPY_AND_ASSIGN(CommandListSwapper);
41 
42 public:
43 
44     //---------------------------------------------------------------------------
45     //! @brief        コマンドリストスワッパーの設定内容です。
46     //---------------------------------------------------------------------------
47     struct Description
48     {
49         size_t commandListCount;            //!< 生成するコマンドリストの数です。
50         size_t bufferSize;                  //!< 1つのコマンドリストのバッファサイズです。
51         size_t requestCount;                //!< 1つのコマンドリクエストの上限数です。
52         size_t reusableBufferSize;          //!< 1つの再利用コマンドリストのコマンドバッファのサイズを表します。
53         size_t reusableRequestCount;        //!< 1つの再利用コマンドリストのコマンドリクエストの上限数です。
54         size_t maxGpuProfilingEntryCount;   //!< GPU プロファイルエントリの上限数です。
55     };
56 
57     //----------------------------------------
58     //! @name 生成/破棄
59     //@{
60 
61     //! @brief        コマンドリストスワッパーを作成します。
62     //!
63     //! @param[in]    allocator アロケータです
64     //! @param[in]    description 生成するコマンドリストスワッパーの設定です。
65     //!
66     static CommandListSwapper* Create(os::IAllocator* allocator, Description& description);
67 
68     //! @brief 破棄します。
69     void Destroy();
70 
71     //@}
72 
73     //----------------------------------------
74     //! @name 操作
75     //@{
76 
77     //! @brief  コマンドリストをバインドします。
78     void Bind();
79 
80     //! @brief  バインドされているコマンドリストを実行します。
Run()81     void Run()
82     {
83         RunAsync();
84         WaitDone();
85     }
86 
87     //! @brief  バインドされているコマンドリストを非同期で実行します。
88     void RunAsync();
89 
90     //! @brief  非同期で実行したコマンドリストの終了待ちをします。
91     void WaitDone();
92 
93     //! @brief  コマンドリストをスワップします。
94     //!
95     //!         この関数だけではバインドされないので注意してください。
96     void Swap();
97 
98     //@}
99 
100     //----------------------------------------
101     //! @name GPU プロファイリング
102     //@{
103 
104     //! @brief  GPU プロファイラをリセットします。
105     //!
106     //!         バインドされているコマンドリストに追加された GPU プロファイルエントリをすべて削除します。
107     //!         コマンドリストが多重化されている場合はコマンドリストをスワップするときに、
108     //!         そうでない場合は終了待ちの直後に自動で呼ばれるため、手動でこの関数を実行する必要はありません。
109     //!
110     //! @sa     Swap
111     //! @sa     WaitDone
112     void ResetGpuProfiling();
113 
114     //! @brief  コマンドリストの GPU プロファイルエントリを追加し、始点を設定します。
115     //!
116     //!         コマンドリストの実行時間を計測する GPU プロファイラのエントリをバインドされているコマンドリストに追加し、
117     //!         その始点をこの関数が実行された時点で最後に蓄積されたコマンドリクエストの終了時に設定します。
118     //!
119     //!         この関数は 3D コマンドバッファを区切らないので、必要に応じて nngxSplitCmdlist() 関数を呼び出してください。
120     //!
121     //!         複数の CommandListSwapper インスタンスから GPU プロファイルを行うことはできません。
122     //!
123     //!         エントリの追加に失敗した場合、負の値が返されます。
124     //!
125     //! @param  IsInTotal この引数に true を設定すると、この GPU プロファイルエントリを GetGpuProfilingTotalCostTime() での計算に含めます。
126     //!
127     //! @return 追加された GPU プロファイルエントリの番号を返します。
128     //!
129     //! @sa     SetGpuProfilingEndPoint
130     //! @sa     GetGpuProfilingTotalCostTime
131     s32 AddGpuProfilingStartPoint(bool IsInTotal);
132 
133     //! @brief  GPU プロファイルエントリの終点を設定します。
134     //!
135     //!         指定した GPU プロファイルエントリの終点を
136     //!         この関数が実行された時点で最後に蓄積されたコマンドリクエストの終了時に設定します。
137     //!         計測された実行時間を取得するには GetGpuProfilingCostTime() や GetGpuProfilingTotalCostTime() を使用します。
138     //!
139     //!         この関数は 3D コマンドバッファを区切らないので、必要に応じて nngxSplitCmdlist() 関数を呼び出してください。
140     //!
141     //!         複数の CommandListSwapper インスタンスから GPU プロファイルを行うことはできません。
142     //!
143     //! @param  profilingId AddGpuProfilerStartPoint() で返されたエントリの番号を指定します。
144     //!
145     //! @sa     AddGpuProfilingStartPoint
146     //! @sa     GetGpuProfilingTotalCostTime
147     void SetGpuProfilingEndPoint(u32 profilingId);
148 
149     //! @brief  計測された GPU プロファイルエントリの実行時間を取得します。
150     //!
151     //!         実行されたコマンドリストに追加された GPU プロファイルエントリの実行時間をミリ秒単位で取得します。
152     //!         この関数で実行時間を取得する前に、WaitDone() によりコマンドリストの終了待ちをする必要があります。
153     //!         指定した番号のエントリが存在しない場合、この関数は 0.0f を返します。
154     //!
155     //!         コマンドリストが多重化されている場合は Swap() 実行時に、
156     //!         そうでない場合は Run() 実行時に GPU プロファイルの結果が失われます。
157     //!
158     //!         得られる GPU プロファイルエントリの結果はバインドされているコマンドリストではなく、
159     //!         WaitDone() で終了待ちをしたコマンドリストが対象であることに注意してください。
160     //!
161     //! @param  profilingId AddGpuProfilingStartPoint() で返されたエントリの番号を指定します。
162     //!
163     //! @return ミリ秒単位の実行時間です。
164     //!
165     //! @sa     AddGpuProfilingStartPoint
166     //! @sa     GetGpuProfilingTotalCostTime
167     f32 GetGpuProfilingCostTime(u32 profilingId);
168 
169     //! @brief  GPU プロファイルエントリの合計実行時間を取得します。
170     //!
171     //!         AddGpuProfilerStartPoint() で、引数 IsInTotal に true を指定した GPU プロファイルエントリの合計実行時間をミリ秒単位で取得します。
172     //!         実行区間が重複している GPU プロファイルエントリについても単純に加算されますので注意してください。
173     //!
174     //!         コマンドリストが多重化されている場合は Swap() 実行時に、
175     //!         そうでない場合は Run() 実行時に GPU プロファイルの結果が失われます。
176     //!
177     //!         得られる GPU プロファイルエントリの結果はバインドされているコマンドリストではなく、
178     //!         WaitDone() で終了待ちをしたコマンドリストが対象であることに注意してください。
179     //!
180     //! @return ミリ秒単位の実行時間です。
181     //!
182     //! @sa     AddGpuProfilingStartPoint
183     //! @sa     GetGpuProfilingCostTime
184     f32 GetGpuProfilingTotalCostTime();
185 
186     //}
187 
188     //----------------------------------------
189     //! @name 取得/設定
190     //@{
191 
192     //! @brief コマンドリストの ID を取得します。
GetCommandListId()193     GLuint GetCommandListId() const { return m_CommandLists[m_BoundIndex]; }
194 
195     //! @brief コマンドリストの数を取得します。
GetListCount()196     size_t GetListCount() const { return this->m_CommandLists.size(); }
197 
198     //! @brief  蓄積された 3D コマンドバッファのサイズを取得します。
199     //!
200     //!         現在バインドされているコマンドリストの 3D コマンドバッファのサイズを
201     //!         バイト単位で取得します。
202     //!
203     //!         再利用するために保存されたコマンドリストの 3D コマンドバッファのサイズを求めるときは
204     //!         GetReusableCommandBufferSize を使用してください。
205     //!
206     //! @return 3D コマンドバッファのサイズをバイト単位で返します。
207     //!
208     //! @sa GetReusableCommandBufferSize
209     int GetCommandBufferSize() const;
210 
211     //! @brief  再利用するために保存されたコマンドリストの 3D コマンドバッファのサイズを取得します。
212     //!
213     //!         再利用するために保存されたコマンドリストの 3D コマンドバッファのサイズを
214     //!         バイト単位で取得します。
215     //!
216     //!         現在バインドされているコマンドリストの 3D コマンドバッファのサイズを求めるときは
217     //!         GetCommandBufferSize を使用してください。
218     //!
219     //!         また、StartCommandSave と EndCommandSave の間で再利用するコマンドのサイズを取得するときは、
220     //!         GetCommandBufferSize を使用してください。StartCommandSave で再利用するためのコマンドリストがバインドされるためです。
221     //!
222     //! @return 3D コマンドバッファのサイズをバイト単位で返します。
223     //!
224     //! @sa GetCommandBufferSize
225     //! @sa StartCommandSave
226     int GetReusableCommandBufferSize() const;
227 
228     //@}
229 
230     //----------------------------------------
231     //! @name コマンドの再利用
232     //@{
233 
234     //! @brief  再利用するコマンドの保存を開始します。
235     //!
236     //!         再利用するためのコマンドリストをバインドし、コマンドの保存を開始します。
237     //!         保存は EndSaving() が実行されるまで行われます。
238     //!         保存されたコマンドは ReuseCommand() で再利用することができます。
239     //!
240     //!         コマンドの再利用を有効にするためには Create() の引数である Description 構造体の
241     //!         メンバ reusableListBufferSize と reusableListRequestCount に正の値を設定します。
242     //!
243     //! @sa     EndCommandSave
244     //! @sa     ReuseCommand
245     void StartCommandSave();
246 
247     //! @brief  再利用するコマンドの保存を終了します。
248     //!
249     //!         コマンドの保存を終了し、コマンドリストをバインドしなおします。
250     //!
251     //! @sa     StartCommandSave
252     //! @sa     ReuseCommand
253     void EndCommandSave();
254 
255     //! @brief  保存されたコマンドを再利用します。
256     //!
257     //!         StartCommandSave() と EndCommandSave() により保存されたコマンドをバインドされているコマンドリストへ追加します。
258     //!         isCopyBuffer に true を指定した場合はコマンドがコピーされて追加されます。
259     //!         false を指定した場合は、3D コマンドバッファは保存されたコマンドを参照します。
260     //!         詳細は CTR-SDK の nngxUseSavedCmdlist 関数を参照してください。
261     //!
262     //! @param[in] isCopyBuffer バッファをコピーするかを指定します。
263     //!
264     //! @sa     StartCommandSave
265     //! @sa     EndCommandSave
266     void ReuseCommand(bool isCopyBuffer);
267 
268     //@}
269 
270 private:
271     CommandListSwapper(os::IAllocator* allocator, Description& description);
272 
~CommandListSwapper()273     ~CommandListSwapper() {}
274 
275     //! @brief  GPU プロファイルエントリの実行時間を計算します。
276     void CalcGpuProfilingCostTime();
277 
278     //! @brief  コマンドリストの実行時間を計測するためにシステムチックを記録します。
279     void SetGpuProfilingTick(GLint id);
280 
281     //! @brief  登録されるコールバック関数です。
282     static void CommandListCallback(GLint id);
283 
284     //! @brief  コールバックを登録します。
285     //!
286     //! @return コールバックが登録されたコマンドリクエストの番号を返します。
287     GLuint RegisterCallback();
288 
289     //! @brief  コマンドリスト実行完了待ちがタイムアウトした際に呼び出されるコールバック関数です。
290     static void TimeoutWaitCommandListDone();
291 
292     //! @brief  コマンドリストのパラメータをログに出力します。
293     void DumpCommandListParameter();
294 
295     struct GpuProfilingEntry {
296         GLuint beginId;
297         GLuint endId;
298 
299         s64 beginTick;
300         s64 endTick;
301 
302         f32 costTime;
303 
304         bool isInTotal;
305 
GpuProfilingEntryGpuProfilingEntry306         GpuProfilingEntry()
307         : beginId(0),
308           endId(0),
309           beginTick(0),
310           endTick(0),
311           costTime(0.0f),
312           isInTotal(false)
313         {}
314     };
315 
316     os::IAllocator* m_Allocator;
317     typedef ut::MoveArray<GLuint> CommandListArray;
318     CommandListArray m_CommandLists;
319     int m_BoundIndex;
320 
321     int m_RunningIndex;
322     bool m_IsRunning;
323 
324     typedef ut::MoveArray<GpuProfilingEntry> GpuProfilingEntryArray;
325     GpuProfilingEntryArray m_GpuProfilingEntries;
326     GpuProfilingEntryArray m_GpuProfilingResults;
327 
328     CommandListArray m_ReusableCommandLists;
329     GLuint m_ReusableBufferOffset;
330     GLsizei m_ReusableBufferSize;
331     GLuint m_ReusableRequestId;
332     GLsizei m_ReusableRequestSize;
333 
334     u8* m_DumpCommandListBuffer;
335     static const s64 COMMAND_LIST_WAIT_TIME_OUT;
336 
337     static CommandListSwapper*   s_CommandListSwapper;
338 };
339 
340 } // namespace demo
341 } // namespace nw
342 
343 #endif // NW_DEMO_COMMANDLISTSWAPPER_H_
344