Използването на множество преминавания за изобразяване обикновено е по-бавно от използването на едно преминаване с MRT изход, но това също ще зависи от вашата ситуация.
Доколкото разбирам, и f(I)
, и g(I)
семплират входното изображение I
и ако всеки семплира едни и същи (или близко съседни) локации, можете да спечелите значително от кеша на текстурите между различните операции - имате за да пробвате входната текстура само веднъж, вместо два пъти с подхода с много преминавания.
Вземете този подход още една крачка напред: Имате ли нужда дори от междинните резултати f(I)
и g(I)
отделно? Може би бихте могли просто да поставите h(f(I),g(I))
директно върху един шейдър, така че нито да имате нужда от множество пропуски и MRT. Ако искате да можете да комбинирате динамически операциите си, все пак можете да използвате този подход и програмно да комбинирате различни части на кода на шейдъра динамично, за да приложите операциите (където е възможно), и да използвате множество преминавания само когато е абсолютно необходимо.
РЕДАКТИРАНЕ
Тъй като въпросът беше актуализиран междувременно, мисля, че мога да дам някои по-конкретни отговори:
Това, което казах досега, особено за поставянето на h(f(I),g(f(I)) в един шейдър е добра идея само ако h (или f и g) няма да се нуждаят от съседни пиксели. Ако h е nxn филтърно ядро, ще трябва да получите достъп до nxn различни входни тексела и тъй като тези входове не са директно известни, ще трябва да изчислите f и g за всеки от тях. Ако и f, и h са филтърни ядра, ефективният размер на филтъра на комбинираната операция ще бъде по-голяма и е много по-добре първо да се изчислят междинните резултати и да се използват множество преминавания.
Разглеждайки конкретния проблем, който описвате, се свежда до това.
Ако използвате два отделни шейдъра по най-наивния начин, рендирането ви ще изглежда така.
- използвайте shader1
- изберете някакъв изходен цветен буфер
- начертайте четворка
- използвай shader2
- изберете някакъв различен цветови буфер
- начертайте четворка
Всяко повикване за теглене има своите допълнителни разходи. GL ще трябва да направи допълнително валидиране. Превключването на шейдърите може да е най-скъпата допълнителна стъпка тук в сравнение с комбинирания подход на шейдъри, тъй като може да наложи промиване на конвейера на GPU. Освен това за всяко извикване на чертеж имате операции за обработка на върхове, растеризация и интеролация на атрибут на фрагмент. Само с един шейдър голяма част от тези допълнителни разходи изчезват и описаните досега изчисления на фрагмент могат да бъдат „споделени“ и за двата филтъра.
Но ако не беше местоположението на текстурата: щях ли все още да се радвам на повишаване на производителността?
Поради нещата, които казах досега и специфични за шейдърите, които представихте, съм склонен да кажа: да. Но ефектът ще бъде много малък до пренебрежим, ако пренебрегнем достъпа до текстури тук, особено ако приемем изображения с разумна висока разделителна способност, така че относителните разходи в сравнение с общото количество работа да изглеждат малки. Бих казал поне, че използването на MRT настройка с едно преминаване няма да бъде по-бавно. Въпреки това, само сравняването/профилирането на много специфичната реализация на конкретен GPU ще даде окончателен отговор.
Защо казах "шейдърите, които представихте". Защото и в двата случая правите квадратурата на изображението в един шейдър. Бихте могли да го разделите на два различни шейдъра и рендерпасове. В този случай ще получите допълнителни разходи (в допълнение към вече споменатите) за писане на междинните резултати и трябва да ги прочетете обратно. Въпреки това, тъй като изпълнявате филтър върху междинния резултат, не е необходимо да повдигате всеки входен тексел повече от веднъж, но при комбинирания подход го правите. Ако операцията за повдигане на квадрат е достатъчно скъпа и размерът на вашия филтър е достатъчно голям, на теория бихте могли да спестите повече време, отколкото се въвежда от режийните разходи на множество преминавания. Отново, само сравнителният анализ/профилирането може да ви каже къде ще бъде безпроблемността.
В миналото съм правил някои сравнителни анализи с MRT срещу многобройни рендиращи преминавания, въпреки че операциите за обработка на изображения, които ме интересуваха, са малко по-различни от вашите. Това, което открих е, че в такива сценарии достъпът до текстурата е ключовият фактор и можете да скриете много други изчисления (като повдигане на стойност на цвят) в латентността на достъпа до текстурата. Мисля, че вашето „Но ако не беше локалността на текстурата“ е малко нереалистично, тъй като това е основният принос към общото време на работа. И това не е само местоположението, но и общият брой достъпи до текстури: С вашия подход с множество шейдъри, изображение с размер w*h
и 1D филтър с размер n
, ще получите като цяло 2*w*h*n
достъпа до текстури , докато с комбинирания подход просто ще намалите до *w*h*n
и това ще направи огромна разлика в миналото.
За AMD FirePro V9800, размер на изображението 1920x1080 и просто копиране на пикселите в два изходни буфера чрез изобразяване на текстурирани quds, получих с две преминавания: ~0,320ms (дори без превключване на шейдъри) срещу 1 преминаване MRT: ~0,230ms. Така че времето за изпълнение беше намалено с "само" 30%, но това беше само с едно извличане на текстура на извикване на шейдър. С филтърните ядра бих очаквал тази цифра да се доближава до 50% намаление с увеличаване на размера на ядрото (но все пак не съм го измерил).
person
derhass
schedule
02.05.2014
I
като идентификатор и пишете въпрос, тогава го маркирайте, така че да е по-лесно да се прави разлика между идентификатораI
и Аз (ти). - person t.niese   schedule 02.05.2014a
отrgba
, когато нямам нужда от прозрачност. Но тъй като обработвате изображения, вероятно имате нужда от целия цвят, който можете да получите, в който случай помислете за предложението на @Freddy. - person zero298   schedule 02.05.2014