Condividi tramite


Modifiche da Direct3D 10

Questa sezione si applica solo a Windows 7 e versioni successive e Windows Server 2008 R2 e versioni successive del sistema operativo Windows.

Le sezioni seguenti descrivono come Direct3D 11 è cambiato da Direct3D 10.

Funzioni di callback del driver per Kernel-Mode Services

Le funzioni di callback specifiche del dispositivo fornite dal runtime Direct3D versione 11 nella struttura D3DDDI_DEVICECALLBACKS quando il runtime chiama la funzione CreateDevice(D3D10) del driver di visualizzazione in modalità utente isolare il driver dagli handle del kernel e dalle firme della funzione kernel. Il runtime Direct3D versione 11 modifica la semantica di callback e, pertanto, l'implementazione delle funzioni di callback per supportare una modalità di funzionamento a thread libero, mentre i runtime di versione Direct3D precedenti non supportavano una modalità di funzionamento a thread libero. Le regole per l'operazione in modalità thread libero si applicano dopo che il driver indica che supporta la modalità a thread libero (D3D11DDICAPS_FREETHREADED); in caso contrario, si applicano le regole fortemente limitate precedenti. Per informazioni sul modo in cui il driver indica il supporto per la modalità a thread libero, vedere Threading e elenchi di comandi. Esistono ancora le restrizioni seguenti per Direct3D versione 11:

  • Solo un singolo thread può funzionare su un HCONTEXT alla volta. Le funzioni di callback esistenti che attualmente usano un HCONTEXT sono pfnPresentCb, pfnRenderCb, pfnEscapeCb, pfnDestroyContextCb, pfnWaitForSynchronizationObjectCb e pfnSignalSynchronizationObjectCb. Pertanto, se più di un thread chiamano queste funzioni di callback e usano lo stesso HCONTEXT, il driver deve sincronizzare le chiamate alle funzioni di callback. Soddisfare questo requisito è piuttosto naturale perché è probabile che queste funzioni di callback vengano chiamate solo dal thread che modifica il contesto immediato.

  • Il driver deve chiamare le funzioni di callback seguenti solo durante le chiamate alle funzioni driver seguenti usando gli stessi thread che chiamano tali funzioni driver:

  • La funzione di callback pfnDeallocateCb merita una menzione speciale perché il driver non è necessario chiamare pfnDeallocateCb prima che il driver restituisca dalla funzione DestroyResource(D3D10) per la maggior parte dei tipi di risorse. Poiché DestroyResource(D3D10) è una funzione a thread libero, il driver deve rinviare la distruzione dell'oggetto fino a quando il driver non può garantire che il riferimento immediato esistente rimanga , ovvero il driver deve chiamare pfnRenderCb prima di pfnDeallocateCb. Questa restrizione si applica anche alle risorse condivise o a qualsiasi altra funzione di callback che usa HRESOURCE per integrare l'utilizzo di HRESOURCE con pfnAllocateCb. Tuttavia, questa restrizione non si applica ai primari. Per altre informazioni sulle eccezioni primarie, vedere Eccezioni primarie. Poiché alcune applicazioni potrebbero richiedere l'aspetto della distruzione sincrona, il driver deve assicurarsi che chiami pfnDeallocateCb per tutte le risorse condivise precedentemente eliminate durante una chiamata alla relativa funzione Flush(D3D10). Un driver deve anche pulire tutti gli oggetti eliminati in precedenza (solo quelli che non bloccano la pipeline) durante una chiamata alla relativa funzione Flush(D3D10); Il driver deve farlo per garantire che il runtime chiami Flush(D3D10) come meccanismo ufficiale per pulire gli oggetti eliminati eliminati posticipati per le poche applicazioni che potrebbero richiedere un meccanismo di questo tipo. Per altre informazioni su questo meccanismo, vedere Distruzione posticipata e Scaricamento (D3D10). Il driver deve anche assicurarsi che tutti gli oggetti per cui è stata posticipata la distruzione vengano eliminati completamente prima che la funzione DestroyDevice(D3D10) del driver restituisca durante la pulizia.

Possibilità di deprecare la possibilità di consentire la modifica di Free-Threaded DDI

Per Direct3D versione 11, il concetto a livello di API di un dispositivo di visualizzazione e un contesto immediato sono ancora raggruppati a livello DDI dal concetto legacy di un dispositivo di visualizzazione. Questo raggruppamento di dispositivi di visualizzazione e contesto immediato ottimizza la compatibilità con le DDI precedenti (ad esempio, Direct3D versione 10 DDI) e riduce la varianza dei driver quando supporta più versioni delle API tramite più versioni di DDI. Tuttavia, questo raggruppamento di dispositivi di visualizzazione e contesto immediato comporta un DDI più confuso perché i domini di threading non sono estremamente espliciti. Per comprendere invece i requisiti di threading di più interfacce e le funzioni all'interno di tali interfacce, gli sviluppatori di driver devono fare riferimento alla documentazione.

