Pular para o conteúdo principal
Um projeto de exemplo chamado Streaming demonstra o uso das APIs de Sampler Feedback para streaming de texturas. Ele usa as APIs padrão e de extensão do Direct3D 12 para criar recursos de mapa de feedback MinMip e exibições de acesso não ordenado, além de recursos de mapa MinMip, exibições de recurso de sombreador e samplers. O exemplo inclui dois builds para plataformas diferentes: Microsoft Game Development Kit (GDK) para XBOX Series X|S e um build para Windows desktop. Somente o build para XBOX Series X|S usa as novas APIs de Sampler Feedback do Direct3D 12. As outras plataformas emulam o Sampler Feedback usando a funcionalidade existente do Direct3D 12. Uma versão futura do exemplo oferecerá suporte às novas APIs de Sampler Feedback presentes na versão de primavera de 2020 do Windows. Também há uma ferramenta de geração de conteúdo, que deve ser compilada e executada em um PC desktop para gerar os arquivos de dados de textura em blocos usados no exemplo. Na versão inicial, a ferramenta de geração de conteúdo (ContentTool) deve ser executada em um PC desktop com uma GPU de nível de recurso 12_0 do Direct3D. Em uma versão futura, esse requisito será reduzido para o nível de recurso 11_0. O build desktop do exemplo Streaming requer uma GPU de nível de recurso 11_0 com suporte a recursos em blocos de camada 2.

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. Captura de tela do build UWP do exemplo Streaming, exibindo conteúdo de textura gerado pelo ContentTool

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

  1. 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.
  2. 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.
  3. 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.
  4. 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. Um fluxograma que representa o ciclo de operações, agrupadas por trabalho de GPU e CPU, executadas para uma textura em blocos individual no mecanismo de streaming de texturas O ciclo de operações se repete a cada quadro. No entanto, para qualquer bloco individual, concluir o ciclo leva mais de um quadro. Observe também que a implementação do mecanismo de streaming é principalmente de thread único, exceto pela E/S de arquivo assíncrona para carregar dados de blocos do disco rígido. Essa abordagem maximiza a legibilidade e a flexibilidade do sistema. Um uso mais agressivo de threads e otimização reduziria bastante a latência, mas tornaria o código mais difícil de entender.

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.
  1. A própria textura em blocos, por meio da API ID3D12Device::CreateReservedResource.
  2. 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.
  3. Um pequeno mapa de feedback MinMip, com as mesmas dimensões do mapa MinMip.
Descritores de exibição de recurso de sombreador (SRV) são criados para a textura em blocos e o mapa MinMip, e um descritor de exibição de acesso não ordenado (UAV) é criado para o mapa de feedback MinMip usando a API 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 API ID3D12CommandQueue::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 usando ID3D12GraphicsCommandList::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.

Recursos e otimizações ainda não implementados

Este exemplo ilustra apenas uma abordagem específica para usar o Sampler Feedback no streaming de texturas. Diferentes compensações entre computação na CPU e na GPU, computação e footprint de memória, e precisão e resultados visuais percebidos levariam a implementações diferentes. As observações a seguir discutem algumas dessas compensações.

Análise de feedback usando computação na GPU

A implementação atual usa a leitura dos dados de feedback pela CPU, analisados em relação a um banco de dados de blocos atualmente conhecidos em uma tabela de hash, para calcular listas de blocos a serem carregados via streaming e expirados. Esse trabalho também poderia ser feito na GPU, criando uma estrutura de dados de blocos conhecidos adequada à GPU. Um sombreador de computação seria executado a cada quadro, comparando os dados de feedback com o conjunto de blocos atualmente carregado. O sombreador de computação geraria listas de blocos para carregar e descarregar a cada quadro. A CPU trabalharia então apenas com esse conjunto de dados bastante reduzido, em vez de examinar todo o conjunto de dados de feedback por quadro.

Resolução do mapa de feedback

As dimensões do mapa de feedback podem ser escolhidas como qualquer fração em potência de dois do tamanho da textura em blocos (escolhida individualmente para as dimensões U, V e W). Atualmente, o exemplo usa as dimensões de um bloco de 64 KB, mas isso exige que o trabalho de análise do mapa de feedback seja dimensionado com o número total de blocos que podem ser mapeados em todos os recursos, o que pode rapidamente chegar a centenas de milhares de blocos. Escolher as dimensões do mapa de feedback para representar 2 × 2 blocos de 64 KB no mip 0 reduziria o trabalho de análise em 75% e possivelmente não afetaria muito os resultados visuais.

Compartilhamento do mapa de feedback entre várias texturas em blocos

Os sombreadores de renderização da cena usam três texturas mapeadas para as mesmas coordenadas UV: difusa, normal e especular. O sampler feedback capturado em relação a uma dessas texturas (ou seja, apenas o mapa difuso) pode ser facilmente extrapolado para tomar as mesmas decisões de streaming em relação às outras texturas do conjunto, mesmo que essas outras texturas tenham tamanhos de bloco ou dimensões de textura diferentes. Fazer essa alteração reduziria o trabalho de análise do mapa de feedback em 66% nesse caso. Além disso, as operações de E/S do disco rígido poderiam ser otimizadas empacotando blocos do conjunto de texturas juntos, de modo que o carregamento simultâneo de um bloco de cada mapa difuso, normal e especular pudesse ser feito em uma única solicitação de E/S. Uma atualização futura do exemplo incluirá essa otimização.

Consulte também

Visão geral do Sampler Feedback (versão prévia)
Última modificação em 8 de outubro de 2026