Restez organisé à l'aide des collections
Enregistrez et classez les contenus selon vos préférences.
AGI Frame Profiler vous permet d'examiner vos nuanceurs en sélectionnant un appel de dessin à partir de l'un de nos passes de rendu, puis en parcourant la section Vertex Shader ou Fragment Shader du volet Pipeline.
Vous y trouverez des statistiques utiles issues de l'analyse statique du code du nuanceur, ainsi que l'assemblage Standard Portable Intermediate Representation (SPIR-V) dans lequel notre GLSL a été compilé. Un onglet permet également d'afficher une représentation du GLSL d'origine (avec les noms générés par le compilateur pour les variables, les fonctions, etc.) qui a été décompilé avec SPIR-V Cross, afin de fournir un contexte supplémentaire pour le SPIR-V.
Analyse statique
Figure 1 Légende ?
Utilisez les compteurs d'analyse statique pour afficher les opérations de bas niveau dans le nuanceur.
Instructions ALU : ce nombre indique le nombre d'opérations ALU (additions, multiplications, divisions, etc.) exécutées dans le nuanceur. Il s'agit d'un bon indicateur de la complexité du nuanceur. Essayez de minimiser cette valeur.
La refactorisation des calculs courants ou la simplification des calculs effectués dans le nuanceur peuvent aider à réduire le nombre d'instructions nécessaires.
Instructions de texture : ce nombre indique le nombre de fois où l'échantillonnage de texture se produit dans le nuanceur.
L'échantillonnage de textures peut être coûteux selon le type de textures à partir desquelles l'échantillonnage est effectué. Par conséquent, la vérification croisée du code du nuanceur avec les textures liées trouvées dans la section Ensembles de descripteurs peut fournir plus d'informations sur les types de textures utilisées.
Évitez l'accès aléatoire lors de l'échantillonnage des textures, car ce comportement n'est pas idéal pour la mise en cache des textures.
Instructions de branche : ce nombre indique le nombre d'opérations de branche dans le nuanceur. La réduction des branchements est idéale sur les processeurs parallélisés tels que le GPU, et peut même aider le compilateur à trouver des optimisations supplémentaires :
Utilisez des fonctions telles que min, max et clamp pour éviter d'avoir à créer des branches en fonction de valeurs numériques.
Testez le coût de calcul sur la ramification. Étant donné que les deux chemins d'une branche sont exécutés dans de nombreuses architectures, il existe de nombreux scénarios dans lesquels le calcul est toujours plus rapide que l'omission du calcul avec une branche.
Registres temporaires : il s'agit de registres rapides sur le cœur qui sont utilisés pour stocker les résultats des opérations intermédiaires requises par les calculs sur le GPU. Le nombre de registres disponibles pour les calculs est limité avant que le GPU ne doive utiliser d'autres mémoires hors cœur pour stocker les valeurs intermédiaires, ce qui réduit les performances globales. (Cette limite varie selon le modèle de GPU.)
Le nombre de registres temporaires utilisés peut être plus élevé que prévu si le compilateur de nuanceurs effectue des opérations telles que le déroulement de boucles. Il est donc judicieux de croiser cette valeur avec le SPIR-V ou le GLSL décompilé pour voir ce que fait le code.
Analyse du code du nuanceur
Examinez le code du nuanceur décompilé lui-même pour déterminer si des améliorations potentielles sont possibles.
Figure 2 Légende ?
Précision : la précision des variables de nuanceur peut avoir un impact sur les performances du GPU de votre application.
Essayez d'utiliser le modificateur de précision mediump sur les variables chaque fois que possible, car les variables 16 bits de précision moyenne (mediump) sont généralement plus rapides et plus économes en énergie que les variables 32 bits de précision totale (highp).
Si vous ne voyez aucun qualificatif de précision dans le nuanceur sur les déclarations de variables, ou en haut du nuanceur avec un precision precision-qualifier type, la précision par défaut est la précision complète (highp). Assurez-vous également de consulter les déclarations de variables.
L'utilisation de mediump pour la sortie du nuanceur de vertex est également préférable pour les mêmes raisons que celles décrites ci-dessus. Elle présente également l'avantage de réduire la bande passante mémoire et l'utilisation potentielle de registres temporaires nécessaires à l'interpolation.
Tampons uniformes : essayez de réduire au maximum la taille des tampons uniformes (tout en respectant les règles d'alignement). Cela permet de rendre les calculs plus compatibles avec la mise en cache et peut permettre de promouvoir les données uniformes vers des registres sur cœur plus rapides.
Supprimez les sorties de nuanceur de vertex inutilisées : si vous constatez que des sorties de nuanceur de vertex ne sont pas utilisées dans le nuanceur de fragment, supprimez-les du nuanceur pour libérer de la bande passante mémoire et des registres temporaires.
Déplacer le calcul du nuanceur de fragment vers le nuanceur de vertex : si le code du nuanceur de fragment effectue des calculs indépendants de l'état spécifique au fragment ombré (ou peut être interpolé correctement), il est idéal de le déplacer vers le nuanceur de vertex. En effet, dans la plupart des applications, le nuanceur de sommets est exécuté beaucoup moins souvent que le nuanceur de fragments.
Le contenu et les exemples de code de cette page sont soumis aux licences décrites dans la Licence de contenu. Java et OpenJDK sont des marques ou des marques déposées d'Oracle et/ou de ses sociétés affiliées.
Dernière mise à jour le 2025/07/27 (UTC).
[[["Facile à comprendre","easyToUnderstand","thumb-up"],["J'ai pu résoudre mon problème","solvedMyProblem","thumb-up"],["Autre","otherUp","thumb-up"]],[["Il n'y a pas l'information dont j'ai besoin","missingTheInformationINeed","thumb-down"],["Trop compliqué/Trop d'étapes","tooComplicatedTooManySteps","thumb-down"],["Obsolète","outOfDate","thumb-down"],["Problème de traduction","translationIssue","thumb-down"],["Mauvais exemple/Erreur de code","samplesCodeIssue","thumb-down"],["Autre","otherDown","thumb-down"]],["Dernière mise à jour le 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."]]