1 /*---------------------------------------------------------------------------*
2 Project: NintendoWare
3 File : demo_CommandListSwapper.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: 23208 $
14 *---------------------------------------------------------------------------*/
15
16 #include <nw/demo/demo_CommandListSwapper.h>
17 #include <nw/demo/demo_DebugUtility.h>
18
19 #include <nw/os/os_Memory.h>
20 #include <nn/os/os_Tick.h>
21
22 namespace nw
23 {
24 namespace demo
25 {
26
27 CommandListSwapper* CommandListSwapper::s_CommandListSwapper = NULL;
28
29 //----------------------------------------
30 CommandListSwapper*
Create(os::IAllocator * allocator,CommandListSwapper::Description & description)31 CommandListSwapper::Create(
32 os::IAllocator* allocator,
33 CommandListSwapper::Description& description)
34 {
35 void* memory = allocator->Alloc(sizeof(CommandListSwapper));
36
37 NW_NULL_ASSERT(memory);
38
39 CommandListSwapper* swapper = new(memory) CommandListSwapper(allocator, description);
40
41 return swapper;
42 }
43
44 //----------------------------------------
CommandListSwapper(os::IAllocator * allocator,CommandListSwapper::Description & description)45 CommandListSwapper::CommandListSwapper(
46 os::IAllocator* allocator,
47 CommandListSwapper::Description& description)
48 : m_Allocator(allocator),
49 m_CommandLists(description.commandListCount, allocator),
50 m_BoundIndex(0),
51 m_RunningIndex(0),
52 m_IsRunning(false),
53 m_GpuProfilingEntries(description.maxGpuProfilingEntryCount, allocator),
54 m_GpuProfilingResults(description.maxGpuProfilingEntryCount, allocator),
55 m_ReusableCommandLists(),
56 m_ReusableBufferOffset(0),
57 m_ReusableBufferSize(0),
58 m_ReusableRequestId(0),
59 m_ReusableRequestSize(0)
60 {
61 m_CommandLists.resize(description.commandListCount);
62 CommandListArray::iterator listEnd = m_CommandLists.end();
63 for (CommandListArray::iterator commandList = m_CommandLists.begin();
64 commandList != listEnd; ++commandList)
65 {
66 nngxGenCmdlists(1, &(*commandList));
67 nngxBindCmdlist(*commandList);
68 nngxCmdlistStorage(description.bufferSize, description.requestCount);
69 nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN);
70 nngxSetCmdlistCallback(CommandListSwapper::CommandListCallback);
71 }
72
73 if (description.reusableBufferSize > 0 && description.reusableRequestCount > 0)
74 {
75 m_ReusableCommandLists = CommandListArray(description.commandListCount, allocator),
76 m_ReusableCommandLists.resize(description.commandListCount);
77 CommandListArray::iterator cacheEnd = m_ReusableCommandLists.end();
78 for (CommandListArray::iterator commandList = m_ReusableCommandLists.begin();
79 commandList != cacheEnd; ++commandList)
80 {
81 nngxGenCmdlists(1, &(*commandList));
82 nngxBindCmdlist(*commandList);
83 nngxCmdlistStorage(description.reusableBufferSize, description.reusableRequestCount);
84 nngxSetCmdlistParameteri(NN_GX_CMDLIST_RUN_MODE, NN_GX_CMDLIST_SERIAL_RUN);
85 }
86 }
87 s_CommandListSwapper = this;
88 }
89
90 //----------------------------------------
91 void
Destroy()92 CommandListSwapper::Destroy()
93 {
94 os::IAllocator* allocator = this->m_Allocator;
95
96 void* memory = static_cast<void*>(this);
97 this->~CommandListSwapper();
98
99 allocator->Free(memory);
100 }
101
102 //----------------------------------------
103 void
Bind()104 CommandListSwapper::Bind()
105 {
106 nngxBindCmdlist(this->GetCommandListId());
107 }
108 //----------------------------------------
109 void
RunAsync()110 CommandListSwapper::RunAsync()
111 {
112 m_GpuProfilingEntries.swap( m_GpuProfilingResults );
113
114 m_RunningIndex = m_BoundIndex;
115 m_IsRunning = true;
116
117 if (! nw::demo::DebugUtility::IsCpuProfilingMode())
118 {
119 nngxRunCmdlist();
120 }
121 }
122
123 //----------------------------------------
124 void
Swap()125 CommandListSwapper::Swap()
126 {
127 ++this->m_BoundIndex;
128 if (this->m_CommandLists.size() <= this->m_BoundIndex)
129 {
130 this->m_BoundIndex = 0;
131 }
132 if (this->m_CommandLists.size() > 1)
133 {
134 ResetGpuProfiling();
135 }
136 }
137
138 //----------------------------------------
139 void
WaitDone()140 CommandListSwapper::WaitDone()
141 {
142 if (!m_IsRunning)
143 {
144 return;
145 }
146
147 nngxBindCmdlist(m_CommandLists[m_RunningIndex]);
148 nngxSplitDrawCmdlist();
149 nngxWaitCmdlistDone();
150 nngxStopCmdlist();
151 nngxClearCmdlist();
152 Bind();
153 m_IsRunning = false;
154
155 CalcGpuProfilingCostTime();
156 if (this->m_CommandLists.size() == 1)
157 {
158 ResetGpuProfiling();
159 }
160 }
161
162 //----------------------------------------
163 void
ResetGpuProfiling()164 CommandListSwapper::ResetGpuProfiling()
165 {
166 m_GpuProfilingEntries.clear();
167 }
168
169 //----------------------------------------
170 s32
AddGpuProfilingStartPoint(bool IsInTotal)171 CommandListSwapper::AddGpuProfilingStartPoint(bool IsInTotal)
172 {
173 if (!m_GpuProfilingEntries.push_back( GpuProfilingEntry() ))
174 {
175 return -1;
176 }
177
178 GpuProfilingEntry& gpuProfilingEntry = m_GpuProfilingEntries.back();
179
180 GLuint id = RegisterCallback();
181
182 gpuProfilingEntry.beginId = id;
183 gpuProfilingEntry.isInTotal = IsInTotal;
184
185 return m_GpuProfilingEntries.size() - 1;
186 }
187
188 //----------------------------------------
189 void
SetGpuProfilingEndPoint(u32 profilingId)190 CommandListSwapper::SetGpuProfilingEndPoint(u32 profilingId)
191 {
192 NW_ASSERT(profilingId < m_GpuProfilingEntries.size());
193
194 m_GpuProfilingEntries[profilingId].endId = RegisterCallback();
195 }
196
197 //----------------------------------------
198 GLuint
RegisterCallback()199 CommandListSwapper::RegisterCallback()
200 {
201 GLint requestCount = 0;
202 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_REQCOUNT, &requestCount);
203 if (requestCount == 0)
204 {
205 // コマンドリクエストが無い場合はコマンドバッファを区切ることでコマンドリクエストを追加する。
206 nngxSplitDrawCmdlist();
207 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_REQCOUNT, &requestCount);
208 }
209 nngxEnableCmdlistCallback( requestCount );
210
211 return requestCount;
212 }
213
214
215 //----------------------------------------
216 void
CalcGpuProfilingCostTime()217 CommandListSwapper::CalcGpuProfilingCostTime()
218 {
219 GpuProfilingEntryArray::iterator end = m_GpuProfilingResults.end();
220 for (GpuProfilingEntryArray::iterator gpuProfilingEntry = m_GpuProfilingResults.begin();
221 gpuProfilingEntry != end; ++gpuProfilingEntry)
222 {
223 const s64 span =
224 nn::os::Tick(gpuProfilingEntry->endTick - gpuProfilingEntry->beginTick)
225 .ToTimeSpan()
226 .GetMicroSeconds();
227
228 gpuProfilingEntry->costTime = static_cast<float>(span) / 1000.0f;
229 }
230 }
231
232 //----------------------------------------
233 f32
GetGpuProfilingCostTime(u32 profilingId)234 CommandListSwapper::GetGpuProfilingCostTime(u32 profilingId)
235 {
236 if (profilingId < m_GpuProfilingResults.size())
237 {
238 return m_GpuProfilingResults[profilingId].costTime;
239 }
240 else
241 {
242 return 0.0f;
243 }
244 }
245
246 //----------------------------------------
247 f32
GetGpuProfilingTotalCostTime()248 CommandListSwapper::GetGpuProfilingTotalCostTime()
249 {
250 f32 total = 0.0f;
251
252 GpuProfilingEntryArray::iterator end = m_GpuProfilingResults.end();
253 for (GpuProfilingEntryArray::iterator gpuProfilingEntry = m_GpuProfilingResults.begin();
254 gpuProfilingEntry != end; ++gpuProfilingEntry)
255 {
256 if (gpuProfilingEntry->isInTotal)
257 {
258 total += gpuProfilingEntry->costTime;
259 }
260 }
261
262 return total;
263 }
264
265 //----------------------------------------
266 void
SetGpuProfilingTick(GLint id)267 CommandListSwapper::SetGpuProfilingTick(GLint id)
268 {
269 s64 tick = static_cast<s64>(nn::os::Tick::GetSystemCurrent());
270
271 size_t size = m_GpuProfilingResults.size();
272
273 for (u32 i = 0 ; i < size ; ++i)
274 {
275 if (m_GpuProfilingResults[i].beginId == id)
276 {
277 m_GpuProfilingResults[i].beginTick = tick;
278 }
279 if (m_GpuProfilingResults[i].endId == id)
280 {
281 m_GpuProfilingResults[i].endTick = tick;
282 }
283 }
284 }
285
286 //----------------------------------------
287 void
CommandListCallback(GLint id)288 CommandListSwapper::CommandListCallback(GLint id)
289 {
290 if ( s_CommandListSwapper )
291 {
292 s_CommandListSwapper->SetGpuProfilingTick(id);
293 }
294 }
295
296 //----------------------------------------
297 void
StartCommandSave()298 CommandListSwapper::StartCommandSave()
299 {
300 NW_ASSERT( !m_ReusableCommandLists.empty() );
301
302 nngxBindCmdlist(m_ReusableCommandLists[m_BoundIndex]);
303 nngxClearCmdlist();
304 nngxStartCmdlistSave();
305 NW_GL_ASSERT();
306 }
307
308 //----------------------------------------
309 void
EndCommandSave()310 CommandListSwapper::EndCommandSave()
311 {
312 NW_ASSERT( !m_ReusableCommandLists.empty() );
313
314 nngxSplitDrawCmdlist();
315 NW_GL_ASSERT();
316
317 nngxStopCmdlistSave(
318 &m_ReusableBufferOffset,
319 &m_ReusableBufferSize,
320 &m_ReusableRequestId,
321 &m_ReusableRequestSize);
322 NW_GL_ASSERT();
323
324 Bind();
325 }
326
327 //----------------------------------------
328 void
ReuseCommand(bool isCopyBuffer)329 CommandListSwapper::ReuseCommand(bool isCopyBuffer)
330 {
331 NW_ASSERT( !m_ReusableCommandLists.empty() );
332
333 nngxUseSavedCmdlist(
334 m_ReusableCommandLists[m_BoundIndex],
335 m_ReusableBufferOffset,
336 m_ReusableBufferSize,
337 m_ReusableRequestId,
338 m_ReusableRequestSize,
339 0,
340 isCopyBuffer ? GL_TRUE : GL_FALSE);
341 NW_GL_ASSERT();
342 }
343
344 //----------------------------------------
345 int
GetCommandBufferSize() const346 CommandListSwapper::GetCommandBufferSize() const
347 {
348 GLint bufferSize;
349
350 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, &bufferSize);
351 NW_GL_ASSERT();
352
353 return static_cast<int>(bufferSize);
354 }
355
356 //----------------------------------------
357 int
GetReusableCommandBufferSize() const358 CommandListSwapper::GetReusableCommandBufferSize() const
359 {
360 GLint bufferSize;
361 GLint boundId;
362
363 nngxGetCmdlistParameteri(NN_GX_CMDLIST_BINDING, &boundId);
364
365 nngxBindCmdlist(m_ReusableCommandLists[m_BoundIndex]);
366
367 nngxGetCmdlistParameteri(NN_GX_CMDLIST_USED_BUFSIZE, &bufferSize);
368
369 nngxBindCmdlist(boundId);
370
371 NW_GL_ASSERT();
372
373 return static_cast<int>(bufferSize);
374 }
375
376
377
378
379 } // demo
380 } // nw
381
382
383