すでにセマフォを使用している場合、スワップチェーン コマンド バッファーごとに VkFence が必要なのはなぜですか? 質問する

すでにセマフォを使用している場合、スワップチェーン コマンド バッファーごとに VkFence が必要なのはなぜですか? 質問する

私はスワップチェーン用にちょうど3つのイメージを使用し、スワップチェーンイメージごとに1つの(CB)を使用しています。GPU同期は、 用と用のVkCommandBuffer2つのセマフォで行われます。現在のモードは(presentation_finishedrendering_finishedVK_PRESENT_MODE_MAILBOX_KHR概要)。

ここで、CB フェンスを待たずに例を実行すると、スワップチェーン イメージが 2 回目に使用されるとすぐに検証レイヤーによってこのエラーが報告されます。

vkBeginCommandBuffer()完了する前にアクティブな CB を呼び出しています。この呼び出しの前に CB フェンスを確認する必要があります。

一見すると、CB からのコマンドの処理がまだ完了していないだけかもしれないので、これは合理的に思えます。しかし、考えれば考えるほど、これは決して起こるべきではないという結論に達します。

私の現在の理解では、vkAcquireImageKHR特定の画像インデックスを返す場合、返される画像はレンダリングが完了している必要があることを意味します。

rendering_finishedこれは、レンダリングが終了したときにシグナルがvkQueueSubmit送信されるようにセマフォを に渡し、vkQueuePresentKHRシグナルが送信されるまで待ってから画像を表示するためです。

の仕様には次のようにVkQueuePresentInfoKHR記載されています。

pWaitSemaphoresVkSemaphoreVK_NULL_HANDLEでない場合は、エントリを持つオブジェクトの配列でありwaitSemaphoreCount、現在の要求を発行する前に待機するセマフォを指定します。

意味: レンダリングが完了していない画像は決して提示しないので、画像が提示されるとすぐに、関連する CB は使用できなくなります。

2 番目のセマフォは、同じものpresentation_finishedによってシグナルされvkAqcuireImageKHR、同じものに渡されますvkQueueSubmit(レンダリングを開始するため)。つまり、イメージのレンダリングは、プレゼンテーション エンジンによって許可された時間より早く開始されることはありません。

結論: からの現在の要求は、vkQueuePresentKHRイメージのレンダリングが完了するまで発行されず、vkAcquireImageKHRイメージが利用可能になるまでブロックされ、現在取得されたイメージが返されることもありません。

フェンスが必要な理由は何でしょうか?


問題を説明するために、概念的に重要な部分のみを含む最小限のコード例を含めました。

VkImage[] swapchain_images;
VkCommandBuffer[] command_buffers;

VkSemaphore rendering_finished;
VkSemaphore presentation_finished;

void RenderLoop()
{
    /* Acquire an image from the swapchain. Block until one is available.
       Signal presentation_finished when we are allowed to render into the image */
    int index;
    vkAcquireImageKHR(device, swapchain, UINT64_MAX, presentation_finished, nullptr, &index);

    /* (...) Frambuffer creation, etc. */

    /* Begin CB: The command pool is flagged to reset the command buffer on reuse */
    VkCommandBuffer cb = command_buffers[index];
    vkBeginCommandBuffer(cb, ...);

    /* (...) Trivial rendering of a single color image */

    /* End CB */
    vkEndCommandBuffer(cb);


    /* Queue the rendering and wait for presentation_finished.
       When rendering is finished, signal rendering_finished.

       The VkSubmitInfo will have these important members set among others:
       .pWaitSemaphores = &presentation_finished;
       .pSignalSemaphores = &rendering_finished;
    */
    vkQueueSubmit(render_queue, &submit_info);

    /* Submit the presentation request as soon as the rendering_finished
       semaphore gets signalled

       The VkPresentInfoKHR will have these important members set among others:
       .pWaitSemaphores = &rendering_finished;
    */
    vkQueuePresentKHR(present_queue, &present_info);
}

CB をレンダリング キューに送信するときにフェンスを挿入し、その CB を再度使用する前に待機すると、問題は明らかに解決されますが、説明したように冗長であるように思われます。

ベストアンサー1

vkAcquireNextImageKHR進行中の非同期操作の宛先またはソースであるイメージを返すことが許可されています。これは、コマンドバッファが再利用時に利用可能であるという保証がないことを意味します。だろうこれらのコマンドがセマフォを待機するように構成されている限り、取得したイメージに書き込むための追加の個別のコマンド バッファーをキューに登録することは正しいですpresentation_finishedが、そのコマンド バッファーを安全に再利用するには、に渡されるフェンスを待機する必要がありますvkQueueSubmit

見るセクション 29.6. WSI スワップチェーンKHR 拡張機能を備えた Vulkan 仕様:

アプリケーションはvkAcquireNextImageKHRを使用して表示可能な画像の使用権を取得できます。表示可能な画像を取得した後、それを変更する前に、アプリケーションは、同期プリミティブを使用して、プレゼンテーション エンジンがイメージからの読み取りを完了したことを確認する必要があります。その後、アプリケーションはイメージのレイアウトを遷移したり、レンダリング コマンドをキューに入れたりすることができます。最後に、アプリケーションは vkQueuePresentKHR を使用してイメージを提示し、イメージの取得を解放します。

以下の注記も参照してください。vkAcquireNextImageKHR

成功すると、vkAcquireNextImageKHRはアプリケーションが使用できる表示可能な画像を取得し、その画像のインデックスにpImageIndexを設定します。プレゼンテーションエンジンは、画像が取得された時点で画像の読み取りを完了していない可能性があります。アプリケーションはセマフォとフェンスを使用する必要があります画像のレイアウトや内容が変更されないようにするためプレゼンテーションエンジンの読み取りが完了するまで

[...]

前述のように、プレゼンテーション エンジンは、アプリケーションや論理デバイスに対して非同期になる場合があります。vkAcquireNextImageKHRは、取得されるイメージを識別でき次第、セマフォとフェンスがプレゼンテーションエンジンによって通知されることを保証できます。; すぐには正常に返されない可能性があります。アプリケーションは、タイムアウトを使用して、vkAcquireNextImageKHR がイメージの取得を待機する時間を指定します。

これは、vkAcquireNextImageKHRプレゼンテーション操作をブロックする必要がないこと、そして、プレゼンテーション操作自体が待機しているグラフィックス コマンドをブロックする必要がないことを示しています。

おすすめ記事