LINUX.ORG.RU

Vulkan API — (vkEnumeratePhysicalDevices() == VK_ERROR_INITIALIZATION_FAILED) = true

 , , , ,


0

1

имеется видяха gtx1650 и такой код — и он по непонятной мне причине выдает VK_ERROR_INITIALIZATION_FAILED при попытке заполнить массив VkPhysicalDevice'ов:

`--> ./src/vulkan_xcb
Detected devices: 1
terminate called after throwing an instance of 'std::runtime_error'
  what():  In Devices::PhysicalDevices() vkEnumeratePhysicalDevices returned VK_ERROR_INITIALIZATION_FAILED
zsh: abort (core dumped)  ./src/vulkan_xcb


п.с. при ентом первый прогон с nullptr указателем все же находит 1 девайс, что правда.
п.п.с система арч.

★★

Последнее исправление: safocl (всего исправлений: 5)

Ответ на: комментарий от anonymous

не — я тока начал с вулканом разбираться
мне интересно — у других будет норм — енто у меня траббла какая то или в коде?

safocl ★★
() автор топика
Ответ на: комментарий от safocl

Нет, не норм. На с++ так легко наговнокодить, что сразу не понятно, где баг

deadplace
()

Короче, приводи в соответствие

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stdint.h>
#include <vulkan/vulkan.h>

int main () {
    VkInstance instance;
    VkInstanceCreateInfo instanceCreateInfo;
    VkApplicationInfo    appInfo;

    memset (&instanceCreateInfo, 0, sizeof (instanceCreateInfo));
    memset (&appInfo, 0, sizeof (appInfo));

    appInfo.applicationVersion = VK_MAKE_VERSION (1, 0, 0);
    appInfo.apiVersion         = VK_MAKE_VERSION (1, 0, 0);
    appInfo.engineVersion      = VK_MAKE_VERSION (1, 0, 0);
	nfo.pApplicationName   =	
    appInfo.pEngineName        = "No engine";
    appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;

    instanceCreateInfo.pApplicationInfo = &appInfo;
    instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;

    VkResult res = vkCreateInstance (&instanceCreateInfo, NULL, &instance);
    if (res != VK_SUCCESS) {
        exit (1);
    }

	32_t count = 0;
    vkEnumeratePhysicalDevices (instance, &count, NULL);
    if (count == 0) {
        exit (1);
    }

    VkPhysicalDevice dev;
    count = 1;
    vkEnumeratePhysicalDevices (instance, &count, &dev);

	ysicalDeviceProperties deviceProperties;
    vkGetPhysicalDeviceProperties(dev, &deviceProperties);

    printf ("%s\n", deviceProperties.deviceName);

    return 0;
}
deadplace
()

std::vector< VkPhysicalDevice > devices;

Не уверен, что при такой инициализации там найдется место под count устройств, например

deadplace
()
Ответ на: комментарий от safocl

ну так настраивай, с этого нужно начинать

создавай в каталоге с бинарём программы vk_layer_settings.txt с содержимым

khronos_validation.enables=VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT
khronos_validation.report_flags=error,warn,perf,info

https://vulkan.lunarg.com/doc/view/latest/linux/layer_configuration.html

anonymous
()
#include <iostream>
#include <cstdint>
#include <cstdlib>
#include <vulkan/vulkan.h>
#include <vector>
#include <vulkan/vulkan_core.h>
#include <string_view>
#include <xcb/xcb.h>
#include <vulkan/vulkan_xcb.h>
#include <stdexcept>

namespace core::vk {

class Instance final {
    VkInstance                        instance;
    static constexpr std::string_view appName { "vulkan_xcb" };
    static constexpr std::string_view engineName { "vulkan_xcb" };
    static constexpr uint32_t         appVersion { 1 };
    static constexpr uint32_t         engineVersion { 1 };
    static constexpr uint32_t         apiVersion { VK_MAKE_VERSION(
    1, 0, 3 ) };
    std::vector< const char * >       extensions {
        { VK_KHR_SURFACE_EXTENSION_NAME,
          VK_KHR_XCB_SURFACE_EXTENSION_NAME }
    };
    VkInstanceCreateInfo instanceCreateInfo {};
    VkApplicationInfo    appInfo {};

public:
    Instance() {
        appInfo.applicationVersion = appVersion;
        appInfo.apiVersion         = apiVersion;
        appInfo.engineVersion      = engineVersion;
        appInfo.pApplicationName   = appName.data();
        appInfo.pEngineName        = engineName.data();
        appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
        appInfo.pNext = nullptr;

        instanceCreateInfo.pApplicationInfo = &appInfo;
        instanceCreateInfo.sType =
        VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
        instanceCreateInfo.pNext = nullptr;
        instanceCreateInfo.flags = 0;

        instanceCreateInfo.enabledExtensionCount = extensions.size();
        instanceCreateInfo.ppEnabledExtensionNames =
        extensions.data();

        auto result =
        vkCreateInstance( &instanceCreateInfo, nullptr, &instance );
        switch ( result ) {
        case VK_SUCCESS: break;
        case VK_ERROR_INCOMPATIBLE_DRIVER:
            throw std::runtime_error(
            "VK_ERROR_INCOMPATIBLE_DRIVER" );
            break;
        default:
            throw std::runtime_error( "Unknow error in VkInstance" );
        }
    }
    ~Instance() { vkDestroyInstance( instance, nullptr ); std::cout << "RR" << std::endl; }

    VkInstance get() const { return instance; }
};

class Devices final {
    struct PhysicalDevices final {
        std::uint32_t                   count;
        std::vector< VkPhysicalDevice > devices;

        PhysicalDevices( Instance &instance ) :
        count { [ &instance ]() -> std::uint32_t {
            std::uint32_t count { 0 };
            vkEnumeratePhysicalDevices(
            instance.get(), &count, nullptr );
            return count;
        }() },
        devices { count } {
            VkResult result = vkEnumeratePhysicalDevices(
            instance.get(),
            &count,
            const_cast< VkPhysicalDevice * >( devices.data() ) );
            std::cout << "Detected devices: " << devices.size()
                      << std::endl;

            switch ( result ) {
            case VK_SUCCESS: break;
            case VK_ERROR_OUT_OF_DEVICE_MEMORY:
                throw std::runtime_error {
                    "In Devices::PhysicalDevices() vkEnumeratePhysicalDevices returned VK_ERROR_OUT_OF_DEVICE_MEMORY"
                };
            case VK_ERROR_INITIALIZATION_FAILED:
                throw std::runtime_error {
                    "In Devices::PhysicalDevices() vkEnumeratePhysicalDevices returned VK_ERROR_INITIALIZATION_FAILED"
                };
            case VK_ERROR_OUT_OF_HOST_MEMORY:
                throw std::runtime_error {
                    "In Devices::PhysicalDevices() vkEnumeratePhysicalDevices returned VK_ERROR_OUT_OF_HOST_MEMORY"
                };
            default:
                std::cout << count << std::endl;
                throw std::runtime_error {
                    "In Devices::PhysicalDevices() vkEnumeratePhysicalDevices returned failure"
                };
            }
        }
        ~PhysicalDevices() {}
    };

    struct LogicalDevices final {};

    Instance        &instance;
    PhysicalDevices physDevices;

public:
    Devices( Instance &instance ) :
    instance { instance }, physDevices( instance ) {}

    void printDevicesInfo() const {
        VkPhysicalDeviceProperties phDevProp;
        for ( auto && device : physDevices.devices ) {
            vkGetPhysicalDeviceProperties( device, &phDevProp );
            std::cout << phDevProp.deviceName << std::endl;
        }
    }
};

}   // namespace core::vk

int main() {
    core::vk::Instance vkInstance {};

    core::vk::Devices devices { vkInstance };
    devices.printDevicesInfo();

    return EXIT_SUCCESS;
}

P.S. учи c++

P.P.S. новые глаза мне должен. Достали своими неуместными переносами строк, лишь бы в 80-100 символов влезло :(

robus ★★★★★
()
Ответ на: комментарий от deadplace

в смсле под какой count устройств? енто же вектор девайсов уже — там нету count...

safocl ★★
() автор топика
Ответ на: комментарий от robus

да — спс — так работает — сча посмотрю какая разница в коде — чот я не понял где и чо — вроде все тоже самое...

safocl ★★
() автор топика
Ответ на: комментарий от safocl

Instance в исправленном передаётся по ссылке, а не по значению. А в изначальном просто срабатывал деструктор на временный объект и удалял вулкан инстанц.

robus ★★★★★
()
Ответ на: комментарий от robus

так я вроде тоже так до ентого пробовал — но я делал константные ссылки — чот с ними не прокатывает почему то...

safocl ★★
() автор топика
Ответ на: комментарий от safocl

ясно — я в лямбде забыл по ссылке значение инстанса захватить — там оно и удалялося...

safocl ★★
() автор топика
Ответ на: комментарий от robus

типа было не очень отличным решением делать RAII подобное поведение у инстанса? — мне чот изначально показалося удобным...
а если не уследить за временем жизни — то будет пичаль.

safocl ★★
() автор топика

спс за утыканье в трабблу... чот перед сном не мог ее усмотреть — даже гдб проганял — но не понял чо происходит...

safocl ★★
() автор топика

еще в планах сделать

operator VkInstance()

для более удобного юзания без get().

safocl ★★
() автор топика
Ответ на: комментарий от safocl

а изначально было в планах раздавать шаред поинтер от VkInstance. Поскольку как я понимаю инстанс должен быть один в проге... и его лучше сделать потипу сингл тона?

safocl ★★
() автор топика
Ответ на: комментарий от safocl

У вас здесь

    Instance        instance; // <---------- копируется сюда
    PhysicalDevices physDevices;

public:
    Devices( Instance instance ) :
    instance { instance }, physDevices( instance ) {} // <--------- копирование происходит здесь

структура Instance копируется в Devices, вне зависимости от того, по значению вы ее передаете, или по константной ссылке.

Здесь же

        PhysicalDevices( Instance instance ) :
        count { [ instance ]() -> std::uint32_t {
            std::uint32_t count { 0 };
            vkEnumeratePhysicalDevices(
            instance.get(), &count, nullptr );
            return count;
        }() },

если бы вы передавали по (константной) ссылке, все должно было бы быть в порядке, но в данный момент здесь происходит второе копирование Instance. Итого, у вас 3 экземпляра Instance «владеют» одним и тем же ресурсом.

edit: вру, еще одно (третье) копирование происходит при захвате instance в лямбду.

Siborgium ★★★★★
()
Последнее исправление: Siborgium (всего исправлений: 2)
Ответ на: комментарий от Siborgium

да енто не первая вариация кода — до того как написать суда — я думал чо инстанс за счет RAII эффекта убивается — делал все по константным ссылкам, вот тока в лямбде действительно пропустил поставить амперсанд.

а в девайсе я тоже сохранял инстанс уже после первых попыток отладки... — и ваше его там следует хранить по указателю — shared_ptr например — енто так просто набросок кода — для тестинга самого апи... — ваще не думал особо над его переприменимостью — ну вот как раз на ентих ошибках сделаю нормальные выводы как буду строить архитектуру своей уже реальной проги...

safocl ★★
() автор топика
Последнее исправление: safocl (всего исправлений: 1)
Ответ на: комментарий от safocl

зачем тебе вообще убивать instance? он тебе наиболее вероятно нужен на всём протяжении работы программы. местных царей си++шки наслушался?

anonymous
()
Ответ на: комментарий от xaizek

devices { count }

Тут круглые скобки нужны.

@robus, ты, кстати, тоже этот момент пропустил.

А всё потому что @safocl решил выпендриться с форматированием кода. Ну молодец, выпендрился. Баг спрятал хорошо.

i-rinat ★★★★★
()
Ответ на: комментарий от anonymous

никаво не слушал — просто изначально почему то появилась ента идея — но так да — сча уже понял чо енто никчему...

safocl ★★
() автор топика
Ответ на: комментарий от i-rinat

Можно и круглые (ТС похоже экспериментирует, потом вернётся к нормальному написанию кода), но не обязательно. Это синтаксис инициализации из C++11.

xaizek ★★★★★
()
Ответ на: комментарий от i-rinat

зачем там круглые скобки то? енто тоже инициализация через фигурные жеж...

safocl ★★
() автор топика
Ответ на: комментарий от safocl

Просто RAII надо делать правильно, отражая в обёртке свойства ресурса. В данном случае класс должен быть move-only, чтобы его нельзя было копировать. Или сначала даже без перемещения, если оно не нужно.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

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

safocl ★★
() автор топика
Ответ на: комментарий от xaizek

да я понял уже, спс — я просто вначале думал чо енто будет юзаться несколько иначе — не во всей ше проге должен быть все время инициализирован инстанс вулкана — по ентому и решил его так сделать... что бы не делать доп метода потипу destroy().

safocl ★★
() автор топика
Ответ на: комментарий от safocl

например

Instanse instanse();
 — чо енто за запись??? енто функция которая возвращает объект типа Instance??? или чо?
т.е. прототип ентой функции ессесна...
или же енто инициализация объекта типа Instance???
типа понятно чо внутри функций енто только второй случай — но все равно....

safocl ★★
() автор топика
Последнее исправление: safocl (всего исправлений: 3)
Ответ на: комментарий от safocl

В списке инициализации без разницы: и переменные и конструкторы можно вызывать используя {}. В других местах скобки часто не нужны, достаточно =. Я в этом примере сразу вижу тонну скобок и всё выглядит как блоки кода в блоках кода, этим оно мне и не нравится.

xaizek ★★★★★
()
Ответ на: комментарий от xaizek

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

safocl ★★
() автор топика
Ответ на: комментарий от xaizek

Можно и круглые (ТС похоже экспериментирует, потом вернётся к нормальному написанию кода), но не обязательно.

Результат этих выражений разный. Потому что с круглыми вызывается конструктор с int, а с фигурными — с std::initializer_list<>. Поэтому вот эта программа:

#include <iostream>
#include <vector>

int main(void) {
  std::vector<int> v1{99};
  std::vector<int> v2(99);

  std::cout << "v1, " << v1.size() << std::endl;
  std::cout << "v2, " << v2.size() << std::endl;
  return 0;
}

напечатает

v1, 1
v2, 99

Сюрприз!

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

А, мы же о векторе, я про типы вроде int почему-то думал. Но всё равно, ТСа спасло то, что конструктор с std::initializer_list здесь отвалится по SFINAE:

#include <iostream>
#include <string>
#include <vector>

// не знаю, как на самом деле, но написано opaque, скорее указатель на incomplete struct, но даже это работает "как ожидается"
using VkPhysicalDevice = void *;

int
main(void)
{
    std::vector<VkPhysicalDevice> v1(10);
    std::vector<VkPhysicalDevice> v2{10};

    std::cout << v1.size() << std::endl;
    std::cout << v2.size() << std::endl;

    return 0;
}
10
10
xaizek ★★★★★
()
Ответ на: комментарий от safocl

У тебя какой-то неправильный RAII. Нужно запретить копирование (или сделать его адекватным) и опционально навернуть move-семантику. То что у тебя все ломается из-за забытого значка & — говнокод.

filosofia
()
Ответ на: комментарий от robus

У меня была такая мысля, но я подумал, что раз компилятор не ругнулся, то всё ок. Как кодеры на цэпэпэ вообще умудряются на нём кодить?

deadplace
()
Ответ на: комментарий от i-rinat

ну собсна я так и грил выше... — чо фигурные скобки по возможности сначала подставляют конструктор с инишиалайзер листом...

safocl ★★
() автор топика
Ответ на: комментарий от filosofia

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

safocl ★★
() автор топика
Ответ на: комментарий от deadplace

так енто не ошибка синтаксиса — по ентому компилятор и не ругается — енто ошибка в логике проги...

safocl ★★
() автор топика
Ответ на: комментарий от filosofia

ну да — но в нем выполняется разрушение инстанса — того же, которого хранит и первоначальный объект...

safocl ★★
() автор топика
Ответ на: комментарий от deadplace

как раз нет — переменная не живая если уже вызвался деструктор...

safocl ★★
() автор топика
Ответ на: комментарий от xaizek

Да, пропустил этот момент. В этот раз грабли не сработали.

i-rinat ★★★★★
()
Ответ на: комментарий от filosofia

Нужно запретить копирование (или сделать его адекватным) и опционально навернуть move-семантику

В данном конкретном случае логичнее именно что ссылку (или указатель) на Instance иметь. Потому что семантически инстанц не часть набора VkDevice-ов и владение им не должно переходить ни к конструктору, ни к лямбде, ни к Devices.

А ещё это лаконичнее.

robus ★★★★★
()
Ответ на: комментарий от deadplace

Ну я хз даже. По большей части просто думаем, что делаем, а не фигачим строки не приходя в сознание :D

robus ★★★★★
()
Ответ на: комментарий от i-rinat

Нет. VkPhysicalDevice является в вулкане dispatchable handle. А значит на всех архитектурах / платформах развернётся в указатель (не в число).

robus ★★★★★
()
Последнее исправление: robus (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.