2016-06-06 3 views
2

С man page for vkEnumerateDeviceExtensionProperties,Вызов vkEnumerateDeviceExtensionProperties «дважды» - это требуется?

vkEnumerateDeviceExtensionProperties извлекает свойства расширений на физическом устройстве, дескриптор которого приводится в physicalDevice. Чтобы определить расширения, реализованные набором слоев , pLayerName указывает на имя слоя, и любые возвращаемые расширения реализованы этим слоем. Установка имени pLayerName в NULL вернет доступные не-слоистые расширения. pPropertyCount должен быть установлен в размере размера массива VkExtensionProperties, на который указывает pProperties. Параметры 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); 
//... 

против

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

Мой вопрос: я в зависимости от неподдерживаемых функциональности, делая это , или это как-то рекламируется где-то еще в документации?

+1

Человеко-рефлекторные страницы плохо обслуживаются банкоматом, напрямую читайте Spec. ; AFAIK вам, возможно, придется звонить четыре и более раз, в невероятном случае, если вы получите VK_INCOMPLETE. ; Ничего плохого в вашем вызове aproach тоже, и спецификация достаточно подробно об этом. – krOoze

ответ

2

От latest spec:

Для обоих vkEnumerateInstanceExtensionProperties и vkEnumerateDeviceExtensionProperties, если pProperties является NULL, то число расширений свойств, доступных возвращается в pPropertyCount. В противном случае pPropertyCount должен указывать на переменную, заданную пользователем на количество элементов в массиве pProperties, и при возврате переменная перезаписывается количеством структур, фактически написанных на pProperties. Если pPropertyCount меньше количества доступных свойств расширения, будет написано не более pPropertyCount. Если pPropertyCount меньше количества доступных расширений, VK_INCOMPLETE будет возвращен вместо VK_SUCCESS, чтобы указать, что не все доступные свойства были возвращены.

Так что ваш подход правильный, хотя он немного расточительно по памяти. Аналогичные функции, возвращающие массивы, также ведут себя так.

Также обратите внимание, что с 1.0.13 уровни устройств устарели. Все уровни экземпляров могут перехватывать команды как экземпляру, так и созданным им устройствам.

+0

спасибо - не видел новый язык спецификации. Кроме того, мой подход не расточительно по памяти - стек выделенных объектов на самом деле не «подсчитывается», если у вас не закончилось пространство стека. – MuertoExcobito

+1

@MuertoExcobito: Stack память очень стоит. Как только виртуальная страница стека будет зафиксирована, вы не сможете ее освободить. Он занимает пространство навсегда. Поэтому, если вы * регулярно * не используете тонны пространства стека, вы занимаете память, которая никогда не будет использоваться. Кроме того, многие компиляторы дают вам 1 МБ пространства стека. 1024 слоев позволяют только «VkLayerProperties» быть размером 1 КБ до переполнения. И 'sizeof (VkLayerProperties)' составляет более 500 байт. Так что это не просто расточительно; он, скорее всего, переполнится. –

+0

Справедливая точка, хотя этот код работает на всех платформах Vulkan без переполнения стека.Возможно, размер массива может немного уменьшиться, поскольку 1024 расширения, вероятно, будут излишними. – MuertoExcobito

0

Большинство Vulkan команд реле в двойных вызовов:

  1. Первый звонок, чтобы получить подсчета количества возвращения структур или ручки;
  2. Второй вызов передать массив должным образом, чтобы вернуть запрошенные структуры/дескриптор. В этом втором вызове параметр count указывает размер вашего массива.

Если на втором этапе вы получите результат VkResult :: VK_INCOMPLETE, вы передали массив слишком короткий, чтобы вернуть все объекты. Примечание VK_INCOMPLETE не ошибка, это частичный успех (2.6.2 Коды возврата ... «Все успешные коды завершения неотрицательные значения.»)

Ваш вопрос:

Am Я в зависимости от неподдерживаемой функциональности делаю , или это как-то рекламируется где-то еще в документации ?

Вы предложили создать большой массив перед вызовом функции, чтобы избежать вызова функции 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   
} 

То есть мои два цента о двойном вызове функций Вулкан. Это наивная реализация и может не работать для всех случаев! Обратите внимание, что вы должны создать вектор ДО того, как вы вызываете функцию обертывания.

Удачи!

+0

@Jherico - Спасибо за подсказку в параметре stl :: vector <>! –

+0

@NicolBolas спасибо за исправления! –

Смежные вопросы