Zadbaj o dobrą organizację dzięki kolekcji
Zapisuj i kategoryzuj treści zgodnie ze swoimi preferencjami.
AGI Frame Profiler umożliwia zbadanie shaderów przez wybranie wywołania rysowania z jednego z naszych przebiegów renderowania i przejście do sekcji Vertex Shader lub Fragment Shader w panelu Pipeline.
Znajdziesz tu przydatne statystyki pochodzące z analizy statycznej kodu shadera, a także standardową przenośną reprezentację pośrednią (SPIR-V), do której skompilowaliśmy nasz GLSL. Jest też karta, na której można wyświetlić reprezentację oryginalnego kodu GLSL (z nazwami zmiennych, funkcji itp. wygenerowanymi przez kompilator), który został zdekompilowany za pomocą SPIR-V Cross, aby zapewnić dodatkowy kontekst dla SPIR-V.
Analiza statyczna
Rysunek 1. Podpis??
Użyj liczników analizy statycznej, aby wyświetlić operacje niskiego poziomu w cieniowaniu.
Instrukcje ALU: ta liczba pokazuje, ile operacji ALU (dodawanie, mnożenie, dzielenie itp.) jest wykonywanych w cieniowaniu. Jest to dobry wskaźnik złożoności cieniowania. Staraj się minimalizować tę wartość.
Refaktoryzacja typowych obliczeń lub uproszczenie obliczeń wykonywanych w cieniowaniu może pomóc zmniejszyć liczbę potrzebnych instrukcji.
Instrukcje dotyczące tekstury: ta liczba pokazuje, ile razy w cieniu następuje próbkowanie tekstury.
Próbkowanie tekstur może być kosztowne w zależności od typu tekstur, z których pobierane są próbki. Porównanie kodu shadera z powiązanymi teksturami znalezionymi w sekcji Zbiory deskryptorów może dostarczyć więcej informacji o rodzajach używanych tekstur.
Unikaj losowego dostępu podczas próbkowania tekstur, ponieważ nie jest to idealne rozwiązanie w przypadku buforowania tekstur.
Instrukcje rozgałęzienia: ta liczba pokazuje liczbę operacji rozgałęzienia w cieniowaniu. Minimalizowanie rozgałęzień jest idealne w przypadku procesorów równoległych, takich jak GPU, a nawet może pomóc kompilatorowi w znalezieniu dodatkowych optymalizacji:
Używaj funkcji takich jak min, max i clamp, aby uniknąć rozgałęziania wartości liczbowych.
Sprawdź koszt obliczeń w przypadku rozgałęzienia. W wielu architekturach wykonuje się obie ścieżki rozgałęzienia, więc w wielu przypadkach zawsze szybsze jest wykonanie obliczeń niż pominięcie ich za pomocą rozgałęzienia.
Rejestry tymczasowe: są to szybkie rejestry w rdzeniu, które służą do przechowywania wyników operacji pośrednich wymaganych przez obliczenia na GPU. Liczba rejestrów dostępnych do obliczeń jest ograniczona, zanim GPU będzie musiał użyć innej pamięci poza rdzeniem do przechowywania wartości pośrednich, co zmniejsza ogólną wydajność. (Ten limit różni się w zależności od modelu GPU).
Liczba używanych rejestrów tymczasowych może być wyższa niż oczekiwana, jeśli kompilator cieniowania wykonuje operacje takie jak rozwijanie pętli. Warto więc porównać tę wartość z kodem SPIR-V lub zdekompilowanym kodem GLSL, aby sprawdzić, co robi kod.
Analiza kodu shadera
Sprawdź zdekompilowany kod shadera, aby określić, czy można wprowadzić jakieś ulepszenia.
Rysunek 2. Podpis??
Precyzja: precyzja zmiennych shadera może mieć wpływ na wydajność procesora graficznego aplikacji.
W miarę możliwości używaj modyfikatora precyzji mediump w przypadku zmiennych, ponieważ zmienne 16-bitowe o średniej precyzji (mediump) są zwykle szybsze i bardziej energooszczędne niż zmienne 32-bitowe o pełnej precyzji (highp).
Jeśli w shaderze nie widzisz żadnych kwalifikatorów precyzji w deklaracjach zmiennych ani u góry shadera z symbolem precision precision-qualifier type, domyślnie używana jest pełna precyzja (highp). Sprawdź też deklaracje zmiennych.
Używanie mediump w przypadku danych wyjściowych shadera wierzchołków jest również preferowane z tych samych powodów, co opisane powyżej. Ma też tę zaletę, że zmniejsza przepustowość pamięci i potencjalnie wykorzystanie rejestrów tymczasowych potrzebnych do interpolacji.
Bufory jednolite: staraj się, aby rozmiar buforów jednolitych był jak najmniejszy (przy zachowaniu zasad wyrównania). Ułatwia to obliczenia w pamięci podręcznej i może umożliwić przenoszenie jednolitych danych do szybszych rejestrów w rdzeniu.
Usuń nieużywane dane wyjściowe shadera wierzchołków: jeśli w shaderze fragmentów znajdziesz nieużywane dane wyjściowe shadera wierzchołków, usuń je z shadera, aby zwolnić przepustowość pamięci i rejestry tymczasowe.
Przenieś obliczenia z shadera fragmentów do shadera wierzchołków: jeśli kod shadera fragmentów wykonuje obliczenia niezależne od stanu specyficznego dla fragmentu, który jest cieniowany (lub może być prawidłowo interpolowany), przeniesienie go do shadera wierzchołków jest idealnym rozwiązaniem. Dzieje się tak dlatego, że w większości aplikacji program cieniowania wierzchołków jest uruchamiany znacznie rzadziej niż program cieniowania fragmentów.
Treść strony i umieszczone na niej fragmenty kodu podlegają licencjom opisanym w Licencji na treści. Java i OpenJDK są znakami towarowymi lub zastrzeżonymi znakami towarowymi należącymi do firmy Oracle lub jej podmiotów stowarzyszonych.
Ostatnia aktualizacja: 2025-07-27 UTC.
[null,null,["Ostatnia aktualizacja: 2025-07-27 UTC."],[],[],null,["# Analyze shader performance\n\nAGI Frame Profiler allows you to investigate your shaders by\nselecting a draw call from one of our render passes, and going through either\nthe **Vertex Shader** section or **Fragment Shader** section of the **Pipeline**\npane.\n\nHere you'll find useful statistics coming from static analysis of the shader\ncode, as well as the [Standard Portable Intermediate Representation](https://en.wikipedia.org/wiki/Standard_Portable_Intermediate_Representation)\n(SPIR-V) assembly that our GLSL has been compiled down to. There's also a tab\nfor viewing a representation of the original GLSL (with compiler generated names for variables, functions, and more) that was decompiled with SPIR-V Cross, to provide additional context for the SPIR-V.\n\nStatic analysis\n---------------\n\n**Figure 1.**Caption??\n\nUse static analysis counters to view low-level operations in the shader.\n\n- **ALU Instructions**: This count shows the number of ALU operations\n (adds, multiplies, divisions, and more) are being executed within the\n shader, and is a good proxy for how complex the shader is. Try to minimize\n this value.\n\n Refactoring common computations or simplify computations done in the\n shader can help reduce the number of instructions needed.\n- **Texture Instructions**: This count shows the number of times texture\n sampling occurs in the shader.\n\n - Texture sampling can be expensive depending on the type of textures being sampled from, so cross-referencing the shader code with the bound textures found in the **Descriptor Sets** section can provide more information on the types of textures being used.\n - Avoid random access when sampling textures, because this behavior is not ideal for texture-caching.\n- **Branch Instructions**: This count shows the number of branch operations\n in the shader. Minimizing branching is ideal on parallelized processors such\n as the GPU, and can even help the compiler find additional optimizations:\n\n - Use functions such as `min`, `max`, and `clamp` to avoid needing to branch on numeric values.\n - Test the cost of computation over branching. Because both paths of a branch are executed in many architectures, there are many scenarios where always doing the computation is faster than skipping over the computation with a branch.\n- **Temporary Registers**: These are fast, on-core registers that are used to\n hold the results of intermediate operations required by computations on the\n GPU. There is a limit to the number of registers available for computations\n before the GPU has to spill over into using other off-core memory to store\n intermediate values, reducing overall performance. (This limit varies\n depending on the GPU model.)\n\n The number of temporary registers used may be higher than expected if the\n shader compiler performs operations such as unrolling loops, so it's good\n to cross-reference this value with the SPIR-V or decompiled GLSL to see what\n the code is doing.\n\n### Shader code analysis\n\nInvestigate the decompiled shader code itself to determine if there any\npotential improvements are possible.\n**Figure 2.**Caption??\n\n- **Precision** : The precision of shader variables can impact the GPU performance of your application.\n - Try using the `mediump` precision modifier on variables wherever possible, since medium precision (`mediump`) 16-bit variables are usually faster and more power efficient than full precision (`highp`) 32-bit variables.\n - If you don't see any precision qualifiers in the shader on variable declarations, or at the top of the shader with a `precision precision-qualifier type`, it defaults to full precision (`highp`). Make sure to look at variable declarations as well.\n - Using `mediump` for vertex shader output is also preferred for the same reasons described above, and also has the benefit of reducing memory bandwidth and potentially temporary register usage needed to do interpolation.\n- **Uniform Buffers** : Try to keep the size of **Uniform Buffers** as small as possible (while maintaining alignment rules). This helps make computations more compatible with caching and potentially allow for uniform data to be promoted to faster on-core registers.\n- **Remove unused Vertex Shader Outputs**: If you find vertex shader outputs\n being unused in the fragment shader, remove them from the shader to free up\n memory bandwidth and temporary registers.\n\n- **Move computation from Fragment Shader to Vertex Shader**: If the fragment\n shader code performs computations that are independent of state specific to\n the fragment being shaded (or can be interpolated properly), moving it to\n the vertex shader is ideal. The reason for this is that in most apps, the\n vertex shader is run much less frequently compared to the fragment shader."]]