Mercurial > hg > Papers > 2012 > yutaka-master
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 その対処の一つとしてそれにパイプライン化は有効である。 |