Procédure pas à pas : objets manquants en raison d'un pipeline mal configuréWalkthrough: Missing Objects Due to Misconfigured Pipeline

Cette procédure pas à pas montre comment utiliser les outils Graphics Diagnostics de Visual StudioVisual Studio pour examiner un objet qui est manquant, car un nuanceur de pixels n’a pas été défini.This walkthrough demonstrates how to use the Visual StudioVisual Studio Graphics Diagnostics tools to investigate an object that's missing due to an unset pixel shader.

Cette procédure pas à pas décrit les tâches suivantes :This walkthrough illustrates these tasks:

  • Utilisation de la liste des événements Graphics pour rechercher les sources potentielles du problème.Using the Graphics Event List to locate potential sources of the problem.

  • Utilisation de la fenêtre Étapes de canalisation Graphics pour examiner l’effet de l’appel de l’API Direct3D DrawIndexed .Using the Graphics Pipeline Stages window to examine the effect of the DrawIndexed Direct3D API call.

  • Inspection du contexte de périphérique pour confirmer qu’aucune étape de nuanceur n’a été définie.Inspecting the device context to confirm that a shader stage was not set.

  • Utilisation de la fenêtre Étapes de canalisation Graphics avec la Pile des appels des événements Graphics pour aider à trouver la source du nuanceur de pixels non défini.Using the Graphics Pipeline Stages window together with the Graphics Event Call Stack to help find the source of the unset pixel shader.

ScénarioScenario

Quand un objet est manquant dans une application 3D, c’est parfois dû au fait que l’une des étapes du nuanceur n’est pas définie avant le rendu de l’objet.When an object is missing in a 3-D app, it's sometimes because one of the shader stages is not set before the object is rendered. Dans les applications qui ont des besoins de rendu simples, la source de cette erreur se situe généralement quelque part dans la pile des appels de dessin de l’objet.In apps that have simple rendering needs, the source of this error is usually located somewhere in the call stack of the object's draw call. Toutefois, en guise d’optimisation, certaines applications rassemblent des objets qui ont des programmes nuanceurs, des textures ou d’autres données en commun pour minimiser la surcharge liée au changement d’état.However, as an optimization, some apps batch together objects that have shader programs, textures, or other data in common to minimize state-change overhead. Dans ces applications, la source de l’erreur peut être dissimulée au fond du système de traitement par lot, plutôt que située dans la pile des appels de l’appel de dessin.In these apps, the source of the error might be buried in the batching system, rather than located in the call stack of the draw call. Comme le scénario de cette procédure pas à pas illustre une application ayant des besoins de rendu simples, la source de l’erreur se trouve dans la pile des appels.The scenario in this walkthrough demonstrates an app that has simple rendering needs, and so the source of the error can be found in the call stack.

Dans ce scénario, quand l’application est exécutée pour être testée, l’arrière-plan est affiché comme prévu, mais l’un des objets ne s’affiche pas.In this scenario, when the app is run to test it, the background is rendered as expected, but one of the objects doesn't appear. À l’aide de Graphics Diagnostics, vous capturez le problème dans un journal de graphisme pour déboguer l’application.By using Graphics Diagnostics, you capture the problem to a graphics log so that you can debug the app. Le problème se présente ainsi dans l'application :The problem looks like this in the app:

L’objet ne peut pas être visualiséThe object cannot be seen

ExamenInvestigation

À l'aide des outils Graphics Diagnostics, vous pouvez charger le document du journal de graphisme pour examiner les frames capturés pendant le test.By using the Graphics Diagnostics tools, you can load the graphics log document to inspect the frames that were captured during the test.

