Я использую vkEnumerateInstanceVersion, чтобы получить версию vulkan API и передать ее в структуру VkApplicationInfo. Я легко различаю VK_VERSION_1_0 и VK_VERSION_1_1
//query the api version in order to use the correct vulkan functionality
PFN_vkEnumerateInstanceVersion FN_vkEnumerateInstanceVersion =
PFN_vkEnumerateInstanceVersion(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
uint32_t *instanceVersion = (uint32_t*)malloc(sizeof(uint32_t));
VkResult result = FN_vkEnumerateInstanceVersion(instanceVersion);
//check what is returned
if (result == VK_SUCCESS){
std::cout<<"RESULT(vkEnumerateInstanceVersion) : Intance version enumeration successful"<<std::endl;
if (instanceVersion!=nullptr){
std::cout<<"API_VERSION : VK_API_VERSION_1_1"<<std::endl;
appInfo.apiVersion = VK_API_VERSION_1_1;
}
else{
std::cout<<"API_VERSION : VK_API_VERSION_1_0"<<std::endl;
}
std::cout<<"Version number returned : "<<*instanceVersion<<std::endl;
}else if (result == VK_ERROR_OUT_OF_HOST_MEMORY){
std::cerr<<"RESULT(vkEnumerateInstanceVersion) : VK_ERROR_HOST_OUT_OF_MEMORY"<<std::endl;
}else{
std::cerr<<"RESULT(vkEnumerateInstanceVersion) : Something else returned while enumerating instance version"<<std::endl;
}
Я использую приведенный выше код, чтобы получить версию API. В спецификации вулкана указано:
Чтобы запросить версию функциональности уровня экземпляра, поддерживаемую реализация, звоните: // Предоставлено VK_VERSION_1_1 VkResult vkEnumerateInstanceVersion( uint32_t* pApiVersion);
Комментарий в блоке выше означает, что это предоставлено VK_VERSION_1_1, а не VK_VERSION_1_0. Теперь, когда я открываю терминал и набираю:
vulkaninfo | head -n 5
Я получаю следующее:
ERROR: [Loader Message] Code 0 : /usr/lib32/libvulkan_intel.so: wrong ELF class: ELFCLASS32
ERROR: [Loader Message] Code 0 : /usr/lib32/libvulkan_radeon.so: wrong ELF class: ELFCLASS32
==========
VULKANINFO
==========
Vulkan Instance Version: 1.2.159
Это означает, что у меня есть VK_API_VERSION_1_2. Я хочу получить точную версию API. При выполнении первого блока кода я получаю:
RESULT(vkEnumerateInstanceVersion) : Intance version enumeration successful
API_VERSION : VK_API_VERSION_1_1
Version number returned : 4202655
Есть ли способ определить VK_VERSION_1_1 или VK_VERSION_1_2 в программе. Также я проверяю справочник vulkan для версии 1.2.165
Переход только от instanceVersion к FN_vkEnumerateInstanceVersion дает ошибку
Я попробовал это первым: uint32_t *instanceVersion; FN_vkEnumerateInstanceVersion(instanceVersion);
Я не говорил создавать переменную стека, которая является указателем на целое число. Я сказал создать переменную стека, которая является целым числом; затем вы передаете указатель на эту переменную Vulkan. Я надеюсь, что вы не используете кучу других вещей где-то еще в своем коде Vulkan.
Хорошо, позвольте мне попробовать это... Нет, я этого не делаю... пока что в моем файле cpp присутствует только 116 строк кода.
uint32_t instanceVersion, *pInstanceVersion; pInstanceVersion = &instanceVersion;
?
А потом FN_vkEnumerateInstanceVersion(pInstanceVersion);
Я не понимаю, в чем проблема. Версия экземпляра возвращается из файла vkEnumerateInstanceVersion. Вот и все. Что вы имеете в виду под "точной версией API". Насколько точнее вы хотите этого, чем то, что дает вам команда?
@krOoze Возвращает число. Как я узнаю, что это 1.1 или 1.2 во время выполнения?
Ладно, никогда не знал, что такой макрос существует... Спасибо... @krOoze. Это имеет больше смысла.
Я использую vkEnumerateInstanceVersion, чтобы получить версию vulkan API и передать ее в структуру VkApplicationInfo.
VkEnumerateInstanceVersion не для этого.
VkApplicationInfo::apiVersion указывает версию Vulkan, для которой написан ваш код. Эта версия должна быть фиксированным значением, потому что ваш код не может быть написан для версий Vulkan, которых еще не существует. То есть, если вы пишете приложение, работающее против 1.1, то вы указываете VK_VERSION_1_1.
Вы все еще можете получить версию 1.2, но это нормально, потому что все основные версии Vulkan обратно совместимы с более низкими младшими номерами версий. Поэтому, если вы напишете свой код для Vulkan 1.1, он будет работать на любой реализации 1.2.
Вы также неправильно используете версию экземпляра. Версия экземпляра — это версия механизма экземпляра Vulkan, а не реализации Vulkan в целом. Вы можете быть подключены к оборудованию экземпляра 1.2, но реализация устройства Vulkan может дать вам только 1.1. Это нормально, что касается Вулкана.
Что касается деталей вашего кода:
Этот код фактически не различает Vulkan 1.0 и Vulkan 1.1 правильно. Действительно, он содержит множество ошибок и запутанных битов.
Первая нерешенная потенциальная проблема — это возможность того, что реализация экземпляра слишком старая для поддержки vkEnumerateInstanceVersion. Поскольку эта функция не предусмотрена реализациями экземпляра Vulkan 1.0, вы должны сначала убедиться, что функция действительно существует. То есть вы должны проверить значение FN_vkEnumerateInstanceVersion перед его вызовом. Если функция не существует, версия экземпляра должна быть 1.0.
Далее вы вызываете функцию. Но функция не может дать сбой; он может вернуть только код ошибки VK_SUCCESS. Поэтому нет смысла проверять его код результата.
Как только вы идете, чтобы проверить фактическое значение, о котором идет речь, вы делаете что-то странное. Вы тестируете instanceVersion!=nullptr. Но в этом нет смысла, потому что это всегда будет указывать на действительную память. Поэтому делать из этого вывод о том, что версия реализации экземпляра 1.1, просто неправильно.
Значение номера версии в Vulkan четко указано в спецификации. В вашем случае, если вы просто ищете основной и дополнительный номера версий, вы можете отрезать номера версий патчей.
Таким образом, правильный код для получения версии экземпляра будет таким:
auto FN_vkEnumerateInstanceVersion = PFN_vkEnumerateInstanceVersion(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
if (FN_vkEnumerateInstanceVersion == nullptr)
return VK_API_VERSION_1_0;
else
{
uint32_t instanceVersion;
auto result = FN_vkEnumerateInstanceVersion(&instanceVersion);
return instanceVersion & 0xFFFFF000; //Remove the patch version.
}
Итак, я неправильно понял vkspec. Спасибо! :-)
@brightprogrammer: Пожалуйста, прочтите и мои последние правки.
@NicolBolas Спасибо за ваш ответ, он очень полезен. Однако я хочу отметить, что версия патча состоит из 12-битной, а не 16-битной версии. Таким образом, маска должна быть 0xFFFFF000.
Вы можете получить информацию о версии Vulkan из версии экземпляра, возвращаемой vkEnumerateInstanceVersion, с помощью 3 макросов, определенных в заголовке vulkan.
Вот фрагмент, который делает трюк:
uint32 instanceVersion = VK_API_VERSION_1_0;
auto FN_vkEnumerateInstanceVersion = PFN_vkEnumerateInstanceVersion(vkGetInstanceProcAddr(nullptr, "vkEnumerateInstanceVersion"));
if (vkEnumerateInstanceVersion){
vkEnumerateInstanceVersion(&instanceVersion );
}
// 3 macros to extract version info
uint32_t major = VK_VERSION_MAJOR(instanceVersion);
uint32_t minor = VK_VERSION_MINOR(instanceVersion);
uint32_t patch = VK_VERSION_PATCH(instanceVersion);
cout << "Vulkan Version:" << major << "." << minor << "." << patch << endl;
Это напечатает что-то вроде строк:
Vulkan Version:1.1.121
Почему вы выделяете целое число в куче, а не просто заполняете переменную стека?