PFND3DDDI_LOCKCB funzione di callback (d3dumddi.h)
La funzione pfnLockCb blocca un'allocazione e ottiene un puntatore all'allocazione dal driver miniport visualizzato o dal gestore di memoria video.
Sintassi
PFND3DDDI_LOCKCB Pfnd3dddiLockcb;
HRESULT Pfnd3dddiLockcb(
HANDLE hDevice,
D3DDDICB_LOCK *unnamedParam2
)
{...}
Parametri
hDevice
Handle per il dispositivo di visualizzazione (contesto grafico).
unnamedParam2
pData [in, out]
Puntatore a una struttura D3DDDICB_LOCK che descrive l'allocazione per bloccare.
Valore restituito
pfnLockCb restituisce uno dei valori seguenti:
Codice restituito | Descrizione |
---|---|
S_OK | L'allocazione è stata bloccata correttamente. |
D3DERR_NOTAVAILABLE | Non era disponibile un'apertura. |
D3DERR_WASSTILLDRAWING | L'allocazione è ancora in uso per il rendering. |
D3DDDIERR_CANTEVICTPINNEDALLOCATION | Impossibile bloccare l'allocazione a causa dell'indisponibilità di un'apertura deswizzling e dell'impossibilità di eliminare l'allocazione perché è stata aggiunta. |
E_OUTOFMEMORY | PfnLockCb non è stato possibile completare a causa di memoria insufficiente (questa situazione si verifica quando il sistema si trova in una situazione di memoria estremamente bassa e non è disponibile spazio sufficiente per allocare la matrice di pagine). |
E_INVALIDARG | I parametri sono stati convalidati e determinati per essere non corretti. |
D3DDDIERR_DEVICEREMOVED | PfnLockCb non è riuscito a causare l'esecuzione del driver di miniport e della gestione della memoria video per eseguire le azioni appropriate perché si è verificato un arresto di Plug and Play (PnP) o un evento TDR (Timeout Detection and Recovery). La funzione del driver di visualizzazione in modalità utente denominata pfnLockCb(in genere, la funzione Lock o ResourceMap ) deve restituire il codice di errore al runtime Direct3D. Direct3D versione 9 Nota: per altre informazioni sulla restituzione di codici di errore, vedere Restituzione di codici di errore ricevuti da Funzioni di runtime. Direct3D versioni 10 e 11 Nota: se la funzione driver non restituisce un valore , ovvero void per un tipo di parametro restituito, la funzione driver chiama la funzione pfnSetErrorCb per inviare nuovamente un codice di errore al runtime. Per altre informazioni sulla gestione dei codici di errore, vedere Gestione degli errori. |
Questa funzione potrebbe anche restituire altri valori HRESULT.
Commenti
Il driver di visualizzazione in modalità utente può chiamare la funzione pfnLockCb del runtime di Microsoft Direct3D per bloccare un'allocazione e ottenere un puntatore all'allocazione dal driver miniport visualizzato o dalla gestione memoria video. Il driver di visualizzazione in modalità utente chiama in genere pfnLockCb in risposta a una chiamata alla funzione Lock o ResourceMap (o altre varianti di ResourceMap , ad esempio DynamicIABufferMapDiscard) per bloccare una risorsa o una superficie all'interno della risorsa. Prima di restituire dalla chiamata Lock o ResourceMap , il driver di visualizzazione in modalità utente deve prima eseguire il mapping della risorsa o della superficie all'allocazione appropriata e quindi chiamare pfnLockCb per bloccare l'allocazione. L'allocazione deve essere bloccata prima di poter essere letti da o scritti in perché il blocco:
- Garantisce che l'intervallo di indirizzi virtuali per l'allocazione rimanga invariato, valido, leggibile e scrivibile per la durata del blocco. La gestione memoria video offre questa garanzia.
- Consente di sincronizzare le operazioni di lettura e scrittura dell'allocazione con gli accessi hardware grafici dell'allocazione. La gestione della memoria video e il driver miniport visualizzano eseguire la sincronizzazione.
Il driver di visualizzazione in modalità utente chiama in genere le funzioni pfnLockCb e pfnUnlockCb che corrispondono a ogni chiamata alle funzioni Blocco eSblocco, rispettivamente, tranne quando il driver gestisce le risorse in cui è stato impostato il flag di campo a bit dinamico nel membro Flag della struttura D3DDDIARG_CREATERESOURCE quando sono state create le risorse. Il runtime richiede spesso che il driver blocchi questi tipi di risorse, spesso con il flag di campo a bit NoOverwrite impostato nel membro Flag della struttura D3DDDIARG_LOCK . Poiché i dati in tali risorse non devono essere modificati (come indicato da NoOverwrite), chiamando pfnLockCb per ogni richiesta di blocco utilizza un tempo di elaborazione eccessivo. Per evitare di chiamare pfnLockCb per ogni richiesta di blocco, il driver può memorizzare nella cache il puntatore alla memoria virtuale restituito nel membro pSurfData di D3DDDIARG_LOCK quando viene chiamata la funzione Lock con il flag di bit NoOverwrite impostato. Tuttavia, il driver può continuare a chiamare pfnLockCb ogni volta che viene chiamata la sua funzione Lock con il set di flag di bit di eliminazione o nessun flag impostato.
Nota delle versioni Direct3D 10 e 11:
Il driver di visualizzazione in modalità utente chiama in genere le funzioni pfnLockCb e pfnUnlockCb che corrispondono a ogni chiamata alle funzioni ResourceMap e ResourceUnmap (o altre varianti di queste funzioni). Ciò non avviene quando il driver gestisce le risorse in cui è stato impostato il valore di D3D10_DDI_USAGE_DYNAMIC nel membro Utilizzodella struttura D3D10DDIARG_CREATERESOURCE o D3D11DDIARG_CREATERESOURCE quando sono state create le risorse. Il runtime richiede spesso che il driver blocchi questi tipi di risorse, spesso passando il valore D3D10_DDI_MAP_WRITE_NOOVERWRITE al parametro DDIMap nella chiamata a ResourceMap. Poiché i dati in tali risorse non devono essere modificati (come indicato da D3D10_DDI_MAP_WRITE_NOOVERWRITE), la chiamata di pfnLockCb per ogni richiesta di blocco utilizza un tempo di elaborazione eccessivo. Per impedire la chiamata a pfnLockCb per ogni richiesta di blocco, il driver può memorizzare nella cache il puntatore alla memoria virtuale restituito nel parametro pMappedSubResource quando viene chiamata la funzione ResourceMap con D3D10_DDI_MAP_WRITE_NOOVERWRITE. Tuttavia, il driver può continuare a chiamare pfnLockCb ogni volta che viene chiamata la funzione ResourceMap con il valore D3D10_DDI_MAP_WRITE_DISCARD o 0 passato al parametro DDIMap .
Sebbene l'applicazione non contenga un blocco in sospeso alla risorsa associata al puntatore alla memoria virtuale, il driver in genere annulla il puntatore alla memoria virtuale chiamando la funzione pfnUnlockCb prima che il driver chiami la funzione pfnRenderCb . Se il blocco non è bloccato o se il blocco non può essere bloccato perché l'applicazione ha ancora la risorsa bloccata, l'hardware potrebbe eseguire il rendering da un'allocazione bloccata. La gestione memoria video non può supportare questa modalità di operazione se l'allocazione è in memoria video locale; pertanto, gestione memoria espelle l'allocazione al sistema o alla memoria AGP quando la gestione memoria rileva questa situazione. Se l'allocazione non è supportata nel segmento di memoria di sistema o AGP, la gestione memoria non riesce la chiamata a pfnRenderCb con D3DDDIERR_CANTRENDERLOCKEDALLOCATION. Pertanto, le allocazioni del vertice e del buffer di indice allocati in risposta alla creazione di risorse in cui il flag di campo a bit dinamico è impostato nel membro Flag di D3DDDIARG_CREATERESOURCE (o il valore D3D10_DDI_USAGE_DYNAMIC viene impostato nel membro Utilizzo di D3D10DDIARG_CREATERESOURCE o D3D11DDIARG_CREATERESOURCE) deve essere supportato nei segmenti di sistema o AGP.
Se si imposta il flag di campo a bit di eliminazione nel membro Flag di D3DDDICB_LOCK in una chiamata a pfnLockCb , la gestione memoria video crea una nuova istanza dell'allocazione bloccata. Gestione memoria video rappresenta la nuova istanza restituendo un nuovo handle al driver di visualizzazione in modalità utente nel membro hAllocation di D3DDDICB_LOCK.
Dopo aver scaricato il buffer dei comandi, il driver di visualizzazione in modalità utente deve provare a bloccare di nuovo la superficie usando sia i flag Di eliminazione che NoExistingReference . Il flag di campo di bit NoExistingReference indica alla gestione memoria video che il driver attualmente non ha un riferimento a nessuna istanza dell'allocazione bloccata nel buffer dei comandi. Gestione memoria video può quindi riutilizzare qualsiasi istanza dell'allocazione per gestire il blocco, inclusa l'istanza corrente.
Dopo una chiamata a pfnLockCb in cui è impostato il flag di campo di bit di eliminazione , il driver di visualizzazione in modalità utente deve sempre controllare la presenza di un valore di handle aggiornato nel membro hAllocation di D3DDDICB_LOCK. Se viene fornito un nuovo handle di allocazione, il driver di visualizzazione in modalità utente deve aggiornare la struttura dati interna per fare riferimento al nuovo handle di allocazione. Il driver di visualizzazione in modalità utente deve anche aggiungere una versione riprogrammata dell'indirizzo di base di allocazione bloccata al buffer di comando corrente(perché le istanze di allocazione contengono indirizzi di base diversi). La gestione memoria video convalida l'uso delle istanze di allocazione usate dal driver e rifiuta i buffer DMA che usano le istanze di allocazione in modo errato, ovvero chiamate a pfnPresentCb e pfnRenderCb non riescono se usano in modo errato le istanze di allocazione. Dopo che il driver fa riferimento a una determinata istanza di un'allocazione, il driver non può più fare riferimento a un'istanza precedente della stessa allocazione. Ad esempio, se un buffer di comandi usa l'allocazione A e attualmente usa istanze A0 e A1, non appena viene usato A1 ,ovvero nell'elenco di patch-location, A0 diventa non valido. Il driver miniport visualizzato può generare un elenco di patch che fa riferimento sia A0 che A1. Tuttavia, i riferimenti devono essere ordinati ( ovvero, A0 può essere usato prima; A0 diventa non valido dopo l'uso di A2; A1 diventa non valido quando viene usato A2 e così via.
Il driver di visualizzazione in modalità utente potrebbe chiamare pfnLockCb per le allocazioni di memoria di sistema, anche se la memoria non è stata preallocata, perché il driver miniport visualizzato potrebbe effettivamente essere nel processo di invio, tramite DMA o trasferimento asincrono di tali allocazioni all'hardware grafico. Pertanto, prima che un'applicazione possa scrivere nella superficie, il driver miniport visualizzato e la gestione memoria video devono essere notificati in modo che possano bloccare il blocco se necessario.
Il driver di visualizzazione in modalità utente può anche bloccare le sottoregioni di un'allocazione. Questo tipo di blocco non è in genere necessario quando è disponibile un'apertura hardware senza interruzione o lineare perché, in questa situazione, il driver di visualizzazione in modalità utente può tradurre un blocco sull'intera allocazione nella sottoregion offsetndo il puntatore. Tuttavia, quando pfnLockCb ha esito negativo usando D3DERR_NOTAVAILABLE per indicare che un'apertura non è disponibile, la gestione memoria richiede al driver di visualizzazione in modalità utente di copiare il contenuto della memoria video. Il driver di visualizzazione in modalità utente non visualizza o linearizza il contenuto della memoria video durante la copia in un'altra area di memoria. In questo caso, il driver di visualizzazione in modalità utente può fornire un elenco di pagine da copiare per risparmiare grandi quantità di copia durante il blocco di piccole sottoregioni in un'allocazione di grandi dimensioni. Si noti che la gestione memoria ha esito negativo una chiamata a pfnLockCb con D3DERR_NOTAVAILABLE se il driver di visualizzazione in modalità utente non ha impostato il flag di campo lockEntire nel membro Flag della struttura D3DDDICB_LOCK e non ha specificato un elenco di pagine nel membro pPages di D3DDDICB_LOCK. Se il driver di visualizzazione in modalità utente imposta rispettivamente il flag di campo a bit LockEntire , deve impostare rispettivamente i membri NumPages e pPages di D3DDDICB_LOCK su 0 e NULL. Il driver di visualizzazione in modalità utente deve sempre fornire un elenco di pagine in pPages durante il blocco di un'allocazione creata con un archivio di backup permanente. In questo caso, gestione memoria usa l'elenco di pagine per contrassegnare come sporchi solo pagine specifiche e non è necessario copiare l'intera allocazione dall'archivio di backup quando viene usato per il rendering.
Il driver di visualizzazione in modalità utente può chiamare pfnLockCb per acquisire più intervalli di scorrimento per una singola allocazione(ad esempio, un intervallo di scorrimento per ogni livello MIP). Se il driver non può acquisire uno degli intervalli, il runtime Direct3D elimina l'intera allocazione per gestire il blocco (tutti i livelli MIP) e recupera tutti gli intervalli di scorrimento.
Quando il driver di visualizzazione in modalità utente richiede che venga assegnato un intervallo di scorrimento all'allocazione, il driver richiede in modo efficace l'accesso ai bit nonwizzled dell'allocazione. Per tali richieste, la gestione memoria video nell'allocazione in un segmento di memoria e imposta un intervallo di scorrimento per accedere all'allocazione o alle pagine nell'allocazione in un segmento di memoria e quindi elimina l'allocazione nella memoria di sistema mentre richiede che il driver annulla l'allocazione nel modo in cui la memoria di sistema. Un'allocazione non swizzled alla memoria di sistema è reswizzled (eseguendo la pagina nella memoria video) prima che la GPU usi nuovamente l'allocazione. Di conseguenza, il driver non può richiedere un blocco senza sovrascrivere (impostando il flag di campo bit DonotWait ) quando acquisisce un intervallo di scorrimento. Analogamente, il driver non può fare riferimento a un blocco di allocazione in modo tale in un buffer DMA inviato alla GPU (perché il buffer DMA verrà rifiutato).
Il driver di visualizzazione in modalità utente potrebbe bloccare un'allocazione swizzled senza acquisire un intervallo di scorrimento se il driver deve accedere ai bit dell'allocazione in un formato swizzled. In questa situazione, la gestione memoria video fornisce al driver un puntatore ai bit swizzled dell'allocazione. Tuttavia, il driver non può richiedere un puntatore ai bit swizzled dell'allocazione mentre una richiesta per i bit nonwizzled è in sospeso e viceversa (ovvero un blocco è attualmente in sospeso sull'allocazione con un intervallo di scorrimento acquisito).
Il driver di visualizzazione in modalità utente deve passare il flag di campo di bit Discard nel membro Flags di D3DDDICB_LOCK nella chiamata pfnLockCb nelle situazioni seguenti:
- Quando il runtime Direct3D passa il flag di campo di bit Discard nel membro Flags della struttura D3DDDIARG_LOCK nella chiamata alla funzione Lock del driver di visualizzazione in modalità utente
- Quando il runtime passa il valore D3D10_DDI_MAP_WRITE_DISCARD al parametro DDIMap nella chiamata alla funzione ResourceMap del driver
Nell'esempio di codice seguente viene illustrato come viene usato il flag di campo di bit Discard in una chiamata a pfnLockCb.
HRESULT hr;
D3DDDICB_LOCK LockData;
LockData.hAllocation = AllocationToLock;
LockData.Flags.Discard = TRUE;
hr = pfnLockCb(&LockData)
if (FAILED(hr)) {
FlushAccumulatedCommandBufferToKernel();
LockData.Flags.Discard = TRUE;
LockData.Flags.NoExistingReference = TRUE;
hr = pfnLockCb(&LockData);
if (FAILED(hr)) {
// Fails the lock to the application
}
}
UpdateAllocationHandleInUMDDataStructure(LockData.hAllocation);
ProgramSurfaceBaseAddressInCurrentCommandBuffer(LockData.hAllocation);
Requisiti
Requisito | Valore |
---|---|
Client minimo supportato | Disponibile in Windows Vista e versioni successive dei sistemi operativi Windows. |
Piattaforma di destinazione | Desktop |
Intestazione | d3dumddi.h (include D3dumddi.h) |