Dividir um buffer de AMD
Os pontos de divisão são usados pelo gerenciador de memória de vídeo para dividir um item de trabalho grande enviado pelo driver de miniporta de exibição em itens de trabalho menores que exigem menos recursos de GPU para execução. Por exemplo, um buffer DMA grande pode referenciar um conjunto de alocações que possivelmente não cabem na memória de vídeo local ou na memória não local. A única maneira de processar esse item de trabalho é dividi-lo em vários itens de trabalho menores que exigem menos recursos de GPU.
Nota A divisão de buffer de DMA e a preempção de buffer de DMA são conceitos independentes diferentes. Um driver de miniporta de exibição sempre deve dar suporte à divisão de buffer de DMA mesmo em um sistema com uma GPU em que a preempção do buffer de DMA não é possível. Em um sistema com uma GPU em que não é possível salvar e restaurar contexto, o agendador de GPU agenda partes divididas de um buffer de DMA de volta para trás, garantindo que as partes divididas não sejam intercaladas com outro buffer de DMA de um contexto de GPU diferente. No entanto, um buffer de paginação deve ser enviado entre partes de um buffer DMA dividido porque as operações de paginação são necessárias entre partes divididas de um buffer DMA. Cada ponto de divisão que o driver usa para criar um fluxo de DMA do aplicativo é usado pelo gerenciador de memória de vídeo. Um buffer de DMA enviado deve reprogramar estado de GPU suficiente após cada ponto de divisão para considerar um buffer de paginação potencial que pode ser inserido nesse local.
Para especificar pontos de divisão, o driver de miniporto de exibição especifica valores nos membros SplitOffset e SlotId da estrutura D3DDDI_PATCHLOCATIONLIST para cada alocação referenciada no membro AllocationIndex do D3DDDI_PATCHLOCATIONLIST. Para acompanhar o uso de alocação em um buffer de DMA específico, o gerenciador de memória de vídeo cria as dimensões necessárias de uma matriz usando o membro MaxAllocationListSlotId da estrutura DXGK_DRIVERCAPS que o driver forneceu por meio de uma chamada para sua função DxgkDdiQueryAdapterInfo . Essa matriz é inicializada em zero e é preenchida à medida que as entradas de parte dividida da lista de locais de patch são processadas. O membro SlotId do D3DDDI_PATCHLOCATIONLIST para o local do patch indica qual linha da tabela de recursos deve ser atualizada enquanto o membro SplitOffset indica o deslocamento dentro do buffer DMA em que a alocação é necessária. O buffer DMA pode ser executado até o ponto especificado por SplitOffset sem que o recurso esteja acessível à GPU. Da mesma forma, se uma nova entrada de divisão de local de patch se referir à mesma SlotId, a alocação anterior será substituída pela nova alocação e a alocação anterior não será mais necessária (ou seja, a alocação anterior pode ser paginada).
Ao paginar os recursos exigidos por um buffer de DMA, o gerenciador de memória de vídeo processa a lista de locais de patch começando com o primeiro elemento e movendo-se para baixo em direção ao último elemento. Os elementos D3DDDI_PATCHLOCATIONLIST preenchidos pelo driver devem conter valores em seus membros SplitOffset ; os elementos estão aumentando estritamente (ou seja, as alocações devem aparecer na ordem em que são usadas no fluxo). As páginas do gerenciador de memória de vídeo em alocações que são referenciadas na lista de locais de patch na ordem em que são fornecidas. Quando um ponto é atingido onde o gerenciador de memória de vídeo não pode mais paginar uma alocação devido a uma condição de memória baixa, o gerenciador de memória de vídeo envia a parte atual do buffer de DMA que está sendo preparado para o agendador de GPU para execução. O buffer DMA é executado desde o início do ponto de divisão anterior até o valor SplitOffset especificado para uma alocação que não pôde ser trazida. Depois de enviado, o gerenciador de memória de vídeo determina a lista de alocações necessárias no deslocamento dividido atual no fluxo de DMA usando a tabela de recursos. Todas as alocações na tabela são mantidas em seu local físico atual, enquanto outras alocações que não estão mais em uso podem ser removidas. Em seguida, o gerenciador de memória de vídeo continua a processar a lista de locais de patch, potencialmente dividindo várias vezes novamente.
O driver deve especificar pontos divididos sempre que uma alocação for associada ou não associada. Para especificar que uma alocação não está associada, o driver pode especificar um identificador de alocação NULL no membro hDeviceSpecificAllocation da estrutura DXGK_ALLOCATIONLIST com o valor apropriado no membro SlotId do D3DDDI_PATCHLOCATIONLIST associado. O driver deve desassociar recursos grandes para aumentar as chances de que o gerenciador de memória de vídeo possa resolver problemas complexos de posicionamento de memória.
Da mesma forma, o driver deve reprogramar recursos grandes em cada ponto de divisão. Ao usar um ponto de divisão, o gerenciador de memória de vídeo é forçado a deixar uma alocação associada anteriormente à alocação anterior. Isso causa fragmentação de memória que pode levar a uma falha ao resolver problemas complexos de posicionamento de memória que poderiam ter sido resolvidos se não fosse a restrição de alocação associada anteriormente. Ao calcular o estado em um ponto de divisão, o gerenciador de memória de vídeo determina qual identificador de slot (SlotId) está sendo reprogramado nesse ponto de divisão (ou seja, cada elemento de lista de localização de patch que compartilha o mesmo valor SplitOffset com outros elementos) e ignora a restrição de posicionamento nesse ponto de divisão. Por exemplo, se o driver usar uma textura de 64 MB, reprogramar essa textura em cada ponto de divisão dará ao gerenciador de memória de vídeo a flexibilidade para mover essa textura na memória entre pontos de divisão, se necessário.