Записки сумасшедшего: Qt+OpenGL

Мы продолжаем наш репортаж про Qt и OpenGL.

В Qt, если кто не знает, есть приятные врапперы для OpenGL. QOpenGLShaderProgram для шейдеров, QOpenGLBuffer для буферов ну и так далее. Я ими пользуюсь, потому что удобно, сахарок вкусный типа QOpenGLVertexArrayObject::Binder, опять же деструкторы все удалят и так далее.

И есть QOpenGLTexture, любовь с ней в FRV у меня не задалась (делаю все руками в результате), а тут в рамках HelloWorld-2017 решил вернуться к ней.

И получился (почти) полный fail:

В native-OpenGL-режиме все хорошо и работает (моя ошибка была в том, что я не звал setFormat() /в примерах Qt текстуры используются для загрузки прямо из png/jpeg и там не надо инициализировать по частям: create/allocateStorage/setData, но я нашел пример на github).

А вот в родном/основном для Qt режиме "GL ES поверх ANGLE поверх DX11" оно не просто не работает, а валится с грохотом (для 3D-текстур):

  • Оно, внутри у себя, определяет, что возможен immutable storage
  • И, соответственно, пытается аллоцировать данные черех glTexStorage3D
  • А эта функция в ANGLE не резолвится (2D, я надеюсь, работает нормально)

А почему, спрашивается? Да, поди, ни одна сука не использовала, хоть враппер и есть. Если кто и использовал, так с 2D.

Даже баг файлить не буду, буду по старинке, glGenTextures() (это не говоря о том, что я вот не понимаю как скрестить QOpenGLTexture с PBO, а хочется и этого тоже).

 

 

Comments

Но зачем такое извращение с OpenGL и зачем ES на большой платформе?!

Какое именно извращение?

А с ES на большой платформе все просто: есть некоторое количество юзеров у которых OpenGL неживой, а DX11 - вполне живой.

Ну вот именно это изврещение — имитация ES поверх чего попало. Но ответ, в общем, понятен.

Это не извращение, это жизнь. Весь WebGL (в том же Chrome) так и работает, в точности через эту дырочку.

Да и FireFox. Но как же Вулкан? Как же нативный DX?!
Все эти дырочки обычно же очень ограничивают.

Ну мне же не нужно вертеть миллион полигонов на 120fps.
А для совсем простой демозаики на 8Mpix (экран 4k) хватит и GL ES3 и вообще там надо очень мало. И данных, помимо собственно текстур, у меня очень мало.

То есть я понял что хочу гарантированную плавучку и гарантированные 3D-текстуры (для LUT), это соответственно GL ES3 и/или OpenGL 3+ (3.3/Core чтобы не заморачиваться со всякой ерундой, там посмотрим).

А писать две/три/четыре версии кода (native DX, Vulcan, GL4.3+) я не вижу пока смысла на своих задачах. С тем же FRV извернулись с 2.1+ (но color management сделан через анус и больше я так не хочу)

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

"виндовые встроенные драйвера" - это SVGA-драйвер?

Начиная с семерки точно (вглубь не проверял) - драйвера из windows update полноценные.

скорее из образа системы. пару раз точно приходилось ставить родные для получения opengl, при том что aero/DX работали полностью.

Все таки для людей не репортящих баги есть в аду отдельный котел)

Есть, да.
Но я их репорчу (немало, штуки 3 за этот месяц) и результат меня огорчает.

Пусть починят что-то, для чего я не дал готового патча (таких сейчас 2 или 3 висит в bugreports.qt) - тогда я увижу что конструкция работает.

Я пару дней назад написал одной солидной компании, что для людей, не реагирующих на баг-репорты, есть специальный круг ада.

Вот там все и встретимся. Потому что это все одни и те же люди

В аду остро стоит квартирный вопрос.

Запалим пионерский костер, погреемся у него

Случайно выяснилось, что этот баг исправлен в Qt 5.9.3
(ну или раньше, но в 5.9.3 уже все хорошо)

Ну и значит без моего костра обойдутся.

Алексей, здравсвуйте!

