2

vkEnumerateDeviceExtensionPropertiesのマニュアルページから、

vkEnumerateDeviceExtensionProperties は、physicalDevice でハンドルが指定されている物理デバイスの拡張機能のプロパティを取得します。層によって実装される拡張機能を決定するには、層の名前を指すように pLayerName を設定し、返される拡張機能はその層によって実装されます。pLayerName を NULL に設定すると、使用可能な非レイヤー エクステンションが返されます。pPropertyCount は、pProperties が指す VkExtensionProperties 配列のサイズに設定する必要があります。pProperties は、入力する VkExtensionProperties の配列または null を指す必要があります。null の場合、vkEnumerateDeviceExtensionProperties は、見つかった拡張機能の数で pPropertyCount を更新します。VkExtensionProperties の定義は次のとおりです。

(強調鉱山)。現在の実装 (Window SDK v1.0.13) では、nullかどうかに関係なく、拡張機能の数で更新されているpPropertyCount ようです。pPropertiesただし、ドキュメントは、この状況で何が起こるかについて明示していないようです。

このような機能を持つことが「より良い」理由の例を次に示します。

const uint32_t MaxCount = 1024; // More than you'll ever need
uint32_t ActualCount = MaxCount;
VkLayerProperties layers[MaxCount];
VkResult result = vkEnumerateDeviceLayerProperties(physicalDevice, &ActualCount, layers);
//...

対。

uint32_t ActualCount = 0;
VkLayerProperties* layers;
VkResult result = vkEnumerateDeviceLayerProperties(physicalDevice, &ActualCount, nullptr);
if (ActualCount > 0) 
{
    extensions = alloca(ActualCount * sizeof(VkLayerProperties));
    result = vkEnumerateDeviceLayerProperties(physicalDevice, &ActualCount, layers);
    //...
}

私の質問は、これを行うことでサポートされていない機能に依存しているのでしょうか、それともドキュメントのどこかで宣伝されているのでしょうか?

4

2 に答える 2

0

ほとんどの Vulkan コマンドは、二重呼び出しでリレーします。

  1. 返される構造体またはハンドルのカウント数を取得するための最初の呼び出し。
  2. 適切なサイズの配列を渡して、要求された構造体/ハンドルを取得するための 2 番目の呼び出し。この 2 番目の呼び出しでは、count パラメーターが配列のサイズを示します。

2 番目のステップで VkResult::VK_INCOMPLETE の結果が得られた場合は、短すぎる配列を渡してすべてのオブジェクトを取得できません。注 VK_INCOMPLETE はエラーではなく、部分的な成功です (2.6.2 リターン コード ... "すべての成功した完了コードは負でない値です。")

あなたの質問 :

これを行うことでサポートされていない機能に依存していますか、それともドキュメントのどこかで宣伝されていますか?

Vulkan関数を2回呼び出すのを避けるために、関数を呼び出す前に大きな配列を作成することを提案しました。

私の回答: はい、配列のサイズを「推測」することで、設計上の決定を誤っています。

誤解しないでください。同じ関数を 2 回呼び出すのが煩わしいという意見には強く同意しますが、これらの並べ替え関数をよりプログラマーに優しい動作でラップすることで解決できます。

説明のために、別の Vulkan 関数を使用します。への二重呼び出しを避けたいとしましょう:

VkResult vkEnumeratePhysicalDevices(
VkInstance                                  instance,
uint32_t*                                   pPhysicalDeviceCount,
VkPhysicalDevice*                           pPhysicalDevices);

考えられる解決策は、スイート ラップ関数を記述することです。

VkResult getPhysicalDevices(VkInstance instance,  std::vector<VkPhysicalDevice>& container){
   uint32_t count = 0;
   VkResult res = vkEnumeratePhysicalDevices(instance, &count, NULL); // get #count
   container.resize(count); //Removes extra entries or allocates more.
   if (res < 0) // something goes wrong here
         return res;       
   res =  vkEnumeratePhysicalDevices(instance, &count, container.data()); // all entries overwritten.
   return res; // possible OK        
}

これは、Vulkan 関数への二重呼び出しに関する私の 2 セントです。これは単純な実装であり、すべてのケースで機能するとは限りません! ラッピング関数を呼び出す前にベクトルを作成する必要があることに注意してください。

幸運を!

于 2016-06-07T16:40:27.473 に答える