Оптимизируйте свои подборки
Сохраняйте и классифицируйте контент в соответствии со своими настройками.
AGI Frame Profiler позволяет вам исследовать ваши шейдеры, выбрав вызов отрисовки на одном из наших проходов рендеринга и просмотрев раздел «Вершинный шейдер» или раздел «Фрагментный шейдер» на панели «Конвейер» .
Здесь вы найдете полезную статистику, полученную в результате статического анализа кода шейдера, а также сборки стандартного переносимого промежуточного представления (SPIR-V), в которую был скомпилирован наш GLSL. Также имеется вкладка для просмотра представления исходного GLSL (с сгенерированными компилятором именами для переменных, функций и т. д.), которое было декомпилировано с помощью SPIR-V Cross, чтобы обеспечить дополнительный контекст для SPIR-V.
Статический анализ
Рисунок 1. Подпись??
Используйте счетчики статического анализа для просмотра низкоуровневых операций в шейдере.
Инструкции ALU : этот счетчик показывает количество операций ALU (сложение, умножение, деление и т. д.), выполняемых в шейдере, и является хорошим показателем сложности шейдера. Постарайтесь минимизировать это значение.
Рефакторинг общих вычислений или упрощение вычислений, выполняемых в шейдере, могут помочь уменьшить количество необходимых инструкций.
Инструкции по текстурам : этот счетчик показывает, сколько раз в шейдере происходит выборка текстуры.
Выборка текстур может быть дорогостоящей в зависимости от типа текстур, из которых производится выборка, поэтому перекрестные ссылки на код шейдера с привязанными текстурами, найденными в разделе «Наборы дескрипторов» , могут предоставить дополнительную информацию о типах используемых текстур.
Избегайте произвольного доступа при выборке текстур, поскольку такое поведение не идеально подходит для кэширования текстур.
Инструкции ветвления : этот счетчик показывает количество операций ветвления в шейдере. Минимизация ветвления идеально подходит для параллельных процессоров, таких как графический процессор, и может даже помочь компилятору найти дополнительные оптимизации:
Используйте такие функции, как min , max и clamp , чтобы избежать необходимости ветвления по числовым значениям.
Проверьте стоимость вычислений при ветвлении. Поскольку оба пути ветки выполняются во многих архитектурах, существует множество сценариев, в которых всегда выполнение вычислений происходит быстрее, чем пропуск вычислений с помощью ветки.
Временные регистры : это быстрые встроенные регистры, которые используются для хранения результатов промежуточных операций, необходимых для вычислений на графическом процессоре. Существует ограничение на количество регистров, доступных для вычислений, прежде чем графическому процессору придется использовать другую внеъядерную память для хранения промежуточных значений, что снижает общую производительность. (Этот предел зависит от модели графического процессора.)
Количество используемых временных регистров может оказаться больше, чем ожидалось, если компилятор шейдеров выполняет такие операции, как развертывание циклов, поэтому полезно сопоставить это значение с SPIR-V или декомпилированным GLSL, чтобы увидеть, что делает код.
Анализ шейдерного кода
Исследуйте сам декомпилированный код шейдера, чтобы определить, возможны ли какие-либо потенциальные улучшения.
Рисунок 2. Подпись??
Точность . Точность переменных шейдера может повлиять на производительность графического процессора вашего приложения.
Попробуйте использовать модификатор точности mediump для переменных везде, где это возможно, поскольку 16-битные переменные средней точности ( mediump ) обычно работают быстрее и более энергоэффективны, чем 32-битные переменные полной точности ( highp ).
Если вы не видите никаких квалификаторов точности в шейдере в объявлениях переменных или в верхней части шейдера с precision precision-qualifier type , по умолчанию используется полная точность ( highp ). Обязательно обратите внимание на объявления переменных.
Использование mediump для вывода вершинного шейдера также является предпочтительным по тем же причинам, которые описаны выше, а также дает преимущество в уменьшении пропускной способности памяти и потенциально использовании временного регистра, необходимого для выполнения интерполяции.
Единые буферы : старайтесь, чтобы размер унифицированных буферов был как можно меньшим (при соблюдении правил выравнивания). Это помогает сделать вычисления более совместимыми с кэшированием и потенциально позволяет перемещать унифицированные данные в более быстрые регистры ядра.
Удалите неиспользуемые выходные данные вершинного шейдера . Если вы обнаружите, что выходные данные вершинного шейдера не используются во фрагментном шейдере, удалите их из шейдера, чтобы освободить пропускную способность памяти и временные регистры.
Переместить вычисления из фрагментного шейдера в вершинный шейдер . Если код фрагментного шейдера выполняет вычисления, которые не зависят от состояния, специфичного для закрашиваемого фрагмента (или могут быть правильно интерполированы), идеальным решением является перемещение его в вершинный шейдер. Причина этого в том, что в большинстве приложений вершинный шейдер запускается гораздо реже по сравнению с фрагментным шейдером.
Контент и образцы кода на этой странице предоставлены по лицензиям. Java и OpenJDK – это зарегистрированные товарные знаки корпорации Oracle и ее аффилированных лиц.
Последнее обновление: 2025-07-29 UTC.
[[["Прост для понимания","easyToUnderstand","thumb-up"],["Помог мне решить мою проблему","solvedMyProblem","thumb-up"],["Другое","otherUp","thumb-up"]],[["Отсутствует нужная мне информация","missingTheInformationINeed","thumb-down"],["Слишком сложен/слишком много шагов","tooComplicatedTooManySteps","thumb-down"],["Устарел","outOfDate","thumb-down"],["Проблема с переводом текста","translationIssue","thumb-down"],["Проблемы образцов/кода","samplesCodeIssue","thumb-down"],["Другое","otherDown","thumb-down"]],["Последнее обновление: 2025-07-29 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."]]