Pour examiner un frame dans un journal de graphismeTo examine a frame in a graphics log

  1. Dans Visual StudioVisual Studio, chargez un document de journal de graphisme qui contient un frame qui montre l’objet manquant.In Visual StudioVisual Studio, load a graphics log document that contains a frame that exhibits the missing object. Un nouvel onglet de journal de graphisme s’affiche dans Visual StudioVisual Studio.A new graphics log tab appears in Visual StudioVisual Studio. La partie supérieure de cet onglet contient la sortie de la cible de rendu du frame sélectionné.In the top part of this tab is the render target output of the selected frame. La partie inférieure contient la Liste de frames, qui affiche chaque frame capturé sous forme de miniature.In the bottom part is the Frame List, which displays each captured frame as a thumbnail image.

  2. Dans la Liste de frames, sélectionnez un frame qui montre que l’objet n’est pas affiché.In the Frame List, select a frame that demonstrates that the object is not displayed. La cible de rendu est mise à jour pour refléter le frame sélectionné.The render target is updated to reflect the selected frame. Dans ce scénario, l'onglet du journal de graphisme se présente comme suit :In this scenario, the graphics log tab looks like this:

    Document du journal des graphiques dans Visual StudioThe graphics log document in Visual Studio

    Une fois que vous avez sélectionné un frame qui illustre le problème, vous pouvez commencer le diagnostic à l’aide de la Liste des événements Graphics.After you select a frame that demonstrates the problem, you can begin to diagnose it by using the Graphics Event List. La Liste des événements Graphics contient chaque appel d’API Direct3D qui a été effectué pour afficher le frame actif, par exemple pour configurer l’état du périphérique, créer et mettre à jour les mémoires tampons, et dessiner des objets qui apparaissent dans le frame.The Graphics Event List contains every Direct3D API call that was made to render the active frame—for example, to set up device state, to create and update buffers, and to draw objects that appear in the frame. Plusieurs types d’appels (par exemple les appels de dessin, de distribution, de copie ou d’effacement) sont intéressants, car il y a souvent (mais pas toujours) une modification correspondante de la cible de rendu quand l’application fonctionne comme prévu.Many kinds of calls—for example, Draw, Dispatch, Copy, or Clear calls—are interesting because there is often (but not always) a corresponding change in the render target when the app is working as expected. Les appels de dessin sont particulièrement intéressants, car chacun d’eux représente la géométrie affichée par l’application.Draw calls are particularly interesting because each one represents geometry that the app rendered.

    Comme vous savez que la cible de rendu ne contient pas l’objet manquant, mais qu’il semble également ne pas y avoir d’autre erreur, vous pouvez utiliser la Liste des événements Graphics avec l’outil Étapes de canalisation Graphics pour identifier l’appel de dessin qui correspond à la géométrie de l’objet manquant.Because you know that the render target doesn't contain the missing object but also that there do not appear to be other errors, you can use the Graphics Event List together with the Graphics Pipeline Stages tool to determine which draw call corresponds to the missing object's geometry. La fenêtre Étapes de canalisation Graphics affiche la géométrie qui a été envoyée à chaque appel de dessin, quel que soit son effet sur la cible de rendu.The Graphics Pipeline Stages window shows the geometry that was sent to each draw call, regardless of its effect on the render target. À mesure que vous parcourez les appels de dessin, les étapes de canalisation sont mises à jour pour afficher la géométrie qui est associée à chaque appel quand il transite par chaque étape activé, et la sortie de cible de rendu est mise à jour pour afficher l’état de la cible de rendu une fois l’appel terminé.As you move through the draw calls, the pipeline stages are updated to show the geometry that's associated with each call as it flows through each enabled stage, and the render target output is updated to show the state of the render target after the call is completed.

