DXGKDDI_BUILDPAGINGBUFFER função de retorno de chamada (d3dkmddi.h)
A função DxgkDdiBuildPagingBuffer cria buffers de paginação para operações de memória.
Sintaxe
DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;
NTSTATUS DxgkddiBuildpagingbuffer(
[in] IN_CONST_HANDLE hAdapter,
[in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}
Parâmetros
[in] hAdapter
Um identificador para um bloco de contexto associado a um adaptador de exibição. O driver de miniporto de exibição forneceu anteriormente esse identificador para o subsistema de kernel de elementos gráficos do Microsoft DirectX no parâmetro de saída MiniportDeviceContext da função DxgkDdiAddDevice .
[in/out] pBuildPagingBuffer
Um ponteiro para uma estrutura DXGKARG_BUILDPAGINGBUFFER que contém informações para criar um buffer de paginação.
Retornar valor
DxgkDdiBuildPagingBuffer retorna um dos seguintes valores:
Código de retorno | Descrição |
---|---|
STATUS_SUCCESS | DxgkDdiBuildPagingBuffersuccessfully criou um buffer de paginação. |
STATUS_GRAPHICS_ALLOCATION_BUSY | Atualmente, a GPU está usando a alocação para o buffer de paginação. |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER | Mais espaço é necessário no buffer de paginação (ou seja, no membro pDmaBuffer da estrutura DXGKARG_BUILDPAGINGBUFFER à qual o parâmetro pBuildPagingBuffer aponta). |
Comentários
A função DxgkDdiBuildPagingBuffer é chamada para criar buffers de DMA (acesso direto à memória) de finalidade especial que são conhecidos como buffers de paginação. Um buffer de paginação contém uma operação que move o conteúdo de partes de alocações:
- Dentro de um segmento de uma alocação.
- Entre segmentos de alocações.
- De um segmento de uma alocação para a memória do sistema.
- Da memória do sistema a um segmento de uma alocação.
O driver de miniporto de exibição deve escrever a instrução de GPU (unidade de processamento gráfico) apropriada no buffer de paginação fornecido (no membro pDmaBuffer de DXGKARG_BUILDPAGINGBUFFER) de acordo com a operação de paginação solicitada; e, em seguida, o driver deve retornar o buffer de paginação de volta para o gerenciador de memória de vídeo (que faz parte de Dxgkrnl.sys). O agendador de GPU (que também faz parte do Dxgkrnl.sys) chama posteriormente a função DxgkDdiSubmitCommand do driver para solicitar que o driver envie o buffer de paginação como um buffer DMA regular para a GPU.
Se DxgkDdiBuildPagingBuffer determinar que uma operação de paginação requer mais de um buffer de paginação, o driver poderá especificar informações no membro multipassOffset do DXGKARG_BUILDPAGINGBUFFER e poderá usar essas informações em várias iterações da operação de paginação. O gerenciador de memória de vídeo inicializa as informações em MultipassOffset como zero antes da primeira solicitação de operação de paginação e não modifica as informações em MultipassOffset entre iterações. Portanto, o driver pode usar o MultipassOffset para salvar o progresso entre iterações. Por exemplo, o driver pode armazenar o número de página que foi transferido pela última vez para uma transferência baseada em página.
No momento, um buffer de paginação é criado para os seguintes tipos de operações:
-
Transferência
A operação de transferência move o conteúdo de uma alocação de um local para outro. Essa operação é o tipo mais comum de operação de memória.
Uma alocação é sempre totalmente transferida de um local para outro. No entanto, devido a restrições de memória, a transferência de uma alocação pode ser dividida em várias sub-transferências (ou seja, uma parte da alocação é movida do local A para B e, em seguida, a parte a seguir é movida e assim por diante, até que toda a alocação seja transferida). A primeira sub-transferência de uma alocação é marcada com o sinalizador de campo de bits TransferStart no membro Flags do membro Transfer de DXGKARG_BUILDPAGINGBUFFER; a última sub-transferência de uma alocação é marcada com o sinalizador de campo de bits TransferEnd . O driver tem a garantia de receber o fim de uma transferência pendente (ou seja, a última sub-transferência) antes que o driver receba o início de uma nova transferência.
Cada sub-transferência pode exigir que várias chamadas para DxgkDdiBuildPagingBuffer sejam concluídas (por exemplo, o driver pode ficar sem espaço de buffer de DMA). Portanto, o driver pode receber o sinalizador TransferStart em várias chamadas para DxgkDdiBuildPagingBuffer até que o driver receba o sinalizador TransferEnd em uma chamada para DxgkDdiBuildPagingBuffer. Receber o sinalizador TransferStart várias vezes não indica o início de várias novas transferências; indica que as sub-transferências para a alocação exigem várias iterações (por exemplo, se o driver ficou sem espaço de buffer de DMA). O driver pode usar o membro MultipassOffset do DXGKARG_BUILDPAGINGBUFFER para acompanhar o progresso de uma sub-transferência específica entre várias iterações de DxgkDdiBuildPagingBuffer.
Normalmente, uma transferência ocorre em uma única operação. Nessa situação, os sinalizadores de campo de bits TransferStart e TransferEnd são definidos.
Em alguns cenários, o driver pode ser necessário para configurar recursos de hardware quando determinadas alocações são paginada dentro ou fora da memória. Por padrão, a GPU pode estar usando a alocação referenciada durante a chamada para DxgkDdiBuildPagingBuffer. Nesses cenários, o driver pode exigir que a alocação fique ociosa antes que o driver programe os recursos de hardware necessários (ou seja, a programação dos recursos de hardware não pode ser enfileirada no buffer de DMA fornecido). Para esses cenários, o driver pode falhar na chamada para DxgkDdiBuildPagingBuffer com STATUS_GRAPHICS_ALLOCATION_BUSY.
Se o driver retornar STATUS_GRAPHICS_ALLOCATION_BUSY, o gerenciador de memória de vídeo aguardará até que a GPU seja concluída com qualquer referência à alocação atual e chame a função DxgkDdiBuildPagingBuffer do driver novamente. Na segunda chamada para DxgkDdiBuildPagingBuffer, o gerenciador de memória de vídeo define o sinalizador de campo de bit AllocationIsIdle no membro Flags do membro Transfer de DXGKARG_BUILDPAGINGBUFFER para indicar que a alocação que está sendo referenciada está ociosa. Se o sinalizador ocioso não estiver definido, o driver sempre deverá determinar que a alocação está ocupada no momento ou pode ficar ocupada em breve. Se o sinalizador ocioso estiver definido, o gerenciador de memória de vídeo garantirá que a alocação que está sendo referenciada permaneça ociosa durante a chamada para DxgkDdiBuildPagingBuffer.
Se o membro hAllocation de DXGKARG_BUILDPAGINGBUFFER for NULL, o driver deverá copiar os dados na origem para o destino sem executar nenhum giro ou bloco.
-
Preencher
A operação de preenchimento preenche uma alocação com um padrão especificado. A operação de preenchimento é usada para configurar o conteúdo inicial de uma alocação. Quando o conteúdo da alocação é preenchido, a alocação é garantida como ociosa (ou seja, não em uso pela GPU). A operação de preenchimento só pode ser executada em um segmento de memória. O gerenciador de memória de vídeo nunca solicita que o driver de miniporto de exibição preencha um segmento de abertura.
-
Descartar conteúdo
A operação de descarte de conteúdo notifica o driver de que uma alocação é descartada do local atual da alocação em um segmento de memória. Ou seja, a alocação é removida e não copiada de volta para a memória do sistema.
Em alguns cenários, o driver pode ser necessário para configurar recursos de hardware quando determinadas alocações são paginada dentro ou fora da memória. Por padrão, a GPU pode usar a alocação referenciada durante a chamada para DxgkDdiBuildPagingBuffer. Nesses cenários, o driver pode exigir que a alocação fique ociosa antes que o driver programe os recursos de hardware necessários (ou seja, a programação dos recursos de hardware não pode ser enfileirada no buffer de DMA fornecido). Para esses cenários, o driver pode falhar na chamada para DxgkDdiBuildPagingBuffer com STATUS_GRAPHICS_ALLOCATION_BUSY.
Se o driver retornar STATUS_GRAPHICS_ALLOCATION_BUSY, o gerenciador de memória de vídeo aguardará até que a GPU seja concluída com qualquer referência à alocação atual e chame a função DxgkDdiBuildPagingBuffer do driver novamente. Na segunda chamada para DxgkDdiBuildPagingBuffer, o gerenciador de memória de vídeo define o sinalizador de campo de bit AllocationIsIdle no membro Flags do membro DiscardContent da estrutura DXGKARG_BUILDPAGINGBUFFER para indicar que a alocação que está sendo referenciada está ociosa. Se o sinalizador ocioso não estiver definido, o driver sempre deverá determinar que a alocação está ocupada no momento ou pode ficar ocupada em breve. Se o sinalizador ocioso estiver definido, o gerenciador de memória de vídeo garantirá que a alocação que está sendo referenciada permaneça ociosa durante a chamada para DxgkDdiBuildPagingBuffer.
-
Ler físico
A operação de leitura física lê de um endereço de memória física especificado. O driver é solicitado a programar a GPU para a operação. O tamanho da memória física a ser acessada para a leitura pode ser de 1 byte a 8 bytes. Como os dados lidos são irrelevantes, DxgkDdiBuildPagingBuffer não é necessário para retornar os dados. No entanto, em cenários em que a CPU tenta ler a partir da memória do AGP após a gravação da GPU na memória do AGP, a operação de leitura-física é essencial para garantir a coerência da memória.
-
Gravar físico
A operação write-physical é gravada em um endereço físico especificado. O driver é solicitado a programar a GPU para a operação. O tamanho da memória física a ser acessada para a operação de gravação pode ser de 1 byte a 8 bytes. Como os dados gravados são irrelevantes, DxgkDdiBuildPagingBuffer pode gravar todos os dados na memória. No entanto, em cenários em que a CPU tenta ler a partir da memória do AGP após a gravação da GPU na memória do AGP, a operação write-physical é essencial para garantir a coerência da memória.
-
Segmento de abertura de mapa
A operação map-aperture-segment mapeia uma MDL (lista de descritores de memória) especificada em um segmento de abertura especificado em um deslocamento de segmento especificado para um número especificado de páginas. Se o sinalizador de campo de bit CacheCoherent estiver definido no membro Flags do membro MapApertureSegment da estrutura DXGKARG_BUILDPAGINGBUFFER , o driver deverá garantir que a coerência do cache seja imposta nas páginas mapeadas; caso contrário, a coerência de cache não é necessária para as páginas mapeadas.
Nota O sinalizador cacheCoherent bit-field é definido somente quando a memória em cache está sendo mapeada em um segmento de abertura coerente de cache e nunca é definida em um segmento de abertura não coerente com cache ou em uma alocação combinada de gravação mapeada em um segmento coerente de cache. -
Cancelar o mapa do segmento de abertura
A operação unmap-aperture-segment descompacta um intervalo mapeado anteriormente de um segmento de abertura especificado. O driver deve mapear o intervalo que não é mapeado para a página fictícia que o membro DummyPage do membro UnmapApertureSegment da estrutura DXGKARG_BUILDPAGINGBUFFER especifica.
Nota Quando o driver desmarca a página fictícia, o driver deve habilitar os acessos de GPU por meio do intervalo de abertura especificado para que o subsistema de kernel de elementos gráficos DirectX possa detectar problemas de corrupção. Existem testes de conformidade para marcar essa situação.Opcionalmente, o driver pode usar o MMIO para configurar um segmento de abertura. A GPU não acessará o intervalo de abertura no momento da configuração. No entanto, essa configuração de abertura não deve interferir na execução da GPU. A GPU não ficará ociosa quando DxgkDdiBuildPagingBuffer for chamado com o conjunto de tipos de operação DXGK_OPERATION_UNMAP_APERTURE_SEGMENT e a GPU poderá estar ocupada acessando outras partes do segmento de abertura que está sendo reconfigurado.
-
Transferência de bloqueio especial
A operação de transferência de bloqueio especial é semelhante à operação de transferência regular. No entanto, em vez de transferir o conteúdo da alocação de ou para o repositório de backup regular da alocação, a operação de transferência de bloqueio especial transfere o conteúdo da alocação de ou para o endereço virtual alternativo que foi configurado para a alocação quando a função pfnLockCb foi chamada com o sinalizador de campo de bit UseAlternateVA definido.
A operação de transferência de bloqueio especial ocorre apenas em um dos seguintes cenários:
- No momento, a alocação está acessível à CPU com um endereço virtual alternativo e está sendo removida.
- Uma alocação que foi removida anteriormente, como a situação descrita no marcador anterior, está sendo paginada novamente.
Em alguns cenários, o driver pode ser necessário para configurar recursos de hardware quando determinadas alocações são paginada dentro ou fora da memória. Por padrão, a GPU pode estar usando a alocação referenciada durante a chamada para DxgkDdiBuildPagingBuffer. Nesses cenários, o driver pode exigir que a alocação fique ociosa antes que o driver programe os recursos de hardware necessários (ou seja, a programação dos recursos de hardware não pode ser enfileirada no buffer de DMA fornecido). Para esses cenários, o driver pode falhar na chamada para DxgkDdiBuildPagingBuffer com STATUS_GRAPHICS_ALLOCATION_BUSY.
Se o driver retornar STATUS_GRAPHICS_ALLOCATION_BUSY, o gerenciador de memória de vídeo aguardará até que a GPU seja concluída com qualquer referência à alocação atual e chame a função DxgkDdiBuildPagingBuffer do driver novamente. Na segunda chamada para DxgkDdiBuildPagingBuffer, o gerenciador de memória de vídeo define o sinalizador de campo de bit AllocationIsIdle no membro Flags do membro SpecialLockTransfer da estrutura DXGKARG_BUILDPAGINGBUFFER para indicar que a alocação que está sendo referenciada está ociosa. Se o sinalizador ocioso não estiver definido, o driver sempre deverá determinar que a alocação está ocupada no momento ou pode ficar ocupada em breve. Se o sinalizador ocioso estiver definido, o gerenciador de memória de vídeo garantirá que a alocação que está sendo referenciada permaneça ociosa durante a chamada para DxgkDdiBuildPagingBuffer.
O gerenciador de memória do sistema garante que a transferência seja invisível para o aplicativo. No entanto, como a alocação está na memória do sistema e o endereço virtual da alocação não pode mais passar pela abertura de hardware, o driver deve garantir que a ordenação de bytes na memória do sistema corresponda ao que estava visível por meio da abertura.
DxgkDdiBuildPagingBuffer deve se tornar paginável.
Exemplos
O exemplo de código a seguir mostra como usar DxgkDdiBuildPagingBuffer.
NTSTATUS ntStatus;
DXGKARG_BUILDPAGINGBUFFER param;
// The driver receives the following paging operation to build:
//
param.Flags = 0;
param.pDmaBuffer= CurrentPagingBuffer;
param.DmaSize = CurrentPagingBufferSizeLeft;
param.pDmaBufferPrivateData = CurrentPagingBufferPrivateData;
param.DmaBufferPrivateDataSize = CurrentPagingBufferPrivateDataSizeLeft;
param.Operation = DXGK_OPERATION_TRANSFER;
param.Transfer.Flags = 0;
param.Transfer.TransferOffset = CurrentOffsetInAllocationBeingTransfered;
param.Transfer.hAllocation = DriverContextForAllocationBeingMoved;
param.Transfer.Source.SegmentId = 0; // Source is an MDL.
param.Transfer.Source.pMdl = MDLDescribingPagesForAllocationBeingMoved;
param.Transfer.Destination.SegmentId = 1; // Source to segment #1.
param.Transfer.Destination.SegmentAddress = 0; // Source to offset 0 of segment #1.
// The driver receives MultipassOffset when it is initialized to zero
// and uses it for multiple iterations of the paging operation.
//
param.MultipassOffset = 0;
do {
// Call the driver's BuildPagingBuffer function to build a paging buffer.
//
ntStatus = BuildPagingBuffer(hAdapter, ¶m);
// BuildPagingBuffer updates the size that is left in the
// paging buffer with the amount of bytes that were written.
//
if (NT_SUCCESS(ntStatus)) {
//
// If STATUS_SUCCESS, batch the paging buffer to the
// scheduler after multiple paging operations are batched.
}
else if (ntStatus == STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER) {
//
// If STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER, submit the current paging buffer to the scheduler to let
// the GPU start working on a partial transfer.
VidSchSubmitPagingBuffer(CurrentPagingBuffer, CurrentPagingBufferSizeLeft);
// Acquire a new paging buffer to complete the transfer.
//
VidMmAcquirePagingBuffer(&CurrentPagingBuffer, &CurrentPagingBufferSizeLeft);
}
else {
//
// A critical failure occurred, so bugcheck the system.
// This situation should never occur because the driver can
// fail the call only if it requires more DMA buffer space.
}
} while(!NT_SUCCESS(ntStatus))
Requisitos
Requisito | Valor |
---|---|
Cliente mínimo com suporte | Windows Vista |
Plataforma de Destino | Área de Trabalho |
Cabeçalho | d3dkmddi.h |
IRQL | PASSIVE_LEVEL |