Acompanhamento de uso de alocação
Com a lista de alocação desaparecendo, o gerenciador de memória de vídeo (VidMm) não tem mais visibilidade das alocações que estão sendo referenciadas em um buffer de comando específico. Como resultado, o VidMm não está mais em posição de acompanhar o uso da alocação e lidar com a sincronização relacionada. Essa responsabilidade agora se enquadra no UMD (driver de modo de usuário). Em particular, o UMD precisa lidar com a sincronização em relação ao acesso direto da CPU à alocação e renomeação.
O VidMm adia de forma assíncrona a destruição da alocação de maneira segura, não desbloqueando o thread de chamada e o desempenho. Como tal, um UMD não precisa se preocupar em ter que adiar a destruição da alocação. Quando o VidMm recebe uma solicitação de destruição de alocação, ele pressupõe, por padrão, que os comandos enfileirados antes da solicitação de destruição podem potencialmente acessar a alocação que está sendo destruída. Assim, o VidMm adia a operação de destruição até que os comandos enfileirados sejam concluídos. Se o UMD souber que os comandos pendentes não acessam a alocação que está sendo destruída, ele poderá instruir o VidMm a processar a solicitação sem esperar definindo o sinalizador AssumeNotInUse ao chamar Deallocate2 ou DestroyAllocation2.
Lock2
O UMD é responsável por lidar com a sincronização adequada em relação ao acesso direto à CPU. Em particular, um UMD é necessário para:
Suporte à semântica de bloqueio sem substituição e descarte, o que implica que o UMD precisa implementar seu próprio esquema de renomeação.
Para operações de mapa que exigem sincronização (ou seja, não a não substituição ou descarte acima):
- Retornar WasStillDrawing se for feita uma tentativa de acessar uma alocação que está ocupada no momento e o chamador solicitar que a operação de bloqueio não bloqueie o thread de chamada (D3D11_MAP_FLAG_DO_NOT_WAIT).
- Ou, se o sinalizador D3D11_MAP_FLAG_DO_NOT_WAIT não estiver definido, aguarde até que uma alocação fique disponível para acesso à CPU. O UMD precisa implementar uma espera nãopolada. O UMD usará o novo mecanismo de monitoramento de contexto.
Por enquanto, o UMD continua precisando chamar LockCb/UnlockCb para pedir ao VidMm para configurar uma alocação para acesso à CPU. Na maioria dos casos, o UMD é capaz de manter a alocação mapeada durante todo o tempo de vida. No entanto, no futuro, LockCb e UnlockCb serão preteridos em favor de novas chamadas Lock2Cb e Unlock2Cb . O objetivo desses retornos de chamada mais recentes é fornecer uma nova implementação de limpo com um novo conjunto de argumentos e sinalizadores.
Os intervalos de swizzling são removidos do WDDM versão 2. É responsabilidade do desenvolvedor do driver remover a dependência de intervalos de giro de chamadas para LockCb à medida que eles se movem em direção a uma implementação baseada em Lock2Cb.
Lock2Cb é exposto como um método simples para obter um endereço virtual para uma alocação. Há algumas restrições com base no tipo de alocação e no segmento atual em que ele reside atualmente.
O driver indica se um segmento é acessível pela CPU por meio do sinalizador CpuVisible , que está no membro Flags da estrutura DXGK_SEGMENTDESCRIPTOR .
Para alocações acessíveis à CPU:
- As alocações acessíveis à CPU armazenadas em cache devem residir em um segmento de abertura ou não residir para serem bloqueadas. Não podemos garantir a coerência de cache entre a CPU e um segmento de memória na GPU (unidade de processamento gráfico).
- As alocações acessíveis à CPU localizadas em um segmento de memória totalmente acessível pela CPU (redimensionado usando a BARRA redimensionável) têm a garantia de serem bloqueáveis e poderão retornar um endereço virtual. Nenhuma restrição especial é necessária neste cenário.
- As alocações acessíveis à CPU localizadas em um segmento de memória não acessível pela CPU (com ou sem acesso a um CpuHostAperture) podem falhar ao serem mapeadas em um endereço virtual de CPU por vários motivos. Se cpuHostAperture estiver sem espaço disponível ou a alocação não especificar um segmento de abertura, um endereço virtual será impossível de obter. Por esse motivo, todas as alocações acessíveis à CPU em segmentos de memória não acessíveis à CPU devem conter um segmento de abertura em seu conjunto de segmentos com suporte. Esse requisito garante que o VidMm seja capaz de colocar a alocação na memória do sistema e fornecer um endereço virtual.
- As alocações acessíveis à CPU já localizadas na memória do sistema (e/ou mapeadas em um segmento de abertura) têm a garantia de funcionar.
Para alocações não acessíveis à CPU:
- As alocações acessíveis à CPU são apoiadas por objetos de seção que não podem apontar diretamente para o buffer de quadros de GPUs. Para bloquear uma alocação não acessível à CPU, a alocação deve dar suporte a um segmento de abertura no conjunto de segmentos com suporte ou já estar na memória do sistema (não deve ser residente no dispositivo).
Se uma alocação for bloqueada com êxito enquanto a alocação não estiver residente no dispositivo, mas não der suporte a um segmento de abertura, a alocação não deverá ser confirmada em um segmento de memória durante o bloqueio.
No momento, Lock2 não contém sinalizadores e os bits de sinalizador reservados devem ser todos 0.
CpuHostAperture
Para dar melhor suporte ao bloqueio com segmentos de memória não acessíveis à CPU ao redimensionar a BARRA, uma CpuHostAperture é fornecida na abertura PCI. O CpuHostAperture se comporta como um gerenciador baseado em página, que pode ser mapeado diretamente para regiões de memória de vídeo por meio da função DDI (interface de driver de dispositivo) DxgkDdiMapCpuHostAperture. O VidMm pode mapear um intervalo de espaço de endereço virtual diretamente para um intervalo não contíguo da CpuHostAperture e fazer com que o CpuHostAperture seja mapeado para a memória de vídeo sem a necessidade de intervalos de giro.
A quantidade máxima de memória bloqueável que a CPU pode referenciar em segmentos de memória não acessíveis à CPU é limitada ao tamanho do CpuHostAperture. Os detalhes para expor o CpuHostAperture ao kernel de elementos gráficos DirectX podem ser encontrados na abertura do host da CPU.
Coerência de E/S
No x86/x64 de hoje, todas as GPUs devem dar suporte à coerência de E/S sobre PCIe para permitir que uma GPU leia ou escreva em uma superfície de memória do sistema armazenável em cache e mantenha a coerência com a CPU. Quando uma superfície é mapeada como um cache coerente do ponto de vista da GPU, a GPU precisa bisbilhotar os caches de CPU ao acessar a superfície. Essa forma de coerência normalmente é usada para recursos dos quais se espera que a CPU leia, como algumas superfícies de preparo.
Em algumas plataformas arm, a coerência de E/S não tem suporte diretamente no hardware. Nessas plataformas, a coerência de E/S precisa ser emulada invalidando manualmente a hierarquia de cache de CPU. O VidMm faz isso acompanhando as operações para uma alocação proveniente da GPU (operação de leitura/gravação da lista de alocação) e da CPU (operação de mapa, leitura/gravação). O VidMm emite uma invalidação de cache quando determina que o cache pode conter:
- Dados que precisam ser gravados (gravação da CPU, leitura de GPU)
- Dados obsoletos que precisam ser invalidados (gravação de GPU, leituras de CPU).
Na plataforma sem coerência de E/S, a responsabilidade de acompanhar o acesso de CPU e GPU às alocações recai sobre o UMD. O kernel de gráficos expõe uma nova DDI de Cache invalidadoque o UMD pode usar para fazer write-back e invalidar o intervalo de endereços virtuais associado a uma alocação armazenável em cache. Em plataformas que não têm suporte para coerência de E/S, o UMD é necessário para chamar essa função após a gravação da CPU e antes da leitura da GPU, bem como após a gravação e antes da leitura da CPU. O último pode parecer pouco intuitivo no início. Mas, como a CPU pode ter lido dados especulativamente antes da gravação da GPU chegar à memória, é necessário invalidar todos os caches de CPU para garantir que a CPU leia novamente os dados da RAM.