Otimizações de UMA: texturas acessíveis por CPU e swizzling padrão
As GPUs de UMA (Arquitetura de Memória Universal) oferecem algumas vantagens de eficiência em relação a GPUs discretas, especialmente ao otimizar para dispositivos móveis. Fornecer aos recursos acesso à CPU quando a GPU é UMA pode reduzir a quantidade de cópia que ocorre entre a CPU e a GPU. Embora não recomendemos que os aplicativos dêem acesso à CPU cegamente a todos os recursos em designs de UMA, há oportunidades para melhorar a eficiência fornecendo aos recursos corretos acesso à CPU. Ao contrário das GPUs discretas, a CPU tecnicamente pode ter um ponteiro para todos os recursos que a GPU pode acessar.
Visão geral das texturas acessíveis à CPU
As texturas acessíveis à CPU, no pipeline de gráficos, 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, que normalmente envolvem seguir os processos em Carregar dados de textura por meio de buffers, resumidos como:
- Não ter acesso à CPU para a maioria das texturas.
- Definindo o layout de textura como D3D12_TEXTURE_LAYOUT_UNKNOWN.
- Carregando as texturas para a GPU com CopyTextureRegion.
No entanto, para determinados casos, a CPU e a GPU podem interagir com tanta frequência nos mesmos dados, que as texturas de mapeamento se tornam úteis para economizar energia ou para acelerar um design específico em adaptadores ou arquiteturas específicas. Os aplicativos devem detectar esses casos e otimizar as cópias desnecessárias. Nesse caso, para melhor desempenho, considere o seguinte:
Comece a entreter apenas 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 de 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 dar suporte a texturas row_major ao copiar dados de textura ao redor.
As GPUs uma devem se beneficiar universalmente de uma otimização simples para reduzir os tempos de carregamento de nível. Depois de reconhecer 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 realizar marshaling dos dados de textura, o aplicativo pode usar WriteToSubresource para evitar entender o layout de textura real.
Na 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. Durante o teste de 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 a adaptadores cruzados.
Usar D3D12_TEXTURE_LAYOUT_UNKNOWN com acesso à CPU permite os métodos WriteToSubresource, ReadFromSubresource, Map (precluding application access to pointer) e Unmap; mas pode sacrificar a eficiência do acesso à GPU.
Usar D3D12_TEXTURE_LAYOUT_STANDARD_SWIZZLE com acesso à CPU permite 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 acesso à CPU.
Visão geral do Swizzle Standard
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 girar os dados entre vários layouts. Um layout padronizado permite ganhos de eficiência por meio de efeitos de rede e permite que 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 compatível com todas as GPUs.
Para obter informações em segundo plano sobre swizzling, consulte Curva de ordem Z.
APIs
Ao contrário do D3D11.3, d3D12 dá suporte ao mapeamento de textura por padrão, portanto, não há necessidade de consultar D3D12_FEATURE_DATA_D3D12_OPTIONS. No entanto, 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 referenciam o mapeamento de textura:
Enumerações
- D3D12_TEXTURE_LAYOUT : controla o padrão de swizzle de texturas padrão e habilita o suporte ao mapa em texturas acessíveis à CPU.
Estruturas
- D3D12_RESOURCE_DESC : descreve um recurso, como uma textura, essa é uma estrutura amplamente usada.
- 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 criação de 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 em blocos para locais de memória em um heap de recursos.
- ID3D12Resource::Map : obtém um ponteiro para os dados especificados no recurso e nega o acesso de GPU ao sub-recurso.
- ID3D12Resource::GetDesc : obtém as propriedades do recurso.
- ID3D12Heap::GetDesc obtém as propriedades do heap.
- ReadFromSubresource : copia dados de uma textura que foi mapeada usando o Mapa.
- WriteToSubresource : copia dados em uma textura que foi mapeada usando o Mapa.
Os recursos e os 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 linear deve ser alinhada a D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT (512 bytes), com o tom 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 alteram cada quadro), a CPU gravará linearmente no heap de upload, seguido 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 Suballocação dentro de buffers). Para criar recursos de preparo, crie um buffer grande em um heap de readback. Para criar recursos estáticos padrão, crie recursos adjacentes em um heap padrão. Para criar recursos de alias padrão, crie recursos sobrepostos em um heap padrão.
WriteToSubresource e ReadFromSubresource reorganizam dados de textura entre um layout principal de linha e um layout de recurso indefinido. A operação é síncrona, portanto, o aplicativo deve ter em mente o agendamento da CPU. 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 compatíveis com essas operações de cópia de CPU e causarão uma falha. Formatos que não têm um tamanho de elemento power-of-two também não têm suporte e também causarão uma falha. Códigos de retorno fora da memória podem ocorrer.
Tópicos relacionados