comparison paper/chapter2.tex @ 1:5dbcea03717e draft

fix
author Yutaka_Kinjyo <yutaka@cr.ie.u-ryukyu.ac.jp>
date Tue, 07 Feb 2012 17:38:59 +0900
parents 6d80c2c895e4
children 6cf0f731cbde
comparison
equal deleted inserted replaced
0:6d80c2c895e4 1:5dbcea03717e
1 \chapter{議論} 1 \chapter{Cerium} \label{chapter:cerium}
2 2 Cerium \cite{gongo} は Cell 用の Fine-Grain Task Manager として同研究室の宮國が実装した。
3 \section{はじめに} 3 本章ではその実装について説明する
4 はじめに 4
5 \section{Cerium の概要}
6
7 Cerium は、我々が提案したフレームワークで、TaskManager (\ref{sec:cerium_taskmanager}),
8 SceneGraph (\ref{sec:cerium_scenegraph}) と Rendering Engine (\ref{sec:cerium_renderingengine}) の
9 3つの要素から構成されており、PS3, Mac OS X, Linux 上でゲームフレームワークとして動作する。ゲーム中の
10 オブジェクトの振る舞いやルールは SceneGraph で管理し、それらの動きや Rendering の処理を動的に SPE に
11 割り振るカーネルとして、TaskManager が用いられる。PS3 の Graphics Engine の仕様は公開されておらず、
12 Cerium は独自の Rendering Engine を有している。
13
14 \section{Cerium TaskManager} \label{sec:cerium_taskmanager}
15
16 Task Manager は、 Task と呼ばれる、分割された各プログラムを管理する。 Task の単位は
17 サブルーチンまたは関数として、 Task 同士の依存関係を考慮しながら実行していく。
18 先行研究において実装されていた TaskManager の API を \tabref{old_taskmanager_api} に示す。
19 \begin{table}[htb]
20 \caption{旧Task Manager API} \label{tab:old_taskmanager_api}
21 \hbox to\hsize{\hfil
22 \begin{tabular}{|c|l|} \hline
23 create\_task & Task を生成する \\ \hline
24 run & 実行 Task Queue の実行 \\ \hline
25 allocate & 環境のアライメントを考慮した allocator \\ \hline
26 set\_inData & Task への入力データのアドレスを追加 \\ \hline
27 set\_outData & Task からのデータ出力先アドレスを追加 \\ \hline
28 set\_param & Task のパラメータ (32 bits) \\ \hline
29 wait\_for & Task の依存関係の考慮 \\\hline
30 set\_cpu & Task を実行する CPU の設定 \\ \hline
31 set\_post & Task が終了したら PPE 側で実行される関数の登録 \\ \hline
32 spawn & Task を実行 Task Queue に登録する \\ \hline
33 \end{tabular}\hfil}
34 \end{table}
35
36 \section{Cerium における Task} \label{sec:task_depandency}
37
38 Task は TaskManager を使って生成する。 Task を生成する際に、以下のような要素が設定可能
39 である。
40
41 \begin{enumerate}
42 \item input data
43 \item output data
44 \item parameter
45 \item cpu type
46 \item dependency
47 \end{enumerate}
48
49 input, output, data, parameter は関数でいうところの引数に価する。cpu type は Task が
50 PPE または SPE のどちらで実行されるかを示している。 dependency は他の Task との
51 依存関係を示している。依存関係の情報は PPE 側が持っており、 SPE, PPE の Task が終了
52 すると、Task の終了が通知され、その通知に従って PPE が依存関係を処理していく(例:
53 Task A の終了通知を受け、 PPE は Task B を実行可能状態にする)。Task の依存関係の
54 処理を図を用いて説明する。\\
55
56 Task B は Task A の終了を待っている。他の Task の終了を待っている Task は、Wait Queue に、
57 Task を待っていない Task は Active Queue に入れる。この時点で Task A が先頭にあるので
58 Task A が SPE に送られる(\figref{task-dependency1})。
59
60 \begin{figure}[htb]
61 \begin{center}
62 \includegraphics[scale=0.70]{./images/task-dependency1.pdf}
63 \end{center}
64 \caption{Task dependency 1}
65 \label{fig:task-dependency1}
66 \end{figure}
67
68 \newpage
69
70 そして、SPE に送られた Task A は SPE で処理が行われる(\figref{task-dependency2})。
71
72 \begin{figure}[htb]
73 \begin{center}
74 \includegraphics[scale=0.68]{./images/task-dependency2.pdf}
75 \end{center}
76 \caption{Task dependency 2}
77 \label{fig:task-dependency2}
78 \end{figure}
79
80 Task A の処理が終了すると mail で Task B へ通知される。Task B はその通知を受け取ると
81 待ち状態が解除される(\figref{task-dependency3})。
82
83 \begin{figure}[htb]
84 \begin{center}
85 \includegraphics[scale=0.68]{./images/task-dependency3.pdf}
86 \end{center}
87 \caption{Task dependency 3}
88 \label{fig:task-dependency3}
89 \end{figure}
90
91 待ち状態が解除された Task B は、Active Queue に追加され、
92 この図(\figref{task-dependency4})では、Task C 終了後に
93 SPE に送られ処理が行われる。
94
95 \begin{figure}[htb]
96 \begin{center}
97 \includegraphics[scale=0.68]{./images/task-dependency4.pdf}
98 \end{center}
99 \caption{Task dependency 4}
100 \label{fig:task-dependency4}
101 \end{figure}
102
103 \newpage
104
105 \section{Task のスケジューリング}
106
107 SPE は、Task を一つずつ受け取るのではなく、ある程度まとめて受け取る。それを TaskList
108 と呼んでいる。 TaskList は各 SPE 用に PPE側で生成される。(\figref{task_scheduler})
109 SPE は 受け取ったTaskList に沿って Task を実行していき、 Task 毎に実行完了の Mail を送る。
110 TaskList の Task をすべて実行すると、次の TaskList を要求する Mail を PPE 側に送る。
111
112 \begin{figure}[htb]
113 \begin{center}
114 \includegraphics[scale=0.61]{./images/scheduler.pdf}
115 \end{center}
116 \caption{Task scheduler}
117 \label{fig:task_scheduler}
118 \end{figure}
119
120
121 \section{Task の入出力} \label{sec:input_output}
122
123 Task の入出力の API として、set\_inData, set\_param , set\_oudData がある。
124 \begin{description}
125
126 \item[set\_inData(index, addr, size)] は、 データを受け取る buffer の配列番号とデータのアドレス、そのデータのサイズを
127 引数として入力する。このデータは DMA 転送されるため、addr は 16 byte alignment が取れており、size は 16 byte の
128 倍数である必要がある。
129
130 \item[set\_param(index, param)] は、データを受け取る buffer の配列番号と 32bit のデータを渡す。set\_inData で渡すには
131 小さいデータを送るのに適している。 param はアドレスとしてではなく、値を Task オブジェクトが直接持っているので、 DMA
132 転送は行わない。
133
134 \item[set\_outData(index, addr, size)] は、Task のデータの出力先を指定する。使用方法は set\_inData と同じで、alignment,
135 byte 数に気をつける必要がある。
136
137 \end{description}
138 \section{SceneGraph} \label{sec:cerium_scenegraph}
139
140 本研究では、ゲーム中の一つの場面 (Scene) を構成するオブジェクトやその振る舞い、ゲームのルールの集合を SceneGraph とする \cite{chiaki}。SceneGraph のノードは親子関係を持つ tree で構成される(\figref{scenegraph})。親子関係とは、親オブジェクトの
141 回転や平行移動などの行列計算による頂点座標の変更が、子オブジェクトにも反映する関係のことである。これは子に対して
142 スタックに積まれた親の変換行列を掛けることで実現できる。SceneGraph ノードは以下のようなデータと動作を持つ。
143
144 \begin{description}
145 \item[Vertex:] ポリゴンオブジェクトの頂点座標
146 \item[Texture:] ポリゴンオブジェクトのテクスチャ座標
147 \item[TextureImage:] テクスチャイメージ
148 \item[TransMatrix:] ポリゴンオブジェクトの変換行列
149 \item[Coordinates:] オブジェクトの座標
150 \item[Angle:] オブジェクトの角度
151 \item[Move:] 自律的なオブジェクトの動き
152 \item[Collision:] 他のノードと衝突したときの動き
153 \end{description}
154
155 \begin{figure}[htb]
156 \begin{center}
157 \includegraphics[scale=0.61]{./images/scenegraph.pdf}
158 \end{center}
159 \caption{SceneGraph}
160 \label{fig:scenegraph}
161 \end{figure}
162
163 \subsection{Scene ポリゴンの生成}
164
165 ゲーム中に登場するオブジェクトは、オープンソースの 3D モデリングツール
166 である Blender \cite{blender} を用いる。
167 Blender で記述したポリゴンオブジェクトを、座標やテクスチャイメージを
168 埋め込んだ xml ファイルとして出力する。
169 Blender にはPython インタプリタがあり、xml ファイルを生成する Python スクリプトを作成している。
170 xml には、オブジェクトの名前、ポリゴン情報、ポリゴンに対応するテクスチャ座標、
171 テクスチャイメージがある。
172
173 xml ファイル形式を採用している理由は、Cerium が MacOSX や PS3 Linux などの
174 複数の環境で動作することを目的としており、環境に依存しないテキスト形式での
175 データ構造を構築できるからである。また、Cerium は将来的にネットワークを
176 使用することを考えており、その際に有効なフォーマットであると考えたからである。\\
177
178 ネットワークを使用した例題として、Federated Linda \cite{akamine}
179 を用いた「水族館ゲーム」を赤嶺が作成した。
180
181 このゲームは、複数のクライアントのディスプレイを並べて使用する。各プレイヤーは1匹
182 ずつ魚のオブジェクトが与えられ、それを自由に操作することができる。また、魚は画面の
183 端まで移動すると、自分の画面上からは消え、接続している他のプレイヤーの画面の端
184 から出てくる。(\figref{aquarium}) このゲームは、初めに xml ファイルをすべての
185 プレイヤーが共有した状態で開始される。
186
187 \begin{figure}[htb]
188 \begin{center}
189 \includegraphics[scale=0.61]{./images/aquarium.pdf}
190 \end{center}
191 \caption{水族館ゲーム}
192 \label{fig:aquarium}
193 \end{figure}
194
195 \subsection{SceneGraph オブジェクトの生成} \label{sec:cerium_renderingengine}
196
197 Cerium は生成された xml ファイルから、そのパラメータを持つ SceneGraph オブジェクト
198 を生成する (Original SceneGraph)。ここで作られたオブジェクトはユーザには見せず、
199 ユーザが該当する SceneGraph を生成したい場合は Original を参照し、そのコピー
200 (Copy SceneGraph) を渡す。
201
202 Original SceneGraph の情報は Cerium が配列として持っており、xml ファイルを
203 読み込んで生成された SceneGraph を SceneGraph ID の位置に格納する。
204 SceneGraph ID は SceneGraph に割り当てられるグローバル ID である。配列に
205 格納する時点で登録された順に ID が割り当てられる。改良後では、同時に、 Scenegraph の
206 名前を key, ID を value として hash に登録しているので、ユーザは ID と
207 名前の両方から Scenegraph を生成することができる。
208
209
210 \section{RenderingEngine}
211 RenderingEngineは TaskManager から提供される Task から構成され、主に以下の3つの Task から成る。(\figref{rendering_flow})
212
213 \begin{description}
214 \item[CreatePolygonTask: ] SceneGraph での処理結果を元に、モデリングデータの座標変換を行う
215 \item[CreateSpanTask: ] 座標変換されたポリゴンを、水平な線(Span)に分割する
216 \item[DrawSpanTask: ] 分割された Span を実際に画面へと描画する。
217 \end{description}
218
219 \begin{figure}[htb]
220 \begin{center}
221 \includegraphics[scale=0.5]{./images/rendering3.pdf}
222 \end{center}
223 \caption{Rendering flow}
224 \label{fig:rendering_flow}
225 \end{figure}
226
227 これら Task の入出力のデータとして、PolygonPack, SpanPack がある。それぞれポリゴンの情報を格納する構造体、Spanの情報を格納する構造体である。Task と合わせてその構造体について説明していく。
228
229 \subsubsection{PolygonPack}
230
231 PolygonPack は、SceneGraph から抽出されたポリゴンの集合である。CreatePolygonTask で扱う構造体である。
232 以下に構造を示す。
233
234 \begin{verbatim}
235 // ポリゴンを構成する情報
236 typedef struct TrianglePack {
237 // テクスチャ情報
238 TriTexInfo tex_info;
239
240 // ポリゴンを構成する頂点の情報
241 VertexPack ver1, ver2, ver3;
242
243 // 法線ベクトルの情報
244 NormalPack normal1, normal2, normal3;
245
246 } TrianglePack, *TrianglePackPtr;
247
248 typedef struct PolygonPack {
249
250 TrianglePack tri[MAX_SIZE_TRIANGLE];
251
252 struct POLYGON_info {
253 int size;
254 int light_pos[3]; // 光源の位置
255 int light_rgb[3]; // 光源の色
256 }info;
257 PolygonPack* next;
258 } PolygonPack, *PolygonPackPtr;
259 \end{verbatim}
260
261 \begin{description}
262 \item[TriTexInfo] は、テクスチャイメージのアドレス、幅、高さ、
263 縮小率が格納されている
264
265 \item[VertexPack] は、ポリゴンの頂点座標と対応するテクスチャの座標が
266 格納されている
267
268 \item[NormalPack] は、ポリゴンの法線ベクトルの情報が格納されている
269
270 \newpage
271
272 \begin{figure}[htb]
273 \begin{center}
274 \includegraphics[scale=0.70]{./images/polygonpack.pdf}
275 \end{center}
276 \caption{PolygonPack(TrianglePack)}
277 \label{fig:polyonpack}
278 \end{figure}
279
280 \end{description}
281
282 PolygonPack は光源やテクスチャ、頂点の情報から構成される。
283 テクスチャの縮小率に関しては \ref{sec:cerium_scale} で詳しく説明する。
284
285 \subsubsection{SpanPack}
286
287 SpanPack は、ポリゴンから抽出された Span の集合である。CreateSpan で PolygonPack を元に SpanPack が生成される。以下に構造を示す。
288
289 \begin{verbatim}
290 class Span {
291 public:
292 // テクスチャ情報
293 uint32 *tex_addr;
294 int tex_width, tex_height;
295
296 // span の開始 x 座標、y 座標、長さ
297 int x, y, length_x;
298
299 // span の z 座標(開始、終了)
300 float start_z, end_z;
301
302 // span に対応するテクスチャの座標
303 float tex_x1, tex_x2, tex_y1, tex_y2;
304
305 // span の法線ベクトル
306 float normal_x, normal_y, normal_z;
307 };
308
309 class SpanPack {
310 public: /* fields */
311 struct SpanInfo {
312 int start;
313 int size;
314 int y_top;
315 int light_pos[3];
316 int light_rgb[3];
317 } info;
318 Span span[MAX_SIZE_SPAN];
319 SpanPack *next;
320 };
321 \end{verbatim}
322
323 Span は、その座標と対応するテクスチャの座標を持つ(\figref{cerium_span})
324
325 \begin{figure}[htb]
326 \begin{center}
327 \includegraphics[scale=0.80]{./images/spanpack.pdf}
328 \end{center}
329 \caption{Span の構造}
330 \label{fig:cerium_span}
331 \end{figure}
332
333 Rendering には SpanPack を用いる。
334 ここからは、SceneGraph から Rendering までの流れを それぞれの Task を用いて説明する。
335
336 \subsection{CreatePolygonTask} \label{createpolygonfromscenegraph}
337
338 SceneGraph の move や collision を行い、各オブジェクトの変換行列
339 を生成する。その後、SceneGraph が持つポリゴンの座標と法線ベクトルに
340 変換行列をかけ、得られた座標を PolygonPack に格納していく。
341 これまでは関数で書かれていたが、SPE に処理を割り振ることも視野に入れ、
342 Task で書いている。新しい Rendering のデータ構造で述べた法線ベクトルの
343 計算も追加している。以下がそのコードである。
344
345 \newpage
346
347 \begin{verbatim}
348
349 SceneGraphPtr sg_top = sg_draw_tree;
350
351 // ポリゴンの1辺
352 xyz1[0] = sg->coord_xyz[(i+0)*3];
353 xyz1[1] = sg->coord_xyz[(i+0)*3+1];
354 xyz1[2] = sg->coord_xyz[(i+0)*3+2]*-1.0f;
355 xyz1[3] = 1.0f;
356
357 /* xyz2, xyz3 は省略 */
358
359 // ポリゴンの1辺の法線ベクトル
360 normal1[0] = sg->normal[(i+0)*3];
361 normal1[1] = sg->normal[(i+0)*3+1];
362 normal1[2] = sg->normal[(i+0)*3+2]*-1.0f;
363
364 /* normal2, normal3 は省略 */
365
366 // sg->matrix = 回転行列*透視変換行列
367 ApplyMatrix(xyz1, sg->matrix);
368 ApplyMatrix(normal1, sg->real_matrix);
369
370 // PolygonPack の TrianglePack に計算した値とテクスチャの座標を格納する
371 PolygonPackPtr pp = new PolygonPack;
372 TrianglePack *triangle = &pp->tri[pp->info.size++];
373
374 triangle->ver1.x = xyz1[0];
375 triangle->ver1.y = xyz1[1];
376 triangle->ver1.z = xyz1[2];
377 triangle->ver1.tex_x = sg->coord_tex[(i+0)*3];
378 triangle->ver1.tex_y = sg->coord_tex[(i+0)*3+1];
379 triangle->normal1.x = normal1[0];
380 triangle->normal1.y = normal1[1];
381 triangle->normal1.z = normal1[2];
382
383 /* ver2, ver3, normal2. normal3 は省略 */
384
385 // テクスチャのアドレス、幅、高さ、縮小率を格納する
386 triangle->tex_info.addr = sg->texture_info.pixels;
387 triangle->tex_info.width = sg->texture_info.t_w;
388 triangle->tex_info.height = sg->texture_info.t_h;
389 triangle->tex_info.scale_max = sg->texture_info.scale_max;
390 \end{verbatim}
391
392 これらの処理を全ての Scenegraph に行い、PolygonPack を生成していく。
393
394 \subsection{CreateSpanTask} \label{createspan}
395
396 生成された PolygonPack に格納されているポリゴンから、Span を抽出していく。
397 Span は x 軸に平行な線分を表しているため、初めにポリゴンを水平に分割して
398 二つの三角形 (Triangle1, Triangle2) を作り、それぞれに対してSpan を求める
399 \cite{akira} (\figref{sep-polygon})。
400
401 \begin{figure}[htb]
402 \begin{center}
403 \includegraphics[scale=0.90]{./images/sep-polygon.pdf}
404 \end{center}
405 \caption{ポリゴンの分割と Span 生成}
406 \label{fig:sep-polygon}
407 \end{figure}
408
409 得られた Span を SpanPack に格納する場合、その SpanPack が持つ全ての Span の y 座標
410 が一定範囲内に入るようにする。
411
412 Rendering する場合、画面を複数の領域に分割し、それぞれを一つの Task で担当する。Cerium
413 では Rendering 時に Z Buffer を用いているため、同じ Task に違う領域の Span があると
414 正常に描画できない。そこで、一つの SpanPack には決まった y 座標を持った Span だけを
415 入れることにより、Rendering 時には独立して行うことができる。
416 y の範囲は 8 としている(\figref{spanpack-rendering})。
417
418 \newpage
419
420 \begin{figure}[htb]
421 \begin{center}
422 \includegraphics[scale=0.80]{./images/spanpack-rendering.pdf}
423 \end{center}
424 \caption{SpanPack の割り当て(height = 1080)}
425 \label{fig:spanpack-rendering}
426 \end{figure}
427
428 \subsection{Rendering するための準備}
429
430 画面に Rendering するためには、SpanPack の中の Span を辿り、対応する RGB 値をテクスチャイメージから取り出して
431 frame buffer に書きこむ必要がある。しかし、SPE のメモリ領域は 256KB しかないため、Span が参照している
432 テクスチャイメージ全てを SPE に送ることはできない。
433
434 そこで我々は、テクスチャイメージに対して分割、Tile管理、縮小という操作を行うことでこの問題
435 を解決した。
436
437 \subsection{Texture の分割} \label{separate_texture}
438
439 SPE のメモリ領域は 256KB しかないため、テクスチャイメージを全て転送すると動かなくなる可能性がある。
440 そこで、そこで、テクスチャをブロックに分割し、ブロックごとに転送することにした。そのブロックを Tile
441 と呼び、分割単位は 8 x 8 とする(\figref{cerium_tile})。Tile は \figref{cerium_tile}
442 の順番で配列に変換する。
443
444 \begin{figure}[htb]
445 \begin{center}
446 \includegraphics[scale=0.80]{./images/cerium_tile.pdf}
447 \end{center}
448 \caption{Texture の分割と Tile}
449 \label{fig:cerium_tile}
450 \end{figure}
451
452 Span が持つテクスチャのアドレスはこの配列を指しており、描画する Span 中の 1 pixel の座標から、
453 目的の Tile を計算する。その Tile をメインメモリから DMA で持ってきて RGB 値を取り出す。
454
455 \subsection{SPE 上での Tile 管理}
456
457 描画 Task が変わるたびに、新しい Tile を転送していては、DMA 転送のコストがかかりすぎる。そこで、
458 すでに SPE 上に転送してある Tile を保存しておく。そして、次に描画する Span が保存してある Tile
459 を参照する場合、新たに DMA 転送を行わずに保存してある Tile を使用する。新たに Tile を参照し且つ領域に
460 空きが無い場合、 FIFO で Tile の入れ替えを行う。Tile の検索は、テクスチャのアドレスを key とし、
461 Tile を value としてハッシュを用いる。
462 \begin{comment}
463 SPE 上で保存する Tile の数を変化させることによって、Rendering の実行速度がどのように変化するか
464 実験した(\figref{cerium_hash_test})。
465
466 \begin{table}[htb]
467 \begin{center}
468 \caption{SPE 上での Tile 管理数による実行速度比較} \label{tab:cerium_hash_test}
469 \hbox to\hsize{\hfil
470 \begin{tabular}{c|l} \hline \hline
471 Tile 保存数 & 実行速度 (FPS) & \\ \hline
472 \hline
473 1 & &\\ \hline
474 128 & &\\ \hline
475 \end{tabular}\hfil}
476 \end{center}
477 \end{table}
478
479 \figref{cerium_hash_test} より、SPE 上で保存する Tile の数を増やすことによりテクスチャ
480 のヒット率が上昇し、DMA 転送回数が減ることで実行速度が向上するがわかる。
481
482 \end{comment}
483
484 \subsection{Texture の縮小} \label{sec:cerium_scale}
485
486 遠くにあるオブジェクトは小さく描画される。この場合、使用されるテクスチャは原寸大である
487 必要がない。そこで、オリジナルのテクスチャの他に縮小したテクスチャを用意し、描画される
488 オブジェクトの大きさによって、使用するテクスチャを変更する。
489
490 テクスチャは Tile に分割しなければならないため、縦横ともに 8 の倍数を保つようにする。
491 これまでは、テクスチャの縦横どちらかのサイズが最小 (8ドット) になったとき、縮小画像生成を終了
492 していたが、テクスチャのサイズが縦横で違う場合、長い方に合わせて空のデータを埋め込み 8 の倍数
493 の正方形にするように改良した。この改良によってテクスチャの最大縮小率を正確に求めることが出来るよう
494 になったこの制約を守りながら 2 分の 1 ずつ縮小させたときの最大縮小率を求める。縮小したテクスチャ
495 毎に Tile で分割し、すべての縮小率で求めた Tile を繋げて Tile Array とする(\figref{tapestry})。
496
497 \begin{figure}[htb]
498 \begin{center}
499 \includegraphics[scale=0.80]{./images/tapestry.pdf}
500 \end{center}
501 \caption{Tapestry の生成}
502 \label{fig:tapestry}
503 \end{figure}
504
505 縮小したテクスチャを Tapestry と呼ぶ。 SceneGraph や PolygonPack の時点では
506 テクスチャイメージとして Tile Array の先頭アドレスを持っている。CreateSpan の中で
507 使用する Span の長さに適した scale を求め、その scale にあった Tapestry を span 生成
508 ためのテクスチャとする。
509
510 \ref{separate_texture} でも話したとおり、テクスチャを全て SPE 内に送ることはできない。
511 Tile 単位で分割し、更にハッシュを用いて SPE 内にキャッシュすることによって無駄な転送
512 コストを減少させた。さらに Scale によって 描画に用いる Tapestry を変更することで、
513 1テクスチャの Tile の数を減少させることができる。必要 Tile のヒット率が上昇し、結果
514 転送コストの削減に繋がる。
515
516 この Texture hash の効果を示す。(\tabref{ball_bound})例題として、ball bound を使用した。
517
518 \begin{table}[!htb]
519 \begin{center}
520 \caption{キャッシュの効果(ball bound)} \label{tab:ball_bound}
521 \hbox to\hsize{\hfil
522 \begin{tabular}{|c|c|c|c|c|} \hline
523 キャッシュ & FPS & DMA転送待ち時間 & mail待ちの割合 & SPE稼働率\\ \hline
524 なし & 24.6FPS & 5.5\% & 72.4\% & 22.1\% \\ \hline
525 あり & 27.2FPS & 1.8\% & 76.2\% & 22.0\% \\ \hline
526 \end{tabular}\hfil}
527 \end{center}
528 \end{table}
529
530
531 \subsection{DrawSpanTask} \label{drawspan}
532
533 現在、PlayStation 3 の GPU にアクセスする API は公開されていないため、Cerium では
534 Frame Buffer に直接描画する。Frame Buffer のアドレスは mmap() で取得できるため、 Task
535 出力として Frame Buffer を指定するか、Task 内で DMA 転送を行えば描画することができる。
536 Mac OSX 上で動かす場合は SDL を用いて描画を行う。
537
538 Rendering は DrawSpan という Task で行う。受け取った SpanPack から Span を取り出す。
539 Span の端から 1 pixel ずつ見ていき、その pixel の z 座標と Z Buffer を見比べ、描画
540 するものと判断されると、対応する RGB 値を書きこむ。
541
542 また、DrawSpan は分割された画面領域の一部を担当するので、Span がその領域を
543 越えている場合は描画しない。現在、一つの DrawSpan が描画する領域は 256x8 としてい
544 る(\figref{drawspan})。
545
546 \begin{figure}[htb]
547 \begin{center}
548 \includegraphics[scale=0.80]{./images/drawspan.pdf}
549 \end{center}
550 \caption{DrawSpan の担当領域}
551 \label{fig:drawspan}
552 \end{figure}
553
554 \subsection{RenderingTask のパイプライン化} \label{drawspan}
555 主に 3つの Task から構成されいる RenderingEngine だが、それぞれの Task はバリア同期を行なっている。Cerium においてバリア同期を行う場合に、2つの待ち時間がある。
556 \begin{itemize}
557 \item SPEが他のSPEの処理完了を待つ時間
558 \item バリア同期が完了し、PPE 側で次の Task が作られる時間
559 \end{itemize}
560
561 この二つの時間の間SPEの処理が止まり、処理性能の低下につながる。この待ち時間を回避するためには、Taskの粒度を下げる、他の SPE の処理完了を待っている SPE に、別の Task を割り当てる、等の方法がある。別の Task を割り当てるには Task の実行をパイプライン化する方法がある。そこで、特に3つの Task の中でも処理の重い DrawSpanTask と、CreatePolygonTask, CreateSpanTask の Task でパイプライン化を行っている。(\figref{rend-dep}) 速度比較の対象として、SuperDnady と呼ばれる、学生実験で制作されたシューティングゲームを用いた。FPSは一秒あたりの RednderingEngine 全体の処理回数(Frame per Scecond)であり、busy ration はSPEの稼働率である。(\tabref{pipeline_superdandy})
562
563 \begin{figure}[htb]
564 \begin{center}
565 \includegraphics[scale=0.90]{./images/rend-dep.pdf}
566 \end{center}
567 \caption{DrawSpan の担当領域}
568 \label{fig:rend-dep}
569 \end{figure}
570
571 \begin{table}[!htb]
572 \begin{center}
573 \caption{パイプライン化の効果(ball bound)} \label{tab:pipeline_ballbound}
574 \hbox to\hsize{\hfil
575 \begin{tabular}{|c|c|c|c|c|} \hline
576 PipeLine & FPS & DMA転送待ち時間 & mail待ちの割合 & SPE稼働率\\ \hline
577 なし & 27.2FPS & 1.8\% & 76.2\% & 22.0\% \\ \hline
578 あり & 30.2FPS & 1.8\% & 74.3\% & 23.7\% \\ \hline
579 \end{tabular}\hfil}
580 \end{center}
581 \end{table}
582
583 パイプライン化した結果(\tabref{pipeline_ballbound})、SPEの稼働率が向上し、FPSも向上した。
584 処理性能を維持するには、SPEはなるべく稼働させ続けなければならない。
585 その為には処理をTaskに分割し、並列実行するだけでなく、バリア同期などで、
586 SPEの待ち時間が発生することへ対処しないといけない。
587 その対処の一つとしてそれにパイプライン化は有効である。