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