Compilando o exemplo de streaming e a ferramenta de conteúdo
Para compilar o exemplo, verifique se você tem um ambiente de desenvolvimento do Visual Studio 2017 atualizado, o GDK 1911 instalado e o Windows SDK 17134 ou mais recente instalado. Todos os recursos necessários do Visual Studio solicitarão a instalação automaticamente ao abrir a solução, caso ainda não estejam presentes. Abra a solução (Streaming\Streaming.sln) e recompile-a. Os builds de lançamento e de perfil são muito mais rápidos do que os builds de depuração, mas o build de depuração permite a validação da API do Direct3D 12 usando a camada de depuração.Criando e implantando conteúdo de textura
Compile o build de lançamento do ContentTool. Execute-o com a seguinte linha de comando: contenttool.exe 64 8192 c:\temp O parâmetro “c:\temp” pode ser substituído por qualquer outro local de diretório temporário adequado. Essas opções gerarão 64 conjuntos difuso-normal-especular de texturas em blocos com mipmaps de 8192 × 8192, totalizando aproximadamente 10 GB de conteúdo. O ContentTool consumirá uma grande quantidade de memória durante a criação das texturas. Recomendamos executá-lo em um sistema com pelo menos 16 GB de memória. Copie o conteúdo de textura gerado pelo ContentTool (arquivos .trimg e .trdata) para um subdiretório “streamingtextures” dentro do layout do exemplo Streaming e implante. Para o build da Plataforma Universal do Windows (UWP) do devtest Streaming, os arquivos de textura devem ser implantados em um local de diretório temporário do pacote. Implante o build UWP do aplicativo Streaming sem conteúdo e execute-o uma vez. O exemplo será iniciado, exibirá uma mensagem sobre conteúdo de textura ausente e abrirá uma janela do Explorador de Arquivos em um local dentro do diretório temporário do aplicativo. Copie os arquivos de dados de textura para um subdiretório “streamingtextures” desse diretório temporário. Depois que o conteúdo for implantado com sucesso, o exemplo deverá ser iniciado mostrando uma grade de cubos coloridos, semelhante à imagem a seguir.
Controles e uso
O exemplo foi projetado para uso com um controle XBOX. Para o build desktop do exemplo, recomendamos conectar um controle XBOX ao seu PC de desenvolvimento. Se isso não for possível, também há controles de teclado e mouse disponíveis, conforme detalhado na tabela a seguir.Opções e exibições de depuração
- Os modos de renderização podem ser alternados com a primeira opção do menu. A complexidade do sombreador da cena pode ser aumentada de uma camada (difuso-normal-especular) para três camadas (três de cada difuso-normal-especular). Além disso, o mapa MinMip pode ser sobreposto à geometria da cena.
- As estatísticas de streaming são habilitadas por padrão e podem ser alternadas no menu Streaming Debug Views. As estatísticas de streaming incluem contadores em tempo real do número de blocos em andamento, o tamanho virtual total de todas as texturas, a capacidade e a ocupação do pool de blocos, estatísticas de latência, gargalos e estatísticas de residência/acesso por mip.
- Texturas de streaming individuais podem ser examinadas, incluindo a textura principal (recurso em blocos) e seus mapas MinMip e de feedback MinMip associados. Basta habilitar o Debug Texture Mode no menu Streaming Debug Views e usar os controles da câmera para apontar a mira para um objeto da cena. A textura dele é exibida e é possível selecionar entre os mapas difuso, normal ou especular da primeira camada.
- Os tempos de CPU dos vários subsistemas de streaming podem ser habilitados no menu Streaming Debug Views.
Visão geral do mecanismo de streaming
O mecanismo de streaming de texturas do exemplo Streaming foi projetado para streaming de blocos individuais de 64 KB. Os blocos são armazenados na memória em um único pool de blocos (um objeto ID3D12Heap) com tamanho de 512 MB por padrão. Qualquer número de texturas em blocos pode ser instanciado no mecanismo de streaming de texturas, limitado apenas pelo tamanho máximo dos heaps de descritores que rastreiam as exibições de recurso de sombreador e as exibições de acesso não ordenado dos recursos de textura em blocos e seus mapas MinMip e de feedback MinMip associados. O diagrama a seguir representa o ciclo de operações para uma textura em blocos individual no mecanismo de streaming de texturas.
Criação de texturas em blocos e configuração do grafo de cena
Quando uma textura em blocos é criada no mecanismo de streaming, os três recursos a seguir são criados.- A própria textura em blocos, por meio da API
ID3D12Device::CreateReservedResource. - Um pequeno mapa MinMip, criado usando as dimensões da textura em blocos divididas pelas dimensões de um único bloco de 64 KB nesse formato. Por exemplo, uma textura em blocos de 8192 × 8192 com o formato BC1 resultaria em um mapa MinMip com 16 × 32 texels, porque um bloco de 64 KB em BC1 tem dimensões de 512 × 256.
- Um pequeno mapa de feedback MinMip, com as mesmas dimensões do mapa MinMip.
ID3D12Device8::CreateSamplerFeedbackUnorderedAccessViewX.
Por questões de eficiência, os mapas de feedback MinMip não são criados como recursos individuais. Em vez disso, eles são criados como fatias subalocadas de um recurso opaco Texture2DArray maior, criado por meio da API ID3D12Device8::CreatePlacedResource1. Essa estratégia é possível porque muitos mapas de feedback MinMip compartilham as mesmas dimensões. Criá-los como uma matriz de texturas maior garante o layout de empacotamento de memória mais eficiente para o hardware e, além disso, garante que os mapas de feedback MinMip sejam contíguos na memória, permitindo limpeza e transcodificação em massa muito eficientes.
O grafo de cena contém os descritores visíveis para a GPU, que são organizados por objeto. Quando os objetos da cena são instanciados junto com seus materiais associados (seleções de texturas em blocos), os descritores são copiados do heap de descritores do mecanismo de streaming para o heap de descritores visível para a GPU do grafo de cena.
No momento da criação da textura em blocos, a cauda de mips empacotada (todos os níveis de mip menores que o tamanho de bloco de 64 KB) é carregada do disco rígido e mapeada para a textura em blocos, e o mapa MinMip é limpo com o valor do primeiro nível de mip empacotado.
Renderização da cena e sampler feedback
Antes de a cena ser renderizada, todos os mapas de feedback do sistema são limpos em massa para o valor máximo possível em um mapa de feedback: um valor binário de 0xFF, ou 31,875 na codificação fixa sem sinal 5.3. Durante a renderização da cena, o mapa MinMip é amostrado para produzir um valor de limitação de nível de detalhe (LOD) e, em seguida, a textura em blocos é amostrada com esse valor de limitação aplicado. Separadamente, o sampler feedback é coletado em relação à textura em blocos e gravado no mapa de feedback MinMip, sem a limitação de LOD aplicada. O sampler feedback é executado usando uma função da linguagem de sombreador de alto nível (HLSL),FeedbackTexture2D::WriteSamplerFeedback.
Os dados de sampler feedback são altamente redundantes. A cobertura de tela de qualquer bloco específico de 64 KB é garantidamente bastante grande para objetos razoavelmente próximos da câmera. Portanto, o sombreador da cena executa apenas 1/128 (0,7%) das operações de sampler feedback por padrão.
Leitura e análise dos dados de sampler feedback
A cada quadro, a CPU lê os dados de sampler feedback para determinar quais blocos precisam ser carregados em seguida. Primeiro, o sombreador de computação é usado para copiar em massa os dados de sampler feedback dos recursos de textura de matriz de feedback graváveis pela GPU para footprints posicionados legíveis pela CPU. Em seguida, o código da CPU itera por cada texel dos mapas de feedback MinMip. Para cada texel, o valor de feedback MinMip é comparado com o banco de dados de blocos para determinar se o bloco necessário para esse local, dentro desse nível de mip, para essa textura, está presente. Se o bloco não estiver presente, uma entrada de rastreamento de bloco será criada para ele e adicionada à fila “Seen Tiles”. Se o bloco já estiver presente, ele será marcado com um carimbo de data/hora atual. Depois que os mapas de feedback MinMip são processados, a lista “Seen Tiles” é classificada por nível de LOD, e alguns blocos são enfileirados para carregamento do disco rígido, começando pelos maiores níveis de LOD. Antes de um bloco ser carregado, é necessário alocar armazenamento temporário para os dados compactados do bloco, bem como um local de destino dentro do pool de blocos. A disponibilidade de armazenamento temporário e de armazenamento no pool de blocos é o principal fator limitante de quantos blocos podem ser carregados de uma vez. Depois que um bloco é enfileirado para carregamento, uma operação assíncrona de E/S de arquivo Win32 é iniciada para carregá-lo. Após a conclusão, vários quadros depois, os dados são descompactados em um local de preparo descompactado. Em paralelo ao carregamento e à descompactação do arquivo, o bloco também é enfileirado para mapeamento no recurso em blocos na GPU por meio da APIID3D12CommandQueue::UpdateTileMappings. O carregamento e o mapeamento de qualquer bloco específico podem levar vários quadros para serem concluídos.
Conclusão de blocos e expiração para atualizações do mapa MinMip
A cada quadro, o mecanismo de streaming monitora várias filas quanto à conclusão do carregamento e da descompactação de blocos, bem como à conclusão do mapeamento de blocos. Os blocos que concluíram o carregamento, a descompactação e o mapeamento são colocados em uma lista “Complete Tiles” e ficam prontos para serem expostos à renderização da cena por meio de uma atualização do mapa MinMip. Essas atualizações são enfileiradas e executadas em uma cópia de preparo na CPU de cada mapa MinMip e, em seguida, transferidas para os mapas MinMip legíveis pela GPU por meio de uma cópia de textura usandoID3D12GraphicsCommandList::CopyTextureRegion.
A lista “Complete Tiles” também é classificada por carimbo de data/hora a cada quadro. Todos os blocos com carimbo de data/hora mais antigo que um determinado limite (dois segundos) são considerados expirados e marcados para desmapeamento e exclusão. Os blocos desmapeados também resultam em atualizações do mapa MinMip, que são enfileiradas e processadas junto com as atualizações do mapa MinMip para os blocos recém-carregados.
