Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
pcim
Založen: 28. 12. 2007 Příspěvky: 3
|
Zaslal: 28. prosinec 2007, 10:58:55 Předmět: Více OpenGL rendering kontextů |
|
|
Můžete mi prosím někdo objasnit následujcící ? :
Pokud mám v OpenGL více než jeden rendering kontext, a tyto kontexty mezi sebou sdílí objekty (WGL_share_lists), nese to s sebou nějakou zvýšenou režii při volání OpenGL funkcí ? Říkám si, že pokud dva thready přes dva kontexty nějak manipulují s jedním a tím samým sdíleným OpenGL objektem (např. texturou), tak přístup k objektu jako takovému musí být obalen nějakou kritickou sekcí, mutexem apod., který by v tam v případě jednoho kontextu být nemusel.
Jde mi například i situaci, kdy jeden thread čistě jen renderuje a v druhém se plní VBOs, textury apod. Samozřejmě to asi jde udělat i bez použití druhého kontextu např. pomoci glMapBuffer(), ale to už je jiná otázka. |
|
Návrat nahoru |
|
|
Marek
Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 29. prosinec 2007, 00:13:47 Předmět: |
|
|
Řežie tam rozhodně je a podle mě je zbytečné mít 2 kontexty, protože grafická karta dokáže v jednu chvíli obsloužit jen jeden. Když už chceš něco uploadovat za běhu, používej třeba glBufferData nebo glMapBuffer s parametrem GL_WRITE_ONLY. Ve chvíli uploadování může být aktuální buffer používán grafickou kartou a inteligentní driver zpravidla vytvoří druhý, kde uloží ty data a po dokončení práce grafické karty ho aktivuje a ten starý uvolní. To je asi nejvhodnější způsob, protože se nic nemusí zamykat a karta nemusí přerušovat svoji činnost. Nutno podotknout, že když použiješ glBufferSubData nebo glMapBuffer s jinými parametry, tohle nastat nemůže, protože si tím vynutíš editaci toho stávajícího bufferu a tam už driver musí zamykat. Zajímavá myšlenka co? - mít na kartě 2 buffery a mezi nima přepínat - zatímco se jeden plní, druhý se používá. U VBO to inteligentní drivery dělají automaticky. Jak je to u textur si nejsem jistej, ale není problém stejnou fintu naprogramovat pomocí dvou textur, že. _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
|
pcim
Založen: 28. 12. 2007 Příspěvky: 3
|
Zaslal: 29. prosinec 2007, 18:01:06 Předmět: |
|
|
Myslel jsem si, že ty dva kontexty asi nebude to nejlepší řešení, ale zdálo se mi takhle to načítání na pozadí implementačně trochu jednoduší. Pokud bude všechen GL kód jen v renderovacím threadu, bude se zde muset např. zavolat glMapBuffer, pak nějak sdělit načítacím threadu,, že ho může naplnit a až ten to udělá tak zase sdělí rwenderovacímu threadu, že je hotov a ten pak provede glUnmapBuffer. Trochu složitější, ale nějak by se to asi udělat dalo.
To co jsi psal o přeínání více bufferů mě ale přivádí na otázku jak vlastně spravovat buffery, např. VBO. Četl jsem na to různé názory, ale stále vlastně nevím jak to správně řešit. Jsou třeba tyto dvě možnosti :
1. Každý objekt, nebo prostě něco co se rederuje v jednom render callu má svůj VBO :
Výhody :
- Implementačně jednoduché
- Alikace ani driver asi nemají problém s nějakou fragmentací bufferů
- Buffer se dá snadno a rychle naplnit a nebrzdí se tím rendering z jiných bufferů,
navíc jak píše Eosie by se driver měl postarat o vytvoření nového bufferu v případě, že by se plněný buffer právě používal pro rendering.
Nevýhody:
- Pokud se objekty načítají nabo donačítávají na pozadí až za běhu, budou se buffery vytvářet a rušit až v hlavní renderovací smyčce, což asi může brzdit.
- Častý glBindBuffer, pro každý render call se mapuje buffer(y) znovu.
2. Při startu engine se zaalokuje určitý počet poměrně velkých bufferů (např. 10 bufferů po 2MB) a ty se potom používají pro rendering všech objektů. V hlavní smyčce se žádné nové buffery nevytvářejí pouze se plní tyto existující.
Výhody :
- Žádné alokace bufferů v hlavní smyčce
- Méně časté přepínání bufferů, glBindBUffer.
Nevýhody :
- Složitější implementace, nutno vyřešit přidělování prostoru v bufferech objektům
- Při plnění dat objektu do jednoho bufferu pomocí glBufferSubData nebo glMapBuffer je třeba mít zajištěno, že z tohoto bufferu neprobíhá rendering ani žádných jiných objektů. Takže by bylo nutné vzájemně sladit pořadí renderování objektů s plněním bufferů tak, aby pokud možno nedocházelo ke kolizím.
- Problémy s framentací těchto velkých VBO
Jak to řešíte Vy ? |
|
Návrat nahoru |
|
|
tempicek
Založen: 04. 12. 2007 Příspěvky: 62
|
Zaslal: 29. prosinec 2007, 18:24:26 Předmět: |
|
|
pcim napsal: |
Jak to řešíte Vy ? |
Dle potreby a casu. Zalezi na projektu. Pokud to ma za neco stat, tak je treba udelat kombinaci obou pristupu, resp. pro kazdy typ dat/assetu zvolit nejlepsi pristup a naimplementovat ho (teren, velke objekty, vegetace, "odpad" ... vsechno si zada svoje).
Volani funkci grafickeho API z vice threadu je dobre se vyhnout, kdyz to trochu jde (ne za kazdou cenu). Pouziti double/tripple-bufferingu je vhodne kdekoli je s tim bufferem vice prace, zvlaste, pokud se pripravuje nekolik snimku. Idealni je to, kdyz se muzes spolehnout na driver a nechat update na nem, jak zminil Eosie.
Pro ten "drobny odpad" (projektily a jine objekty vznikajici ve vetsim mnozstvi za behu) je dobre udelat si buffery "per object type" nebo "per material", tzn. seskupovat je nejakym pravidlem k sobe tak, aby se co nejvice snizil pocet nutnych volani API (zmeny materialu a draw calls). Opet hodne zalezi na konkretni situaci kolik takovych typu je, jak jsou velke, zda neni mozne vyhradit kazdemu objektu stejny prostor atd.
Kazdopade alokovani bufferu za behu (ve vetsim mnozstvi) neni vubec dobry napad, takze tomu je rozhodne dobre se vyhnout. Kdyz ne jinak, tak alespon buffer poolem, ve kterem se vali nepouzivane (na pocatku alokovane) buffery. Tech moznosti je hodne, jako obvykle YMMV. |
|
Návrat nahoru |
|
|
Marek
Založen: 28. 07. 2007 Příspěvky: 1782 Bydliště: Velká Morava
|
Zaslal: 30. prosinec 2007, 02:05:49 Předmět: |
|
|
pcim> Pokud chceš méně bufferů, můžeš ho udělat interleaved - prokládaný, tzn. uložíš za sebe pozici, normálu, koordináty, pozici, normálu... atd. Pak použiješ v gl*Pointer parametr stride, kde dáš velikost celého vertexu (sizeof(pozice a normála a koordináty)), a do pointer dáš akorát offset na konkretní atribut (pro pozici 0, pro normálu ((char*)0)+sizeof(pozice), pro koordináty ((char*)0)+sizeof(pozice a normála)). _________________ AMD Open Source Graphics Driver Developer |
|
Návrat nahoru |
|
|
|