Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
2
Help us understand the problem. What is going on with this article?
@yuky_az

[iOS]MetalでGPUコンピューティング(10) Metal Shading Languageで記述されたライフゲームのロジック

More than 3 years have passed since last update.

この記事は、Metal Advent Calendar2016の14日目です。

これまで、MetalのGPUコンピューティングについて解説記事を書いてきました。
[iOS] MetalでGPUコンピューティング (1) 最小限のコードの記述と特性の把握
[iOS] MetalでGPUコンピューティング (2) 群知能
[iOS] MetalでGPUコンピューティング (3) MTLDevice
[iOS] MetalでGPUコンピューティング (4) MTKView
[iOS] MetalでGPUコンピューティング (5) MTLLibrary
[iOS] MetalでGPUコンピューティング (6) MTLCommandQueue
[iOS] MetalでGPUコンピューティング (7) MTLCommandBuffer
[iOS] MetalでGPUコンピューティング (8) MTLComputeCommandEncoder
[iOS] MetalでGPUコンピューティング (9) MTLComputePipelineState

本記事では、前回に引き続きAppleが提供するサンプルコードの解説を行います。

扱うサンプルコードは、前回と同じライフゲームのアプリ、MetalGameOfLifeです。
MetalGameOfLife

IMG_5933.PNG
(実行画面)

今回は、サンプルコード内のに記述されたライフゲームのロジックについて解説を行います。
ライフゲームそのものに関しては、YouTubeなどで動画を検索していただければ概観がつかめるかとおもます。
要約すると、周囲のマス目の個体数の疎密により、個体の生死や存続が決定されるプログラムです。

このライフゲームのロジックは、シェーダ内にコンピューティング用の関数で記述されています。

繰り返しになるのですが、このサンプルコードは、主に以下のファイルで構成されています。

AAPLRender.h
AAPLRender.m
AAPLViewController.h
AAPLViewController.m
Sharder.metal

このうち、AAPLRender.mには並列コンピューティング及び描画のCPU側のロジックが、Shader.metalには頂点シェーダー、フラグメントシェーダー、GPUコンピューティング用のシェーダーが書かれています。

予めテクスチャの各点に対応するスレッドが割り当てられているので、各点に対応する処理は並列で行われます。

ここからは、Shader.metal内におけるライフゲームのロジックの箇所を解説していきます。
Shader.mに以下の記述があります。

Shader
kernel void game_of_life(texture2d<uint, access::sample> readTexture [[texture(0)]],
                         texture2d<uint, access::write> writeTexture [[texture(1)]],
                         sampler wrapSampler [[sampler(0)]],
                         ushort2 gridPosition [[thread_position_in_grid]])
{
    ushort width = readTexture.get_width();
    ushort height = readTexture.get_height();
    float2 bounds(width, height);
    float2 position = float2(gridPosition);
...                                                                    

game_of_life関数が記述されています。kernerlと書かれているのでこれはコンピューティング用の関数になります。
引数として、入力用のテクスチャ、出力用のテクスチャ、サンプラー、グリッド内におけるこのスレッドの位置(gridPosition)が渡されています。
flot2型はfloat型の二次元ベクトルです。

この関数外に、周囲のセルの生死判定用の構造体が記述されています。Metal Shading LanguageはC++ベースなので構造体を使用することもできます。

Shader
constant float2 kNeighborDirections[] =
{
    float2(-1, -1), float2(-1, 0), float2(-1, 1),
    float2( 0, -1), /*  center  */ float2( 0, 1),
    float2( 1, -1), float2( 1, 0), float2( 1, 1),
};

また、セルの生死を判定する定数を設定しています。テクスチャのrgbを利用しているので生を0、死を255としています。

Shader
constant int kCellValueAlive = 0;
constant int kCellValueDead = 255;

これらを用いて、以下のロジックで周囲の生きているセルの数がカウントされます。

Shader
ushort neighbors = 0;
for (int i = 0; i < 8; ++i)
{
    // Sample from the current game state texture, wrapping around edges if necessary
    float2 coords = (position + kNeighborDirections[i] + float2(0.5)) / bounds;
    ushort cellValue = readTexture.sample(wrapSampler, coords).r;
    neighbors += (cellValue == kCellValueAlive) ? 1 : 0;
}

そして、以下のロジックでセルの生死を判定し、結果をテクスチャに書き出しています。

Shader
ushort deadFrames = readTexture.read(uint2(position)).r;
...        
bool alive = (deadFrames == 0 && (neighbors == 2 || neighbors == 3)) || (deadFrames > 0 && (neighbors == 3));
...
ushort cellValue = alive ? kCellValueAlive : deadFrames + 1;
...        
writeTexture.write(cellValue, uint2(position));

cellValueが、
alive ? kCellValueAlive : kCellValueDeadではなく、
alive ? kCellValueAlive : deadFrames + 1;なのは、
死亡したセルの色を徐々に変化させるためです。

このように、ライフゲームのような並列処理に適したコードは、Metal Shading Languageで記述可能なわけなのです。

今回はライフゲームのサンプルコード内におけるライフゲームのロジックの解説を行いました。
次回以降、さらに他の箇所についての解説を行なっていきます。

2
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
yuky_az
「ヒトとAIの共生」がミッションの会社、SAI-Lab株式会社の代表取締役。 東北大学大学院理学研究科修了。理学博士(物理学)。 著書に「はじめてのディープラーニング」、「No.1スクール講師陣による 世界一受けたいiPhoneアプリ開発の授業」。オンライン教育プラットフォームUdemyで、2万人近くを指導する人気講師。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
2
Help us understand the problem. What is going on with this article?