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 na função MiniportDeviceContext da função DxgkDdiAddDevice.
[in/out] pBuildPagingBuffer
Um ponteiro para uma estrutura de DXGKARG_BUILDPAGINGBUFFER que contém informações para a criação de um buffer de paginação.
Valor de retorno
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). |
Observações
A função DxgkDdiBuildPagingBuffer é chamada para criar buffers de DMA (acesso direto à memória) de finalidade especial 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 gravar a instrução de GPU (unidade de processamento gráfico) apropriada no buffer de paginação fornecido (no pDmaBuffer membro do DXGKARG_BUILDPAGINGBUFFER) de acordo com a operação de paginação solicitada; e, em seguida, o driver deve retornar o buffer de paginação para o gerenciador de memória de vídeo (que faz parte do 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 multipassOffset membro do DXGKARG_BUILDPAGINGBUFFER e pode 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 a 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 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áginas.
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 subtransmissões (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 subtransmissão de uma alocação é marcada com o sinalizador TransferStart de campo de bits no Flags membro do Transfer membro do DXGKARG_BUILDPAGINGBUFFER; a última subtransmissão de uma alocação é marcada com o sinalizador TransferEnd campo de bits. O driver tem a garantia de receber o fim de uma transferência pendente (ou seja, a última subtransmissão) antes que o driver receba o início de uma nova transferência.
Cada subtransmissão pode exigir várias chamadas para DxgkDdiBuildPagingBuffer para concluir (por exemplo, o driver pode ficar sem espaço no 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 subtransmissões para a alocação exigem várias iterações (por exemplo, se o driver ficou sem espaço de buffer DMA). O driver pode usar o MultipassOffset membro do DXGKARG_BUILDPAGINGBUFFER para acompanhar o andamento de uma subtransposição específica entre várias iterações de DxgkDdiBuildPagingBuffer.
Normalmente, uma transferência ocorre em uma única operação. Nessa situação, os sinalizadores TransferStart e TransferEnd campo de bits são definidos.
Em alguns cenários, o driver pode ser necessário para configurar recursos de hardware quando determinadas alocações são paginados 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, em seguida, chame a função DxgkDdiBuildPagingBuffer do driver novamente. Na segunda chamada para DxgkDdiBuildPagingBuffer, o gerenciador de memória de vídeo define o sinalizador AllocationIsIdle bit-field no Flags membro do Transfer membro do 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 poderá 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 hAllocation membro do DXGKARG_BUILDPAGINGBUFFER for NULL, o driver deverá copiar os dados na origem para o destino sem executar nenhum swizzling ou bloco.
-
Encher
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 paginados 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, em seguida, chame a função DxgkDdiBuildPagingBuffer do driver novamente. Na segunda chamada para DxgkDdiBuildPagingBuffer, o gerenciador de memória de vídeo define o sinalizador AllocationIsIdle bit-field no Flags membro do DiscardContent membro 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 poderá 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 da memória AGP depois que a GPU grava nessa memória AGP, a operação de leitura-física é essencial para garantir a coerência de memória.
-
Gravar físico
A operação de gravação física é 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 da memória AGP depois que a GPU grava nessa memória AGP, a operação de gravação-física é essencial para garantir a coerência de memória.
-
Segmento de abertura de mapa
A operação map-aperture-segment mapeia uma MDL (lista de descritores de memória) especificada para um segmento de abertura especificado em um deslocamento de segmento especificado para um número especificado de páginas. Se o cacheCoherent sinalizador de campo de bits estiver definido no Flags membro do MapApertureSegment membro da estrutura DXGKARG_BUILDPAGINGBUFFER, o driver deverá garantir que a coerência de cache seja imposta nas páginas mapeadas; caso contrário, a coerência de cache não é necessária para as páginas mapeadas.
Observação o sinalizador cacheCoherent somente é definido quando a memória em cache está sendo mapeada para um segmento de abertura coerente com 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 com cache. -
Segmento de abertura não mapeado
A operação unmap-aperture-segment descompacta um intervalo mapeado anteriormente de um segmento de abertura especificado. O driver deve mapear o intervalo não mapeado para a página fictícia que o DummyPage membro do UnmapApertureSegment membro da estrutura DXGKARG_BUILDPAGINGBUFFER especifica.
Observação Quando o driver não for mapeado para a página fictícia, o driver deve habilitar 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 verificar 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 ou para o endereço virtual alternativo que foi configurado para a alocação quando a função pfnLockCb foi chamada com o UseAlternateVA conjunto de sinalizadores de campo de bit.
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 colocada de volta.
Em alguns cenários, o driver pode ser necessário para configurar recursos de hardware quando determinadas alocações são paginados 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, em seguida, chame a função DxgkDdiBuildPagingBuffer do driver novamente. Na segunda chamada para DxgkDdiBuildPagingBuffer, o gerenciador de memória de vídeo define o sinalizador AllocationIsIdle bit-field no Flags membro do SpecialLockTransfer membro 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 poderá 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 ficar 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 |
---|---|
de cliente com suporte mínimo | Windows Vista |
da Plataforma de Destino | Área de trabalho |
cabeçalho | d3dkmddi.h |
IRQL | PASSIVE_LEVEL |