Добрался таки и я до Qt/GL... Увы
Уже после дня экспериментов с PBO нашел пример (http://www.songho.ca/opengl/gl_pbo.html). В примере три режима: без PBO, с одним PBO, c двумя PBO

Что вижу в результатах:

PBO mode: 1 (single PBO)
Transfer Rate: 1347.2 MB/s. (21.1 FPS)
Transfer Rate: 1360.9 MB/s. (21.3 FPS)
Transfer Rate: 1419.8 MB/s. (22.2 FPS)

PBO mode: 2 (two PBO)
Transfer Rate: 2405.6 MB/s. (37.6 FPS)
Transfer Rate: 2441.2 MB/s. (38.1 FPS)
Transfer Rate: 2446.7 MB/s. (38.2 FPS)

PBO mode: 0 (glTexSubImage2D)
Transfer Rate: 1855.7 MB/s. (29.0 FPS)
Transfer Rate: 1852.0 MB/s. (28.9 FPS)
Transfer Rate: 1860.3 MB/s. (29.1 FPS)

И что-то не понимаю. Т.е. цикл с glTexSubImage2D быстрее, чем с одним PBO.
Но в примере хоть тайминги glTexSubImage2D соответствуют действительности.

На моем же Qt-шном рабочем примере glTexSubImage2D при включенном буфере ну совсем не non-blocking.
Вызов glTexSubImage2D для данных ~80Mb блокирует на 50мс в пике, почти столько же, сколько занимает вышележащий memcpy в замапленный указатель.

Может, вы с подскажете, что я могу делать не так... Может, Qt резолвит функции OpenGL как-то по своему. Куда смотреть?

Спасибо!

У меня, во всяком случае пока, не бывает "следующего кадра", соотв. в PBO не вижу смысла.

Глянул тот пример.
pboMode=0 - 500fps,
1,2 = 1000fps
(округленно).

А имеет смысл, похоже, даже с одним буфером (а второй - смысла не имеет). Если вылезет заметно в профайлере - буду пробовать (хотя на фоне распаковки raw - вылезет вряд-ли)

Я рассчитывал, что с одним PBO буффером glTexSubImage будет работать асинхронно (через DMA) и я не залипну на 50мс в главном потоке. Но, по сути glTexSubImage _у меня_ почему-то блокирующий и занимает те же миллисикунды, что и простой glTexSubImage и memcpy.
Т.е., не учитывая распаковки, получается, что только загнать 80Mb рав в (избыточном, но оптимальном?) формате RGBA8 - это 50мс (macbook pro'14)... А с ним там еще что-то делать нужно. Т.е. в данном случае с OpenGL работать нужно с несколькими контекстами в разных потоках? Или есть какие известные решения? Ну, может, там, из области обработки видео - там, по идее, движение туда-сюда должно быть существенным?

Ну да, glTex(Sub)Image - блокирующий.

В том примерчике - он не блокирующий. Я там сделал размеры текстуры 4096x4096 и вижу copyTime в режиме c PBO - меньше 1мс.

У вас в любом случае отрисовка не может начаться до того, как в GPU залита текстура.

Да, это понятно. Но хотелось избежать именно блокировки в потоке CPU.
Но почему в примере вызов не блокирующий, а у меня блокирующий - не понятно.

Там с вынесением OpenGL в другой thread какие-то пляски с бубном.
Впрочем, в районе Qt 5.6 появился пример про threaded OpenGL - возможно эти пляски как-то упростили, не вдавался.

Даже в 5.4 он есть.

У меня все в главном потоке покаместь. С новым контекстом в отдельном потоке вроде ничего сложного. Это будет следующий шаг.
Не то что бы асинхронность glTexImage2D меня спасет... На рендеринге выскочит, да и простой memcpy в замапленный пиксельный буффер плюс теже 50мс.
Буду дальше пытаться разбираться...

Вообщем, glTextSubImage2d из буффера действительно асинхронный.
У меня была проблема, видимо, с тем, что я генерировал и настраивал текстуру в том же цикле, в котором создавал буфер. После переноса генерации и настройки текстуры на стадию инициализации - glTextSubImage2d заработала с нулевой задержкой.

Ну возможно там есть какие-то неявные синхронизации, я не задумывался