Residência

Um objeto é considerado residente quando está acessível pela GPU.

Orçamento de residência

As GPUs ainda não dão suporte à falha de página, portanto, os aplicativos devem confirmar dados na memória física enquanto a GPU pode acessá-los. Esse processo é conhecido como "fazer algo residente" e deve ser feito para memória do sistema físico e memória de vídeo discreta física. No D3D12, a maioria dos objetos de API encapsula alguma quantidade de memória acessível por GPU. Essa memória acessível por GPU é feita residente durante a criação do objeto de API e removida na destruição de objetos da API.

A quantidade de memória física disponível para o processo é conhecida como o orçamento de memória de vídeo. O orçamento pode flutuar visivelmente à medida que os processos em segundo plano são ativados e dormem; e flutuam drasticamente quando o usuário muda para outro aplicativo. O aplicativo pode ser notificado quando o orçamento muda e sonda o orçamento atual e a quantidade de memória consumida no momento. Se um aplicativo não permanecer dentro de seu orçamento, o processo será intermitentemente congelado para permitir que outros aplicativos sejam executados e/ou as APIs de criação retornarão falha. A interface IDXGIAdapter3 fornece os métodos relativos a essa funcionalidade, em particular QueryVideoMemoryInfo e RegisterVideoMemoryBudgetChangeNotificationEvent.

Os aplicativos são incentivados a usar uma reserva para denotar a quantidade de memória sem a qual não podem ficar. O ideal é que as configurações gráficas "baixas" especificadas pelo usuário, ou algo ainda menor, sejam o valor certo para essa reserva. A configuração de uma reserva nunca dará a um aplicativo um orçamento mais alto do que normalmente receberia. Em vez disso, as informações de reserva ajudam o kernel do sistema operacional a minimizar rapidamente o impacto de grandes situações de pressão de memória. Mesmo a reserva não tem garantia de estar disponível para o aplicativo quando o aplicativo não é o aplicativo em primeiro plano.

Recursos de heap

Embora muitos objetos de API encapsulam alguma memória acessível por GPU, espera-se que os recursos de heaps & sejam a maneira mais significativa de os aplicativos consumirem e gerenciarem a memória física. Um heap é a unidade de nível mais baixo para gerenciar a memória física, portanto, é bom ter alguma familiaridade com suas propriedades de residência.

  • Heaps não podem ser parcialmente residentes, mas existem soluções alternativas com recursos reservados.
  • Os heaps devem ser orçados como parte de um pool específico. Os adaptadores uma têm um pool, enquanto adaptadores discretos têm dois pools. Embora seja verdade que o kernel pode deslocar alguns heaps em adaptadores discretos da memória de vídeo para a memória do sistema, ele faz isso apenas como um último recurso extremo. Os aplicativos não devem depender do comportamento de excesso de orçamento do kernel e devem se concentrar em um bom gerenciamento de orçamento.
  • Os heaps podem ser removidos da residência, o que permite que seu conteúdo seja paginado em disco. Mas a destruição de heaps é uma técnica mais confiável para liberar residência em todas as arquiteturas do adaptador. Em adaptadores em que o campoMaxGPUVirtualAddressBitsPerProcess de D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT está próximo do tamanho do orçamento, o Despejo não recuperará a residência de forma confiável.
  • A criação de heap pode ser lenta; mas é otimizado para processamento de thread em segundo plano. É recomendável criar heaps em threads em segundo plano para evitar falhas no thread de renderização. No D3D12, vários threads podem chamar com segurança a criação de rotinas simultaneamente.

O D3D12 introduz mais flexibilidade e ortogonalidade em seu modelo de recursos para habilitar mais opções para aplicativos. Há três tipos de recursos de alto nível em D3D12: confirmados, colocados e reservados.

  • Os recursos confirmados criam um recurso e um heap ao mesmo tempo. O heap é implícito e não pode ser acessado diretamente. O heap é dimensionado adequadamente para localizar todo o recurso dentro do heap.
  • Os recursos colocados permitem o posicionamento de um recurso em um deslocamento diferente de zero em um heap. Normalmente, os deslocamentos devem ser alinhados a 64 KB; mas existem algumas exceções em ambas as direções. Os recursos msaa exigem alinhamento de deslocamento de 4 MB e o alinhamento de deslocamento de 4KB está disponível para texturas pequenas. Os recursos colocados não podem ser realocados ou remapeados para outro heap diretamente; mas permitem a realocação simples dos dados de recurso entre heaps. Depois de criar um novo recurso colocado em um heap diferente e copiar os dados do recurso, os novos descritores de recursos precisarão ser usados para o novo local de dados do recurso.
  • Os recursos reservados só estão disponíveis quando o adaptador dá suporte à camada 1 ou superior de recursos em bloco. Quando disponíveis, eles oferecem as técnicas de gerenciamento de residência mais avançadas disponíveis; mas nem todos os adaptadores atualmente dão suporte a eles. Eles permitem remapear um recurso sem a necessidade de regeneração de descritores de recursos, residência parcial em nível de mip e cenários de textura esparsa, etc. Nem todos os tipos de recursos têm suporte mesmo quando recursos reservados estão disponíveis, portanto, um gerente de residência totalmente geral baseado em página ainda não é viável.

Prioridades de residência

