Edited at
Quad incDay 13

【Swift2.0でMetal入門】1.Metalの初期化フェーズ

More than 3 years have passed since last update.

この記事は前回の解説的内容です。

入門としては1.5回目に位置します。


目的

Metalの使用用途がGameというイメージが強すぎるので、通常のアプリや表現としても使えることを探っていきます。


注意

MetalはiOS8以上の固有機能です。Metalを動かすにはA7チップ以上のデバイスが必要です。Macで開発する場合は

シュミレーターではなく、実機で確認するようにしてください。


前回のコードと確認しながら進めると分かりやすいと思います。


MetalとOpenGLの違い

MetalはOpenGLESより高速で動きます。しかしOpenGLESはクロスプラットフォームというメリットがあります。そのためOpenGLESのアプリはAndroid、Windowsなどに移植しやすいです。ちなみにSpriteKitやSceneKitはOpenGLESを利用しています。

MetalのメリットはOpenGLESより優れたパフォーマンスと、個人的にはコードの記述がスマートな所だと思います。パファーマンスが出ない場合はMetalの使用を検討しても良いと思います。

まとめるとMetalのメリットとしては


  • OpenGLESよりすぐれたパフォーマンス(CPUとGPUのメモリを共通使用するためとかとか)

  • コードの記述がスマート(私の個人的な感想です)


グラフィックスライブラリの2つのフェーズ

前回の投稿をみても、グラフィックスライブラリを使う場合、大きく2つのフェーズに分かれます。


  • 初期化フェーズ

  • 描画フェーズ


初期化フェーズ

まず初期化フェーズではグラフィックスライブラリの初期化、描画の準備を行います。

順番にみると


  • 1.GPUへのアクセス方法を用意

  • 2.CPUとGPUの連携準備

  • 3.頂点やバッファの準備

  • 4.レンダリングパイプラインを準備

で設定します。


1.GPUへのアクセス方法を用意

ここで最初にすることは、deviceを取得することです。これでプログラムを実行しているdeviceとやり取りができます。またデバイスの情報も取得できます。

let device: MTLDevice! = MTLCreateSystemDefaultDevice()


2.CPUとGPUの連携準備

グラフィックスの情報は非同期にCPUからGPUに送信されます。これはCPUでまず処理が実行され、次にGPUに転送されます。画面上の特定の1pxで考えると、CPUとGPUが同一のピクセルに対して同時に処理をすることはないです。

この処理を順番に行うためにキューを準備します。CPUはGPUに渡す情報をキューに追加していき、GPUはキューから順番に情報を抜き出し処理します。

let commandQueue: MTLCommandQueue!  = device.newCommandQueue()


3.頂点、バッファの準備

GPUへ渡したい頂点情報を準備します。スクリーン上に表示するオブジェクトを定義します。


// 頂点
let vertexArray: [Float] = [
-1.0, 1.0, 0, 1,
-1.0, -1.0, 0, 1,
1.0, -1.0, 0, 1,
-1.0, 1.0, 0, 1,
1.0, -1.0, 0, 1,
1.0, 1.0, 0, 1
]

ヴァッファは頂点、色、テクスチャなどあり、頂点の数だけバッファを作成します。

let vertexBuffer: MTLBuffer! = device.newBufferWithBytes( vertexArray,

length: vertexArray.count * sizeofValue(vertexArray[0]),
options: MTLResourceOptions.OptionCPUCacheModeDefault
)


4.レンダリングパイプラインを準備

このステップは2に分かれます。最初のフェーズでは、Shaderプログラムを用意し読み込みます。

SwiftでShaderプログラムを使う場合は、Shader Libraryに読み込む必要があります。

// Shader Library設定

let defaultLibrary = device.newDefaultLibrary()
let newVertexFunction = defaultLibrary!.newFunctionWithName("vertexShader")
let newFragmentFunction = defaultLibrary?.newFunctionWithName("fragmentShader")

次のステップではディスクリプタを作成します。

ディスクリプタに

パイプラインを初期化し画像をラスタライズしながら、フォーマットが使用するピクセルを教えてくれます。

let pipelineStateDescriptor = MTLRenderPipelineDescriptor()

pipelineStateDescriptor.vertexFunction = newVertexFunction
pipelineStateDescriptor.fragmentFunction = newFragmentFunction pipelineStateDescriptor.colorAttachments[0].pixelFormat = .BGRA8Unorm // 色成分の順序を設定

ディスクリプタの役目あたりは、まだ曖昧ですみません。

今回は初期化フェーズまでとします。次回は描画フェーズの解説を投稿します。