Warsztat » Forum

[DirectX] Narzut BeginPass / EndPass

Apr 23, 2009 | Kot |
20 wypowiedzi na 2 stronach:
1 2
Kot
Apr 23, 2009

Narzut BeginPass / EndPass

Cześć,
Powiedzcie mi, czy narzut powodowany przez wywoływanie BeginPass / EndPass na obiekcie efektu w DXie powoduje dużą utratę czasu czy jest pomijalnie mały?
Chodzi mi o zaprojektowanie pętli renderującej obiekty i rozważam dwie możliwości:
Kod: 

for(i=0...liczba passow)
{
  efekt.BeginPass(i);
  foreach(obiekt)
    obiekt.Render();
  efekt.EndPass();
}
Kod: 

foreach(obiekt)
{
  for(i=0...liczba passow)
  {
     efekt.BeginPass(i);
     obiekt.Render();
     efekt.EndPass();
  }
}

Skłaniałbym się do tej drugiej opcji, gdyż w przypadku, gdyby istniały obiekty korzystające z innej techniki czy nawet liczby passów niż pozostałe modyfikacja byłaby natychmiastowa i w pełni skalowalna. Zastanawiam się jednak właśnie nad tym narzutem czasowym, gdyż szacuję, że tych "niestandardowych" obiektów będzie 10-20%, więc spokojnie mógłbym je renderować też w osobnej pętli, a te 80-90% typowych jak w rozwiązaniu 1.
Co doradzicie?
upshader
Apr 22, 2009

Odp: Narzut BeginPass / EndPass

Uzwaj drugiego sposobu dla wszystkich obiektow. Narzut o ktorym wspominasz jest minimalny (lub w ogole go nie ma bo sterownik to zoptymalizuje).
Kot
Apr 23, 2009

Odp: Narzut BeginPass / EndPass

Ok, dzięki to już wiem jak z BeginPass. A co z samym Effect.Begin czyli co się z nim wiąże zmianą aktywnej techniki, opłaca się grupować obiekty wykorzystujące te same techniki czy znowu wywołanie Effect.Begin / Effect.End jest pomijalnie kosztowne i mogę podobnie jak w drugim sposobie wywoływać je bez obaw dla każdego obiektu?
Charibo
Apr 23, 2009

Odp: Narzut BeginPass / EndPass

Zmiana shaderow jest jedna z najkosztowniejszych operacji jakie mozesz wykonac na karcie, poniewaz karta, w uproszczeniu, musi skonczyc renderowac, zmienic wewnetrzne stany i dopiero po dluzszej chwili zaczyna znowu pracowac, takze najlepiej jest grupowac siatki wzgledem shaderow.

(nawiasem mowiac, ciekawym jest wstawienie sobie Sleep(..) przed Present(..) - fps'y nie spadaja nawet przy kilku milisekundach opoznienia[1])

[1] Eksperyment by (z tego co pamietam) St3tc i https://nvdeveloper.nvidia.com
Kot
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

To nie kończy renderowania wraz z EndPass?
Czy wywołanie Effect.Begin z flagą D3DXFX_DONOTSAVESTATE nie spowoduje, że żadne wewnętrzne stany nie będą automatycznie przywracane?
upshader
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

Grupowac nalezy zawsze i to nie tylko po shaderach. Grupuje sie po texturach, po blendingu itd. Generalnie trzeba tak grupowac aby jak najmniej przelaczac stany urzadzenia.
Charibo
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

Nie wiem jak z Directowymi plikami .fx - ja uzywam wlasnych. W kazdym razie, wywolania SetRenderState() sa raczej dosyc tanie. W kolejnosci "ceny" wywolania od najwiekszej, plasuja sie[1]:

  • zmiany PS

  • zmiany stalych PS

  • zmiany VS

  • zmiany stalych VS

  • zmiany Render Targets

  • zmiany formatu wierzchoklow

  • zmiany stanow Samplera

  • zmiany VB i IB

  • zmiany tekstur

  • zmiany stanow renderowania (SetRenderState())

  • wywolania DrawPrimitive



Karta grafiki "konczy" renderowanie tylko wtedy kiedy nie ma nic do roboty. Dla niej nie ma roznicy podzial na meshe, poki uzywaja tych samych shaderow i ich stalych, dla niej to tylko pakiet wierzcholkow. Nalezy tez uwazac na zbyt duza ilosc wywolan DP[2], bo to tez robi roznice. Zreszta, potestuj sobie z NvperfHUDem albo PIXem :)

[1] Wziete z http://tomsdxfaq.blogspot.com/
[2] Polecam przyklad Instancing z NV SDK

EDIT:/ @up

Prawda, jednak lepiej jest przelaczac prawie ze bez kosztow blending niz shadery :)
Kot
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

Ok, dzięki za odpowiedzi i linka - trochę sobie poczytam.
upshader
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

Cytat:

Prawda, jednak lepiej jest przelaczac prawie ze bez kosztow blending niz shadery :)