Pour rechercher l’appel de dessin correspondant à la géométrie manquanteTo find the draw call for the missing geometry

  1. Ouvrez la fenêtre Liste des événements Graphics .Open the Graphics Event List window. Dans la barre d’outils Graphics Diagnostics , choisissez Liste des événements.On the Graphics Diagnostics toolbar, choose Event List.

  2. Ouvrez la fenêtre Étapes de canalisation Graphics .Open the Graphics Pipeline Stages window. Dans la barre d’outils Graphics Diagnostics , choisissez Étapes de canalisation.On the Graphics Diagnostics toolbar, choose Pipeline Stages.

  3. À mesure que vous parcourez chaque appel de dessin dans la fenêtre Liste des événements Graphics , recherchez l’objet manquant dans la fenêtre Étapes de canalisation Graphics .As you move through each draw call in the Graphics Event List window, watch the Graphics Pipeline Stages window for the missing object. Pour rendre la tâche plus simple, entrez “Draw” dans la zone Rechercher , en haut à droite de la fenêtre Liste des événements Graphics .To make this easier, enter "Draw" in the Search box in the upper-right corner of the Graphics Event List window. Cela permet de filtrer la liste pour retenir uniquement les événements qui contiennent « Draw » dans leur titre.This filters the list so that it only contains events that have "Draw" in their titles.

    Dans la fenêtre Étapes de canalisation Graphics , l’étape Assembleur d’entrée montre la géométrie de l’objet avant sa transformation tandis que l’étape Nuanceur de sommets montre le même objet après sa transformation.In the Graphics Pipeline Stages window, the Input Assembler stage shows the object's geometry before it's transformed, and the Vertex Shader stage shows the same object after it's transformed. Dans ce scénario, notez que la fenêtre Étapes de canalisation Graphics montre les étapes Assembleur d’entrée et Nuanceur de sommets , mais pas l’étape Nuanceur de pixels pour l’un des appels de dessin.In this scenario, notice that the Graphics Pipeline Stages window shows the Input Assembler and Vertex Shader stages, but not the Pixel Shader stage for one of the draw calls.

    Note

    Si d’autres étapes de canalisation (par exemple Nuanceur de coque, Nuanceur de domaine ou Nuanceur de géométrie) traitent l’objet, elles peuvent être la cause du problème.If other pipeline stages—for example, the hull shader, domain shader, or geometry shader stages—process the object, any of them might be the cause of the problem. En règle générale, le problème est lié à la première étape durant laquelle le résultat n’est pas affiché ou est affiché de manière inattendue.Typically, the problem is related to the earliest stage in which the result is not displayed or is displayed in an unexpected way.

  4. Arrêtez quand vous atteignez l’appel de dessin qui correspond à l’objet manquant.Stop when you reach the draw call that corresponds to the missing object. Dans ce scénario, la fenêtre Étapes de canalisation Graphics indique que la géométrie a été émise vers le GPU (indiqué par la présence de l’étape Assembleur d’entrée ) et transformée (indiqué par l’étape Nuanceur de sommets ), mais elle n’apparaît pas dans la cible de rendu, car il ne semble pas y avoir de nuanceur de pixels actif (indiqué par l’absence de l’étape Nuanceur de pixels ).In this scenario, the Graphics Pipeline Stages window indicates that the geometry was issued to the GPU (indicated by the presence of the Input Assembler stage) and transformed (indicated by the Vertex Shader stage), but doesn't appear in the render target because there doesn't seem to be an active pixel shader (indicated by the absence of the Pixel Shader stage). Dans ce scénario, vous pouvez même voir la silhouette de l'objet manquant à l’étape Fusion de sortie :In this scenario, you can even see the silhouette of the missing object in the Output Merger stage:

    Événement DrawIndexed et son effet sur le pipelineA DrawIndexed event and its effect on the pipeline

    Une fois que vous avez confirmé que l’application avait émis un appel de dessin pour la géométrie de l’objet manquant et que vous avez découvert que l’étape de nuanceur de pixels était inactive, vous pouvez examiner l’état du périphérique pour confirmer vos constatations.After you confirm that the app issued a draw call for the missing object's geometry and discover that the pixel shader stage was inactive, you can examine the device state to confirm your findings. Vous pouvez utiliser la Table des objets Graphics pour examiner le contexte de périphérique et d’autres données d’objets Direct3D.You can use the Graphics Object Table to examine device context and other Direct3D object data.

Pour examiner le contexte de périphériqueTo examine device context

  1. Ouvrez le Contexte de périphérique d3d11.Open the d3d11 device context. Dans le étapes de canalisation Graphics fenêtre, choisissez le ID3D11DeviceContext lien qui fait partie de la DrawIndexed appel qui s’affiche en haut de la fenêtre.In the Graphics Pipeline Stages window, choose the ID3D11DeviceContext link that's part of the DrawIndexed call that's displayed at the top of the window.

  2. Examinez l’état du périphérique affiché sous l’onglet Contexte de périphérique d3d11 pour vérifier qu’aucun nuanceur de pixels n’était actif pendant l’appel de dessin.Examine the device state that's displayed in the d3d11 device context tab to confirm that no pixel shader was active during the draw call. Dans ce scénario, les Informations générales sur le nuanceur(affichées sous État du nuanceur de pixels) indiquent que le nuanceur est NULL:In this scenario, the shader general information—displayed under pixel shader state—indicates that the shader is NULL:

    Le contexte de périphérique D3D 11 affiche l’état de nuanceur de pixelsThe D3D 11 Device Context shows pixel shader state

    Une fois que vous avez confirmé que le nuanceur de pixels avait été défini sur la valeur null par votre application, l’étape suivante consiste à trouver l’emplacement, dans le code source de votre application, où le nuanceur est défini.After you confirm that the pixel shader was set to null by your app, the next step is to find the location in your app's source code where the shader is set. Vous pouvez utiliser la Liste des événements Graphics avec la Pile des appels des événements Graphics pour rechercher cet emplacement.You can use the Graphics Event List together with the Graphics Event Call Stack to find this location.

