3

注: 私は最新の OpenGL の知識がほとんどない Vulkan を自己学習しています。

Vulkan の仕様を読むと、コマンド バッファーとスワップチェーンの同期を可能にする非常に優れたセマフォが表示されます。これは、単純な(しかし非効率的だと思う)物事を行う方法であると私が理解していることです。

  1. vkAcquireNextImageKHR、シグナリングで画像を取得sem_post_acq
  2. 以下を使用してコマンド バッファーをビルドします (または事前にビルドされたものを使用します)。
    • 画像を移行するための画像バリアVK_IMAGE_LAYOUT_UNDEFINED
    • 与える
    • 画像を遷移する画像バリアVK_IMAGE_LAYOUT_PRESENT_SRC_KHR
  3. sem_post_acqキューに送信し、フラグメント ステージで待機し、シグナリングしsem_pre_presentます。
  4. vkQueuePresentKHRお待ちしておりsem_pre_presentます。

ここでの問題は、コマンド バッファー内のイメージ バリアが、どのイメージが遷移しているかを認識している必要があることです。つまりvkAcquireNextImageKHR、コマンド バッファーの作成方法 (または送信するビルド済みのコマンド バッファー) を知る前に、元に戻らなければなりません。ただし、vkAcquireNextImageKHR潜在的に多くのスリープが発生する可能性があります (プレゼンテーション エンジンがビジー状態で、空き画像がないため)。一方で、コマンド バッファーの送信自体にコストがかかります。さらに重要なことは、最終結果がどのイメージにレンダリングされるかを知らなくても、フラグメントの前のすべてのステージを実行できることです。

理論的には、次のようなスキームを使用すると、より高度な並列処理が可能になるように思えます。

  1. 以下を使用してコマンド バッファーをビルドします (または事前にビルドされたものを使用します)。
    • 画像を移行するための画像バリアVK_IMAGE_LAYOUT_UNDEFINED
    • 与える
    • 画像を遷移する画像バリアVK_IMAGE_LAYOUT_PRESENT_SRC_KHR
  2. sem_post_acqキューに送信し、フラグメント ステージで待機し、シグナリングしsem_pre_presentます。
  3. vkAcquireNextImageKHR、シグナリングで画像を取得sem_post_acq
  4. vkQueuePresentKHRお待ちしておりsem_pre_presentます。

これもまた、理論的には、vkAcquireNextImageKHR. これが機能しない唯一の理由は、このイメージが後で決定されることを (適切な同期で) コマンド バッファに伝えることも、プレゼンテーション エンジンに特定のイメージを要求することもできないことです。


私の最初の質問は、私の分析は正しいですか? もしそうなら、そのような最適化はVulkanではまったく不可能ですか?なぜですか?


vkAcquireNextImageKHR2 番目の質問は、取得したい特定の画像を特定して、それらを自分で反復処理できれば、より理にかなっていると思いませんか? そうすれば、どのイメージを要求するかを事前に知ることができ、それに応じてコマンド バッファーを構築して送信できます。

4

2 に答える 2

4

Nicol が言ったように、レンダリング先の画像に関係なく、セカンダリを記録できます。

ただし、さらに一歩進んで、すべての swpachain イメージのコマンド バッファを事前に記録し、取得したイメージから送信する正しいイメージを選択することができます。

このタイプの再利用では、使用されるすべてのメモリ範囲がコマンド バッファーに焼き付けられるため、特別な考慮が必要になります。しかし、多くの場合、必要なレンダリング コマンドは実際にはフレームを次のフレームに変更せず、使用されるデータはほんのわずかです。

したがって、そのようなフレームのシーケンスは次のようになります。

vkAcquireNextImageKHR(vk.dev, vk.swap, 0, vk.acquire, VK_NULL_HANDLE, &vk.image_ind);
vkWaitForFences(vk.dev, 1, &vk.fences[vk.image_ind], true, ~0);

engine_update_render_data(vk.mapped_staging[vk.image_ind]);

VkSubmitInfo submit = build_submit(vk.acquire, vk.rend_cmd[vk.image_ind], vk.present);
vkQueueSubmit(vk.rend_queue, 1, &submit, vk.fences[vk.image_ind]);

VkPresentInfoKHR present = build_present(vk.present, vk.swap, vk.image_ind);
vkQueuePresentKHR(vk.queue, &present);

確かに、これは条件付きレンダリングを許可しませんが、gpu は一般に、目立った遅延なしで一部のジオメトリをフレーム外にレンダリングできるほど十分に高速です。そのため、プレーヤーが新しいジオメトリを表示する必要がある読み込みゾーンに到達するまで、それらのコマンド バッファーを有効にしておくことができます。

于 2016-06-23T10:31:34.627 に答える