Tylko, ze jak masz 10 000 obiektow i 90% z nich renderujesz przy pomocy jednego shadera to takie info pogrupuj po shaderach nie wiele Ci daje. Owszem w pierwszej kolejnosci po shaderach a potem te 9 000 obiektow grupujesz po meshach, texturach itd.
Co do obiektow z blendingiem to wiadomo kiedy je trzeba rysowac, zeby z-buffer nie zwariowal. nie ;] ?
Charibo
Apr 26, 2009

Odp: Narzut BeginPass / EndPass

z blendingiem to byl taki przyklad randomowego renderstate'a :)

Ale nie kumam jak mozna grupowac po meshach :) Z reszta, nie ma znaczenia - to ze grupowac trzeba - wiadomo :)
upshader
Apr 23, 2009

Odp: Narzut BeginPass / EndPass

Cytat:

Ale nie kumam jak mozna grupowac po meshach :)

Jakto jak? Normalnie. Jak masz 100 takich samych drzewek na planszy to renderujesz je wszystkie razem (przestawiajac tylko macierz swiata) i dzieki temu ani razu nie musisz zmienic bufora indeksow ani wierzcholkow ani niczego przesylac na karte graficzna ;]
Charibo
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

Aha w ten sposob :) Ale tym to sie juz instancing zajmuje :)

edit @down: zalezy jak go robisz. Jesli shaderowo, to potrzebujesz co najmniej SM3, a jesli software'owo (co sprowadza sie do tego co powiedziales tak na prawde ;) ), to kazda karta nie ma juz nic do gadania ;)
upshader
Apr 24, 2009

Odp: Narzut BeginPass / EndPass

Cytat:

Aha w ten sposob :) Ale tym to sie juz instancing zajmuje :)

z tego co sie orientuje to tylko radki od 9500 w gore i geforce od  6800 wspieraja geometry instancing ;]
Krzysiek K.
Apr 25, 2009

Odp: Narzut BeginPass / EndPass

Cytat:
Uzwaj drugiego sposobu dla wszystkich obiektow. Narzut o ktorym wspominasz jest minimalny (lub w ogole go nie ma bo sterownik to zoptymalizuje).

Narzut jest zawsze i może być spory.

Jeżeli chcesz efektywnie renderować, posortuj obiekty według używanej techniki i odpalaj całymi grupami (pierwszy pass dla wszystkich, drugi pass dla wszystkich, itd).


Cytat:
To nie kończy renderowania wraz z EndPass?

Wszystkie wywołania do driverów są kolejkowane, dzięki czemu GPU ma zawsze robotę na zapas. Na opróżnienie kolejki i faktyczne skończenie renderowania czeka dopiero Present.

Cytat:
Grupowac nalezy zawsze i to nie tylko po shaderach. Grupuje sie po texturach, po blendingu itd. Generalnie trzeba tak grupowac aby jak najmniej przelaczac stany urzadzenia.

Gdzieś widziałem sugestię, żeby grupować po vertex shaderze. Grupowanie po blendingu jest raczej mało sensowne, bo przełączenie pojedynczej flagi nie może być kosztowną operacją. :)

Cytat:
Co do obiektow z blendingiem to wiadomo kiedy je trzeba rysowac, zeby z-buffer nie zwariowal. nie ;] ?

Albo wykorzystać alpha to coverage. ;)

Cytat:
z tego co sie orientuje to tylko radki od 9500 w gore i geforce od  6800 wspieraja geometry instancing ;]

Pod OpenGL możesz wykorzystać "pseudo instancing" na każdej karcie, która obsługuje vertex shadery. :)
st3tc
Apr 25, 2009

Odp: Narzut BeginPass / EndPass

Cytat:

Zmiana shaderow jest jedna z najkosztowniejszych operacji jakie mozesz wykonac na karcie, poniewaz karta, w uproszczeniu, musi skonczyc renderowac, zmienic wewnetrzne stany i dopiero po dluzszej chwili zaczyna znowu pracowac
Nie  - bo są kolejkowane.

Cytat:
Na opróżnienie kolejki i faktyczne skończenie renderowania czeka dopiero Present.

Nie tylko Present.
Kot
Apr 26, 2009

Odp: Narzut BeginPass / EndPass

Heh, czyli najpierw przeczytałem to co powiedział upshader, ale teraz Krzysiek temu zaprzeczył; st3tc natomiast rozumiem, że przeczy fragmentowi "skończyć renderować", a nie temu, że jest to kosztowna operacja? :)
Reasumując, mam rozumieć, że poniższa konstrukcja jest optymalna i Warsztat recommended :P:
Kod: 

foreach(technika)
{
   efekt(technika);
   efekt.Begin();
   foreach(pass)
   {
      efekt.BeginPass(i);
      foreach(obiekt)
        obiekt.Render();
      efekt.EndPass();
   }  
   efekt.End();
}
Strony:
1 2