графика: лучшая производительность с изображениями с плавающей запятой - PullRequest
2 голосов
/ 26 февраля 2009

Мне нужно ускорить глазную конфету системы частиц, над которой я работаю. Конфета для глаз включает в себя смешивание, накопление, следы и свечение частиц. В данный момент я вручную выполняю рендеринг в буфер изображений с плавающей запятой, преобразуя их в неподписанные символы в последнюю минуту, а затем загружаю их в текстуру OpenGL. Для имитации свечения я рендерил одну и ту же текстуру несколько раз с разным разрешением и различными смещениями. Это оказывается слишком медленным, поэтому я пытаюсь что-то изменить. Проблема в том, что мое аппаратное обеспечение - это Intel GMA950, но на целевой машине установлена ​​Nvidia GeForce 8800, поэтому на этом этапе сложно профилировать OpenGL.

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

  • Замена чисел с плавающей точкой на uint32 в конфигурации с фиксированной точкой 16.16
  • Оптимизация операций с плавающей запятой с использованием сборки SSE2 (буфер изображения представляет собой массив с плавающей запятой 1024 * 768 * 3)
  • Использовать буфер накопления OpenGL вместо массива с плавающей точкой
  • Использовать FBO с плавающей точкой OpenGL вместо плавающего массива
  • Использовать пиксельные / вершинные шейдеры OpenGL

Есть ли у вас опыт использования какой-либо из этих возможностей? Есть мысли, совет? Что-то еще, о чем я не думал?

Ответы [ 4 ]

4 голосов
/ 26 февраля 2009

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

Размер вашего плавающего буфера составляет 9 мегабайт, и вы касаетесь данных более одного раза. Скорее всего, ваш цикл рендеринга выглядит примерно так:

  • Очистить буфер
  • Сделать что-то на нем (использует чтение и запись)
  • Преобразовать в неподписанные байты
  • Загрузить в OpenGL

Это много данных, которые вы перемещаете, и кеш не может вам сильно помочь, потому что изображение намного больше, чем ваш кеш. Давайте предположим, что вы касаетесь каждого пикселя пять раз. Если это так, вы перемещаете 45 МБ данных в медленную основную память и из нее. 45 МБ не похоже на большой объем данных, но учтите, что почти каждый доступ к памяти будет пропуском кеша. Процессор будет проводить большую часть времени в ожидании поступления данных.

Если вы хотите остаться на процессоре для выполнения рендеринга, вы не можете ничего сделать. Некоторые идеи:

  • Использование SSE для невременных загрузок и хранилищ может помочь, но они значительно усложнят вашу задачу (вы должны выровнять чтения и записи).

  • Попробуйте разбить ваш рендеринг на плитки. Например. делать все на меньших прямоугольниках (256 * 256 или около того). Идея заключается в том, что вы на самом деле получаете выгоду от кеша. Например, после того, как вы очистили свой прямоугольник, все растровое изображение будет в кеше. Теперь рендеринг и преобразование в байты будут намного быстрее, потому что больше нет необходимости получать данные из относительно медленной основной памяти.

  • Последнее средство: уменьшите разрешение эффекта частиц. Это даст вам хороший удар по цене за счет визуального качества.

Лучшее решение - перенести рендеринг на графическую карту. Рендеринг в текстуру функциональности является стандартным в наши дни. Немного сложно заставить его работать с OpenGL, потому что вы должны решить, какое расширение использовать, но как только оно заработает, производительность больше не будет проблемой.

Кстати - вам действительно нужны цели с плавающей точкой рендеринга? Если вам не хватает 3 байтов на пиксель, вы увидите хорошее улучшение производительности.

2 голосов
/ 27 февраля 2009

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

Аарон прав: представляйте каждую отдельную частицу спрайтом. Вы можете вычислить движение спрайтов в пространстве (например, накапливать их положение на кадр) на процессоре с помощью SSE2, но выполнять все аддитивное смешивание и накопление на графическом процессоре через OpenGL. (Аддитивно рисовать спрайты достаточно просто.) Вы можете обрабатывать свои трейлы и размытие, либо делая это в шейдерах («про»), рендеринг в буфер накопления и обратно, либо просто генерировать кучу дополнительных спрайтов на процессоре, представляющем след и киньте их в растеризатор.

1 голос
/ 26 февраля 2009

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

1 голос
/ 26 февраля 2009

Попробуйте заменить ручной код спрайтами: текстура OpenGL с альфа-каналом, скажем, 10%. Затем нарисуйте их много на экране (десять из них в одном месте, чтобы получить полное свечение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...