31
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MetalAdvent Calendar 2017

Day 11

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

Last updated at Posted at 2018-01-21

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年まで遡らないとなかったりするので、「どのセッションでどの(デバッグ関連の)話をしているか」をここに整理しておく。

31
28
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
28

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?