6. パケットレコーディング

パケットレコーディング機能を用いると、ひとまとまりのコマンドパケットを記録しておき、あとで再生するような使い方が可能です。この機能は、カメラやライトの設定を除いた大部分が同じシーンを 2 回描画する立体視表示のように、繰り返し同じ描画を行う処理で有効に活用することができます。

パケットレコーディング機能は以下の関数を用いて制御します。

コード 6-1. パケットレコーディング機能の制御に使用する関数
nn::gd::System::StartRecordingPackets(
        u32* forceDirtyModuleFlag,
        nn::gd::RecordingPacketUsage usage = RECORD_COMMAND_LIST_COPY);
nn::gd::System::StopRecordingPackets(nn::gd::RecordedPacketId** packetId);
nn::gd::System::ReplayPackets(nn::gd::RecordedPacketId* packetId,
        u32* forceDirtyModuleFlag);
nn::gd::System::ReleasePackets(nn::gd::RecordedPacketId* packetId);

3D コマンドバッファに出力される 3D コマンドと、リクエストバッファに出力されるコマンドリクエスト(「7.1. nngx 関数の内部使用」を参照)の両方が記録対象となります。

不要になったコマンドパケットは nn::gd::System::ReleasePackets() で解放することができます。

出力される 3D コマンドへの内部状態の影響

GD ライブラリの内部状態によっては呼び出された関数が必ずしも 3D コマンドを出力するとは限らず、コマンドパケットの記録時に期待した通りの挙動にならないことがあります。再生時でも同じように、GPU の状態と GD ライブラリの内部状態が食い違ってしまうことがあります。この問題を回避するため、nn::gd::System::StartRecordingPackets()nn::gd::System::ReplayRecordingPackets() はそれぞれフラグを引数として与えるようになっており、関数を実行する前にどのモジュールを「dirty」として扱うべきかを指示することができます。

最も安全なフラグの設定は MODULE_ALL を指定して、すべてのモジュールを「dirty」として扱うことです。この指定ではすべての 3D コマンドが出力され、状態が破壊されることは絶対にありません。もし、どのモジュールの状態が記録/再生の対象になっているか、状態が衝突するかどうかについて利用する側で分かっていれば、それに合わせて必要最小限のモジュールのみを「dirty」に設定することで性能を改善することができます。

コマンドパケットの編集

記録されたコマンドパケットを再生前に編集することができます。3D コマンドバッファの更新位置は、パケットの記録中に(nn::gd::System::StartRecordingPackets() を呼び出して nn::gd::System::StopRecordingPackets() を呼び出すまでの間に)nn::gd::System::GetCommandBufferOffset() で取得した 3D コマンドバッファの出力先のオフセット値と、記録完了後に nn::gd::System::GetCommandBufferBaseAddress() で取得する 3D コマンドバッファのベースアドレスを組み合わせて算出します。ただし、3D コマンドの書き換えに実際に使用することができるのは、呼び出しと同時に 3D コマンドを 3D コマンドバッファに出力するイミディエート関数だけです。

引数 usage による 3D コマンドバッファのコピー指定

nn::gd::System::StartRecordingPackets()usageRECORD_COMMAND_LIST_COPY を指定したときは、引数が追加される以前と同様に、3D コマンドバッファのコピーを作成します。そのため、記録されたコマンドパケットの 3D コマンドを書き換えることができます。

一方、usageRECORD_COMMAND_LIST_NO_COPY を指定したときは、3D コマンドバッファのコピーが作成されないため、処理時間が短くなりますが 3D コマンドを書き換えることができません。また、コピー元の 3D コマンドバッファをクリアすると、コマンドパケットの実行ができなくなります。

usage RECORD_3D_COMMAND_BUFFER_FOR_JUMP を指定してパケットの記録を開始した場合、nn::gd::System::ReplyPackets() は 3D コマンドバッファのコピーを作成し、nngxAddSubroutineCommand() によるジャンプコマンドの挿入とジャンプによる実行を行います。