2016-06-28 7 views
0

テクスチャからピクセルの近くのピクセルを読み取り、古いピクセル値に基づいて現在のピクセルの値を更新するカーネル関数(計算シェーダ)があります(単純な畳み込みではありません)。iOS Metal - テクスチャに書き込み中に古い値を読み取る

BlitCommandEncoderを使用してテクスチャのコピーを作成し、2つのテクスチャ(1つは読み取り専用、もう1つは書き込み専用)にカーネル機能を追加してみました。残念ながら、このアプローチはGPUには時間がかかります。

コンテンツを更新しているときに、古い値をテクスチャから読み取るのに最も効率的(GPUおよびメモリワイズ)の方法は何ですか?

+0

Time Profiler(計測器で)とGPUフレームキャプチャ(Xcodeで)でアプリをプロファイリングしましたか?リソースの割り当て、カーネルのコピー、実行にどれくらいの時間を費やしているかを判断することで、まず何を最適化するかを理解するのに役立ちます。 – warrenm

+0

@warrenmお返事ありがとうございます。 「BlitCommandEncoder」で動作するルーチンが、遅延を引き起こした別の時間のかかる関数を呼び出していたことが判明しました.Blit操作は遅延の主要な原因ではありませんでした。それは私のせいでした。しかし、GPUフレームキャプチャを見て、私はBlit操作の持続時間について言及していないことを発見しました。(Compute操作とは対照的に) - これを測定する方法はありませんか? – sarasvati

+0

現在、GPUフレームキャプチャで計算エンコーダの時間をキャプチャする方法はないと思います。 – warrenm

答えて

2

(少し遅れたが、まあ)

GPUは、高度な並列プロセッサであるので、あなたはそれが唯一のテクスチャで動作させることができる方法はありません:あなたは、単一のピクセルのために書いたあなたのカーネルがで呼び出されますすべてのピクセルで平行であれば、どのピクセルが最初に表示されるかはわかりません。

2つのテクスチャが必要です。おそらくそれを行うべき方法は、1つが「古い」もので、もう1つが「新しい」ものである2つのテクスチャを使用することです。パスの間で、テクスチャの役割を切り替えます。今は古いものが新しいもので、新しいものは古いものです。

var currentText = MTLTexture() 
var nextText = MTLTexture() 

let semaphore = dispatch_semaphore_create(1) 

func update() { 
    dispatch_semaphore_wait(semaphore) // Wait for updating done signal 

    let commands = commandQueue.commandBuffer() 
    let encoder = commands.computeCommandEncoder() 

    encoder.setTexture(currentText, atIndex: 0) 
    encoder.setTexture(nextText, atIndex: 1) 

    encoder.dispatchThreadgroups(...) 
    encoder.endEncoding() 

    // When updating done, swap the textures and signal that it's done updating 
    commands.addCompletionHandler { 
     swap(&currentText, &nextText) 
     dispatch_semaphore_signal(semaphore) 
    } 
    commands.commit() 
} 
0

レンダリングしているのと同じテクスチャからサンプル(または読み込み)するたくさんのiOSメタルコードを書きました。レンダリングパイプラインを使用して、レンダリングターゲットの添付ファイルとしてテクスチャを設定し、ソーステクスチャとして読み込んでいます。それはうまく動作します。

明確にするため、より効率的なアプローチは、あなたのフラグメントシェーダでcolor()属性を使用することですが、あなたが必要とするすべての現在フラグメントではなく、任意の他の近くの位置の値である場合には、のみに適しています。レンダリングターゲット内の他の位置から読み込む必要がある場合は、レンダリングターゲットをソーステクスチャとしてフラグメントシェーダにロードするだけです。

関連する問題