2016-05-27 20 views
16

Vulkanで同期を処理する方法はいくつかあります。これは私がそれを理解する方法です:Vulkanのコマンドバッファ間の同期

  • フェンスはGPUとCPUの同期です。
  • セマフォはGPUからGPUへの同期であり、(同じキューまたは異なるキュー上の)キュー の送信を同期するために使用されます。
  • イベントはより一般的で、リセットされ、CPUとGPUの両方でチェックされます。
  • バリアは、コマンドバッファ内の同期に使用されます。

私の場合、私は2つのコマンドバッファを持っています。そして、最初のコマンドバッファの後に2番目のコマンドバッファを実行します。

submitInfo.pCommandBuffers = &firstCommandBuffer; 
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 

// wait for first command buffer to finish 
submitInfo.pCommandBuffers = &secondCommandBuffer; 
vkQueueSubmit(queue, 1, &submitInfo, VK_NULL_HANDLE); 

これにはどのような同期が最適ですか? もし私がvkQueueWaitIdle(queue)),を使用しているのであれば、それはフェンスを使用しているのと同じことですか、これに対してイベントまたはセマフォを使うべきですか?

私は同時にキューに複数のcommandbufferを送信する場合:

std::vector<VkCommandBuffer> submitCmdBuffers = { 
     firstCommandBuffer, 
     secondCommandBuffer 
    }; 
    submitInfo.commandBufferCount = submitCmdBuffers.size(); 
    submitInfo.pCommandBuffers = submitCmdBuffers.data(); 

はまだ第一及び第二の1の間で同期化する方法はありますか?

+2

"*そして、最初のコマンドバッファの後に2番目のコマンドバッファを実行します。*"どれくらい "それを実現したいですか?つまり、2番目のコマンドバッファは、2番目のコマンドバッファが起動する前に最初のコマンドが実行されていることが非常に重要であるということをしていますか? –

+1

最初のコマンドバッファは、デプステストをオンにしてレンダリングオブジェクトです。第2のコマンドバッファは、深度テストをオフにしてメッシュの輪郭をレンダリングしている。なぜなら、それは他のオブジェクトの上になければならないからです。 – hidayat

+0

提出を1回行う場合。最初のコマンドバッファーではvkCmdSetEvent、2番目のコマンドバッファーではvkCmdWaitEventsを使用し、srcマスクとdstステージマスクはできるだけ狭くしておきます。 –

答えて

11

最初のコマンドバッファは、デプステストがオンのレンダリングオブジェクトです。第2のコマンドバッファは、深度テストをオフにしてメッシュの輪郭をレンダリングしている。なぜなら、それは他のオブジェクトの上になければならないからです。

この場合、コマンドバッファが何であるかによって、必要なものが異なります。

これらが同じレンダリングパスインスタンス内で実行されるセカンダリコマンドバッファの場合、のいずれかの同期化は必要ありません。セカンダリコマンドバッファの深度テクスチャから手動で読み込んでいる場合を除きます。どうして?

セクション2.2.1のAPI Orderingはあなたを守ります。レンダーパスインスタンス内でのデプステストとデプス書き込みは、常にになります。そのため、深層テスト/執筆に関しては、同じCBであろうと異なるCBであろうと、後のコマンドが発注されます。

しかし、その深度バッファを読み取る必要がある場合、またはコマンドバッファが異なるレンダーパスインスタンスにある場合は、イベントを介して明示的な同期が必要です。

この場合、vkCmdSetEventコマンドのステージマスクは、デプス値を書き込むステージにする必要があります。これはEARLY_FRAGMENT_TESTS_BITまたはLATE_FRAGMENT_TESTS_BITです。安全のためには、両方を使用してください。ただし、おそらく同じカラーバッファを更新しているので、COLOR_ATTACHMENT_OUTPUT_BITステージも必要です。このコマンドを最初のコマンドバッファの最後に挿入します(またはすべての深度書き込みが完了した後)。

vkCmdWaitEventの場合、必要なパイプラインステージを待つ必要があります。あなたの場合、これは断片テストとカラーアタッチメントです。しかし、シェーダステージで深さを読み取る場合は、waitコマンドのステージも必要です。

メモリが含まれているため、vkCmdWaitEventは深度バッファとカラーバッファにメモリ依存関係を使用する必要があります。

しかし、これらすべての複雑さは、可能であれば、これらのコマンドバッファを同じレンダーパスインスタンスに配置する必要がある理由です。あなたがそうすることができない唯一の理由は、シェーダの深度バッファから読み込む必要がある場合です。

+0

あなたの知識は印象的です:)、「それらがセカンダリコマンドバッファである場合」、同じレンダーパスにある場合、プライマリまたはセカンダリコマンドバッファであればどうして問題になりますか? – hidayat

+1

@hidayat:同じレンダーパスインスタンスに2つのプライマリコマンドバッファを持つことはできません。 'vkCmdEndCommandBuffer' *は、レンダーパスインスタンスがアクティブな間は呼び出せません。セカンダリコマンドバッファでのみ、同じレンダーパスインスタンス内でコマンドを発行することは可能です。これは、内部で実行するプライマリコマンドバッファのrenderpassインスタンスを継承することで行います。 –

4

シナリオでは、イベントを使用する必要があります。指定された順序で2つのコマンドバッファの実行を同期させるには、一度にサブミットしても、最も軽量な同期オブジェクトである必要があります。ただし、イベントは異なるキュー間では機能しません。イベントを使用する場合は、イベントを使用して、srcおよびdstのパイプラインステージマスクを可能な限り狭くしてください。

セマフォは、コマンドバッファの実行を同期させるもう1つの方法ですが、これらはキューの送信でのみ機能するため、イベントより重いです。

+0

障壁はできませんでしたか?ここでは、バリアがコマンドバッファ境界を越えて動作することを続けています。http://stackoverflow.com/a/36602598/1364776ここでは適用できませんでしたか?または、障壁よりもイベントが軽量であるということだけですか? – mjwach

関連する問題