Как определить причину зависания драйвера DirectX 11

Я работаю над приложением QT, для которого я интегрировал DirectX 11 в пользовательский виджет. Приложение отображает прокрутку — графическое представление данных, считываемых из файла. Пользователь может ускорять и замедлять скорость прокрутки.

По большей части это работает отлично. Рендеринг DirectX 11 отображается в моем пользовательском виджете, как я и ожидал. Проблема в том, что графический драйвер случайным образом зависает и вылетает моя программа. Я говорю «случайно», потому что я тестировал это с одним и тем же файлом данных, и он никогда не зависает в одной и той же точке файла, по прошествии определенного времени или с определенной скоростью прокрутки (чем выше скорость прокрутки, тем больше работу, выполняемую графическим процессором за кадр).

Когда приложение зависает, мой экран на мгновение зависает, становится черным, а затем возвращается с приятным сообщением от NVidia о том, что оно восстановилось после сбоя драйвера. Выходные данные отладки в Visual Studio содержат следующее:

D3D11: Удаление устройства.

ОШИБКА D3D11: ID3D11Device::RemoveDevice: Удаление устройства было инициировано по следующей причине (DXGI_ERROR_DEVICE_HUNG: Устройству потребовалось неоправданное количество времени для выполнения своих команд, или произошло сбой/зависание оборудования. В результате TDR (обнаружение тайм-аута и Восстановление) был запущен. Текущий контекст устройства выполнял команды, когда произошло зависание. Приложение может захотеть перезапуститься и вернуться к менее агрессивному использованию аппаратного обеспечения дисплея). [ОШИБКА ВЫПОЛНЕНИЯ #378: DEVICE_REMOVAL_PROCESS_AT_FAULT]

Я обнаружил, что просто закомментировав вызов IDXGISwapChain1::Present, приложение будет работать с файлом с молниеносной скоростью. С точки зрения графики он по-прежнему передает данные в графический процессор и рисует для целей рендеринга, он просто никогда не отображается в моем окне.

Я надеюсь на помощь с идеями о том, какие типы вещей вызывают зависание драйвера. Мои шейдеры невероятно просты — в основном я просто позиционирую вершины с помощью проекционной матрицы. И, учитывая то, что я описал в предыдущем абзаце, шейдеры все равно должны проходить через вершины и пиксели, даже когда Present не вызывается, да?

Я подозревал, что это может быть проблема совместимости с Qt — я знаю, что Qt официально не поддерживает DirectX. Поэтому я попытался создать отдельное окно с помощью CreateWindowEx и использовать его для своей цепочки обмена вместо пользовательского виджета Qt. Он отображался в этом окне, но также зависал драйвер, как и раньше.

Я также подозревал ошибку драйвера в моем ноутбуке, поэтому я попытался запустить приложение на более мощном настольном ПК, который регулярно запускает другое приложение DirectX 11 (не Qt) без заминок (стоит упомянуть, что это другое приложение отображает аналогичные данные в прокрутки, используя гораздо более сложные шейдеры). Но мое приложение QT также зависает на этом ПК.

Кто-нибудь знает, как я могу получить более подробное описание того, что заставляет драйвер зависать?

Заранее благодарим вас за любую помощь, которую вы можете предложить.

ОБНОВЛЕНИЕ: 01.08.2013, 17:16 CST В настоящее время я изучаю возможную проблему с синхронизацией потоков, которая может быть причиной. Продолжу завтра утром и опубликую, если решу это самостоятельно.


person Tim Coolman    schedule 01.08.2013    source источник
comment
У вас включен слой отладки? Пробовали ли вы использовать эталонное устройство, а также WARP, чтобы увидеть, воспроизводятся ли проблемы и на этих двух устройствах?   -  person Adam Miles    schedule 02.08.2013
comment
Я попробовал устройство REF, которое было мучительно медленным, но зависание все равно происходило. Не пробовал WARP - не могу сказать, что знаком с этим типом устройств.   -  person Tim Coolman    schedule 02.08.2013
comment
Ну если зависает в референсном устройстве то наверное будет висеть на любом устройстве.   -  person Adam Miles    schedule 02.08.2013


Ответы (1)


После некоторого тестирования сегодня, похоже, это была проблема с потоками. Я запускал несколько раз сегодня без сбоев графики. Так что моя проблема должна быть исправлена, если только мне не повезло с моими тестами сегодня (или, скорее, не повезло - если это снова покажет свое уродливое лицо через день или два).

Я знал, что непосредственный контекст устройства не является потокобезопасным. Однако вместо использования отложенных контекстов я использовал критические секции для синхронизации своих потоков и координации использования контекста устройства. Чего я не осознавал, так это того, что небезопасно вызывать IDXGISwapChain1::Present, пока другой поток использует контекст устройства. Имеет смысл, но поскольку это не вызов непосредственно из самого контекста устройства, я упустил это из виду. Я буквально переместил свой вызов Present() на несколько строк в блок критической секции, и с тех пор он не вызывал у меня сбоев.

person Tim Coolman    schedule 02.08.2013
comment
+1 за то, что избавил меня от часов головоломок - у меня была точно та же проблема, фоновые потоки загружали текстуры и синхронизировались с контекстом, но я также не осознавал необходимость защиты вызова Present. . Простое исправление, и очень ценится. Спасибо! - person Roger Rowland; 26.02.2014