Organiza tus páginas con colecciones
Guarda y categoriza el contenido según tus preferencias.
El Generador de perfiles de marcos de AGI te permite investigar tus sombreadores. Para ello, selecciona una llamada de dibujo de uno de nuestros pases de renderización y revisa la sección Vertex Shader o Fragment Shader del panel Pipeline.
Aquí encontrarás estadísticas útiles que provienen del análisis estático del código del sombreador, así como del ensamblaje de Representación Intermedia Portable Estándar (SPIR-V) en el que se compiló nuestra GLSL. También hay una pestaña para ver una representación de la GLSL original (con nombres generados por el compilador para variables, funciones y más) que se descompiló con SPIR-V Cross, a fin de proporcionar contexto adicional para SPIR-V.
Análisis estático
Figura 1: ¿Subtítulos?
Usa contadores de análisis estáticos para ver las operaciones de bajo nivel en el sombreador.
Instrucciones de ALU: Este recuento muestra la cantidad de operaciones de ALU (agregaciones, multiplicaciones, divisiones y más) que se ejecutan dentro del sombreador y es un buen indicador de la complejidad del sombreador. Intenta minimizar este valor.
La refactorización de cálculos comunes o simplificar los cálculos realizados en el sombreador puede ayudar a reducir la cantidad de instrucciones necesarias.
Instrucciones de textura: Este recuento muestra la cantidad de veces que se produce un muestreo de textura en el sombreador.
El muestreo de texturas puede ser costoso según el tipo de texturas de las que se realice la muestra, por lo que comparar el código del sombreador con las texturas vinculadas que se encuentran en la sección Conjuntos de descriptores puede proporcionar más información sobre los tipos de texturas que se usan.
Evita el acceso aleatorio cuando muestres texturas, ya que este comportamiento no es ideal para el almacenamiento en caché de texturas.
Instrucciones de rama: Este recuento muestra la cantidad de operaciones de rama en el sombreador. Minimizar la ramificación es ideal en procesadores en paralelo, como la GPU, y hasta puede ayudar al compilador a encontrar optimizaciones adicionales:
Usa funciones como min, max y clamp para evitar la necesidad de ramificarse en valores numéricos.
Prueba el costo del procesamiento sobre la ramificación. Debido a que ambas rutas de acceso de una rama se ejecutan en muchas arquitecturas, hay muchas situaciones en las que realizar el procesamiento siempre es más rápido que omitirlo con una rama.
Registros temporales: Son registros rápidos en el núcleo que se usan para conservar los resultados de las operaciones intermedias que requieren los cálculos en la GPU. Existe un límite en la cantidad de registros disponibles para los procesamientos antes de que la GPU tenga que utilizar otra memoria fuera del núcleo para almacenar valores intermedios, lo que reduce el rendimiento general. (Este límite varía según el modelo de GPU).
La cantidad de registros temporales que se usan puede ser mayor de lo esperado si el compilador de sombreadores realiza operaciones como desenrollar bucles. Por lo tanto, se recomienda hacer una referencia cruzada de este valor con SPIR-V o GLSL descompilado para ver qué hace el código.
Análisis de código de sombreadores
Investiga el código del sombreador descompilado para determinar si hay posibles mejoras.
Figura 2: ¿Subtítulos?
Precisión: La precisión de las variables del sombreador puede afectar el rendimiento de la GPU de tu aplicación.
Intenta usar el modificador de precisión mediump en variables siempre que sea posible, ya que las variables de precisión media (mediump) de 16 bits suelen ser más rápidas y eficientes en términos de energía que las variables de precisión completa (highp) de 32 bits.
Si no ves ningún calificador de precisión en el sombreador de las declaraciones de variables o en la parte superior del sombreador con un precision precision-qualifier type, el valor predeterminado es la precisión completa (highp). Asegúrate de observar también las declaraciones de las variables.
También es preferible usar mediump para la salida del sombreador de vértices por los mismos motivos descritos anteriormente; además, tiene el beneficio de reducir el ancho de banda de la memoria y el posible uso de registros temporales necesarios para realizar la interpolación.
Búferes uniformes: Intenta mantener el tamaño de los búferes uniformes lo más pequeño posible (y al mismo tiempo mantener las reglas de alineación). Esto ayuda a que los cálculos sean más compatibles con el almacenamiento en caché y, potencialmente, permita que los datos uniformes se promuevan a registros más rápidos en el núcleo.
Quita los resultados del sombreador de Vertex que no se usen: Si encuentras que los resultados del sombreador de vértices no se usan en el sombreador de fragmentos, quítalos del sombreador para liberar ancho de banda de memoria y registros temporales.
Mueve los cálculos del sombreador de fragmentos al sombreador de Vertex: si el código del sombreador de fragmentos realiza cálculos que son independientes del estado específico del fragmento que se está sombreando (o que se pueden interpolar correctamente), lo ideal es moverlo al sombreador de vértices. Esto se debe a que, en la mayoría de las apps, el sombreador de vértices se ejecuta con mucha menos frecuencia en comparación con el sombreador de fragmentos.
El contenido y las muestras de código que aparecen en esta página están sujetas a las licencias que se describen en la Licencia de Contenido. Java y OpenJDK son marcas registradas de Oracle o sus afiliados.
Última actualización: 2025-07-27 (UTC)
[[["Fácil de comprender","easyToUnderstand","thumb-up"],["Resolvió mi problema","solvedMyProblem","thumb-up"],["Otro","otherUp","thumb-up"]],[["Falta la información que necesito","missingTheInformationINeed","thumb-down"],["Muy complicado o demasiados pasos","tooComplicatedTooManySteps","thumb-down"],["Desactualizado","outOfDate","thumb-down"],["Problema de traducción","translationIssue","thumb-down"],["Problema con las muestras o los códigos","samplesCodeIssue","thumb-down"],["Otro","otherDown","thumb-down"]],["Última actualización: 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."]]