调用vkEnumerateDeviceExtensionProperties"两次" - 需要吗?

时间:2016-06-06 16:35:31

标签: c++ vulkan

来自man page for vkEnumerateDeviceExtensionProperties

  

vkEnumerateDeviceExtensionProperties检索的属性   物理设备上的扩展,其句柄在   physicalDevice。确定图层集实现的扩展   pLayerName指向图层的名称和任何返回的扩展名   由该层实现。将pLayerName设置为NULL将返回   可用的非图层扩展。 pPropertyCount必须设置为   pProperties指向的VkExtensionProperties数组的大小。该   pProperties应该指向一个VkExtensionProperties数组   填写或null。 如果为null,则vkEnumerateDeviceExtensionProperties将   使用找到的扩展数更新pPropertyCount。   VkExtensionProperties的定义如下:

(强调我的)。在当前的实现(Window SDK v1.0.13)中,无论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);
//...

VS

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);
    //...
}

我的问题是:我是通过这样做取决于不受支持的功能,还是以某种方式在文档中的其他位置做广告?

2 个答案:

答案 0 :(得分:2)

来自latest spec

  

对于vkEnumerateInstanceExtensionProperties和vkEnumerateDeviceExtensionProperties,如果pProperties为NULL,则在pPropertyCount中返回可用的扩展属性数。否则,pPropertyCount必须指向用户设置的变量到pProperties数组中的元素数量,并且在返回时,变量将被实际写入pProperties 的结构数覆盖。如果pPropertyCount小于可用的扩展属性数,则最多将写入pPropertyCount结构。如果pPropertyCount小于可用的扩展数,则将返回VK_INCOMPLETE而不是VK_SUCCESS,以指示并未返回所有可用属性。

所以你的方法是正确的,即使它在内存上有点浪费。返回数组的类似函数也表现如下。

另请注意,自1.0.13起,不推荐使用设备层。所有实例层都能够拦截实例和从其创建的设备的命令。

答案 1 :(得分:0)

大多数Vulkan命令在双重调用中进行中继:

  1. 首先调用以获取返回结构或句柄的计数;
  2. 第二次调用传递正确大小的数组以获取请求的结构/句柄。在第二次调用中,count参数指示数组的大小。
  3. 如果在第二步中获得VkResult :: VK_INCOMPLETE结果,那么您传递的数组太短而无法返回所有对象。注意VK_INCOMPLETE不是错误,它是部分成功(2.6.2返回代码......"所有成功的完成代码都是非负值。")

    你的问题:

      

    我是否依赖于不支持的功能   这个,或者是以某种方式在其他地方做广告   文档?

    你建议在调用函数之前创建一个大数组,以避免两次调用Vulkan函数。

      

    我的回答:是的,你正在做一个糟糕的设计决定"猜测"   数组大小。

    请不要误解我的意思。 我非常同意你两次调用同一个函数很烦人,但你可以通过将这些排序函数包装得更友好的行为来解决它。

    我将使用另一个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函数的双重调用,这是我的两分钱。 这是一个天真的实现,可能不适用于所有情况!请注意,您必须在调用包装函数之前创建向量。

    祝你好运!