mcpField
M
metal-gpu

metal-gpu

github.com/ios-agent開発12312 回インストール34 週間前に更新
リポジトリ

metal-gpu について

Metal GPU 開発向けに、実装パターン、API の要点、性能上の注意を示すスキルです。Metal と Swift で GPU 描画や計算を行う開発者向けで、コマンドパイプライン、MSL シェーダー、Apple GPU の最適化を扱います。

主な機能

  1. 01Metal コマンドパイプラインのパターン
  2. 02MSL の頂点、フラグメント、計算シェーダー
  3. 03Swift の描画・計算パイプライン設定
  4. 04ストレージモードとバッファー管理
  5. 05最適化手法とよくある問題
  6. 06Metal 4 API の変更点

活用シーン

  1. 01Metal の描画パイプライン構築
  2. 02GPU 計算カーネルの作成
  3. 03フレームごとのリソース割り当て削減
  4. 04エンコーダー、バッファー番号、ピクセル形式の問題調査

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/ios-agent/iosagent.dev --skill metal-gpu

インストール後、Claude Code で/metal-gpuを入力して読み込まれたか確認します。

同梱ファイルreferences/metal-api-guide.md

詳細

Metal GPU コードスキル

本番品質の Metal コードを、適切なパターン、最適なパフォーマンス、わかりやすい説明とともに記述します。

リファレンスを読むタイミング

API の詳細な構成、Metal 4 の詳細、Apple Silicon の最適化パターンについては、次を参照してください。

/mnt/skills/user/metal-gpu/references/metal-api-guide.md

基本原則

  1. 必ずデバイスから始める:MTLCreateSystemDefaultDevice() — Metal のすべてのワークフローはここから始まります
  2. コマンドパターン:デバイス → コマンドキュー → コマンドバッファー → コマンドエンコーダー → コミット
  3. シェーダーは MSL(Metal Shading Language)です:C++14 をベースに、Metal 固有の型と属性を備えています
  4. リソース管理は重要です:適切なストレージモードを使用し、不要なコピーを避けます
  5. レンダリングループではトリプルバッファリングを使用し、CPU と GPU を並列動作させます

クイックリファレンス:Metal コマンドパイプライン

MTLDevice
  └─ makeCommandQueue() → MTLCommandQueue
       └─ makeCommandBuffer() → MTLCommandBuffer
            ├─ makeRenderCommandEncoder(descriptor:) → MTLRenderCommandEncoder
            ├─ makeComputeCommandEncoder() → MTLComputeCommandEncoder
            └─ makeBlitCommandEncoder() → MTLBlitCommandEncoder

シェーダーの記述(MSL)

Metal Shading Language を使用します。必ず次を含めてください。

  • #include <metal_stdlib> と using namespace metal;
  • 正しい属性修飾子:[[vertex_id]]、[[position]]、[[stage_in]]、[[buffer(n)]]、[[texture(n)]]
  • 適切なアドレス空間修飾子:device、constant、threadgroup、thread
頂点シェーダーのパターン
#include <metal_stdlib>
using namespace metal;

struct VertexIn {
    float3 position [[attribute(0)]];
    float3 normal   [[attribute(1)]];
    float2 texCoord [[attribute(2)]];
};

struct VertexOut {
    float4 position [[position]];
    float3 normal;
    float2 texCoord;
};

vertex VertexOut vertex_main(VertexIn in [[stage_in]],
                             constant float4x4 &mvp [[buffer(1)]]) {
    VertexOut out;
    out.position = mvp * float4(in.position, 1.0);
    out.normal = in.normal;
    out.texCoord = in.texCoord;
    return out;
}
フラグメントシェーダーのパターン
fragment float4 fragment_main(VertexOut in [[stage_in]],
                              texture2d<float> albedo [[texture(0)]],
                              sampler texSampler [[sampler(0)]]) {
    float4 color = albedo.sample(texSampler, in.texCoord);
    return color;
}
コンピュートカーネルのパターン
kernel void compute_main(device float *input  [[buffer(0)]],
                         device float *output [[buffer(1)]],
                         uint id [[thread_position_in_grid]]) {
    output[id] = input[id] * 2.0;
}

Swift 側のセットアップパターン

レンダーパイプラインのセットアップ
let device = MTLCreateSystemDefaultDevice()!
let commandQueue = device.makeCommandQueue()!

// Load shaders
let library = device.makeDefaultLibrary()!
let vertexFunction = library.makeFunction(name: "vertex_main")
let fragmentFunction = library.makeFunction(name: "fragment_main")

