Dlaczego dostęp do tekstur jest znacznie wolniejszy podczas obliczania współrzędnych tekstury w module cieniującym fragmenty?

11

Używając tekstur w GLSL, najlepiej obliczyć ostateczne współrzędne tekstury w module cieniującym wierzchołki i przekazać je do modułu cieniującego fragmenty za pomocą varyings. Przykład z prostym przerzuceniem we współrzędnej y:

// Vertex shader
attribute vec2 texture;
varying highp vec2 texCoord;
// ...
void main() {
    texCoord = vec2(texture.x, 1.0-texture.y);
    // ...
}

// Fragment shader
varying highp vec2 textureCoordinates;
uniform sampler2D tex;
// ...
void main() {
    highp vec4 texColor = texture2D(tex, texCoord);
    // ...
}

Jeśli przerzucanie współrzędnej y lub jeszcze prostsza operacja, taka jak dodanie vec2(0.5)do współrzędnej tekstury, jest wykonywana w module cieniującym fragmenty, dostęp do tekstury jest znacznie wolniejszy. Dlaczego?


Uwaga: np. Zmieszanie dwóch tekstur przy użyciu ich ważonej sumy jest znacznie tańsze pod względem czasu i również musi zostać wykonane dla każdego piksela, więc obliczenie samej współrzędnej tekstury nie wydaje się tak kosztowne.

Nero
źródło
1
Domyślam się, że jeśli współrzędne UV są obliczane w VS, jednostka tekstury może zacząć pobierać je wstępnie podczas uruchamiania PS. Jeśli są obliczane w PS, jednostka tekstury musi najpierw poczekać.
RichieSams,
2
Fwiw nazywa się to „zależnym czytaniem tekstur”, w przypadku gdy pomaga w wyszukiwaniu.
Alan Wolfe
Czy masz jakieś pomiary pokazujące różnicę perf? Właściwie nie spodziewałbym się, że w ogóle będzie wiele różnic; opóźnienie pobierania tekstur powinno zalać kilka operacji ALU. BTW, zależne odczyty tekstur są tam, gdzie są dwa (lub więcej) odczyty tekstur, ze współrzędnymi dla drugiego zależą od wyniku pierwszego. Są one wolniejsze ze względu na ścisłe uporządkowanie wymagane między dwoma odczytami tekstur.
Nathan Reed
Cóż, każda operacja wykonana w module cieniującym fragmenty będzie droższa niż w module cieniującym wierzchołków. Każdy trójkąt przyjmuje 3 wywołania modułu cieniującego wierzchołki, ale może potrzebować więcej rzędów wielkości wywołania modułu cieniującego fragmentów, w zależności od jego wielkości ekranu.
glampert
@NathanReed Nie sądzę, że musisz ograniczać „zależne odczyty tekstur” tylko do tych, które pochodzą z poprzedniego dostępu do tekstur. Prawdopodobnie uwzględniałbym również dowolne współrzędne obliczone w module cieniującym frag, w przeciwieństwie do tych, które można określić jedynie na podstawie interpolacji liniowej (dobrze, hiperbolicznej z perspektywą) atrybutów wierzchołków.
Simon F

Odpowiedzi:

11

To, o czym mówisz, jest powszechnie nazywane „zależnymi odczytami tekstur” w społeczności programistów mobilnych. Jest to szczegół implementacji określonego sprzętu i dlatego tak naprawdę zależy od GPU, czy ma to wpływ na wydajność. Zazwyczaj jest to coś, co wychowujesz dla procesorów graficznych PowerVR w sprzęcie Apple, ponieważ zostało to wyraźnie wspomniane zarówno w Imagination, jak i Appledokumentacja. Jeśli dobrze pamiętam, problem w zasadzie wynikał ze sprzętu w GPU, który zaczął pobierać tekstury jeszcze przed uruchomieniem modułu cieniującego fragmenty, dzięki czemu mógł lepiej ukryć opóźnienie. Dokumenty, które podłączyłem, wspominają, że nie jest to już problem na sprzęcie Series6, więc przynajmniej na nowszym sprzęcie Apple nie jest to coś, o co musisz się martwić. Szczerze mówiąc, nie jestem pewien co do innych mobilnych GPU, ponieważ to nie jest moja specjalizacja. Powinieneś spróbować zapoznać się z ich dokumentacją, aby się upewnić.

Jeśli zdecydujesz się na wyszukiwanie w Google tego problemu, pamiętaj, że prawdopodobnie na starszym sprzęcie komputerowym znajdziesz prawdopodobnie starszy materiał, który mówi o pobieraniu tekstur zależnych. Podstawowy we wczesnych dniach cieniowania pikseli / fragmentów termin „zależne pobieranie tekstur” odnosi się do adresu UV, który opierał się na poprzednim pobieraniu tekstur. Klasycznym przykładem było renderowanie mapy środowiska z wypukłościami, w którym chciałeś użyć wektora odbicia opartego na normalnej mapie w celu próbkowania mapy środowiska. Na tym starszym sprzęcie pojawiły się poważne konsekwencje dotyczące wydajności i myślę, że nie był nawet obsługiwany na niektórych bardzo starych procesorach graficznych. W przypadku nowoczesnych układów GPU sprzęt i moduł cieniujący ISA są znacznie bardziej uogólnione, a więc sytuacja wydajnościowa jest znacznie bardziej skomplikowana.

MJP
źródło
Nawiasem mówiąc: doświadczyłem tego na iPadzie 3. Więc może to jest właściwie specyficzne dla sprzętu.
Nero,