Una funzionalità principale dell'API Direct3D versione 11 consiste nel fatto che consente a più thread di immettere funzioni di creazione e eliminazione simultanea. Tale funzionalità non è compatibile con consentire al driver di scambiare i puntatori di tabella delle funzioni per la creazione e l'eliminazione definitiva, come la semantica DDI direct3D versione 10 per le funzioni specificate in D3D10DDI_DEVICEFUNCS e D3D10_1DDI_DEVICEFUNCS consentite. Pertanto, dopo che il driver passa indietro i puntatori a funzione per la creazione (CreateDevice(D3D10),il driver non deve tentare di modificare il comportamento modificando questi puntatori di funzione specifici quando il driver viene eseguito con Direct3D versione 11 DDI e mentre il driver supporta il threading DDI. Questa restrizione si applica a tutte le funzioni del dispositivo che iniziano con pfnCreate, pfnOpen, pfnDestroy, pfnCalcPrivate e pfnCheck. Tutte le altre funzioni del dispositivo sono fortemente associate al contesto immediato. Poiché un singolo thread modifica il contesto immediato alla volta, è ben definito per continuare a consentire al driver di scambiare voci immediate della tabella delle funzioni di contesto immediate.

pfnRenderCb Versus pfnPerformAmortizedProcessingCb

Le funzioni API Direct3D versione 10 hanno associato la funzione di callback del kernel pfnRenderCb del runtime Direct3D per eseguire l'elaborazione ammortizzata, ovvero anziché eseguire determinate operazioni per ogni chiamata di funzione API, il driver ha eseguito operazioni ammortizzate per ogni chiamata di funzione API. L'API usa in genere questa opportunità per tagliare filigrane elevate e scaricare la coda di distruzione posticipata degli oggetti, tra le altre cose.

Per consentire alle funzioni di callback del kernel di essere il più possibile a thread libero per il driver, l'API Direct3D non usa più pfnRenderCb quando il driver supporta Direct3D versione 11 DDI. Pertanto, i driver che supportano l'DDI Direct3D versione 11 devono chiamare manualmente la funzione di callback del kernel pfnPerformAmortizedProcessingCb dallo stesso thread che ha immesso la funzione DDI driver dopo che il driver invia un buffer di comando nel contesto immediato (o frequenza simile). Poiché l'operazione dovrebbe tagliare filigrane elevate, sarebbe vantaggioso farlo prima che il driver generi preamboli del buffer dei comandi quando si sfruttano le funzioni di callback DDI per l'aggiornamento dello stato.

Inoltre, il driver deve essere a conoscenza del problema di ammortamento dell'API e cercare di bilanciare la frequenza con cui usa la funzione di callback del kernel pfnPerformAmortizedProcessingCb . In un estremo, il driver potrebbe causare un sovraccarico dell'elaborazione. Ad esempio, se il driver chiama sempre pfnPerformAmortizedProcessingCb due volte (back-to-back), probabilmente a causa dell'utilizzo di più motori, sarebbe più efficiente per il driver chiamare pfnPerformAmortizedProcessingCb una sola volta. Nell'altro estremo, il driver potrebbe non consentire all'API Direct3D di eseguire alcuna operazione per un intero frame se il driver non ha mai chiamato pfnPerformAmortizedProcessingCb, probabilmente a causa di una progettazione di rendering dei fotogrammi alternata. Il driver non è necessario chiamare pfnPerformAmortizedProcessingCb più spesso di quanto non lo sarebbe naturalmente, in quanto è eccessivo (ad esempio, se il driver non ha chiamato pfnPerformAmortizedProcessingCb in un intervallo di tempo di 1 millisecondo, deve essere il momento di pompare l'API). Il driver è necessario solo per determinare quale delle chiamate pfnRenderCb esistenti deve essere accompagnato da pfnPerformAmortizedProcessingCb e, naturalmente, conforme alla semantica di threading dell'operazione.

Per i driver che supportano gli elenchi di comandi, tali driver devono anche chiamare pfnPerformAmortizedProcessingCb da contesti posticipati ogni volta che questi driver escono dalla stanza (una frequenza simile a quella di ogni svuotamento immediato del contesto). Il runtime Direct3D versione 11 prevede, almeno, di tagliare le filigrane elevate durante un'operazione di questo tipo. Poiché la semantica di threading correlata a pfnRenderCb è stata rilassata per Direct3D versione 11, i problemi di concorrenza devono essere risolti per consentire a Direct3D versione 11 di continuare ad associare pfnRenderCb, senza restrizioni.

Nuovo codice di errore DDI

