Najlepsza praktyka ustawiania parametrów efektu w XNA

13

Chcę zapytać, czy istnieje najlepsza praktyka ustawiania Effectparametrów w XNA. Innymi słowy, co dokładnie dzieje się, kiedy dzwonię pass.Apply(). Mogę sobie wyobrazić wiele scenariuszy:

  1. Za każdym razem, gdy Applywywoływane, wszystkie parametry efektu są przenoszone do GPU i dlatego nie ma rzeczywistego wpływu na to, jak często ustawiam parametr.
  2. Przy każdym Applywywołaniu przesyłane są tylko parametry, które zostały zresetowane. Dlatego należy unikać buforowania operacji Set, które tak naprawdę nie ustawiają nowej wartości.
  3. Przy każdym Applywywołaniu przesyłane są tylko zmienione parametry. Tak więc buforowanie Zestawów operacji jest bezużyteczne.
  4. Całe to pytanie nie wymaga rozruchu, ponieważ żaden ze wspomnianych sposobów nie ma istotnego wpływu na wydajność gry.

Ostatnie pytanie: czy warto wdrożyć buforowanie operacji set, takie jak:

private Matrix _world;
public Matrix World
{
    get{ return _world; }
    set 
    {
        if (value == world) return;
        _effect.Parameters["xWorld"].SetValue(value);
        _world = value;
    }
}

Z góry dziękuję.

0xBADF00D
źródło
Dodałem tag DirectX, ponieważ jest to funkcja niższego poziomu niż XNA.
Andrew Russell
Znalazłem dowód, że omawiany temat jest BARDZO realny. Wygląda na to, że jeśli jesteś sprytny w ustawianiu parametrów efektu, możesz zwiększyć liczbę wywołań losowania (czyli jak szybko są one przetwarzane na procesorze) ponad dwukrotnie. Nadal jestem w trakcie testowania tego, możesz przeczytać moje pytanie tutaj: gamedev.stackexchange.com/questions/66932/...
cubrman

Odpowiedzi:

8

Wszystko to dzieje się po stronie procesora, więc jeśli buforowanie byłoby przydatną funkcją, to spekulowałbym, że sterownik grafiki sam by to zaimplementował. Dodanie własnej warstwy buforowania nie jest konieczne.

Rozumiem, że za każdym razem, gdy ustawia się parametr i za każdym razem, gdy wywołuje się Apply, te połączenia są przekazywane do DirectX w dużej mierze w stanie „jak jest”, a te z kolei są przekazywane do sterownika GPU w trybie użytkownika w stanie „jak jest”. Sterownik trybu użytkownika może wtedy robić, co tylko chce . Możliwe są wszystkie trzy twoje scenariusze.

(Ponieważ możliwy jest scenariusz nr 2, prawdopodobnie najlepiej nie rozmyślnie zmieniać ustawień parametrów, które się nie zmieniają).

Szczerze mówiąc, nie jestem do końca pewien, co robi typowy kierowca. Głównie dlatego, że tak naprawdę nigdy nie stanowiło to problemu. Nigdy nie słyszałem o tym, żeby ktoś miał ustawienie parametru efektu jako wąskie gardło. Może teoretycznie może być. Ale jest o wiele więcej rzeczy, o które należy się martwić .

Z pewnością nie zacznij wdrażać takich optymalizacji bez mierzenia wydajności i zrozumienia, co się dzieje.

Również porównanie Matrixz ==jest złym voodoo. A Matrixskłada się z floats, a zmiennoprzecinkowe porównania równości są podatne na awarie w wielu przypadkach.

I ogólnie mówiąc, wzór if(x != y) x = y;jest wolniejszy niż po prostu x = y.

Andrew Russell
źródło
Ciekawe, że kierowca powinien o to dbać. Dzięki za link (i ponowne linki).
0xBADF00D
Ostatnio natknąłem się na przykład wystąpienia geometrii z msdn . Wielokrotne resetowanie tych samych stanów renderowania (z tymi samymi wartościami) na klatkę znacznie spowalnia proces renderowania dwa lub trzy razy. Tak więc grupowanie stanów jest zdecydowanie użyteczne. Niestety nie jestem pewien, czy pogoda ta dotyczy również ustawiania parametrów efektu. Ale chciałbym udostępnić moje informacje.
0xBADF00D
4

Znalazłem jedną interesującą rzecz na ten temat.

Z msdn:

Możesz użyć właściwości indeksowanej Parameters w Effect, aby uzyskać dostęp do dowolnego parametru efektu, ale jest to wolniejsze niż użycie EffectParameters. Z tego powodu należy utworzyć parametr EffectParameter dla każdego parametru efektu, który często się zmienia.

i

Tworzenie i przypisywanie instancji EffectParameter dla każdej techniki w Efektie jest znacznie szybsze niż użycie indeksowanej właściwości Parameters w Effect.

Oznacza to, że _effect.Parameters["xWorld"].SetValue(value);jest zauważalnie wolniejszy niżwordlParam.SetValue(value);

Prawdopodobnie powinieneś buforować takie parametry:

public EffectParameter wordlParam;
wordlParam = _effect.Parameters["xWorld"];

Ale nie znalazłem żadnych rzeczywistych testów porównawczych.

Źródła:

http://msdn.microsoft.com/en-us/library/Microsoft.Xna.Framework.Graphics.EffectParameter%28v=xnagamestudio.40%29.aspx http://msdn.microsoft.com/en-us/library /bb976060%28v=xnagamestudio.31%29.aspx

zygzak
źródło
Właśnie przetestowałem to na emulatorze Monogame i WP - mogę potwierdzić, że rzeczywiście istnieje znacząca różnica (w moim przypadku między 5-15%). Czy są jakieś inne sztuczki, które pomagają w wydajności?
Konrad,