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

Metalのデバッグまとめ(随時更新)

More than 1 year has passed since last update.

Metalのデバッグに関連する機能やツールの使い方を本記事にまとめていこうと思います。

GPUフレームキャプチャ

XcodeにビルトインされているMetalのデバッグ機能。

Metal利用アプリを実行中、カメラ型のアイコン("Capture GPU Frame")を押すと、その瞬間のGPUフレームがキャプチャされ、次のような画面になる。

xcode_gpu_overview_draw_2x.png

非常に高機能なので、詳細はそれぞれの項にて。

ラベル

Metalのクラスやプロトコルは文字列型のlabelというプロパティを備えているものが多くある。

例:

  • MTLCommandQueue
  • MTLResource
    • MTLBuffer, MTLTexture
  • MTLFunction
  • MTLRenderPipelineDescriptor
  • MTLCommandBuffer
  • MTLCommandEncoder

たとえば次のようにラベルをつけておいて、

commandQueue.label = "HogeCommandQueue"
texture.label = "HogeTexture"
vertexBuffer.label = "HogeVertexBuffer"
texCoordBuffer.label = "HogeTexCoordBuffer"
vertexFunction.label = "HogeVertexFunction"
fragmentFunction.label = "HogeFragmentFunction"
descriptor.label = "HogeRenderPipeline"
commandBuffer.label = "HogeCommandBuffer"
renderEncoder.label = "HogeRenderCommandEncoder"

XcodeでGPUフレームをキャプチャすると、ナビゲータ内でのコマンドエンコーダやリソース名に、自分がつけたラベルが表示されるので、識別しやすくなる。

Screen Shot 2018-01-20 at 16.19.57.png

ラベルは Instruments で見た場合にもこんな感じで適用されている。

Screen Shot 2018-01-20 at 16.24.42.png

というわけでパスが複雑な処理を行う場合はラベルをつけておくとデバッグやパフォーマンスにおけるボトルネックの特定が捗る。

デバッググループ

MTLCommandEncoderはiOS 8から、MTLCommandBufferはiOS 11から以下のようなメソッドが使える。

public func pushDebugGroup(_ string: String)
public func popDebugGroup()

push〜popの間にそのコマンドエンコーダやコマンドバッファに対して行った処理が、XcodeでのGPUフレームキャプチャ画面におけるナビゲータ上にフォルダアイコンでまとめられて表示される。

commandBuffer.pushDebugGroup("HogeCommandBufferDebugGroup")

guard let renderEncoder = commandBuffer.makeRenderCommandEncoder(descriptor: renderPassDescriptor) else {return}
renderEncoder.label = "HogeRenderCommandEncoder"
renderEncoder.pushDebugGroup("HogeCommandEncoderDebugGroup")
renderEncoder.insertDebugSignpost("HogeDebugSignpost")

guard let renderPipeline = renderPipeline else {fatalError()}
renderEncoder.setRenderPipelineState(renderPipeline)
renderEncoder.setVertexBuffer(vertexBuffer, offset: 0, index: 0)
renderEncoder.setVertexBuffer(texCoordBuffer, offset: 0, index: 1)
renderEncoder.setFragmentTexture(texture, index: 0)
renderEncoder.drawPrimitives(type: .triangleStrip, vertexStart: 0, vertexCount: 4)
renderEncoder.endEncoding()

commandBuffer.present(drawable)
commandBuffer.commit()
commandBuffer.waitUntilCompleted()

commandBuffer.popDebugGroup()
renderEncoder.popDebugGroup()

Screen Shot 2018-01-20 at 16.40.19.png

insertDebugSignpost

MTLCommandEncoderのメソッド。

public func insertDebugSignpost(_ string: String)

公式リファレンスによると、

Inserts a string into the command buffer.

When debugging with Xcode, this string may appear.

ちょっと用途がよくわからない。。コマンドバッファへのエンコードがうまくいってるかを確認するため?

シェーダの処理毎のパフォーマンス確認

ナビゲータの右上の方にあるアイコンをクリックして「View Frame By Performance」を選択。(デフォルトは「View Frame By Call」)

xcode_gpu_view_frame_by_2x.png

リストからパフォーマンスを見たいシェーダを選択すると、ソース上に処理時間のパーセンテージが表示される。

Screen Shot 2018-01-20 at 16.47.38.png

(表示されないケースもあった。理由は分かり次第追記します)

Remarks

ナビゲータから"Pipeline Statistics"を選択すると、"Remarks"という欄に、warning的な事項が表示される。

Screen Shot 2018-01-20 at 16.52.25 copy.png

Instruments

instruments2.png

参考資料

書籍

公式ドキュメント

WWDCセッション

一次情報としてリファレンスだけでは不十分で、WWDCのセッションでしか話されてない情報も多々ある。

そして最新年度のだけ観れば十分かというと全然そんなこともなく、たとえばInstrumentsのMetal System Traceについてのまともな解説は2015年まで遡らないとなかったりするので、「どのセッションでどの(デバッグ関連の)話をしているか」をここに整理しておく。

Why do not you register as a user and use Qiita more conveniently?
  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
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  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