DXGKDDI_BUILDPAGINGBUFFER funzione di callback (d3dkmddi.h)
La funzione DxgkDdiBuildPagingBuffer compila buffer di paging per le operazioni di memoria.
Sintassi
DXGKDDI_BUILDPAGINGBUFFER DxgkddiBuildpagingbuffer;
NTSTATUS DxgkddiBuildpagingbuffer(
[in] IN_CONST_HANDLE hAdapter,
[in/out] IN_PDXGKARG_BUILDPAGINGBUFFER pBuildPagingBuffer
)
{...}
Parametri
[in] hAdapter
Handle a un blocco di contesto associato a una scheda di visualizzazione. Il driver miniport visualizzato in precedenza ha fornito questo handle al sottosistema kernel della grafica Microsoft DirectX nel parametro di output MiniportDeviceContext della funzione DxgkDdiAddDevice .
[in/out] pBuildPagingBuffer
Puntatore a una struttura DXGKARG_BUILDPAGINGBUFFER che contiene informazioni per la creazione di un buffer di paging.
Valore restituito
DxgkDdiBuildPagingBuffer restituisce uno dei valori seguenti:
Codice restituito | Descrizione |
---|---|
STATUS_SUCCESS | DxgkDdiBuildPagingBuffersuccess in modo predefinito un buffer di paging. |
STATUS_GRAPHICS_ALLOCATION_BUSY | La GPU usa attualmente l'allocazione per il buffer di paging. |
STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER | È necessario più spazio nel buffer di paging, ovvero nel membro pDmaBuffer della struttura DXGKARG_BUILDPAGINGBUFFER a cui punta il parametro pBuildPagingBuffer. |
Commenti
La funzione DxgkDdiBuildPagingBuffer viene chiamata per creare buffer DMA (Special Purpose Direct Memory Access) noti come buffer di paging. Un buffer di paging contiene un'operazione che sposta il contenuto delle parti delle allocazioni:
- All'interno di un segmento di un'allocazione.
- Tra segmenti di allocazioni.
- Da un segmento di un'allocazione alla memoria di sistema.
- Dalla memoria di sistema a un segmento di un'allocazione.
Il driver miniport di visualizzazione deve scrivere le istruzioni appropriate per l'unità di elaborazione grafica (GPU) nel buffer di paging fornito (nel membro pDmaBuffer di DXGKARG_BUILDPAGINGBUFFER) in base all'operazione di paging richiesta; e quindi il driver deve restituire il buffer di paging alla gestione memoria video (che fa parte di Dxgkrnl.sys). L'utilità di pianificazione GPU (che fa parte anche di Dxgkrnl.sys) chiama successivamente la funzione DxgkDdiSubmitCommand del driver per richiedere che il driver invii il buffer di paging come buffer DMA normale alla GPU.
Se DxgkDdiBuildPagingBuffer determina che un'operazione di paging richiede più buffer di paging, il driver può specificare informazioni nel membro MultipassOffset di DXGKARG_BUILDPAGINGBUFFER e può usare queste informazioni tra più iterazioni dell'operazione di paging. La gestione memoria video inizializza le informazioni in MultipassOffset su zero prima della prima richiesta di paging dell'operazione e non modifica le informazioni in MultipassOffset tra iterazioni. Pertanto, il driver può usare MultipassOffset per salvare lo stato di avanzamento tra iterazioni. Ad esempio, il driver può archiviare il numero di pagina che è stato trasferito per un trasferimento basato su pagine.
Un buffer di paging è attualmente compilato per i tipi di operazioni seguenti:
-
Trasferimento
L'operazione di trasferimento sposta il contenuto di un'allocazione da una posizione a un'altra. Questa operazione è il tipo più comune di operazione di memoria.
Un'allocazione viene sempre trasferita interamente da una posizione a un'altra. Tuttavia, a causa dei vincoli di memoria, il trasferimento di un'allocazione può essere suddiviso in più trasferimenti secondari, ovvero una parte dell'allocazione viene spostata dalla posizione A a B e quindi la parte seguente viene spostata e così via, fino a quando l'intera allocazione non viene trasferita. Il primo trasferimento secondario di un'allocazione è contrassegnato con il flag di campo bit TransferStart nel membro Flags del membro Transfer di DXGKARG_BUILDPAGINGBUFFER; l'ultimo trasferimento secondario di un'allocazione è contrassegnato con il flag di campo a bit TransferEnd . Il driver è garantito di ricevere la fine di un trasferimento in sospeso (ovvero l'ultimo trasferimento secondario) prima che il driver riceva l'inizio di un nuovo trasferimento.
Ogni sub-transfer potrebbe richiedere più chiamate a DxgkDdiBuildPagingBuffer per completare (ad esempio, il driver potrebbe essere esaurito dallo spazio del buffer DMA). Pertanto, il driver potrebbe ricevere il flag TransferStart in più chiamate a DxgkDdiBuildPagingBuffer finché il driver riceve il flag TransferEnd in una chiamata a DxgkDdiBuildPagingBuffer. La ricezione del flag TransferStart più volte non indica l'inizio di più nuovi trasferimenti; indica che i trasferimenti secondari per l'allocazione richiedono più iterazioni, ad esempio se il driver ha esaurito lo spazio del buffer DMA. Il driver può usare il membro MultipassOffset di DXGKARG_BUILDPAGINGBUFFER per tenere traccia dello stato di avanzamento per un determinato trasferimento secondario tra più iterazioni di DxgkDdiBuildPagingBuffer.
In genere, un trasferimento si verifica in una singola operazione. In questa situazione, vengono impostati sia i flag transferStart che TransferEnd bit-field.
In alcuni scenari, il driver potrebbe essere necessario per configurare le risorse hardware quando alcune allocazioni vengono impaginate o non in memoria. Per impostazione predefinita, la GPU potrebbe usare l'allocazione a cui viene fatto riferimento durante la chiamata a DxgkDdiBuildPagingBuffer. In questi scenari, il driver potrebbe richiedere che l'allocazione sia inattiva prima che i programmi driver le risorse hardware necessarie, ovvero la programmazione delle risorse hardware non può essere accodata nel buffer DMA fornito. Per tali scenari, il driver può non riuscire la chiamata a DxgkDdiBuildPagingBuffer con STATUS_GRAPHICS_ALLOCATION_BUSY.
Se il driver restituisce STATUS_GRAPHICS_ALLOCATION_BUSY, la gestione memoria video attende fino a quando la GPU non viene eseguita con qualsiasi riferimento all'allocazione corrente e quindi chiama nuovamente la funzione DxgkDdiBuildPagingBuffer del driver. Nella seconda chiamata a DxgkDdiBuildPagingBuffer, la gestione memoria video imposta il flag di campo bit AllocationIsIdle nel membro Flag del membro Transfer di DXGKARG_BUILDPAGINGBUFFER per indicare che l'allocazione a cui viene fatto riferimento è inattiva. Se il flag inattiva non è impostato, il driver deve sempre determinare che l'allocazione è attualmente occupato o potrebbe presto diventare occupato. Se il flag inattivo è impostato, la gestione memoria video garantisce che l'allocazione a cui viene fatto riferimento rimanga inattiva per la durata della chiamata a DxgkDdiBuildPagingBuffer.
Se il membro hAllocation di DXGKARG_BUILDPAGINGBUFFER è NULL, il driver deve copiare i dati nell'origine nella destinazione senza eseguire alcuna scorrimento o tiling.
-
Fill
L'operazione di riempimento riempie un'allocazione con un modello specificato. L'operazione di riempimento viene usata per configurare il contenuto iniziale di un'allocazione. Quando il contenuto dell'allocazione viene riempito, l'allocazione deve essere inattiva, ovvero non in uso dalla GPU. L'operazione di riempimento può essere eseguita solo in un segmento di memoria. La gestione memoria video non richiede mai che il driver miniport visualizzato riempia un segmento di apertura.
-
Eliminare il contenuto
L'operazione di eliminazione del contenuto notifica al driver che un'allocazione viene eliminata dalla posizione corrente dell'allocazione in un segmento di memoria. Ovvero, l'allocazione viene rimossa e non copiata nella memoria di sistema.
In alcuni scenari, il driver potrebbe essere necessario per configurare le risorse hardware quando alcune allocazioni vengono impaginate o non in memoria. Per impostazione predefinita, la GPU potrebbe usare l'allocazione a cui viene fatto riferimento durante la chiamata a DxgkDdiBuildPagingBuffer. In questi scenari, il driver potrebbe richiedere che l'allocazione sia inattiva prima che i programmi driver le risorse hardware necessarie, ovvero la programmazione delle risorse hardware non può essere accodata nel buffer DMA fornito. Per tali scenari, il driver può non riuscire la chiamata a DxgkDdiBuildPagingBuffer con STATUS_GRAPHICS_ALLOCATION_BUSY.
Se il driver restituisce STATUS_GRAPHICS_ALLOCATION_BUSY, la gestione memoria video attende fino a quando la GPU non viene eseguita con qualsiasi riferimento all'allocazione corrente e quindi chiama nuovamente la funzione DxgkDdiBuildPagingBuffer del driver. Nella seconda chiamata a DxgkDdiBuildPagingBuffer, la gestione memoria video imposta il flag di campo bit AllocationIsIdle nel membro Flags del membro DiscardContentdella struttura DXGKARG_BUILDPAGINGBUFFER per indicare che l'allocazione a cui si fa riferimento è inattiva. Se il flag inattiva non è impostato, il driver deve sempre determinare che l'allocazione è attualmente occupato o potrebbe presto diventare occupato. Se il flag inattivo è impostato, la gestione memoria video garantisce che l'allocazione a cui viene fatto riferimento rimanga inattiva per la durata della chiamata a DxgkDdiBuildPagingBuffer.
-
Lettura fisica
L'operazione di lettura-fisica legge da un indirizzo di memoria fisica specificato. Il driver viene richiesto di programmare la GPU per l'operazione. Le dimensioni della memoria fisica a cui accedere per la lettura possono essere da 1 byte a 8 byte. Poiché i dati letti sono irrilevanti, DxgkDdiBuildPagingBuffer non è necessario per restituire i dati. Tuttavia, negli scenari in cui la CPU tenta di leggere dalla memoria AGP dopo che la GPU scrive in tale memoria AGP, l'operazione di lettura fisica è fondamentale per garantire la coesistenza della memoria.
-
Scrittura fisica
L'operazione fisica di scrittura scrive in un indirizzo fisico specificato. Il driver viene richiesto di programmare la GPU per l'operazione. Le dimensioni della memoria fisica a cui accedere per l'operazione di scrittura possono essere da 1 byte a 8 byte. Poiché i dati scritti sono irrilevanti, DxgkDdiBuildPagingBuffer può scrivere tutti i dati nella memoria. Tuttavia, negli scenari in cui la CPU tenta di leggere dalla memoria AGP dopo che la GPU scrive in tale memoria AGP, l'operazione fisica di scrittura è fondamentale per garantire la coesistenza della memoria.
-
Segmento di apertura mappa
L'operazione map-aperture-segmento esegue il mapping di un elenco di descrittori di memoria (MDL) specificato in un segmento di apertura specificato in corrispondenza di un offset di segmento specificato per un numero specificato di pagine. Se il flag di campo bitcoherent CacheCoherent è impostato nel membro Flags del membro MapApertureSegment della struttura DXGKARG_BUILDPAGINGBUFFER , il driver deve assicurarsi che la coherency della cache venga applicata nelle pagine mappate; in caso contrario, la coesistenza della cache non è necessaria per le pagine mappate.
Nota Il flag di campo bitcoherent CacheCoherent viene impostato solo quando la memoria memorizzata nella cache viene mappata in un segmento di apertura coerente con la cache e non viene mai impostato su un segmento di apertura coerente con cache o su un'allocazione combinata di scrittura mappata in un segmento coerente della cache. -
Segmento di apertura di unmap
L'operazione unmap-aperture-segmento annulla il mapping di un intervallo precedentemente mappato di un segmento di apertura specificato. Il driver deve eseguire il mapping dell'intervallo non mappato alla pagina fittizia specificata dal membro DummyPage del membro UnmapApertureSegmentdella struttura DXGKARG_BUILDPAGINGBUFFER.
Nota Quando il driver annulla il mapping alla pagina fittizia, il driver deve abilitare gli accessi GPU tramite l'intervallo di apertura specificato in modo che il sottosistema del kernel della grafica DirectX possa rilevare problemi di danneggiamento. I test di conformità esistono per verificare questa situazione.Il driver può facoltativamente usare MMIO per configurare un segmento di apertura. La GPU non accederà all'intervallo di apertura in fase di configurazione. Tuttavia, questa configurazione dell'apertura non deve interferire con l'esecuzione della GPU. La GPU non sarà inattiva quando dxgkDdiBuildPagingBuffer viene chiamato con il set di tipi di operazione DXGK_OPERATION_UNMAP_APERTURE_SEGMENT e la GPU potrebbe essere occupato ad accedere ad altre parti del segmento di apertura che viene riconfigurato.
-
Trasferimento con blocco speciale
L'operazione di trasferimento speciale è simile all'operazione di trasferimento regolare. Tuttavia, invece di trasferire il contenuto dell'allocazione dall'archivio di backup regolare dell'allocazione, l'operazione di trasferimento speciale trasferisce il contenuto dell'allocazione da o all'indirizzo virtuale alternativo configurato per l'allocazione quando la funzione pfnLockCb è stata chiamata con il flag di bit UseAlternateVA impostato.
L'operazione di trasferimento speciale si verifica solo in uno degli scenari seguenti:
- L'allocazione è attualmente accessibile dalla CPU con un indirizzo virtuale alternativo e viene rimossa.
- Un'allocazione precedentemente rimossa, ad esempio la situazione descritta nel punto elenco precedente, viene riscritto.
In alcuni scenari, il driver potrebbe essere necessario per configurare le risorse hardware quando alcune allocazioni vengono impaginate o non in memoria. Per impostazione predefinita, la GPU potrebbe usare l'allocazione a cui viene fatto riferimento durante la chiamata a DxgkDdiBuildPagingBuffer. In questi scenari, il driver potrebbe richiedere che l'allocazione sia inattiva prima che i programmi driver le risorse hardware necessarie, ovvero la programmazione delle risorse hardware non può essere accodata nel buffer DMA fornito. Per tali scenari, il driver può non riuscire la chiamata a DxgkDdiBuildPagingBuffer con STATUS_GRAPHICS_ALLOCATION_BUSY.
Se il driver restituisce STATUS_GRAPHICS_ALLOCATION_BUSY, la gestione memoria video attende fino a quando la GPU non viene eseguita con qualsiasi riferimento all'allocazione corrente e quindi chiama nuovamente la funzione DxgkDdiBuildPagingBuffer del driver. Nella seconda chiamata a DxgkDdiBuildPagingBuffer, la gestione memoria video imposta il flag di campo bit AllocationIsIdle nel membro Flags del membro SpecialLockTransfer della struttura DXGKARG_BUILDPAGINGBUFFER per indicare che l'allocazione a cui viene fatto riferimento è inattiva. Se il flag inattiva non è impostato, il driver deve sempre determinare che l'allocazione è attualmente occupato o potrebbe presto diventare occupato. Se il flag inattivo è impostato, la gestione memoria video garantisce che l'allocazione a cui viene fatto riferimento rimanga inattiva per la durata della chiamata a DxgkDdiBuildPagingBuffer.
Gestione memoria del sistema garantisce che il trasferimento sia invisibile all'applicazione. Tuttavia, poiché l'allocazione è in memoria di sistema e l'indirizzo virtuale dell'allocazione non può più passare dall'apertura hardware, il driver deve garantire che l'ordinamento di byte nella memoria di sistema corrisponda a ciò che era visibile tramite l'apertura.
DxgkDdiBuildPagingBuffer deve essere reso paginabile.
Esempio
Nell'esempio di codice seguente viene illustrato come usare 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))
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Windows Vista |
Piattaforma di destinazione | Desktop |
Intestazione | d3dkmddi.h |
IRQL | PASSIVE_LEVEL |