Войти
ПрограммированиеФорумГрафика

Тормозит 3D на NVIDIA графике на ноутбуках с Win10

Advanced: Тема повышенной сложности или важная.

Страницы: 1 2 3 Следующая »
#0
17:08, 30 мая 2019

Привет,

Начиная с Windows 10 v1803 (вплоть до v1903) на ноутбуках с двойной графикой наше Direct3D9 приложение работает медленнее на дискретной NVIDIA карте, чем на Intel графике. Хотя должно быть наоборот.

Например Geforce 1050 + Intel HD graphics. Или Geforce 920M + Intel HD Graphics.

Ноутбуки с одиночной картой NVIDIA работают быстро. Десктопы также работают быстро.

Проблема только в оконном режиме Direct3D9. В exclusive экранном режиме все быстро.

Мы рендерим по таймеру со Sleep() чтобы уменьшить нагрузку на CPU.

Проверяем приложение используя Проводник и контекстное меню где можно выбрать на какой видеокарте запускать приложение (NVIDIA или Intel).

Не влияют никакие настройки скорости видеокарты, скорости компьютера в настройках Windows, максимальная/оптимальная производительность, питание от аккумулятора или от розетки.

Есть ли какие-нибудь идеи?


#1
17:30, 30 мая 2019

А это проблема только лишь с вашим приложением?
Есть ли fixed pipeline?

#2
17:45, 30 мая 2019

А какой порядок цифр получается, сколько FPS на Intel и сколько на NVIDIA?

#3
(Правка: 17:59) 17:59, 30 мая 2019

У нас FPS упирается в refresh rate.

На NVIDIA FPS около 20-30, на Intel 60.

Кажется нашел еще кое-что. Мы вставляем Sleep() определенной расчетной длительности чтобы подгадать под следующий Present() и не нагружать чрезмерно видеокарту. Видимо в этом проблема.
Убираю Sleep() все плавно рендерится, но получается неоптимально.

#4
18:39, 30 мая 2019

Во-первых, Sleep имеет довольно плохое реальное разрешение, зачастую порядка 10 миллисекунд, так что это не лучшая идея.
Во-вторых, раз вы всё равно используете вертикальную синхронизацию (refresh rate), то где неоптимальность? В таком режиме Present автоматом тормозит поток, пока не будет готов начать следующий кадр.

#5
(Правка: 4:31) 4:29, 31 мая 2019

Malder1
> Проверяем приложение используя Проводник и контекстное меню где можно выбрать
> на какой видеокарте запускать приложение (NVIDIA или Intel).
А вы уверены что оно запускается в NVIDIA?

Там кстати есть магические строчки для принудительного запуска

__declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
  __declspec(dllexport) int AmdPowerXpressRequestHighPerformance = 1;
https://docs.nvidia.com/gameworks/content/technologies/desktop/optimus.htm


Может это надо?

#6
(Правка: 14:58) 14:57, 31 мая 2019

Да, Present() в режиме D3DPRESENT_INTERVAL_DEFAULT нам обеспечивает синхронизацию с refresh rate и не выйдет за пределы 60 fps (например).
Но! Проблема в том, что все это работает неправильно на двойной графике на NVIDIA.

Например убираю все Sleep и тупо рендерю сколько получится кадров - вначале все идет хорошо - fps 60fps. Но ставлю игру на паузу (кадры не рендерю) и после возобновления рендеринга fps падает до 30-40 кадров и уже никогда не поднимается вновь до 60fps. Или НЕ ставлю на паузу, жду, через минуту примерно fps начинает проседать до 30-40 кадров. Логи в обоих случаях показывают, что Present() Direct3D9 начинает занимать слишком много времени (до 30 ms!).

И еще. Наш конкурент, у него другой движок, но тоже Direct3D9 и оконный режим. У него точно такая же проблема - сильное проседание fps на NVIDA (двойная графика).

Т.е. однозначно баг не у нас. И как это починить непонятно.

Я большим трудом добился ответа от техподдержки NVIDIA полгода назад, они подтвердили что проблема есть и они работают с Microsoft над решением. Но после этого они ушли в молчанку и больше не отвечают и ничего не исправлено.

Игры понятно что не затронуты этой проблемой - в exclusive fullscreen режиме все отлично работает.

war_zes
Да, мы тестировали с "магическими строками" для принудительного запуска на NVIDIA. Кстати для AMD это уже не работает почему-то (я видел вопросы других разработчиков на форуме AMD).

