Co właściwie robi ddx (hlsl)?

17

Jestem nieco zdezorientowany. Oficjalna dokumentacja ( http://msdn.microsoft.com/en-us/library/windows/desktop/bb509588(v=vs.85).aspx ) mówi, że ddx (dane wejściowe) jest częściową pochodną danych wejściowych w odniesieniu do „współrzędnej x przestrzeni ekranu”.

Mój rachunek różniczkowy jest w porządku, ale jak rozpoznać, skąd pochodzi dane wejściowe? Gdybym podał jej funkcję, dobrze, mogę sobie wyobrazić, co by to zrobił, ale pochodna liczby jest zawsze równa zero ...?

Czy to tylko skalowanie? Na przykład, skalowałby się do jednej dziesiątej swojego rozmiaru w tej odległości, więc zwraca jedną dziesiątą? Ale wtedy nie potrzebuje danych wejściowych ...

Czy ktoś może szybko wyjaśnić, co się właściwie dzieje?

Richard Rast
źródło
2
ddxi ddyróbcie magię, której nie możecie zrobić sami. Mają dostęp do dodatkowych informacji z potoku rasteryzacji, których nie można uzyskać z poziomu modułu cieniującego piksele. Nie jestem pewien, jakiej dokładnie używają formuły; Zostałem przekonany, że używają techniki szacowania, ale nie jestem pewien.
Sean Middleditch
To głęboko dziwne, ale jednak. Co właściwie reprezentuje ddx (5)? Jeśli mówi .1, jak mam to interpretować? Czy -6?
Richard Rast
1
ddx(5)jest trochę bezcelowe. Użyj go z wartością wejściową, a to da ci pochodną tej wartości w odniesieniu do sąsiednich pikseli w bloku. Znów nie wiem, jak dokładnie oblicza wartości, ale prośba o pochodną nie-danych wejściowych może być po prostu niezdefiniowanym zachowaniem i produkować śmieci. Zobacz fgiesen.wordpress.com/2011/07/10/..., aby uzyskać więcej informacji, niż mogę dostarczyć.
Sean Middleditch
Nie jestem pewien, ale może się okazać, że kompilator HLSL faktycznie dokonuje pełnego symbolicznego różnicowania wyrażenia przekazywanego do ddx / ddy. blogs.msdn.com/b/chuckw/archive/2011/03/08/… research.microsoft.com/pubs/146019/…
Ziriax
Co to robi? Tylko nieznacznie rozsądna rzecz, oczywiście.
MickLH,

Odpowiedzi:

32

Wewnętrznie procesory graficzne nigdy nie uruchamiają jednej instancji modułu cieniującego piksele na raz. Na najwyższym poziomie szczegółowości zawsze działają w tym samym czasie 32-64 piksele przy użyciu architektury SIMD. W ramach tego piksele są dalej zorganizowane w kwadraty 2x2, więc każda grupa 4 kolejnych pikseli w wektorze SIMD odpowiada blokowi pikseli 2x2 na ekranie.

Pochodne oblicza się, biorąc różnice między pikselami w kwadracie. Na przykład ddxodejmie wartości w pikselach po lewej stronie kwadratu od wartości po prawej stronie i ddyodejmie dolne piksele od górnych. Różnice można następnie zwrócić jako pochodną dla wszystkich czterech pikseli w kwadracie.

Ponieważ moduł cieniujący pikseli działa w SIMD, gwarantuje się, że odpowiednia wartość znajduje się w tym samym rejestrze w tym samym czasie dla wszystkich pikseli w kwadracie. Niezależnie od tego, jakie wyrażenie lub wartość wprowadzisz ddxlub ddy, zostanie ono ocenione we wszystkich czterech pikselach kwadratu, a następnie wartości z różnych pikseli odjęte, jak opisano powyżej.

Zatem przyjęcie pochodnej stałej wartości da zero (jak można się spodziewać po rachunku różniczkowym, prawda?), Ponieważ jest to ta sama stała wartość we wszystkich czterech pikselach.

Należy również zauważyć, że istnieją „zgrubne” i „drobne” pochodne, ddx_coarse/ ddy_coarsei ddx_fine/ ddy_fine. Wyjaśnienie tego rozróżnienia znajduje się tutaj . Po prostu zwykłe ddx/ ddysą aliasami dla gruboziarnistych wersji.

BTW, powodem tej funkcjonalności jest to, że procesory graficzne muszą wewnętrznie pobierać pochodne współrzędnych tekstury w celu dokonania wyboru mipmapy i filtrowania anizotropowego. Ponieważ sprzęt i tak potrzebuje tej możliwości (możesz użyć dowolnego wyrażenia dla współrzędnych tekstury w module cieniującym), łatwo było też udostępnić go bezpośrednio programistom modułu cieniującego.

Nathan Reed
źródło
+1; Uznałem to za przydatne przy stosowaniu efektu perturbacji do tekstury; zaburzone texcoords dały pewne zniekształcenie kolorów, ale użycie tex2Dgrad z pochodnymi z oryginalnych (nieprzerwanych) texcoordów dało niezniekształcony wynik.
Maximus Minimus
Dobra, po namyśle myślę, że zrozumiałem swoje zamieszanie. Moim zdaniem ddxdziała jak każda inna funkcja w tradycyjnym języku programowania; oceniasz dane wejściowe, zmieniasz je na zmiennoprzecinkowe lub cokolwiek, a następnie wykonujesz dla niego funkcję zewnętrzną ( ddx). Ale jest inaczej - pobiera ciąg wejściowy , ocenia go w kilku miejscach, oblicza pochodną i zgłasza wynik. Czy to w porządku?
Richard Rast
1
@RichardRast Right. Możesz myśleć, że ddxdziała na podstawie wyrażenia, które do niego przekazujesz, a nie na wartości .
Nathan Reed,
Ale zobacz, to na tyle dziwne, że powinno być w dokumentacji. Nie mogę myśleć o żadnym innym czasie w moim życiu programistycznym, w którym tak się dzieje.
Richard Rast
Nathan Reed wspomniał, że procesory graficzne używają tych funkcji do wyboru mipmap. Można ich również użyć, aby wymusić na GPU wybranie pożądanego poziomu mipmapy lub aby zapobiec nieprawidłowemu wyborowi artefaktów. Proces ten opisano na stronach 163 i 164 programu Shader X3.
JamesHoux,