Приложение Vulkan получило сообщение об ошибке при отправке в очередь под мьютексом - PullRequest
0 голосов
/ 19 апреля 2020

У меня есть приложение с Vulkan для рендеринга и glfw для управления окнами. Если я запускаю несколько потоков, каждый из которых имеет свое окно, я получаю ошибки при обработке потоков и очереди, даже если ВСЕ вызовы vulkan защищены общим мьютексом. Слой вулкана говорит:

ОШИБКА РЕЗЬБЫ: объект типа VkQueue одновременно используется в потоке 0x0 и потоке 0x7fc365b99700

Вот скелет l oop под что происходит в каждом потоке:

while (!finished) {
    window.draw(...);
    std::this_thread::sleep_for(std::chrono::milliseconds(10));
}

Скелет функции рисования выглядит следующим образом:

draw(Arg arg) {
    static std::mutex mtx;
    std::lock_guard lock{mtx};
    // .... drawing calls. Including
    device.acquireNextImageKHR(...);
    // Fill command bufers
    graphicsQueue.submit(...);
    presentQueue.presentKHR(presentInfo);
}

Это C ++ 17, который немного упрощает синтаксис, но в остальном не имеет значения. Понятно, что все под мьютексом. Я также перехватываю вызов отладочного сообщения. Когда я это делаю, я вижу, что один поток ожидает события glfw, один печатает сообщение слоя vulkan, а два других потока пытаются получить мьютекс для lock_guard. Я в растерянности относительно того, что происходит или как даже выяснить, что вызывает это.

Я работаю на linux, и это не вызывает sh. Однако в Ma c OS X, после случайного промежутка времени, код вызовет sh в вызове MoltenVK для отправки в очередь, и когда происходит cra sh, я вижу похожую ситуацию с потоками. То есть, никакой другой поток не находится внутри вызова Vulkan.

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

PS: я создал полный MCVE в рамках Vookoo. Это в https://github.com/FunMiles/Vookoo/tree/lock_guard_queues и является примером 00-параллельных треугольников Чтобы попробовать это, сделайте следующее:

git clone https://github.com/FunMiles/Vookoo.git
cd Vookoo
git checkout lock_guard_queues
mkdir build
cd build
cmake ..
make
examples/00-parallelTriangles

1 Ответ

0 голосов
/ 21 апреля 2020

Как вы называете ничью:

    window.draw(device, fw.graphicsQueue(), [&](){//some lambda});

Внутренности draw защищены мьютексом, но fw.graphicsQueue() нет.

fw.graphicsQueue() миллион Слои абстракции ниже просто вызывают vkGetDeviceQueue. Я обнаружил, что выполнение vkGetDeviceQueue параллельно с vkQueueSubmit вызывает ошибку проверки.

Таким образом, здесь есть несколько проблем:

  • В слоях есть ошибка, которая вызывает многократную инициализацию VkQueue состояние на vkGetDeviceQueue, которое является причиной ошибки проверки
    • KhronosGroup / Vulkan-ValidationLayers # 1751
    • Идентификатор потока 0 не является отдельный вопрос. Поскольку фактических предыдущих обращений нет, идентификатор потока не записывается. Проблема заключается в том, что слои выдают ошибку, поскольку счетчик обращений становится отрицательным, поскольку ранее он был ошибочно сброшен на 0.
  • Возможно, здесь есть какая-то проблема spe c. Из текста не сразу видно, что к VkQueue фактически нет доступа в vkGetDeviceQueue, за исключением молчаливого предположения, что это нормальная вещь.
...