Help us understand the problem. What is going on with this article?

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

More than 5 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 // 色成分の順序を設定

ディスクリプタの役目あたりは、まだ曖昧ですみません。
今回は初期化フェーズまでとします。次回は描画フェーズの解説を投稿します。

pol-inc
「未来を加速する(Accelerate the Future.)」 それがPOLのミッションです。 課題解決とイノベーションにより、良い未来の到来を早める。私たちにしか創れない良い未来を創る。 私たちがPOLに集まっているのは、このためです。
https://pol.co.jp/
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