1<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"[]>
2<html xml:lang="en-US" lang="en-US" xmlns="http://www.w3.org/1999/xhtml">
3  <head>
4    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
5    <meta http-equiv="Content-Style-Type" content="text/css" />
6    <link rel="stylesheet" href="../css/manpage.css" type="text/css" />
7    <style type="text/css">
8      <!--
9      span.static_style
10      {
11        font-size			: 8pt;
12        color				: white;
13        font-weight			: bold;
14        background			: #44f;
15        border-left			: solid 1px #aaf;
16        border-top			: solid 1px #aaf;
17        border-right		: solid 1px #00c;
18        border-bottom		: solid 1px #00c;
19        padding-left		: 2px;
20        padding-right		: 2px;
21      }
22      span.virtual_style
23      {
24        font-size			 : 8pt;
25        color				 : white;
26        font-weight			: bold;
27        background			: #0a0;
28        border-left			: solid 1px #0f0;
29        border-top			: solid 1px #0f0;
30        border-right		: solid 1px #060;
31        border-bottom		: solid 1px #060;
32        padding-left		: 2px;
33        padding-right		: 2px;
34      }
35      span.protected_style
36      {
37        font-size			 : 8pt;
38        color				 : white;
39        font-weight			: bold;
40        background			: #444;
41        border-left			: solid 1px #ccc;
42        border-top			: solid 1px #ccc;
43        border-right		: solid 1px #222;
44        border-bottom		: solid 1px #222;
45        padding-left		: 2px;
46        padding-right		: 2px;
47      }
48      table.table, table.table td, table.table th
49      {
50        border-collapse: collapse;
51        background-color: white;
52      }
53      table.table
54      {
55        width: auto;
56        margin: 1em;
57        position	: static;
58        font-family	: Arial;
59      }
60      table.table td, table.table th
61      {
62        padding: 0.2em;
63      }
64      table.table td.number, table.table th.number
65      {
66        text-align: right;
67      }
68      table.table tbody tr th
69      {
70        text-align: left;
71        font-weight: normal;
72        width: auto;
73      }
74      table.table thead tr th,
75      table.table tbody tr th.category
76      {
77        padding: 0 0.2em;
78      }
79      table.table caption
80      {
81        font-weight: bold;
82        padding: 0.4em;
83      }
84      table.table th
85      {
86        font-weight			: bold;
87        background			: #acf;
88      }
89        -->
90    </style>
91<title>Command-Buffer Jumps</title>
92  </head>
93  <body>
94<h1>Command-Buffer Jumps</h1>
95    <div class="section">
96      <p>
97        <ul>
98<li><a href="#about">Overview</a></li>
99<li><a href="#feature">Features of Command-Buffer Jumps</a></li>
100            <ul>
101<li><a href="#feature_merit">Benefits</a></li>
102<li><a href="#feature_notice">Drawbacks</a></li>
103            </ul>
104<li><a href="#api">Functions That Support Command-Buffer Jumps</a></li>
105            <ul>
106<li><a href="#api_nngx">Only the <CODE>nngx</CODE> API</a></li>
107<li><a href="#api_gr">GR Library and <CODE>nngx</CODE> API</a></li>
108<li><a href="#api_gd">GD Library</a></li>
109<li><a href="#api_direct">Directly Generating 3D Commands</a></li>
110            </ul>
111<li><a href="#complement">Comments</a></li>
112            <ul>
113<li><a href="#comp_buflocation">Placement of Command Buffers</a></li>
114<li><a href="#comp_cpucacheflush">Flushing the CPU Cache When Inserting Split Commands (When Using  <CODE>nngx</CODE> API Functions)</a></li>
115<li><a href="#comp_cmdlist">Execution Status of the Command List</a></li>
116            </ul>
117<li><a href="#log">Revision History</a></li>
118        </ul>
119      </p>
120    </div>
121<h2><a name="about">Overview</a></h2>
122    <div class="section">
123      <p>
124You can use command buffer addresses and sizes and kick commands to make execution jump to command buffers at different addresses.
125      </p>
126      <p>
127The libraries provided by the SDK have API functions not only for normal, unidirectional command-buffer jumps, but also for jumping to command buffers in different locations in the form of subroutines that execute and then jump back to resume execution of subsequent commands in the original command buffer.
128      </p>
129    </div>
130    <!-- 概要 -->
131<h2><a name="feature">Features of Command-Buffer Jumps</a></h2>
132    <div class="section">
133      <p>
134There are both benefits and drawbacks to the use of command-buffer jumps, and these are both considered below.
135      </p>
136<h3><a name="feature_merit">Benefits</a></h3>
137      <div class="section">
138        <p>
139          <ul>
140<li>Enables the reuse of command buffers without adding and duplicating command requests, thereby reducing the load on the CPU.</li>
141<li>Destination commands can be referenced directly from the GPU without copying to the current command buffer, so you can optimize the size of buffer assigned to the command list.</li>
142          </ul>
143        </p>
144      </div>
145<h3><a name="feature_notice">Drawbacks</a></h3>
146      <div class="section">
147        <p>
148          <ul>
149<li>The application must not only create the destination command buffers but also place them and perform all other related tasks.</li>
150<li>When you execute a lot of jumping it becomes difficult to track the causes of rendering-related bugs.</li>
151<li>The jumping process itself places a higher load on the GPU, so heavy use of command-buffer jumps can have an overall negative effect.</li>
152          </ul>
153        </p>
154      </div>
155    </div>
156    <!-- コマンドバッファジャンプの特徴 -->
157<h2><a name="api">Functions That Support Command-Buffer Jumps</a></h2>
158    <div class="section">
159<h3><a name="api_nngx">Only the <CODE>nngx</CODE> API</a></h3>
160      <div class="section">
161      <p>
162There is the <CODE><a href="../nn_gx/nngxAddJumpCommand.html">nngxAddJumpCommand</a></CODE> function for unidirectional jumps, and the <CODE><a href="../nn_gx/nngxAddSubroutineCommand.html">nngxAddSubroutineCommand</a></CODE> function for performing command-buffer jumps as subroutines.
163      </p>
164      <p>
165The <CODE>nngx</CODE> API functions operate internally and automatically to adjust the byte alignment and size.<br />The subroutine made for the command-buffer jump must add a Channel 1 kick command to the end of the command buffer. (For this, you can use the <CODE>nn::gr::MakeChannelKickCommand</CODE> function, which is described later.)
166      </p>
167      <p>
168If you are going to add 3D rendering command requests (to add split commands) including a jump, use the following functions:
169          <ul>
170<li><CODE><a href="../nn_gx/nngxFlush3DCommand.html">nngxFlush3DCommand</a></CODE> function.  (The <CODE><a href="../nn_gx/nngxSplitDrawCmdlist.html">nngxSplitDrawCmdlist</a> </CODE> function is also fine, but not recommended.)</li>
171<li><CODE><a href="../nn_gx/nngxFlush3DCommandNoCacheFlush.html">nngxFlush3DCommandNoCacheFlush</a></CODE> function.</li>
172          </ul>
173If using this later function, you need to explicitly flush the CPU cache for the command buffer.<br /><font color="red">The <a href="../nn_gx/nngxFlush3DCommandPartially.html">nngxFlush3DCommandPartially</a> function does not perform this flush internally.</font>
174      </p>
175      </div>
176<h3><a name="api_gr">GR Library and <CODE>nngx</CODE> API</a></h3>
177      <div class="section">
178      <p>
179For unidirectional jumps there is the <CODE><a href="../nn/gr/CTR/MakeChannel0JumpCommand.html">nn::gr::MakeChannel0JumpCommand</a></CODE> function and the <CODE> <a href="../nn/gr/CTR/MakeChannel1JumpCommand.html">nn::gr::MakeChannel1JumpCommand</a></CODE> function.  For subroutines, there is the <CODE><a href="../nn/gr/CTR/MakeChannel0SubroutineCommand.html">nn::gr::MakeChannel0SubroutineCommand</a></CODE> function and the <CODE><a href="../nn/gr/CTR/MakeChannel1SubroutineCommand.html">nn::gr::MakeChannel1SubroutineCommand</a></CODE> function.<br />In addition, the <CODE><a href="../nn/gr/CTR/MakeChannelKickCommand.html">nn::gr::MakeChannelKickCommand</a></CODE> function is supported for adding the kick command itself.
180      </p>
181      <p>
182The GR library does not take the command buffer size and alignment into consideration when adding jump-related commands.<br />You must make adjustments based on the size of commands added by the API functions.<br />Alternatively, you can select the channels to use and the commands to add. Also, the <a href="../nn/gr/CTR/CommandBufferJumpHelper/Overview.html"><CODE>nn::gr::CommandBufferJumpHelper</CODE></a> class helps you to adjust command sizes and create kick commands, but does not allow you to select channels.
183      </p>
184      <p>
185          <table>
186            <tr>
187<th>API</th>
188<th>Size (in Bytes) of the Added Command</th>
189            </tr>
190            <tr>
191<td><a href="../nn/gr/CTR/MakeChannelKickCommand.html"><CODE>MakeChannelKickCommand</CODE></a></td>
192              <td>8</td>
193            </tr>
194            <tr>
195<td><a href="../nn/gr/CTR/MakeChannel0SubroutineCommand.html"><CODE>MakeChannel0SubroutineCommand</CODE></a></td>
196              <td>24</td>
197            </tr>
198            <tr>
199<td><a href="../nn/gr/CTR/MakeChannel1SubroutineCommand.html"><CODE>MakeChannel1SubroutineCommand</CODE></a></td>
200              <td>32</td>
201            </tr>
202            <tr>
203<td><a href="../nn/gr/CTR/MakeChannel0JumpCommand.html"><CODE>MakeChannel0JumpCommand</CODE></a></td>
204              <td>24</td>
205            </tr>
206            <tr>
207<td><a href="../nn/gr/CTR/MakeChannel1JumpCommand.html"><CODE>MakeChannel1JumpCommand</CODE></a></td>
208              <td>24</td>
209            </tr>
210          </table>
211      </p>
212      <p>
213To add a split command you must use the <CODE><a href="../nn_gx/nngxFlush3DCommandPartially.html">nngxFlush3DCommandPartially</a></CODE> function.<br />For the argument, specify the size from the start of the command buffer to the (first) kick command.<br />If you are using the GR library, you must explicitly flush the CPU cache for the command buffer.<br /><font color="red">The <a href="../nn_gx/nngxFlush3DCommandPartially.html">nngxFlush3DCommandPartially</a> function does not perform this flush internally.</font>
214      </p>
215      </div>
216<h3><a name="api_gd">GD Library</a></h3>
217      <div class="section">
218      <p>
219If you use the GD library, you do not need to make direct calls to the <CODE>nngx</CODE> functions for command-buffer jumping. The library acts internally to call the necessary functions.
220      </p>
221      <p>
222Specify <CODE>RECORD_3D_COMMAND_BUFFER_FOR_JUMP</CODE> for the <SPAN class="argument">usage</SPAN> parameter of the <CODE><a href="../nn/gd/CTR/System/StartRecordingPackets.html">nn::gd::System::StartRecordingPackets</a></CODE> function and create the 3D command buffer you want as a subroutine. After the necessary commands are created, call the <CODE><a href="../nn/gd/CTR/System/StopRecordingPackets.html">nn::gd::System::StopRecordingPackets</a></CODE> function. The jump command is added internally when you specify the saved <CODE>RecordedPacketId</CODE> to the <CODE><a href="../nn/gd/CTR/System/ReplayPackets.html">nn::gd::System::ReplayPackets</a></CODE> function.
223      </p>
224      </div>
225<h3><a name="api_direct">Directly Generating 3D Commands</a></h3>
226      <div class="section">
227      <p>
228You can also jump by directly creating commands to send to the GPU. Use registers 0x238 to 0x23d. For more information, see the documentation.
229      </p>
230      <p>
231However, there is really no benefit to creating your own commands, so we recommend normally using one of the other methods.
232      </p>
233      </div>
234    </div>
235    <!-- コマンドバッファジャンプをサポートする API -->
236<h2><a name="complement">Comments</a></h2>
237    <div class="section">
238      <p>
239The following supplemental information describes cautions to take when implementing command-buffer jumps, and ways to boost efficiency.
240      </p>
241<h3><a name="comp_buflocation">Placement of Command Buffers</a></h3>
242      <div class="section">
243      <p>
244Access to command buffers from the GPU is faster when the subroutines of commands are stored in VRAM rather than in main memory. If access to command buffers in main memory becomes a bottleneck, you can expect an overall boost in processing speed by saving to VRAM.
245      </p>
246      <p>
247To place commands in VRAM, use the <CODE><a href="../nn_gx/nngxAddVramDmaCommand.html">nngxAddVramDmaCommand</a></CODE> function or the <CODE><a href="../nn_gx/nngxAddVramDmaCommandNoCacheFlush.html">nngxAddVramDmaCommandNoCacheFlush</a></CODE> function.
248      </p>
249      </div>
250<h3><a name="comp_cpucacheflush">Flushing the CPU Cache When Inserting Split Commands (When Using  <CODE>nngx</CODE> API Functions)</a></h3>
251      <div class="section">
252      <p>
253If you implement a subroutine using the <CODE>nngx</CODE> API functions, calling the <CODE>nngxFlush3DCommand</CODE> function when adding a split command increases the load on the CPU because the CPU cache is flushed each time it is called.
254      </p>
255      <p>
256For this reason, it is more efficient to keep the 3D rendering command requests together without splitting if they include a subroutine call.<br />If you need to have 3D rendering command requests containing multiple subroutines, what you can do is use the <CODE>nngxFlush3DCommandNoCacheFlush</CODE> function when adding the split command and then later call the <CODE><a href="../nn/gx/CTR/UpdateBuffer.html">nn::gx::UpdateBuffer</a></CODE> function for the entire required region so that all flush operations are done together.
257      </p>
258      </div>
259<h3><a name="comp_cmdlist">Execution Status of the Command List</a></h3>
260      <div class="section">
261      <p>
262If there are no unexecuted command requests in the command list called by the <CODE><a href="../nn_gx/nngxRunCmdlist.html">nngxRunCmdlist</a></CODE> function, that command list enters the &quot;waiting to run&quot; state.<br />In this state, if a new command request is added to the list, that request begins to run. During command request processing, the command list is in the &quot;running&quot; state.
263      </p>
264      <p>
265When the command list is in the running state, some <CODE>nngx</CODE> API functions generate an error and interrupt the processing.<br />You must be particularly careful with the previously-mentioned <CODE><a href="../nn_gx/nngxFlush3DCommandPartially.html">nngxFlush3DCommandPartially</a></CODE> function.
266      </p>
267      <p>
268For implementations similar to the following example, depending on the timing, the intended commands may not be generated and the GPU may hang.
269      </p>
270<h4>Example of a bad implementation (using one command list)</h4>
271        <div class="section">
272        <p>
273<pre>
274// Bad implementation.
275// One command list is used while it remains in the &quot;waiting to run&quot; state.
276
277Draw()
278{
279    // Add a command request to clear the render buffer. ... (A)
280    nngxAddMemoryFillCommand(...);
281
282    // Create some rendering command. (Assume that the GR library is internally applying the jump.)
283    DrawObjects();
284    // Add a split command. (Add a 3D rendering command request.)... (B)
285    nngxFlush3DCommandPartially(buffersize);
286    // Flush the CPU cache for the command buffer.
287    nngxUpdateBuffer(...);
288
289    // Add a command request to transfer data to the display buffer. ... (C)
290    nngxTransferRenderImage(...);
291
292    // Wait for execution to complete.
293    nngxWaitCmdlistDone();
294    // Swap buffers.
295    Swap();
296    // Clear the command list.
297    nngxClearCmdlist();
298}
299</pre>
300If the command list is in the &quot;waiting to run&quot; state, it transitions to the &quot;running&quot; state when the command list is added (A). <br />If (B) takes place before command request (A) completes, the <CODE><a href="../nn_gx/nngxFlush3DCommandPartially.html">nngxFlush3DCommandPartially</a></CODE> function generates the error GL_ERROR_80AD_DMP.<br />The split command is not generated when the error occurs in (B), but when the <CODE><a href="../nn_gx/nngxTransferRenderImage.html">nngxTransferRenderImage</a></CODE> function is called in (C), a split command is added if there is any unprocessed command buffer, and a 3D rendering command request created.<br />Because the execution size is not the size that was intended from the settings (the size from the start to the first kick command), the correct render result is not obtained and, in some cases, the GPU may hang.
301        </p>
302        <p>
303There are several possible workarounds.
304        <ul>
305<li>Duplicate the command list.</li>
306<li>Immediately before step (B), add the <CODE><a href="../nn_gx/nngxWaitCmdlistDone.html">nngxWaitCmdlistDone</a></CODE> function to wait for the command list to finish running.</li>
307        </ul>
308        </p>
309        </div>
310      </div>
311    </div>
312    <!-- 補足 -->
313<h2><a name="log">Revision History</a></h2>
314    <div class="section">
315      <dl class="history">
316        <dt>2012/06/26</dt>
317<dd>Added a note about the <CODE>nn::gr::CommandBufferJumpHelper</CODE> class.<br /></dd>
318        <dt>2012/02/17</dt>
319<dd>Added a table of contents and information about the GD library.<br /></dd>
320        <dt>2012/02/08</dt>
321<dd>Initial version.<br /></dd>
322      </dl>
323    </div>
324  <hr><p>CONFIDENTIAL</p></body>
325</html>
326