Pour trouver où le nuanceur de pixels est défini dans le code source de votre applicationTo find where the pixel shader is set in your app's source code

  1. Recherchez l’appel PSSetShader qui correspond à l’objet manquant.Find the PSSetShader call that corresponds to the missing object. Dans la fenêtre Liste des événements Graphics , entrez “Draw;PSSetShader” dans la zone Rechercher , en haut à droite de la fenêtre Liste des événements Graphics .In the Graphics Event List window, enter "Draw;PSSetShader" in the Search box in the upper-right corner of the Graphics Event List window. Cette opération permet de filtrer la liste pour retenir uniquement les événements “PSSetShader” et les événements dont le titre contient “Draw”.This filters the list so that it only contains "PSSetShader" events, and events that have "Draw" in their titles. Choisissez le premier appel PSSetShader qui apparaît avant l’appel de dessin de l’objet manquant.Choose the first PSSetShader call that appears before the draw call of the missing object.

    Note

    PSSetShader n’apparaît pas dans la fenêtre Liste des événements Graphics s’il n’a pas été défini durant ce frame.PSSetShader won't appear in the Graphics Event List window if it was not set during this frame. En général, cela se produit uniquement si le nuanceur de pixels est utilisé pour tous les objets, ou si l’appel PSSetShader a été ignoré par inadvertance pendant ce frame.Usually this occurs only if just one pixel shader is used for all objects, or if the PSSetShader call was unintentionally skipped during this frame. Dans les deux cas, nous vous recommandons de rechercher les appels PSSetShader dans le code source de l’application et d’appliquer des techniques de débogage classiques pour examiner le comportement de ces appels.In either case, we recommend that you search the app's source code for PSSetShader calls, and use traditional debugging techniques to examine the behavior of these calls.

  2. Ouvrez la fenêtre Pile des appels des événements Graphics .Open the Graphics Event Call Stack window. Dans la barre d’outils Graphics Diagnostics , choisissez Pile des appels des événements Graphics.On the Graphics Diagnostics toolbar, choose Graphics Event Call Stack.

  3. Utilisez la pile des appels pour rechercher l’appel PSSetShader dans le code source de votre application.Use the call stack to locate the PSSetShader call in your app's source code. Dans la fenêtre Pile des appels des événements Graphics , choisissez l’appel supérieur et examinez la valeur définie pour le nuanceur de pixels.In the Graphics Event Call Stack window, choose the top-most call and examine the value that the pixel shader is being set to. Le nuanceur de pixels peut être directement défini comme null, ou la valeur null peut être due à un argument qui a été transmis à la fonction ou autre état.The pixel shader might be set directly to null, or the null value might occur because of an argument that was passed into the function or other state. S’il n’est pas défini directement, vous pourrez peut-être trouver la source de la valeur null vers le haut de la pile des appels.If it's not set directly, you might be able to locate the source of the null value somewhere up the call stack. Dans ce scénario, vous découvrez que le nuanceur de pixels prend directement la valeur nullptr dans la fonction supérieure, qui se nomme CubeRenderer::Render:In this scenario, you discover that the pixel shader is being set directly to nullptr in the top-most function, which is named CubeRenderer::Render:

    Le code qui n’initialise pas le nuanceur de pixelsThe code that doesn't initialize the pixel shader

    Note

    Si vous ne trouvez pas la source de la valeur null en examinant simplement la pile des appels, nous vous recommandons de définir un point d’arrêt conditionnel sur l’appel PSSetShader pour que l’exécution du programme s’arrête quand le nuanceur de pixels prend la valeur null.If you can't locate the source of the null value just by examining the call stack, we recommend that you set a conditional breakpoint on the PSSetShader call, such that execution of the program breaks when the pixel shader will be set to null. Ensuite, redémarrez l’application en mode débogage et appliquez des techniques de débogage traditionnelles pour rechercher la source de la valeur null.Then restart the app in debug mode and use traditional debugging techniques to locate the source of the null value.

    Pour résoudre le problème, affectez le nuanceur de pixels approprié à l’aide du premier paramètre de l’appel d’API ID3D11DeviceContext::PSSetShader .To fix the problem, assign the correct pixel shader by using the first parameter of the ID3D11DeviceContext::PSSetShader API call.

    La correction C+ + code sourceThe corrected C++ source code

    Après avoir corrigé le code, vous pouvez le régénérer et réexécuter l’application pour vérifier que le problème d’affichage est résolu :After you fix the code, you can rebuild it and run the app again to verify that the rendering issue is solved:

    L’objet est maintenant affichéThe object is now displayed