O Atualização do Windows 10 para Criadores permite que os desenvolvedores influenciem quais heaps e recursos serão preferidos para permanecer residentes quando a pressão de memória exigir que alguns de seus recursos sejam rebaixados. Isso ajuda os desenvolvedores a criar aplicativos com melhor desempenho aproveitando o conhecimento de que o runtime não pode inferir do uso da API. Espera-se que os desenvolvedores se tornem mais confortáveis e capazes de especificar prioridades à medida que fazem a transição do uso de recursos confirmados para recursos resseridos e em blocos.

A aplicação dessas prioridades deve ser mais fácil do que gerenciar dois orçamentos de memória dinâmica, rebaixar manualmente e promover recursos entre eles, já que os aplicativos já podem fazer isso. Portanto, o design da API de prioridade de residência é refinado com prioridades padrão razoáveis atribuídas a cada heap ou recurso conforme sua criação. Para obter mais informações, consulte ID3D12Device1::SetResidencyPriority e a enumeração D3D12_RESIDENCY_PRIORITY .

Com prioridades, espera-se que os desenvolvedores:

  • Aumente a prioridade de alguns heaps excepcionais para atenuar melhor o impacto no desempenho experimentado desses heaps sendo rebaixados mais cedo ou mais frequentemente do que seus padrões de acesso natural exigiriam. Espera-se que essa abordagem seja aproveitada por aplicativos portados de APIs gráficas, como Direct3D 11 ou OpenGL, que o modelo de gerenciamento de recursos é significativamente diferente do Direct3D 12.
  • Substitua quase todas as prioridades de heap com o próprio esquema de bucketization do aplicativo, corrigido, com base no conhecimento do programador sobre a frequência de acesso ou dinâmico; um esquema fixo é mais simples de gerenciar do que um dinâmico, mas pode ser menos eficaz e exigir a invenção do programador à medida que os padrões de uso mudam ao longo do desenvolvimento. Espera-se que essa abordagem seja aproveitada por aplicativos criados com o gerenciamento de recursos no estilo Direct3D 12 em mente, como aqueles que usam a biblioteca de residência (especialmente esquemas dinâmicos).

Algoritmo de prioridade padrão

Um aplicativo não pode especificar prioridades úteis para qualquer heap que tenta gerenciar sem primeiro subestanar o algoritmo de prioridade padrão. Isso ocorre porque o valor de atribuir uma prioridade específica a um heap é derivado de sua prioridade relativa a outros heaps priorizados que competem pela mesma memória.

A estratégia escolhida para gerar prioridades padrão é categorizar heaps em dois buckets, favorecendo (dando prioridade mais alta a) heaps que são considerados gravados com frequência pela GPU em vez de heaps que não são.

O bucket de alta prioridade contém heaps e recursos criados com sinalizadores que os identificam como destinos de renderização, buffers de estêncil de profundidade ou UAVs (Exibições de Acesso Não Ordenado). Estes são valores de prioridade atribuídos no intervalo começando em D3D12_RESIDENCY_PRIORITY_HIGH; para priorizar ainda mais entre esses heaps e recursos, os 16 bits mais baixos da prioridade são definidos para o tamanho do heap ou recurso dividido por 10 MB (saturando para 0xFFFF para heaps extremamente grandes). Essa priorização adicional favorece heaps e recursos maiores.

O bucket de baixa prioridade contém todos os outros heaps e recursos, que recebem um valor prioritário de D3D12_RESIDENCY_PRIORITY_NORMAL. Nenhuma priorização adicional entre esses heaps e recursos é tentada.

Gerenciamento de residência de programação

Aplicativos simples podem ser capazes de obter apenas criando recursos confirmados até que haja falhas de memória insuficiente. Após a falha, o aplicativo pode destruir outros recursos confirmados ou objetos de API para permitir que outras criações de recursos tenham êxito. No entanto, mesmo aplicativos simples são altamente recomendados para watch para alterações de orçamento negativas e destruir objetos de API não utilizados aproximadamente uma vez por quadro.

A complexidade de um design de gerenciamento de residência aumentará ao tentar otimizar para arquiteturas de adaptador ou incorporar prioridades de residência. O orçamento discreto e o gerenciamento de dois pools de memória discreta serão mais complexos do que gerenciar apenas um, e atribuir prioridades fixas em larga escala pode se tornar uma carga de manutenção se os padrões de uso evoluirem. O estouro de texturas na memória do sistema adiciona mais complexidade, pois o recurso errado na memória do sistema pode afetar severamente a taxa de quadros. E não há nenhuma funcionalidade simples para ajudar a identificar os recursos que se beneficiariam de maior largura de banda de GPU ou tolerariam largura de banda de GPU mais baixa.

Designs ainda mais complicados consultarão os recursos do adaptador atual. Essas informações estão disponíveis em D3D12_FEATURE_DATA_GPU_VIRTUAL_ADDRESS_SUPPORT, D3D12_FEATURE_DATA_ARCHITECTURE, D3D12_TILED_RESOURCES_TIER e D3D12_RESOURCE_HEAP_TIER.

Várias partes de um aplicativo provavelmente acabarão usando técnicas diferentes. Por exemplo, algumas texturas grandes e caminhos de código raramente exercidos podem usar recursos confirmados, enquanto muitas texturas podem ser designadas com uma propriedade de streaming e usar uma técnica geral de recurso colocado.

ID3D12Heap

Gerenciamento de memória