Otimizações de UMA: texturas acessíveis por CPU e swizzling padrão
As GPUs da Unified Memory Architecture (UMA) oferecem algumas vantagens de eficiência em relação às GPUs discretas, especialmente ao otimizar para dispositivos móveis. Conceder aos recursos acesso à CPU quando a GPU é UMA pode reduzir a quantidade de cópias que ocorre entre a CPU e a GPU. Embora não recomendemos que os aplicativos forneçam cegamente acesso à CPU a todos os recursos em projetos UMA, há oportunidades para melhorar a eficiência dando aos recursos certos acesso à CPU. Ao contrário das GPUs discretas, a CPU pode tecnicamente ter um ponteiro para todos os recursos que a GPU pode acessar.
- Visão geral das texturas acessíveis pela CPU
- Visão geral do Swizzle padrão
- APIs
- Tópicos relacionados
Visão geral das texturas acessíveis pela CPU
As texturas acessíveis pela CPU, no pipeline gráfico, são um recurso da arquitetura UMA, permitindo que as CPUs tenham acesso de leitura e gravação às texturas. Nas GPUs discretas mais comuns, a CPU não tem acesso a texturas no pipeline gráfico.
O conselho geral de práticas recomendadas para texturas é acomodar GPUs discretas, o que normalmente envolve seguir os processos em Carregando dados de textura por meio de buffers, resumidos como:
- Não ter nenhum acesso à CPU para a maioria das texturas.
- Definir o layout da textura como D3D12_TEXTURE_LAYOUT_UNKNOWN.
- Carregando as texturas para a GPU com CopyTextureRegion.
No entanto, para certos casos, a CPU e a GPU podem interagir com tanta frequência nos mesmos dados que o mapeamento de texturas se torna útil para economizar energia ou acelerar um design específico em adaptadores ou arquiteturas específicos. Os aplicativos devem detectar esses casos e otimizar as cópias desnecessárias. Nesse caso, para obter o melhor desempenho, considere o seguinte:
Só comece a entreter o melhor desempenho de texturas de mapeamento quando D3D12_FEATURE_DATA_ARCHITECTURE::UMA for TRUE. Em seguida, preste atenção ao CacheCoherentUMA se decidir quais propriedades de cache da CPU escolher no heap.
Aproveitar o acesso à CPU para texturas é mais complicado do que para buffers. Os layouts de textura mais eficientes para GPUs raramente são row_major. Na verdade, algumas GPUs só podem suportar texturas row_major ao copiar dados de textura.
As GPUs UMA devem se beneficiar universalmente de uma otimização simples para reduzir os tempos de carregamento de nível. Depois de reconhecer o UMA, o aplicativo pode otimizar o CopyTextureRegion inicial para preencher texturas que a GPU não modificará. Em vez de criar a textura em um heap com D3D12_HEAP_TYPE_DEFAULT e empacotar os dados de textura, o aplicativo pode usar WriteToSubresource para evitar entender o layout de textura real.
No D3D12, as texturas criadas com D3D12_TEXTURE_LAYOUT_UNKNOWN e sem acesso à CPU são as mais eficientes para renderização e amostragem frequentes de GPU. Ao testar o desempenho, essas texturas devem ser comparadas com D3D12_TEXTURE_LAYOUT_UNKNOWN com acesso à CPU e D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE com acesso à CPU e D3D12_TEXTURE_LAYOUT_ROW_MAJOR para suporte entre adaptadores.
O uso de D3D12_TEXTURE_LAYOUT_UNKNOWN com acesso à CPU habilita os métodos WriteToSubresource, ReadFromSubresource, Map (impedindo o acesso do aplicativo ao ponteiro) e Unmap; mas pode sacrificar a eficiência do acesso à GPU.
O uso do D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE com acesso à CPU habilita WriteToSubresource, ReadFromSubresource, Map (que retorna um ponteiro válido para o aplicativo) e Unmap. Ele também pode sacrificar a eficiência do acesso à GPU mais do que D3D12_TEXTURE_LAYOUT_UNKNOWN com o acesso à CPU.
Visão geral do Swizzle padrão
D3D12 (e D3D11.3) introduzem um layout de dados multidimensional padrão. Isso é feito para permitir que várias unidades de processamento operem nos mesmos dados sem copiar os dados ou alternar os dados entre vários layouts. Um layout padronizado permite ganhos de eficiência por meio de efeitos de rede e permite que os algoritmos façam atalhos assumindo um padrão específico.
Para obter uma descrição detalhada dos layouts de textura, consulte D3D12_TEXTURE_LAYOUT.
Observe, porém, que esse swizzle padrão é um recurso de hardware e pode não ser suportado por todas as GPUs.
Para obter informações básicas sobre swizzling, consulte Curva de ordem Z.
APIs
Ao contrário do D3D11.3, o D3D12 dá suporte ao mapeamento de textura por padrão, portanto, não há necessidade de consultar D3D12_FEATURE_DATA_D3D12_OPTIONS. No entanto, o D3D12 nem sempre dá suporte ao swizzle padrão – esse recurso precisará ser consultado com uma chamada para CheckFeatureSupport e verificando o campo StandardSwizzle64KBSupported de D3D12_FEATURE_DATA_D3D12_OPTIONS.
As seguintes APIs fazem referência ao mapeamento de textura:
Enumerações
- D3D12_TEXTURE_LAYOUT : controla o padrão de swizzle de texturas padrão e habilita o suporte a mapas em texturas acessíveis pela CPU.
Estruturas
- D3D12_RESOURCE_DESC : descreve um recurso, como uma textura, esta é uma estrutura amplamente utilizada.
- D3D12_HEAP_DESC : descreve um heap.
Métodos
- ID3D12Device::CreateCommittedResource : cria um único recurso e um heap de backup do tamanho e alinhamento corretos.
- ID3D12Device::CreateHeap : cria um heap para um buffer ou textura.
- ID3D12Device::CreatePlacedResource : cria um recurso que é colocado em um heap específico, geralmente um método mais rápido de criar um recurso do que CreateHeap.
- ID3D12Device::CreateReservedResource : cria um recurso reservado, mas ainda não confirmado ou colocado em um heap.
- ID3D12CommandQueue::UpdateTileMappings : atualiza mapeamentos de locais de bloco em recursos lado a lado para locais de memória em um heap de recurso.
- ID3D12Resource::Map : obtém um ponteiro para os dados especificados no recurso e nega o acesso da GPU ao sub-recurso.
- ID3D12Resource::GetDesc : obtém as propriedades do recurso.
- ID3D12Heap::GetDesc obtém as propriedades de heap.
- ReadFromSubresource : copia dados de uma textura que foi mapeada usando Map.
- WriteToSubresource : copia dados em uma textura que foi mapeada usando Map.
Os recursos e heaps pai têm requisitos de alinhamento:
- D3D12_DEFAULT_MSAA_RESOURCE_PLACEMENT_ALIGNMENT (4 MB) para texturas de várias amostras.
- D3D12_DEFAULT_RESOURCE_PLACEMENT_ALIGNMENT (64 KB) para texturas e buffers de exemplo único.
- A cópia de sub-recursos lineares deve ser alinhada a D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512 bytes), com o passo de linha sendo alinhado a D3D12_TEXTURE_DATA_PITCH_ALIGNMENT (256 bytes).
- As exibições de buffer constante devem ser alinhadas a D3D12_CONSTANT_BUFFER_DATA_PLACEMENT_ALIGNMENT (256 bytes).
Texturas menores que 64 KB devem ser processadas por meio de CreateCommittedResource.
Com texturas dinâmicas (texturas que mudam a cada quadro), a CPU gravará linearmente no heap de upload, seguida por uma operação de cópia de GPU.
Normalmente, para criar recursos dinâmicos, crie um buffer grande em um heap de upload (consulte Subalocação em buffers). Para criar recursos de preparo, crie um buffer grande em um heap de leitura. Para criar recursos estáticos padrão, crie recursos adjacentes em um heap padrão. Para criar recursos com alias padrão, crie recursos sobrepostos em um heap padrão.
WriteToSubresource e ReadFromSubresource reorganizam os dados de textura entre um layout principal de linha e um layout de recurso indefinido. A operação é síncrona, portanto, o aplicativo deve manter o agendamento da CPU em mente. O aplicativo sempre pode dividir a cópia em regiões menores ou agendar essa operação em outra tarefa. Recursos MSAA e recursos de estêncil de profundidade com layouts de recursos opacos não são suportados por essas operações de cópia de CPU e causarão uma falha. Formatos que não têm um tamanho de elemento de potência de dois também não são suportados e também causarão uma falha. Podem ocorrer códigos de retorno de memória insuficiente.
Tópicos relacionados