В Windows 10 в Диспетчере задач показываются 2 видеокарты и можно видеть на какую из них идет основная нагрузка. Поэтому когда запускаем принудительно на NVIDIA через контекстное меню Проводника или через магическую строчку, то я вижу нагрузку карты NVIDIA и соответственно тормоза.

#7
15:43, 31 мая 2019

Malder1
А пробовали сделать минимальный пример, на котором начинается такая проблема? Т.е. если просто залить фон и ничего не рисовать или нарисовать один кубик, проблема останется?
Можно попробовать рисовать кадр в offscreen буфер (рендерить в текстуру), а потом выводить его парой треугольников (по аналогии с deferred render). В таком варианте проблема сохранится?

#8
15:45, 31 мая 2019

И, кстати, раз со временем fps падает, не пробовали посмотреть, может где-то в системе (не обязательно в вашем процессе) течёт память или хэндлы?

#9
(Правка: 16:02) 16:01, 31 мая 2019

Мы как раз написали небольшой тест (мы пишем на FreePascal/Lazarus/Delphi) для проверки проблемы.
В тесте проблема воспроизводится. Достаточно просто выводить с простенькой анимацией большую картинку в 2 треугольника (2048 x 2048). Утечек нет.

Пока результаты тестов такие - если в потоке где рендерим (Direct3D9 вызовы) хоть один Sleep (даже Sleep(0) то скорость рендеринга начинает катастрофически падать и уже не восстанавливается. Хотя этот Sleep ну никаких не может тормозить сам по себе.

Допустим мы можем еще переписать рендеринг в тесте и убрать все во второй поток, и без Sleep().

Но у нашего основного приложения интерфейс программы тоже рендерится через Direct3D9 (самописные контролы) и поэтому рендеринг нужно оставить в главном потоке для удобной обработки мышки, клавиатуры и согласования все этого. И там никто не может гарантировать что в главном потоке нет Sleep() он может встречатся.

#10
16:40, 31 мая 2019

Важный момент: торможение провоцируется только Sleep в основном потоке? Т.е. вызов в параллельном рабочем потоке на fps уже не влияет?

#11
17:23, 31 мая 2019

Sleep в параллельном потоке не влияет.

Влияет только в том потоке где рендеринг. И что интересно, на Intel карту Sleep не влияет.

И в exclusive fullscreen все идеально. В оконном режиме все плохо. Непонятно как тогда работают видеоплееры в оконном (не exclusive) режиме когда играют 4K видео скажем.

#12
21:55, 31 мая 2019

Malder1
> Да, Present() в режиме D3DPRESENT_INTERVAL_DEFAULT нам обеспечивает
> синхронизацию с refresh rate и не выйдет за пределы 60 fps (например).
а если отключить?

#13
22:02, 31 мая 2019

skalogryz
Привет!
C d3dpresent_interval_immediate тоже самое (видимо в оконном режиме DWM Винды ограничивает FPS по refresh rate).

Итог:

1. В оконном режиме в чистом простом тесте если НЕ использовать Sleep() то скорость на NVIDIA графике сопоставима с Intel (хотя должна быть быстрее!)

2. Если использовать Sleep() в потоке рендеринга, то NVIDIA в 2-3 раза медленнее чем Intel.

3. В exclusive fullscreen NVIDIA намного быстрее Intel (как и должно быть).

Это полный провал для NVIDIA, Microsoft и Intel. Так испортить двойную графику надо было постараться. И уже ГОД ничего не исправляют.

P.S. Как достучаться до технического руководства соответствующих отделов этих компаний?

#14
(Правка: 22:10) 22:05, 31 мая 2019

Malder1
> Привет!
доброго времени суток!

Malder1
> C d3dpresent_interval_immediate тоже самое (видимо в оконном режиме DWM Винды ограничивает FPS по refresh rate).
у меня были проблемы, с оконным режимом. Если Vsync для приложение включён - то скорость падала до 1-5 кадров в секунду.
Отключение Vsync, или переход в полноэкранный решал проблему.

Но, как я понял, проблема была или в дровах, или в самой железке.

Malder1
> P.S. Как достучаться до технического руководства соответствующих отделов этих компаний?
поднять обсуждение на Reddit? xD

Malder1
> Это полный провал для NVIDIA, Microsoft и Intel.
Если я правильно помню культуру компании, то для воспроизведения этой проблемы уже есть отдельное тестовое приложение?!
Может быть его опубликовать, а народ посмотрит код и у себя потестирует. Я думаю, найдутся желающие.

Страницы: 1 2 3 Следующая »
ПрограммированиеФорумГрафика