Il codice di errore D3DDDIERR_APPLICATIONERROR viene creato per consentire ai driver di partecipare alla convalida in cui l'API Direct3D versione 11 non lo ha fatto. In precedenza, se il driver ha restituito il codice di errore E_INVALIDARG, l'API genera un'eccezione. La presenza del livello di debug causerebbe l'output di debug e indicherà che il driver aveva restituito un errore interno. L'output di debug suggerisce allo sviluppatore che il driver presenta un bug. Se il driver restituisce D3DDDIERR_APPLICATIONERROR, il livello di debug determina invece che l'applicazione è in errore.

Richiesta retroattiva di Free-Threaded CalcPrivate DDIs

Direct3D versione 11 richiede retroattivamente funzioni driver che iniziano con pfnCalcPrivate nelle funzioni DDI Direct3D versione 10 per essere threading libero. Questo requisito retroattivo corrisponde al comportamento dell'DDI Direct3D versione 11 per richiedere sempre pfnCalcPrivate* e pfnCalcDeferredContextHandleSize funzioni di threading libero anche se il driver indica che non supporta il threading DDI. Per altre informazioni su questo requisito retroattivo, vedere Richiesta retroattiva di Free-Threaded CalcPrivate DDIs.

Distruzione posticipata e scaricamento D3D10

Poiché tutte le funzioni di eliminazione sono ora a thread libero, il runtime Direct3D non può scaricare un buffer di comando durante la distruzione. Pertanto, le funzioni di eliminazione definitiva devono rinviare l'effettiva distruzione di un oggetto fino a quando il driver non può garantire che il thread che modifica il contesto immediato non sia più dipendente da tale oggetto per sopravvivere. Ogni metodo di contesto immediato discreto non può usare in modo efficiente la sincronizzazione per risolvere questo problema di distruzione; pertanto, il driver deve usare la sincronizzazione solo quando scarica un buffer dei comandi. Il runtime Direct3D usa anche questa stessa progettazione quando deve gestire problemi simili.

A causa della ratifica della distruzione posticipata, il runtime Direct3D sostiene che tali applicazioni che non possono tollerare soluzioni alternative di distruzione posticipata usano invece meccanismi espliciti. Pertanto, il driver deve elaborare la coda di distruzione posticipata durante le chiamate alla relativa funzione Flush(D3D10) (anche se il buffer dei comandi è vuoto) per garantire che questi meccanismi funzionino effettivamente.

Le applicazioni che richiedono una forma di distruzione sincrona devono usare uno dei modelli seguenti, a seconda del livello di distruzione richiesto:

  • Dopo che l'applicazione garantisce che tutte le dipendenze di tale oggetto vengano rilasciate ( ovvero elenchi di comandi, viste, middleware e così via), l'applicazione usa il modello seguente:

    Object::Release(); // Final release
    ImmediateContext::ClearState(); // Remove all ImmediateContext references as well.
    ImmediateContext::Flush(); // Destroy all objects as quickly as possible.
    
  • Il modello seguente è una distruzione più pesante:

    Object::Release(); // Final release
    ImmediateContext::ClearState(); // Remove all ImmediateContext references as well.
    ImmediateContext::Flush();
    ImmediateContext::End( EventQuery );
    while( S_FALSE == ImmediateContext::GetData( EventQuery ) ) ;
    ImmediateContext::Flush(); // Destroy all objects, completely.
    

Eccezioni primarie

Le primarie sono risorse create dal runtime nelle chiamate alla funzione CreateResource(D3D11) del driver. Il runtime crea un database primario impostando il membro pPrimaryDesc della struttura D3D11DDIARG_CREATERESOURCE su un puntatore valido a una struttura DXGI_DDI_PRIMARY_DESC . Le primarie presentano le seguenti eccezioni rilevanti per quanto riguarda le modifiche precedenti da Direct3D 10 a Direct3D 11:

  • Le funzioni CreateResource(D3D11) e DestroyResource(D3D10) del driver per le primarie non sono a thread libero e condividono il dominio di threading di contesto immediato. La concorrenza può ancora esistere con funzioni che iniziano con pfnCreate e pfnDestroy, che include CreateResource(D3D11) e DestroyResource(D3D10). Tuttavia, la concorrenza non può esistere con CreateResource(D3D11) e DestroyResource(D3D10) per le primarie. Ad esempio, il driver può rilevare che una chiamata alla relativa funzione CreateResource(D3D11) o DestroyResource(D3D10) è per una funzione primaria e quindi determinare che può usare o toccare in modo sicuro la memoria immediata del contesto per la durata della chiamata di funzione.

  • La distruzione primaria non può essere posticipata dal runtime Direct3D e il driver deve chiamare la funzione pfnDeallocateCb in modo appropriato all'interno di una chiamata alla funzione DestroyResource(D3D10) del driver.