Название: GLSL (производительность) Отправлено: Igors от Октябрь 14, 2011, 20:35 Добрый день
Связался с GLSL. Никогда не любил OpenGL со своей памятью ниже средней, но что поделать если есть заказ. Ну ладно, написал первую тысячу строк на GLSL (язык С++ подобный но совсем не одно и то же). Задача в принципе банальный phong shading, ничего более. Получаю бешеные тормоза. Доходит до смешного - software реализация тянет 15 fps, hardware - менее одного. Где-то я растерял неукротимую мощь hardware/GPU, но вот где - понять сложно. Конечно экспериментирую отключая/подключая различные куски GLSL кода + интенсивно гуглю. Кто сталкивался - подскажите, буду признателен. Спасибо Название: Re: GLSL (производительность) Отправлено: xop от Октябрь 15, 2011, 17:16 1000 строк на GLSL для простого phong shading?? Можно на это посмотреть? :)
Сразу вопрос - какое железо, какая ОС? Не пересоздается или не перелинковывается ли шейдер каждый кадр? И текст шейдеров действительно желательно показать, так будет проще понять в нем ли самом дело. И сразу еще вопрос - а картинка-то корректная получается, или мусор? Название: Re: GLSL (производительность) Отправлено: Igors от Октябрь 16, 2011, 09:46 OSX 10.6.8 (на 10.7 результат тот же). Карта
Цитировать OpenGL Vendor: ATI Technologies Inc. Перелинковки не происходит (простые тесты выполняются прилично), для каждого объекта вызывается glUseProgram(shader) в начале рисования и glUseProgram(0) в конце. OpenGL Renderer: ATI Radeon HD 2600 OpenGL Engine OpenGL Version: 2.1 ATI-1.6.26 "Методом втыка" нашел что не нравится такое Цитата: cpp uniform float tbl[1024]; Хотелось сделать аккуратный dropoff, вот и потребовалась табличка. Интересно что даже если я выскакиваю return'ом это не спасает от тормозов, напрКод
Большой текст связан с тем что надо поддерживать все photoshop blend'ы (multiply, overlay и.т.п). Посмотреть можно, но проект коммерческий, поэтому я Вам напишу в личку, просьба исходники на public не светить. Спасибо за понимание Название: Re: GLSL (производительность) Отправлено: xop от Октябрь 18, 2011, 11:37 Посмотрел сорцы. Печаль ))
Во-первых, по поводу таблицы. В сорцах что-то не нашел ее - можно кинуть вариант с ней? Дальше, про ту же таблицу - обычно такие вещи делаются не массивом uniform, а одномерной текстуркой. И соответствено чтение через texture1DLod( tbl, pos, 0.0 ). Это и быстрее, а если нужна интерполяция и/или ограничения по координатам - еще быстрее, потому что эти операции есть в текстурных семплерах, и на большинстве железа они "бесплатные". Lod - чтобы точно знать, что данные берем с нулевого мипа. Кроме того, некоторые дрова если не могут что-то выполнить аппаратно (например, из-за превышения количества данных через uniformы) - молча падают в software режим. Отсюда и <1 fps. Во-вторых - от вида сорцов волосы дыбом встают. У видеокарты похоже тоже :) В первую очередь - от количества ifов. Бранчинг (if, for, while, switch) - это медленно. Статический бранчинг (в зависимости от значний uniform) - терпимо. Динамический бранчинг (в зависимости от значений varying) в пиксельном шейдере - это ОЧЕНЬ медленно, если только не соблюдаются условия (оба!): 1) самих ветвей мало 2) высокая когерентность в пространстве экрана, т.е. если большие области пикселей пройдут по одному и тому же пути в ifе Наиболее типичные способы уменьшать количество ifов: 1) конструкции вида "if( какой-то uniform флажок ) то выполнить это" можно заменить на "#ifdef КАКОЙ_ТО_ДЕФАЙН выполнить это #endif" и компилировать различные версии шейдера для разных конфигураций флажков. Можно заранее, можно на лету и держать кэш шейдеров. Может звучит дико на первый взгляд, но это обычная практика. 2) конструкции вида "for( int i = 0; i < какой-то uniform int; ++i )" можно заменить на "for( int i = 0; i < КАКОЙ_ТО_ДЕФАЙН; ++i )" и опять же компилировать различные версии шейдера 3) конструкции типа if( x < 0 ) x = 0, и вообще, если надо какое-то значение ограничить - пользоваться не ifами, а функциями min, max и clamp. В данном случае например x = max( x, 0 ) 4) конструкции типа if( x > threshold ) y += "что-то посчитать, но несложное" и тому подобное можно делать через step: y += step( threshold, x ) * "что-то посчитать". Если рассчет относительно простой, то быстрее будет его выполнить и умножить на ноль, чем бранчиться 5) конструкции типа if( x > threshold ) y = "один" else y = "два" и тому подобное можно делать через step и mix: y = mix( "один", "два", step( threshold, x ) ). Если рассчеты один и два несложные, то проще выполнить их оба и выбрать один из двух. Еще момент. Если мы работает с векторными данными (позиция, нормаль, цвет) - крайне желательно делать это в явном виде через вектора. И не забывать, что min/max/clamp/step/mix работают и с векторами. Пример оптимизации маленькой функции в вашем коде. Было: Код: float SomeBlend( float r, float r1 ) Код: vec3 SomeBlend( vec3 r, vec3 r1 ) Еще момент - если нужно делать линейную интерполяцию - не нужно изобретать велосипед и писать (1.0 - t) * a + t * b,и a + t*(b-a) тоже не надо - используйте стандартную функцию mix. В общем, там еще много странных решений я увидел, чуть позже отпишу по ним, но для начала думаю и этого хватит с головой. Название: Re: GLSL (производительность) Отправлено: Igors от Октябрь 18, 2011, 14:42 Дальше, про ту же таблицу - обычно такие вещи делаются не массивом uniform, а одномерной текстуркой. И соответствено чтение через texture1DLod( tbl, pos, 0.0 ). Это и быстрее, а если нужна интерполяция и/или ограничения по координатам - еще быстрее, потому что эти операции есть в текстурных семплерах, Здорово! (и интерполяция как раз нужна). А есть ли возможность сделать это не занимая "слот" текстуры? (т.е. по-прежнему имея 8 Texture2D). СпасибоСтало: В данном случае результат не mix(a. b..), но к чему стремиться - понялКод: vec3 SomeBlend( vec3 r, vec3 r1 ) Во-вторых - от вида сорцов волосы дыбом встают. У видеокарты похоже тоже :) Про Ваши волосы не скажу, но у 2 карт на которых проверял - ничего не встает :) Сегодня перенес на Вындоуз, там карта заметно лучше (NVidia GeForce 8600 GI/PGI/SSE, OpenGL 3.1.0) - в обоих случаях включение разнообразных blend'ов никак не гасит fps (почему не знаю). Правда линкуются с этой картой шейдеры заметно дольше - неск секунд Название: Re: GLSL (производительность) Отправлено: xop от Октябрь 18, 2011, 15:07 А есть ли возможность сделать это не занимая "слот" текстуры? Нет, слот будет занят. Но - этих слотов в современных видеокартах 16 минимум. В той же 8600 их кажется вообще 32. А текстурные координаты вам отдельно передавать не надо.В данном случае результат не mix(a. b..), но к чему стремиться - понял Именно mix( a, b, step( 0.5, r1 ) ). Step вернет 0, если r1 < 0.5 и 1, если r1 > 0.5 - причем поканально. А mix соответственно вернет a или b - опять же поканально. Что полностью соответствует предыдущему куску кода.включение разнообразных blend'ов никак не гасит fps Вы кажется немного не поняли :) Гасит fps не то, что бранч сработает или нет, а сам факт его наличия. Попробуйте для эксперимента вообще из кода шейдера выпилить все бленды. И еще цикл там по текстурам попробуйте развернуть и тоже убрать ifы. Ну, просто для одного какого-нибудь конкретного простого случая. Если упиралось в производительность именно шейдера (а скорее всего в него упиралось, особенно если на весь экран выводить) - скорее всего вы удивитесь :)А вообще - пока производительность устраивает - оптимизировать действительно не имеет смысла. Название: Re: GLSL (производительность) Отправлено: Igors от Октябрь 18, 2011, 16:43 Вы кажется немного не поняли :) Гасит fps не то, что бранч сработает или нет, а сам факт его наличия. Точно! (не могу пока привыкнуть к таким финтам). Да. действительно, blend отгрызает 30-40% (не смертельно, но ощутимо)Название: Re: GLSL (производительность) Отправлено: xop от Октябрь 18, 2011, 17:27 Посмотрите еще сколько отгрызает чтение 8 текстур, вместо одной. Подозреваю, что еще больше, чем вариации бленда.
Кстати, есть еще один прием, может пригодится :) Если не хочется иметь ограничение на количество текстур на объекте - можно выводить в несколько проходов. Т.е. рисуем объект несколько раз с аппаратным блендом, накладывая разные текстуры. Можно по одной текстуре на проход (это проще всего, но медленнее, чем все разом в шейдере смешать), можно группировать текстуры (это быстрее, но больше комбинаций шейдеров). Название: Re: GLSL (производительность) Отправлено: Igors от Октябрь 20, 2011, 18:11 Ну при такой "кровавой" отладке сильно не разгонишься :) Сбить все бленды с аппаратными - куча возни, дело еще осложняется тем что текстуры могут шейдиться или нет.
Нет предвычислений, любые объекты могут быть добавлены в сцену и в любом кол-ве. Поэтому сразу же "поднимать планку" с оптимизацией непрактично - пользователь может воспринять это как должное, потом запросто можно нажить грыжу с "вариациями шейдеров". Пока скорость хотя бы 50% от Gourand - пусть работает. Главный критерий оценки (помимо конечно скорости) - соответствие OpenGL preview чистовому рендеру. Сейчас самое уязвимое место lighting (особенно Area Light - то самое окно которое светит). Сначала я хочу вычистить все остальное - но это не так просто. Вчера получил на NVIDIA карте - шейдер "не выгружается". Запустил, ага, надо подправить - но изменения игнорируются. Все проходит (компиляция, линковка, если есть ошибки - компилятор сообщает) но вот работает предыдущий вариант :) Разбираюсь.. |