Partilhar via


Instruções passo a passo: objetos ausentes devido ao pipeline configurado incorretamente

Este passo a passo demonstra como usar as ferramentas de diagnóstico dos gráficos de Visual Studio para investigar um objeto que está faltando devido a um shader unset em pixels.

Essa explicação passo a passo ilustra essas tarefas:

  • Usando a Lista de Eventos de Elementos Gráficos para localizar fontes potenciais do problema.

  • Usando a janela de Estágios de Pipeline Gráficos para examinar o efeito de chamada à API de DrawIndexed Direct3D.

  • Inspecionando o contexto de dispositivo para confirmar que uma fase de shader não esteve definida.

  • Usando a janela de Estágios de Pipeline Gráficos junto com Pilha de Chamadas do Evento de Gráficos para ajudar a localizar a fonte de shader unset em pixels.

Cenário

Quando um objeto está ausente em um aplicativo 3d, algumas vezes é porque uma das fases de shader não for definido antes que o objeto seja renderizado. Em aplicativos que têm simples a renderização necessário, a origem desse erro é localizada normalmente em algum lugar da pilha de chamadas de chamada de descompasso do objeto. No entanto, como uma otimização, alguns aplicativos lotes juntos os objetos que têm programas de shader, texturas, ou outros dados em comum para minimizar a sobrecarga de alteração de estado. Nesses aplicativos, a origem do erro pode ser descartada no sistema de processamento em lote, em vez de localizada na pilha de chamadas de chamada de descompasso. O cenário deste passo a passo ilustra um aplicativo que tenha necessidades simples de renderização, e assim que a origem do erro pode ser localizada na pilha de chamadas.

Nesse cenário, quando o aplicativo é executado para o teste, o plano de fundo será renderizado como esperado, mas um dos objetos não será exibida. Usando o Diagnósticos Gráficos, você captura o problema para o registro de gráficos de modo a depurar o aplicativo. O problema tem esta aparência no aplicativo:

O objeto não pode ser visto

Investigação

Usando as ferramentas de diagnóstico de gráficos, você pode carregar os gráficos registra em log o documento para inspecionar as peças que foram capturados durante o teste.

Para examinar um quadro no registro de elementos gráficos

  1. Em Visual Studio, carregar gráficos registra o documento que contém um quadro que exibe o objeto ausente. Uma nova guia de log de gráficos aparece no Visual Studio. Na parte superior desta guia está a saída de destino da renderização do quadro selecionado. Na parte inferior está a Lista do Quadro, que exibe cada quadro capturado como a imagem miniatura.

  2. Na Lista do Quadro, selecionar um quadro que demonstra que o objeto não é exibido. O destino de processamento é atualizado para refletir o quadro selecionado. Neste cenário, a guia do log dos gráficos parecem como esta:

    O documento de log de gráficos no Visual Studio

Depois que você selecionar um quadro que demonstra o problema, você pode começar a diagnosticá-lo usando Lista de Eventos de Gráficos. Lista de Eventos de Gráficos Contém cada chamada à API de Direct3D que foi feita para renderizar o ativa quadro- por exemplo, para configurar o estado do dispositivo, o para criar e atualizar buffers, e para desenhar objetos que aparecem no quadro. Muitos tipos atendimento- para de exemplo, de descompasso, de distribuição, de impressão, ou o espaço livre atendimento- são interessantes pois geralmente há (mas não sempre) uma alteração correspondente no destino quando renderizar o aplicativo está funcionando como esperado. As chamadas de descompasso são especialmente interessantes porque cada representa a geometria que o aplicativo é renderizado.

Como você souber que o destino renderizar não contém o objeto ausente mas também que não parece haver outros erros, você pode usar Lista de Eventos de Gráficos junto com a ferramenta de Estágios de Pipeline Gráficos para determinar quais chamada de descompasso corresponde à geometria de objeto ausente. A janela Etapas do pipeline gráfico mostra a geometria enviada para cada chamada de desenho, independentemente do efeito no destino renderização. Quando você se move por chamadas de descompasso, as fases de pipeline são atualizadas para mostrar a geometria que está associada a cada chamada à medida que corré por cada fase habilitado, e a saída de destino renderização são atualizadas para mostrar o estado de destino renderizar depois da chamada for concluído.