// Pipeline descriptor
let pipelineDescriptor = MTLRenderPipelineDescriptor()
pipelineDescriptor.vertexFunction = vertexFunction
pipelineDescriptor.fragmentFunction = fragmentFunction
pipelineDescriptor.colorAttachments[0].pixelFormat = .bgra8Unorm

// Vertex descriptor
let vertexDescriptor = MTLVertexDescriptor()
vertexDescriptor.attributes[0].format = .float3  // position
vertexDescriptor.attributes[0].offset = 0
vertexDescriptor.attributes[0].bufferIndex = 0
vertexDescriptor.layouts[0].stride = MemoryLayout<SIMD3<Float>>.stride
pipelineDescriptor.vertexDescriptor = vertexDescriptor

let pipelineState = try! device.makeRenderPipelineState(descriptor: pipelineDescriptor)
コンピュートパイプラインのセットアップ
let computeFunction = library.makeFunction(name: "compute_main")!
let computePipeline = try! device.makeComputePipelineState(function: computeFunction)

let commandBuffer = commandQueue.makeCommandBuffer()!
let encoder = commandBuffer.makeComputeCommandEncoder()!
encoder.setComputePipelineState(computePipeline)
encoder.setBuffer(inputBuffer, offset: 0, index: 0)
encoder.setBuffer(outputBuffer, offset: 0, index: 1)

let gridSize = MTLSize(width: elementCount, height: 1, depth: 1)
let threadGroupSize = MTLSize(
    width: min(computePipeline.maxTotalThreadsPerThreadgroup, elementCount),
    height: 1, depth: 1
)
encoder.dispatchThreads(gridSize, threadsPerThreadgroup: threadGroupSize)
encoder.endEncoding()
commandBuffer.commit()
MetalKit ビューのレンダリング
import MetalKit

class Renderer: NSObject, MTKViewDelegate {
    let device: MTLDevice
    let commandQueue: MTLCommandQueue
    let pipelineState: MTLRenderPipelineState

    func draw(in view: MTKView) {
        guard let drawable = view.currentDrawable,
              let descriptor = view.currentRenderPassDescriptor else { return }

        let commandBuffer = commandQueue.makeCommandBuffer()!
        let encoder = commandBuffer.makeRenderCommandEncoder(descriptor: descriptor)!

        encoder.setRenderPipelineState(pipelineState)
        // Set buffers, draw primitives...
        encoder.drawPrimitives(type: .triangle, vertexStart: 0, vertexCount: 3)

        encoder.endEncoding()
        commandBuffer.present(drawable)
        commandBuffer.commit()
    }
}

パフォーマンスのベストプラクティス

  1. ストレージモード:Apple Silicon(ユニファイドメモリ)では .shared、GPU 専用データには .private、Intel Mac では .managed を使用します
  2. トリプルバッファリング:セマフォを使用して 3 つのバッファーをローテーションし、CPU/GPU の停止を回避します
  3. フレームごとの割り当てを避ける:バッファーとコマンドエンコーダーを再利用します
  4. 可能であれば、dispatchThreadgroups より dispatchThreads を使用します(Apple Silicon)
  5. Apple GPU ではタイルベースの遅延レンダリングパターンを優先します — imageblock とタイルシェーダーを使用します
  6. パイプラインは事前にコンパイルします:パイプラインの作成には時間がかかるため、読み込み時に行います
  7. Xcode の Metal GPU フレームキャプチャを使用してプロファイルとデバッグを行います

避けるべきよくある間違い

  • コミット前に encoder.endEncoding() を呼び忘れる
  • Swift と MSL でバッファーインデックスが一致していない
  • レンダーターゲットに誤ったピクセルフォーマットを使用する
  • Metal API のオプショナルな呼び出しで nil を処理しない
  • GPU の完了を待つためにメインスレッドをブロックする — 代わりに addCompletedHandler を使用します
  • [[stage_in]] を使用する際に頂点ディスクリプターの設定を忘れる

Metal 4 に関する注意事項

Metal 4 では、最新化されたコア API が導入されています。主な変更点は次のとおりです。

  • シェーダーコンパイルをより細かく制御できる新しいコンパイル API
  • 更新されたコマンドエンコードパターン
  • Metal 4 API の全体構成については、references/metal-api-guide.md を参照してください

フレームワークのエコシステム

フレームワーク用途
MetalGPU への直接アクセス、シェーダー、パイプライン
MetalKitビュー管理、テクスチャ読み込み、モデル I/O
MetalFXパフォーマンス向上のためのアップスケーリング(時間方向/空間方向)
Metal Performance Shaders最適化されたコンピュートおよび画像処理カーネル
Compositor ServicesvisionOS 向けの立体視レンダリング
RealityKit高水準の 3D レンダリング(内部で Metal を使用)

コメント