Para localizar a chamada de desenho para a geometria ausente

  1. Abra a janela Lista de Eventos de Gráficos. Na barra de ferramentas Diagnóstico de Gráficos, escolha Lista de Eventos.

  2. Abra a janela Estágios de Pipeline Gráficos. Na barra de ferramentas Diagnóstico de Gráficos, escolha Estágios de Pipeline.

  3. Conforme você move por cada chamada na janela Lista de eventos de gráficos, veja a janela Fases do pipeline de gráficos para o objeto ausente. Para tornar isso mais fácil, digite um “Desenho” na caixa Pesquisar no canto superior direito da janela Lista de eventos de elementos gráficos . Isso filtra a lista de modo que ela contenha somente os eventos que possuam “Desenho” em seus títulos.

    Na janela de Estágios de Pipeline Gráficos , a fase de Assembler de Entrada mostra a geometria do objeto antes que ela se torne, e a fase de Sombreador de Vértices mostra o mesmo objeto depois que se tornou. Neste cenário, observe que a janela de Estágios de Pipeline Gráficos mostra as fases de Assembler de Entrada e de Sombreador de Vértices , mas não a fase de Sombreador de Pixel para um das chamadas de descompasso.

    Dica

    Se o outro pipeline fase- por exemplo, o shader de forma, o shader de domínio, ou o fase- processo de shader de geometria o objeto, alguns deless pode ser a causa do problema.Normalmente, o problema está relacionado à fase a mais recente em que o resultado não é exibido ou é exibido de uma maneira inesperada.

  4. Interromper quando você atingir a chamada de desenho que corresponde ao objeto ausente. Neste cenário, a janela de Estágios de Pipeline Gráficos indica que a geometria esteve emitida para GPU (indicado pela presença da fase de Assembler de Entrada ) e transformada (indicado pela fase de Sombreador de Vértices ), mas não aparece no destino renderizar porque não parece haver um shader ativa de pixel (indicado pela ausência da fase de Sombreador de Pixel ). Neste cenário, você pode até ver a silhueta de objeto ausente em Fusão de Saída preparação:

    Um evento DrawIndexed e seu efeito sobre o pipeline

Depois que você confirmar que o aplicativo emitiu uma chamada de descompasso para geometria de objeto ausente e descobre que a fase de shader de pixel foi inativa, você pode examinar o estado de dispositivo para confirmar seus resultados. Você pode usar Tabela de Objetos Gráficos para examinar o contexto do dispositivo e os outros dados do objeto de Direct3D.

Para examinar o contexto do dispositivo

  1. Abra contexto de dispositivo d3d11. Na janela de Estágios de Pipeline Gráficos , escolha o link de ID3D11DeviceContext que faz parte da chamada de DrawIndexed que é exibido na parte superior da janela.

  2. Examine o estado do dispositivo que é exibido na guia de contexto de dispositivo d3d11 para confirmar se nenhum shader de pixel ativo durante a chamada de descompasso. Neste cenário, informações gerais do shader— exibido em estado de shader de pixel— indica que o shader é nulo:

    O contexto de dispositivo D3D 11 mostra o estado de sombreador de pixel

Depois que você confirmar que o shader de pixel esteve definido como nulo pelo seu aplicativo, a próxima etapa é encontrar o local no código-fonte do seu aplicativo em que o shader é definido. Você pode usar Lista de Eventos de Gráficos junto com Pilha de Chamadas do Evento de Gráficos para encontrar esse local.

Para descobrir onde o shader de pixel é definido no código-fonte do seu aplicativo

  1. Localizar a chamada de PSSetShader que corresponde ao objeto ausente. Na janela de Lista de Eventos de Gráficos , digite a “descompasso; PSSetShader” na caixa de Pesquisar no canto superior direito da janela de Lista de Eventos de Gráficos . Isso filtra a lista de modo que contém apenas eventos de “PSSetShader”, e os eventos que têm a “descompasso” nos cargos. Escolha a primeira chamada de PSSetShader que aparece antes da chamada de descompasso de objeto ausente.

    Dica

    PSSetShader não aparecerá na janela de Lista de Eventos de Gráficos se não foi definida durante esse quadro.Geralmente isso ocorre apenas se apenas um shader de pixel é usado para todos os objetos, ou se a chamada de PSSetShader esteve querer ignorado durante esse quadro.Em ambos os casos, recomendamos que você pesquisa o código-fonte do aplicativo por chamadas de PSSetShader , e usar técnicas tradicionais de depuração analisar o comportamento dessas chamadas.

  2. Abra a janela Pilha de Chamadas do Evento de Gráficos. Na barra de ferramentas Diagnóstico de Gráficos, escolha Pilha de Chamadas do Evento de Gráficos.

  3. Use a pilha de chamadas para localizar a chamada de PSSetShader no código-fonte do seu aplicativo. Na janela de Pilha de Chamadas do Evento de Gráficos , escolha a chamada de superiores e examine o valor que o shader de pixel está sendo definido como. O shader de pixel pode ser definido diretamente como nulo, ou o valor nulo pode ocorrer devido a um argumento que é passada para a função ou em outro estado. Se não for definido diretamente, você poderá localizar em algum lugar a origem do valor nulo acima da pilha de chamadas. Neste cenário, você descobre que o shader de pixel está sendo definido diretamente a nullptr na função de superiores, denominada CubeRenderer::Render:

    O código que não inicializam o sombreador de pixels

    Dica

    Se você não puder localizar a origem do valor nulo apenas por meio do exame da pilha de chamadas, é recomendável definir um ponto de interrupção condicional na chamada de PSSetShader , de modo que a execução do programa será interrompido quando o shader de pixel será definido como nulo.Reiniciar o aplicativo no modo de depuração e use técnicas tradicionais de depuração localizar a origem do valor nulo.

Para corrigir o problema, atribua o shader correto de pixel usando o primeiro parâmetro de chamada de API de ID3D11DeviceContext::PSSetShader .

O código-fonte C++ corrigido

Depois que você corrija o código, você poderá recriá-lo e executar o aplicativo novamente para verificar se o problema de renderização foi resolvido:

O objeto é exibido agora