Condivisione di surface tra le API grafiche di Windows

Questo argomento fornisce una panoramica tecnica dell'interoperabilità usando la condivisione della superficie tra le API grafiche di Windows, tra cui Direct3D 11, Direct2D, DirectWrite, Direct3D 10 e Direct3D 9Ex. Se si ha già una conoscenza approfondita di queste API, questo documento consente di usare più API per eseguire il rendering nella stessa superficie in un'applicazione progettata per i sistemi operativi Windows 7 o Windows Vista. In questo argomento vengono inoltre fornite linee guida e puntatori alle procedure consigliate per risorse aggiuntive.

Nota

Per Direct2D e DirectWrite l'interoperabilità nel runtime DirectX 11.1, è possibile usare dispositivi Direct2D e contesti di dispositivo per eseguire il rendering direttamente nei dispositivi Direct3D 11.

 

In questo argomento sono contenute le sezioni seguenti.

Introduzione

In questo documento, l'interoperabilità dell'API grafica di Windows si riferisce alla condivisione della stessa superficie di rendering tramite API diverse. Questo tipo di interoperabilità consente alle applicazioni di creare visualizzazioni accattivanti sfruttando più API grafiche Di Windows e di semplificare la migrazione alle nuove tecnologie mantenendo la compatibilità con le API esistenti.

In Windows 7 (e Windows Vista SP2 con Windows 7 Interop Pack, Vista 7IP), le API per il rendering della grafica sono Direct3D 11, Direct2D, Direct3D 10.1, Direct3D 10.0, Direct3D 9Ex, Direct3D 9c e api Direct3D precedenti, nonché GDI e GDI+. Windows Imaging Component (WIC) e DirectWrite sono tecnologie correlate per l'elaborazione delle immagini e Direct2D esegue il rendering del testo. L'API di accelerazione video DirectX (DXVA), basata su Direct3D 9c e Direct3D 9Ex, viene usata per l'elaborazione video.

Man mano che le API grafiche di Windows si evolvono verso l'essere basate su Direct3D, Microsoft sta investendo più impegno per garantire l'interoperabilità tra le API. Le API Direct3D appena sviluppate e le API di livello superiore basate sulle API Direct3D forniscono anche il supporto, se necessario per garantire la compatibilità con le API meno recenti. Per illustrare, le applicazioni Direct2D possono usare Direct3D 10.1 condividendo un dispositivo Direct3D 10.1. Inoltre, le API Direct3D 11, Direct2D e Direct3D 10.1 possono sfruttare tutti i vantaggi di DirectX Graphics Infrastructure (DXGI) 1.1, che consente superfici condivise sincronizzate che supportano completamente l'interoperabilità tra queste API. Le API basate su DXGI 1.1 interagiscono con GDI e GDI+ per associazione, ottenendo il contesto di dispositivo GDI da una superficie DXGI 1.1. Per altre informazioni, vedere la documentazione sull'interoperabilità DXGI e GDI disponibile su MSDN.

La condivisione della superficie non sincronizzata è supportata dal runtime Direct3D 9Ex. Le applicazioni video basate su DXVA possono usare l'helper di interoperabilità Direct3D 9Ex e DXGI per l'interoperabilità DXVA basata su Direct3D 9Ex con Direct3D 11 per lo shader di calcolo oppure può interagire con Direct2D per i controlli 2D o il rendering del testo. WIC e DirectWrite interagiscono anche con GDI, Direct2D e per associazione, altre API Direct3D.

I runtime Direct3D 10.0, Direct3D 9c e Versioni precedenti di Direct3D non supportano le superfici condivise. Le copie di memoria di sistema continueranno a essere usate per l'interoperabilità con le API basate su GDI o DXGI.

Si noti che gli scenari di interoperabilità all'interno di questo documento fanno riferimento al rendering di più API grafiche in una superficie di rendering condivisa, anziché alla stessa finestra dell'applicazione. La sincronizzazione per API separate destinate a superfici diverse che vengono quindi composite nella stessa finestra non rientra nell'ambito di questo documento.

Panoramica dell'interoperabilità delle API

L'interoperabilità di condivisione della superficie delle API grafiche di Windows può essere descritta in termini di scenari da API a API e funzionalità di interoperabilità corrispondenti. A partire da Windows 7 e a partire da Windows Vista SP2 con 7IP, le nuove API e i runtime associati includono Direct2D e tecnologie correlate: Direct3D 11 e DXGI 1.1. Le prestazioni GDI sono state migliorate anche in Windows 7. Direct3D 10.1 è stato introdotto in Windows Vista SP1. Il diagramma seguente illustra il supporto dell'interoperabilità tra le API.

diagramma del supporto dell'interoperabilità tra le API grafiche di Windows

In questo diagramma le frecce mostrano scenari di interoperabilità in cui la stessa superficie può essere accessibile dalle API connesse. Le frecce blu indicano meccanismi di interoperabilità introdotti in Windows Vista. Le frecce verdi indicano il supporto dell'interoperabilità per le nuove API o miglioramenti che consentono alle API meno recenti di interagire con le API più recenti. Ad esempio, le frecce verdi rappresentano la condivisione dei dispositivi, il supporto della superficie condivisa sincronizzata, l'helper di sincronizzazione Direct3D 9Ex/DXGI e il recupero di un contesto di dispositivo GDI da una superficie compatibile.

Scenari di interoperabilità

A partire da Windows 7 e Windows Vista 7IP, le offerte Mainstream delle API grafiche windows supportano il rendering di più API nella stessa superficie DXGI 1.1.

Direct3D 11, Direct3D 10.1, Direct2D - Interoperabilità tra loro

Le API Direct3D 11, Direct3D 10.1 e Direct2D (e le relative API come DirectWrite e WIC) possono interagire tra loro usando la condivisione dei dispositivi Direct3D 10.1 o le superfici condivise sincronizzate.

Condivisione di dispositivi Direct3D 10.1 con Direct2D

La condivisione dei dispositivi tra Direct2D e Direct3D 10.1 consente a un'applicazione di usare entrambe le API per eseguire il rendering uniforme ed efficiente nella stessa superficie DXGI 1.1, usando lo stesso oggetto dispositivo Direct3D sottostante. Direct2D offre la possibilità di chiamare LE API Direct2D usando un dispositivo Direct3D 10.1 esistente, sfruttando il fatto che Direct2D è basato su runtime Direct3D 10.1 e DXGI 1.1. I frammenti di codice seguenti illustrano come Direct2D ottiene la destinazione di rendering del dispositivo Direct3D 10.1 da una superficie DXGI 1.1 associata al dispositivo. La destinazione di rendering del dispositivo Direct3D 10.1 può eseguire chiamate di disegno Direct2D tra le API BeginDraw e EndDraw.

// Direct3D 10.1 Device and Swapchain creation
HRESULT hr = D3D10CreateDeviceandSwapChain1(
                pAdapter,
                DriverType,
                Software,
                D3D10_CREATE_DEVICE_BGRA_SUPPORT,
                featureLevel,
                D3D10_1_SDK_VERSION,
                pSwapChainDesc,
                &pSwapChain,
                &pDevice
                );

hr = pSwapChain->GetBuffer(
        0,
        __uuidof(IDXGISurface),
        (void **)&pDXGIBackBuffer
        ));

// Direct3D 10.1 API rendering calls
...

hr = D2D1CreateFactory(
        D2D1_FACTORY_TYPE_SINGLE_THREADED,
        &m_spD2DFactory
        ));

pD2DFactory->CreateDxgiSurfaceRenderTarget(
        pDXGIBackBuffer,
        &renderTargetProperties,
        &pD2DBackBufferRenderTarget
        ));
...

pD2DBackBufferRenderTarget->BeginDraw();
//Direct2D API rendering calls
...

pD2DBackBufferRenderTarget->EndDraw();

pSwapChain->Present(0, 0);

Osservazioni:

  • Il dispositivo Direct3D 10.1 associato deve supportare il formato BGRA. Il dispositivo è stato creato chiamando D3D10CreateDevice1 con il parametro D3D10_CREATE_DEVICE_BGRA_SUPPORT. Il formato BGRA è supportato a partire dal livello di funzionalità Direct3D 10 9.1.
  • L'applicazione non deve creare più ID2D1RenderTargets associati allo stesso dispositivo Direct3D10.1.
  • Per ottenere prestazioni ottimali, mantenere sempre almeno una risorsa, ad esempio trame o superfici associate al dispositivo.

La condivisione dei dispositivi è adatta per l'utilizzo in-process e a thread singolo di un dispositivo di rendering condiviso dalle API di rendering Direct3D 10.1 e Direct2D. Le superfici condivise sincronizzate consentono l'utilizzo multithreading, in-process e out-of-process di più dispositivi di rendering usati dalle API Direct3D 10.1, Direct2D e Direct3D 11.

Un altro metodo di interoperabilità Direct3D 10.1 e Direct2D consiste nell'usare ID3D1RenderTarget::CreateSharedBitmap, che crea un oggetto ID2D1Bitmap da IDXGISurface. È possibile scrivere una scena Direct3D10.1 nella bitmap ed eseguirne il rendering con Direct2D. Per altre informazioni, vedere Metodo ID2D1RenderTarget::CreateSharedBitmap.

Rasterizzazione del software Direct2D

La condivisione di dispositivi con Direct3D 10.1 non è supportata quando si usa il renderer software Direct2D, ad esempio, specificando D2D1_RENDER_TARGET_USAGE_FORCE_SOFTWARE_RENDERING in D2D1_RENDER_TARGET_USAGE quando si crea una destinazione di rendering Direct2D.

Direct2D può usare il rasterizzatore software WARP10 per condividere il dispositivo con Direct3D 10 o Direct3D 11, ma le prestazioni diminuiscno significativamente.

Superfici condivise sincronizzate DXGI 1.1

Le API Direct3D 11, Direct3D 10.1 e Direct2D usano tutti DXGI 1.1, che offre la funzionalità per sincronizzare la lettura e la scrittura nella stessa superficie di memoria video (DXGISurface1) di due o più dispositivi Direct3D. I dispositivi di rendering che usano superfici condivise sincronizzate possono essere dispositivi Direct3D 10.1 o Direct3D 11, ognuno in esecuzione nello stesso processo o tra processi.

Le applicazioni possono usare superfici condivise sincronizzate per interagire tra qualsiasi dispositivo basato su DXGI 1.1, ad esempio Direct3D 11 e Direct3D 10.1 o tra Direct3D 11 e Direct2D, ottenendo il dispositivo Direct3D 10.1 dall'oggetto di destinazione di rendering Direct2D.

Nelle API Direct3D 10.1 e successive, per usare DXGI 1.1, assicurarsi che il dispositivo Direct3D venga creato usando un oggetto adattatore DXGI 1.1, enumerato dall'oggetto factory DXGI 1.1. Chiamare CreateDXGIFactory1 per creare l'oggetto IDXGIFactory1 e EnumAdapters1 per enumerare l'oggetto IDXGIAdapter1. L'oggetto IDXGIAdapter1 deve essere passato come parte della chiamata D3D10CreateDevice o D3D10CreateDeviceAndSwapChain. Per altre informazioni sulle API DXGI 1.1, vedere la Guida alla programmazione per DXGI.

API

D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX
Quando si crea la risorsa condivisa sincronizzata, impostare D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX in D3D10_RESOURCE_MISC_FLAG.

typedef enum D3D10_RESOURCE_MISC_FLAG {
    D3D10_RESOURCE_MISC_GENERATE_MIPS      = 0x1L,
    D3D10_RESOURCE_MISC_SHARED             = 0x2L,
    D3D10_RESOURCE_MISC_TEXTURECUBE        = 0x4L,
    D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX  = 0x10L,
    D3D10_RESOURCE_MISC_GDI_COMPATIBLE     = 0x20L,
}   D3D10_RESOURCE_MISC_FLAG;

D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX
Consente di sincronizzare la risorsa creata usando le API IDXGIKeyedMutex::AcquireSync e ReleaseSync. Le API direct3D 10.1 seguenti per la creazione di risorse che accettano tutti un parametro D3D10_RESOURCE_MISC_FLAG sono state estese per supportare il nuovo flag.

  • ID3D10Device1::CreateTexture1D
  • ID3D10Device1::CreateTexture2D
  • ID3D10Device1::CreateTexture3D
  • ID3D10Device1::CreateBuffer

Se una delle funzioni elencate viene chiamata con il set di flag D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX, è possibile eseguire una query sull'interfaccia restituita per un'interfaccia IDXGIKeyedMutex, che implementa le API AcquireSync e ReleaseSync per sincronizzare l'accesso alla superficie. Il dispositivo che crea la superficie e qualsiasi altro dispositivo che apre la superficie (usando OpenSharedResource) è necessario per chiamare IDXGIKeyedMutex::AcquireSync prima di qualsiasi comando di rendering sulla superficie e IDXGIKeyedMutex::ReleaseSync al termine del rendering.
I dispositivi WARP e REF non supportano le risorse condivise. Se si tenta di creare una risorsa con questo flag in un dispositivo WARP o REF, il metodo di creazione restituirà un codice di errore E_OUTOFMEMORY.
INTERFACCIA IDXGIKEYEDMUTEX
Una nuova interfaccia in DXGI 1.1, IDXGIKeyedMutex, rappresenta un mutex con chiave, che consente l'accesso esclusivo a una risorsa condivisa usata da più dispositivi. Per la documentazione di riferimento su questa interfaccia e sui due metodi AcquireSync e ReleaseSync, vedere IDXGIKeyedMutex.

Esempio: Condivisione della superficie sincronizzata tra due dispositivi Direct3D 10.1

L'esempio seguente illustra la condivisione di una superficie tra due dispositivi Direct3D 10.1. La superficie condivisa sincronizzata viene creata da un dispositivo Direct3D10.1.

// Create Sync Shared Surface using Direct3D10.1 Device 1.
D3D10_TEXTURE2D_DESC desc;
ZeroMemory( &desc, sizeof(desc) );
desc.Width = width;
desc.Height = height;
desc.MipLevels = 1;
desc.ArraySize = 1;
// must match swapchain format in order to CopySubresourceRegion.
desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
desc.SampleDesc.Count = 1;
desc.Usage = D3D10_USAGE_DEFAULT;
// creates 2D texture as a Synchronized Shared Surface.
desc.MiscFlags = D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX;
desc.BindFlags = D3D10_BIND_RENDER_TARGET | D3D10_BIND_SHADER_RESOURCE;
ID3D10Texture2D* g_pShared = NULL;
g_pd3dDevice1->CreateTexture2D( &desc, NULL, &g_pShared );

// QI IDXGIResource interface to synchronized shared surface.
IDXGIResource* pDXGIResource = NULL;
g_pShared->QueryInterface(__uuidof(IDXGIResource), (LPVOID*) &pDXGIResource);

// obtain handle to IDXGIResource object.
pDXGIResource->GetSharedHandle(&g_hsharedHandle);
pDXGIResource->Release();
if ( !g_hsharedHandle )
    return E_FAIL;

// QI IDXGIKeyedMutex interface of synchronized shared surface's resource handle.
hr = g_pShared->QueryInterface( __uuidof(IDXGIKeyedMutex),
    (LPVOID*)&g_pDXGIKeyedMutex_dev1 );
If ( FAILED( hr ) || ( g_pDXGIKeyedMutex_dev1 == NULL ) )
    return E_FAIL;

Lo stesso dispositivo Direct3D10.1 può ottenere la superficie condivisa sincronizzata per il rendering chiamando AcquireSync, quindi rilasciando la superficie per il rendering dell'altro dispositivo chiamando ReleaseSync. Quando non si condivide la superficie condivisa sincronizzata con qualsiasi altro dispositivo Direct3D, l'autore può ottenere e rilasciare la superficie condivisa sincronizzata (per avviare e terminare il rendering) acquisendo e rilasciando lo stesso valore della chiave.

// Obtain handle to Sync Shared Surface created by Direct3D10.1 Device 1.
hr = g_pd3dDevice2->OpenSharedResource( g_hsharedHandle,__uuidof(ID3D10Texture2D),
                                        (LPVOID*) &g_pdev2Shared);
if (FAILED (hr))
    return hr;
hr = g_pdev2Shared->QueryInterface( __uuidof(IDXGIKeyedMutex),
                                    (LPVOID*) &g_pDXGIKeyedMutex_dev2);
if( FAILED( hr ) || ( g_pDXGIKeyedMutex_dev2 == NULL ) )
    return E_FAIL;

// Rendering onto Sync Shared Surface from D3D10.1 Device 1 using D3D10.1 Device 2.
UINT acqKey = 1;
UINT relKey = 0;
DWORD timeOut = 5;
DWORD result = g_pDXGIKeyedMutex_dev2->AcquireSync(acqKey, timeOut);
if ( result == WAIT_OBJECT_0 )
    // Rendering calls using Device 2.
else
    // Handle unable to acquire shared surface error.
result = g_pDXGIKeyedMutex_dev2->ReleaseSync(relKey));
if (result == WAIT_OBJECT_0)
    return S_OK;

Il secondo dispositivo Direct3D10.1 può ottenere la superficie condivisa sincronizzata per il rendering chiamando AcquireSync, quindi rilasciando la superficie per il rendering del primo dispositivo chiamando ReleaseSync. Si noti che il dispositivo 2 è in grado di acquisire l'area condivisa sincronizzata usando lo stesso valore della chiave specificata nella chiamata ReleaseSync per dispositivo 1.

// Rendering onto Sync Shared Surface from D3D10.1 Device 1 using D3D10.1 Device 1.
UINT acqKey = 0;
UINT relKey = 1;
DWORD timeOut = 5;
DWORD result = g_pDXGIKeyedMutex_dev1->AcquireSync(acqKey, timeOut);
if (result == WAIT_OBJECT_0)
    // Rendering calls using Device 1.
else
    // Handle unable to acquire shared surface error.
result = g_pDXGIKeyedMutex_dev1->ReleaseSync(relKey));
if ( result == WAIT_OBJECT_0 )
    return S_OK;

Altri dispositivi che condividono la stessa superficie possono acquisire e rilasciare la superficie usando chiavi aggiuntive, come illustrato nelle chiamate seguenti.

// Within Device 1's process/thread:
// Rendering onto Sync Shared Surface from D3D10.1 Device 1 using D3D10.1 Device 1
result = g_pDXGIKeyedMutex_dev1->AcquireSync(0, timeOut);
// Rendering calls using Device 1
...
result = g_pDXGIKeyedMutex_dev1->ReleaseSync(1);
...
////////////////////////////////////////////////////////////////////////////
// Within Device 2's process/thread:
// Rendering onto Sync Shared Surface from D3D10.1 Device 1 using D3D10.1 Device 2
result = g_pDXGIKeyedMutex_dev2->AcquireSync(1, timeOut);
// Rendering calls using Device 2
...
result = g_pDXGIKeyedMutex_dev1->ReleaseSync(2);

////////////////////////////////////////////////////////////////////////////
// Within Device 3's process/thread:
// Rendering onto Sync Shared Surface from D3D10.1 Device 1 using D3D10.1 Device 3
result = g_pDXGIKeyedMutex_dev1->AcquireSync(2, timeOut);
// Rendering calls using Device 3
...
result = g_pDXGIKeyedMutex_dev1->ReleaseSync(0);
...

Si noti che un'applicazione reale potrebbe sempre eseguire il rendering in una superficie intermedia copiata nell'area condivisa per impedire a un dispositivo in attesa su un altro dispositivo che condivide la superficie.

Uso di superfici condivise sincronizzate con Direct2D e Direct3D 11

Analogamente, per la condivisione tra le API Direct3D 11 e Direct3D 10.1, è possibile creare una superficie condivisa sincronizzata da un dispositivo API e condividere con gli altri dispositivi API, in o fuori processo.

Le applicazioni che usano Direct2D possono condividere un dispositivo Direct3D 10.1 e usare una superficie condivisa sincronizzata per interoperabilità con Direct3D 11 o altri dispositivi Direct3D 10.1, indipendentemente dal fatto che appartengano allo stesso processo o a processi diversi. Tuttavia, per applicazioni a thread singolo, la condivisione dei dispositivi è il metodo più elevato ed efficiente dell'interoperabilità tra Direct2D e Direct3D 10 o Direct3D 11.

Software Rasterizer

Le superfici condivise sincronizzate non sono supportate quando le applicazioni usano i rasterizzatori software Direct3D o Direct2D, inclusi il rasterizzatore di riferimento e WARP, anziché usare l'accelerazione hardware grafica.

Interoperabilità tra API basate su Direct3D 9Ex e DXGI

Le API Direct3D 9Ex includevano la nozione di condivisione della superficie per consentire ad altre API di leggere dalla superficie condivisa. Per condividere la lettura e la scrittura in una superficie condivisa Direct3D 9Ex, è necessario aggiungere la sincronizzazione manuale all'applicazione stessa.

Helper di sincronizzazione manuale Direct3D 9Ex Shared Surface Plus

L'attività più fondamentale in Direct3D 9Ex e Direct3D 10 o 11 passa una singola superficie dal primo dispositivo (dispositivo A) al secondo (dispositivo B) in modo che quando il dispositivo B acquisisce un handle sulla superficie, il rendering del dispositivo A è garantito che sia stato completato. Pertanto, il dispositivo B può usare questa superficie senza preoccuparsi. Questo è molto simile al problema di produttore-consumer classico e questa discussione modella il problema in questo modo. Il primo dispositivo che usa la superficie e quindi rilinquise è il produttore (Device A) e il dispositivo che è inizialmente in attesa è il consumer (Device B). Qualsiasi applicazione reale è più sofisticata di questa e concatena più blocchi predefiniti consumer-producer per creare la funzionalità desiderata.

I blocchi predefiniti producer-consumer vengono implementati nell'helper usando una coda di superfici. Le superfici vengono accodate dal produttore e dequeuate dal consumer. L'helper introduce tre interfacce COM: ISurfaceQueue, ISurfaceProducer e ISurfaceConsumer.

Panoramica High-Level helper

L'oggetto ISurfaceQueue è il blocco predefinito per l'uso delle superfici condivise. Viene creato con un dispositivo Direct3D inizializzato e una descrizione per creare un numero fisso di superfici condivise. L'oggetto queue gestisce la creazione di risorse e l'apertura del codice. Il numero e il tipo di superfici sono fissi; una volta create le superfici, l'applicazione non può aggiungerle o rimuoverle.

Ogni istanza dell'oggetto ISurfaceQueue fornisce una sorta di strada unidirezionale che può essere usata per inviare superfici dal dispositivo di produzione al dispositivo di utilizzo. È possibile usare più strade unidirezionale per abilitare scenari di condivisione della superficie tra dispositivi di applicazioni specifiche.

Durata di creazione/oggetto
Esistono due modi per creare l'oggetto queue: tramite CreateSurfaceQueue o tramite il metodo Clone di ISurfaceQueue. Poiché le interfacce sono oggetti COM, viene applicata la gestione della durata COM standard.
Producer/Consumer Model
Enqueue (): il produttore chiama questa funzione per indicare che viene eseguita con la superficie, che ora può diventare disponibile per un altro dispositivo. Al ritorno da questa funzione, il dispositivo producer non ha più diritti per la superficie e non è sicuro continuare a usarlo.
Dequeue (): l'utilizzo del dispositivo chiama questa funzione per ottenere una superficie condivisa. L'API garantisce che le superfici dequeued siano pronte per l'uso.
Metadata
L'API supporta l'associazione dei metadati alle superfici condivise.
Enqueue() ha la possibilità di specificare metadati aggiuntivi che verranno passati al dispositivo di utilizzo. I metadati devono essere inferiori a un massimo noto in fase di creazione.
Dequeue() può passare facoltativamente un buffer e un puntatore alle dimensioni del buffer. La coda riempie il buffer con i metadati della chiamata Enqueue corrispondente.
Clonazione
Ogni oggetto ISurfaceQueue risolve una sincronizzazione unidirezionale. Si supponga che la maggior parte delle applicazioni che usano questa API userà un sistema chiuso. Il sistema chiuso più semplice con due dispositivi che inviano superfici indietro e avanti richiede due code. L'oggetto ISurfaceQueue ha un metodo Clone() per consentire la creazione di più code che fanno parte della stessa pipeline più grande.
Clone crea un nuovo oggetto ISurfaceQueue da uno esistente e condivide tutte le risorse aperte tra di esse. L'oggetto risultante ha esattamente le stesse superfici della coda di origine. Le code clonate possono avere dimensioni di metadati diverse tra loro.
Superfici
ISurfaceQueue si occupa della creazione e della gestione delle sue superfici. Non è valida per assegnare superfici arbitrarie. Inoltre, una superficie deve avere solo un "proprietario" attivo. Deve essere in una coda specifica o usata da un dispositivo specifico. Non è valido usarlo in più code o per consentire ai dispositivi di continuare a usare la superficie dopo l'esecuzione della procedura.

Dettagli DELL'API

IsurfaceQueue

La coda è responsabile della creazione e della gestione delle risorse condivise. Fornisce anche la funzionalità per concatenare più code usando Clone. La coda include metodi che aprono il dispositivo di produzione e un dispositivo che utilizza. È possibile aprire solo uno di essi in qualsiasi momento.

La coda espone le API seguenti:

API Descrizione
CreateSurfaceQueue Crea un oggetto ISurfaceQueue (coda "radice").
ISurfaceQueue::OpenConsumer Restituisce un'interfaccia per l'utilizzo del dispositivo da dequeue.
ISurfaceQueue::OpenProducer Restituisce un'interfaccia per il dispositivo di produzione da eseguire.
ISurfaceQueue::Clone Crea un oggetto ISurfaceQueue che condivide le superfici con l'oggetto coda radice.

 

CreateSurfaceQueue

typedef struct SURFACE_QUEUE_DESC {
  UINT            Width;
  UINT            Height;
  DXGI_FORMAT     Format;
  UINT            NumSurfaces;
  UINT            MetaDataSize;
  DWORD           Flags;
} SURFACE_QUEUE_DESC;

Members

Larghezza, Altezza Dimensioni delle superfici condivise. Tutte le superfici condivise devono avere le stesse dimensioni.
Formato Formato delle superfici condivise. Tutte le superfici condivise devono avere lo stesso formato. I formati validi dipendono dai dispositivi che verranno usati, perché diverse coppie di dispositivi possono condividere tipi di formato diversi.
NumSurfaces Numero di superfici che fanno parte della coda. Si tratta di un numero fisso.
MetaDataSize Dimensione massima del buffer dei metadati.
Bandiere Flag per controllare il comportamento della coda. Vedere la sezione Osservazioni.

HRESULT CreateSurfaceQueue(
  [in]   SURFACE_QUEUE_DESC *pDesc,
  [in]   IUnknown *pDevice,
  [out]  IDXGIXSurfaceQueue **ppQueue
);

Parameters

pDesc [in] Descrizione della coda di superficie condivisa da creare.

pDevice [in] Dispositivo che deve essere usato per creare le superfici condivise. Questo è un parametro esplicito a causa di una funzionalità in Windows Vista. Per le superfici condivise tra Direct3D 9 e Direct3D 10, le superfici devono essere create con Direct3D 9.

ppQueue [out] In restituzione, contiene un puntatore all'oggetto ISurfaceQueue.

Valori restituiti

Se pDevice non è in grado di condividere le risorse, questa funzione restituisce DXGI_ERROR_INVALID_CALL. Questa funzione crea le risorse. Se ha esito negativo, restituisce un errore. Se ha esito positivo, restituisce S_OK.

Osservazioni:

La creazione dell'oggetto queue crea anche tutte le superfici. Tutte le superfici vengono considerate 2D target di rendering e verranno create con i flag di D3D10_BIND_RENDER_TARGET e D3D10_BIND_SHADER_RESOURCE impostati (o i flag equivalenti per i diversi runtime).

Lo sviluppatore può specificare un flag che indica se la coda sarà accessibile da più thread. Se non vengono impostati flag (flag == 0), la coda verrà usata da più thread. Lo sviluppatore può specificare l'accesso a thread singolo, che disattiva il codice di sincronizzazione e fornisce un miglioramento delle prestazioni per tali casi. Ogni coda clonata ha un proprio flag, quindi è possibile che le code diverse nel sistema dispongano di controlli di sincronizzazione diversi.

Aprire un produttore

HRESULT OpenProducer(
  [in]   IUnknown *pDevice,
  [out]  IDXGIXSurfaceProducer **ppProducer
);

Parameters

pDevice [in]

Dispositivo producer che esegue la sequenza delle superfici nella coda di superficie.

ppProducer [out] Restituisce un oggetto all'interfaccia del produttore.

Valori restituiti

Se il dispositivo non è in grado di condividere le superfici, restituisce DXGI_ERROR_INVALID_CALL.

Aprire un consumer

HRESULT OpenConsumer(
  [in]   IUnknown *pDevice,
  [out]  IDXGIXSurfaceConsumer **ppConsumer
);

Parameters
pDevice [in]
Dispositivo consumer che dequeue le superfici dalla coda di superficie. ppConsumer [out] Restituisce un oggetto all'interfaccia consumer.

Valori restituiti

Se il dispositivo non è in grado di condividere le superfici, restituisce DXGI_ERROR_INVALID_CALL.

Osservazioni:

Questa funzione apre tutte le superfici nella coda per il dispositivo di input e le memorizza nella cache. Le chiamate successive a Dequeue passano semplicemente alla cache e non devono riaprire le superfici ogni volta.

Clonazione di un IDXGIXSurfaceQueue

typedef struct SHARED_SURFACE_QUEUE_CLONE_DESC {
  UINT         MetaDataSize;
  DWORD        Flags;
} SHARED_SURFACE_QUEUE_CLONE_DESC;

I membriMetaDataSize e Flag hanno lo stesso comportamento che fanno per CreateSurfaceQueue.

HRESULT Clone(
  [in]   SHARED_SURFACE_QUEUE_CLONE_DESC *pDesc,
  [out]  IDXGIXSurfaceQueue **ppQueue
);

Parameters

pDesc [in] struct che fornisce una descrizione dell'oggetto Clone da creare. Questo parametro deve essere inizializzato.
ppQueue [out] Restituisce l'oggetto inizializzato.

Osservazioni:

È possibile clonare da qualsiasi oggetto coda esistente, anche se non è la radice.

IDXGIXSurfaceConsumer

HRESULT Dequeue(
  [in]      REFIID    id,
  [out]     void      **ppSurface,
  [in,out]  void      *pBuffer,
  [in,out]  UINT      *pBufferSize,
  [in]      DWORD     dwTimeout
);

Parameters
id [in]
REFIID di una superficie 2D del dispositivo che usa.

  • Per un IDirect3DDevice9, il REFIID deve essere __uuidof(IDirect3DTexture9).
  • Per un ID3D10Device, il REFIID deve essere __uuidof(ID3D10Texture2D).
  • Per un ID3D11Device, il REFIID deve essere __uuidof(ID3D11Texture2D).

ppSurface [out] Restituisce un puntatore alla superficie.
pBuffer [in, out] Parametro facoltativo e, in caso contrario NULL, contiene i metadati passati nella chiamata di accodamento corrispondente.
pBufferSize [in, out] Dimensioni di pBuffer, in byte. Restituisce il numero di byte restituiti in pBuffer. Se la chiamata inqueue non ha fornito metadati, pBuffer è impostato su 0.
dwTimeout [in] Specifica un valore di timeout. Per altri dettagli, vedere le osservazioni.

Valori restituiti

Questa funzione può restituire WAIT_TIMEOUT se viene specificato un valore di timeout e la funzione non restituisce prima del valore di timeout. Vedere la sezione Osservazioni. Se non sono disponibili superfici, la funzione restituisce con ppSurface impostata su NULL, pBufferSize impostata su 0 e il valore restituito è 0x80070120 (WIN32_TO_HRESULT(WAIT_TIMEOUT)).

Osservazioni:

Questa API può bloccare se la coda è vuota. Il parametro dwTimeout funziona in modo identico alle API di sincronizzazione di Windows, ad esempio WaitForSingleObject. Per il comportamento senza blocco, usare un timeout pari a 0.

ISurfaceProducer

Questa interfaccia fornisce due metodi che consentono all'app di eseguire la sequenza delle superfici. Dopo che una superficie è inqueuata, il puntatore di superficie non è più valido e non è sicuro da usare. L'unica azione che l'applicazione deve eseguire con il puntatore consiste nel rilasciarla.

Metodo Descrizione
ISurfaceProducer::Enqueue Inqueue una superficie all'oggetto queue. Al termine di questa chiamata, il produttore viene eseguito con la superficie e la superficie è pronta per un altro dispositivo.
ISurfaceProducer::Flush Usato se le applicazioni devono avere un comportamento non bloccato. Per ulteriori informazioni, vedere Note.

 

Enqueue

HRESULT Enqueue(
  [in]  IUnknown *pSurface,
  [in]  void *pBuffer,
  [in]  UINT BufferSize,
  [in]  DWORD Flags
);

Parameters
pSurface [in]
Superficie del dispositivo di produzione che deve essere accodato. Questa superficie deve essere una superficie dequeued dalla stessa rete di coda. pBuffer [in] Parametro facoltativo, usato per passare i metadati. Deve puntare ai dati che verranno passati alla chiamata dequeue.
BufferSize [in] Dimensioni di pBuffer, in byte.
Contrassegna [in] Un parametro facoltativo che controlla il comportamento di questa funzione. L'unico flag è SURFACE_QUEUE_FLAG_ DO_NOT_WAIT. Vedere le osservazioni per lo scaricamento. Se non viene passato alcun flag (Flag == 0), viene usato il comportamento di blocco predefinito.

Valori restituiti

Questa funzione può restituire DXGI_ERROR_WAS_STILL_DRAWING se viene usato un flag di SURFACE_QUEUE_FLAG_DO_NOT_WAIT.

Osservazioni:

  • Questa funzione inserisce la superficie nella coda. Se l'applicazione non specifica SURFACE_QUEUE_FLAG_DO_NOT_WAIT, questa funzione è bloccata e eseguirà una sincronizzazione DELLA CPU della GPU per garantire che tutto il rendering nell'area inqueued sia completato. Se questa funzione riesce, una superficie sarà disponibile per la dequeue. Se si vuole un comportamento senza blocco, usare il flag di DO_NOT_WAIT. Per informazioni dettagliate, vedere Flush().
  • In base alle regole di conteggio dei riferimenti COM, la superficie restituita da Dequeue sarà AddRef() in modo che l'applicazione non debba eseguire questa operazione. Dopo aver chiamato Enqueue, l'applicazione deve rilasciare la superficie perché non lo usano più.

Svuotamento

HRESULT Flush(
  [in]  DWORD Flags,
  [out] UINT *nSurfaces
);

Parameters
Flag [in]
L'unico flag è SURFACE_QUEUE_FLAG_ DO_NOT_WAIT. Vedere la sezione Osservazioni. nSurfaces [out] Restituisce il numero di superfici ancora in sospeso e non scaricate.

Valori restituiti

Questa funzione può restituire DXGI_ERROR_WAS_STILL_DRAWING se viene usato il flag di SURFACE_QUEUE_FLAG_DO_NOT_WAIT. Questa funzione restituisce S_OK se le superfici sono state scaricate correttamente. Questa funzione restituisce DXGI_ERROR_WAS_STILL_DRAWING solo se non sono state scaricate superfici. Insieme, il valore restituito e nSurfaces indica all'applicazione cosa è stato fatto e se è stato lasciato un lavoro.

Osservazioni:

Lo scaricamento è significativo solo se la chiamata precedente per eseguire la sequenza ha usato il flag di DO_NOT_WAIT; in caso contrario, sarà un no-op. Se la chiamata a usare il flag DO_NOT_WAIT usato, l'accodamento restituisce immediatamente e la sincronizzazione della CPU della GPU non è garantita. La superficie è ancora considerata inqueued, il dispositivo di produzione non può continuare a usarlo, ma non è disponibile per dequeue. Per provare a eseguire il commit della superficie per dequeue, è necessario chiamare Flush. Scarica tentativi di eseguire il commit di tutte le superfici attualmente accodate. Se non viene passato alcun flag a Scarica, blocca e cancella l'intera coda, preparando tutte le superfici in esso contenute per la rimozione dalla coda. Se viene usato il flag DO_NOT_WAIT, la coda verificherà le superfici per verificare se uno di essi è pronto; questo passaggio non blocca. Le superfici che hanno completato la sincronizzazione GPU-CPU saranno pronte per il dispositivo consumer. Le superfici ancora in sospeso non saranno interessate. La funzione restituisce il numero di superfici che devono essere ancora scaricate.

Nota

Lo scaricamento non interromperà la semantica della coda. L'API garantisce che venga eseguito il commit delle superfici accodate prima che le superfici vengano accodate in un secondo momento, indipendentemente dal momento in cui avviene la sincronizzazione gpu-CPU.

 

Helper di interoperabilità Direct3D 9Ex e DXGI: Come usare

Ci aspettiamo che la maggior parte dei casi di utilizzo coinvolga due dispositivi che condividono una serie di superfici. Poiché questo è anche lo scenario più semplice, questo documento illustra in dettaglio come usare le API per raggiungere questo obiettivo, illustra una variante non bloccante e termina con una breve sezione sull'inizializzazione per tre dispositivi.

Due dispositivi

L'applicazione di esempio che usa questo helper può usare Insieme Direct3D 9Ex e Direct3D 11. L'applicazione può elaborare il contenuto con entrambi i dispositivi e presentare contenuto usando Direct3D 9. L'elaborazione può significare il rendering di contenuto, la decodifica di video, l'esecuzione di shader di calcolo e così via. Per ogni fotogramma, l'applicazione verrà prima elaborata con Direct3D 11, quindi elaborata con Direct3D 9 e infine presente con Direct3D 9. Inoltre, l'elaborazione con Direct3D 11 produrrà alcuni metadati che il Direct3D 9 presente dovrà utilizzare. Questa sezione illustra l'utilizzo dell'helper in tre parti che corrispondono a questa sequenza: Inizializzazione, Ciclo principale e Pulizia.

Inizializzazione
L'inizializzazione prevede i passaggi seguenti:

  1. Inizializzare entrambi i dispositivi.
  2. Creare la coda radice: m_11to9Queue.
  3. Clonare dalla coda radice: m_9to11Queue.
  4. Chiamare OpenProducer/OpenConsumer in entrambe le code.

I nomi delle code usano i numeri 9 e 11 per indicare quale API è il producer e quale è il consumer: m_producerallacodaconsumer. Di conseguenza, m_11to9Queue indica una coda per cui il dispositivo Direct3D 11 produce superfici utilizzate dal dispositivo Direct3D 9. Analogamente, m_9to11Queue indica una coda per cui Direct3D 9 produce superfici utilizzate da Direct3D 11.
La coda radice è inizialmente piena e tutte le code clonate sono inizialmente vuote. Non dovrebbe trattarsi di un problema per l'applicazione, ad eccezione del primo ciclo di accodamento e dequeue e della disponibilità dei metadati. Se una coda chiede metadati ma non è stata impostata alcuna proprietà (perché inizialmente non è presente alcun elemento o l'accodamento non ha impostato nulla), la coda non rileva che non è stato ricevuto alcun metadato.

  1. Inizializzare entrambi i dispositivi.

    m_pD3D9Device = InitializeD3D9ExDevice();
    m_pD3D11Device = InitializeD3D11Device();
    
  2. Creare la coda radice.
    Questo passaggio crea anche le superfici. Le restrizioni relative alle dimensioni e al formato sono identiche alla creazione di qualsiasi risorsa condivisa. Le dimensioni del buffer dei metadati sono fisse in fase di creazione e in questo caso si passerà solo un UINT.
    La coda deve essere creata con un numero fisso di superfici. Le prestazioni variano a seconda dello scenario. La presenza di più superfici aumenta le probabilità che i dispositivi siano occupati. Ad esempio, se è presente una sola superficie, non vi sarà alcuna parallelizzazione tra i due dispositivi. D'altra parte, l'aumento del numero di superfici aumenta il footprint della memoria, che può compromettere le prestazioni. In questo esempio vengono utilizzate due superfici.

    SURFACE_QUEUE_DESC Desc;
    Desc.Width        = 640;
    Desc.Height       = 480;
    Desc.Format       = DXGI_FORMAT_R16G16B16A16_FLOAT;
    Desc.NumSurfaces  = 2;
    Desc.MetaDataSize = sizeof(UINT);
    Desc.Flags        = 0;
    
    CreateSurfaceQueue(&Desc, m_pD3D9Device, &m_11to9Queue);
    
  3. Clonare la coda radice.
    Ogni coda clonata deve usare le stesse superfici, ma può avere dimensioni del buffer di metadati e flag diversi. In questo caso, non sono presenti metadati da Direct3D 9 a Direct3D 11.

    SURFACE_QUEUE_CLONE_DESC Desc;
    Desc.MetaDataSize = 0;
    Desc.Flags        = 0;
    
    m_11to9Queue->Clone(&Desc, &m_9to11Queue);
    
  4. Aprire il producer e i dispositivi consumer.
    L'applicazione deve eseguire questo passaggio prima di chiamare Enqueue e Dequeue. L'apertura di un producer e di un consumer restituisce interfacce che contengono le API di accodamento/rimozione dalla coda.

    // Open for m_p9to11Queue.
    m_p9to11Queue->OpenProducer(m_pD3D9Device, &m_pD3D9Producer);
    m_p9to11Queue->OpenConsumer(m_pD3D11Device, &m_pD3D11Consumer);
    
    // Open for m_p11to9Queue.
    m_p11to9Queue->OpenProducer(m_pD3D11Device, &m_pD3D11Producer);
    m_p11to9Queue->OpenConsumer(m_pD3D9Device, &m_pD3D9Consumer);
    

Ciclo principale
L'utilizzo della coda viene modellato dopo il problema di producer/consumer classico. Si pensi a questo da un punto di vista per dispositivo. Ogni dispositivo deve eseguire questi passaggi: annullare la coda per ottenere una superficie dalla coda di utilizzo, dal processo sulla superficie e quindi accodare alla coda di produzione. Per il dispositivo Direct3D 11, l'utilizzo di Direct3D 9 è quasi identico.

// Direct3D 9 Device.
IDirect3DTexture9* pTexture9 = NULL;
REFIID             surfaceID9 = _uuidof(IDirect3DTexture9);
UINT               metaData;
UINT               metaDataSize;
while (!done)
{
    // Dequeue surface.
    m_pD3D9Consumer->Dequeue(surfaceID9, (void**)&pSurface9,
                             &metaData, &metaDataSize, INFINITE);

    // Process the surface.
    ProcessD3D9(pSurface9);

    // Present the surface using the meta data.
    PresentD3D9(pSurface9, metaData, metaDataSize);

    // Enqueue surface.
    m_pD3D9Producer->Enqueue(pSurface9, NULL, 0, 0);
}

Pulizia
Questo passaggio è molto semplice. Oltre ai normali passaggi per la pulizia delle API Direct3D, l'applicazione deve rilasciare le interfacce COM restituite.

m_pD3D9Producer->Release();
m_pD3D9Consumer->Release();
m_pD3D11Producer->Release();
m_pD3D11Consumer->Release();
m_p9to11Queue->Release();
m_p11to9Queue->Release();

Uso non bloccaggio

L'esempio precedente ha senso per un caso di utilizzo multithreading in cui ogni dispositivo ha un proprio thread. Nell'esempio vengono usate le versioni di blocco delle API: INFINITE per il timeout e nessun flag da accodare. Se si vuole usare l'helper in modo non bloccante, è necessario apportare solo alcune modifiche. In questa sezione viene illustrato l'uso non bloccaggio con entrambi i dispositivi in un thread.

Inizializzazione
L'inizializzazione è identica ad eccezione dei flag. Poiché l'applicazione è a thread singolo, usare tale flag per la creazione. Ciò disattiva parte del codice di sincronizzazione, che potenzialmente migliora le prestazioni.

SURFACE_QUEUE_DESC Desc;
Desc.Width        = 640;
Desc.Height       = 480;
Desc.Format       = DXGI_FORMAT_R16G16B16A16_FLOAT;
Desc.NumSurfaces  = 2;
Desc.MetaDataSize = sizeof(UINT);
Desc.Flags        = SURFACE_QUEUE_FLAG_SINGLE_THREADED;

CreateSurfaceQueue(&Desc, m_pD3D9Device, &m_11to9Queue);
SURFACE_QUEUE_CLONE_DESC Desc;
Desc.MetaDataSize = 0;
Desc.Flags        = SURFACE_QUEUE_FLAG_SINGLE_THREADED;

m_11to9Queue->Clone(&Desc, &m_9to11Queue);

L'apertura dei dispositivi producer e consumer è identica a quella dell'esempio di blocco.
Uso della coda
Esistono molti modi per usare la coda in modo non bloccativo con varie caratteristiche delle prestazioni. L'esempio seguente è semplice ma presenta prestazioni scarse a causa di un numero eccessivo di rotazioni e polling. Nonostante questi problemi, nell'esempio viene illustrato come usare l'helper. L'approccio consiste nel rimanere costantemente seduti in un ciclo e dequeue, processo, accodamento e scaricamento. Se uno dei passaggi ha esito negativo perché la risorsa non è disponibile, l'applicazione tenta semplicemente di nuovo il ciclo successivo.

// Direct3D 11 Device.
ID3D11Texture2D* pSurface11 = NULL;
REFIID           surfaceID11 = __uuidof(ID3D11Texture2D);
UINT             metaData;
while (!done)
{
    //
    // D3D11 Portion.
    //

    // Dequeue surface.
    hr = m_pD3D11Consumer->Dequeue(surfaceID11,
                                   (void**)&pSurface11,
                                   NULL, 0, 0);
    // Only continue if we got a surface.
    if (SUCCEEDED(hr))
    {
        // Process the surface and return some meta data.
        ProcessD3D11(pSurface11, &metaData);

        // Enqueue surface.
        m_pD3D11Producer->Enqueue(pSurface11, &metaData,
                                  sizeof(UINT),
                                  SURFACE_QUEUE_FLAG_DO_NOT_WAIT);
    }
    // Flush the queue to check if any surfaces completed.
    m_pD3D11Producer->Flush(NULL,SURFACE_QUEUE_FLAG_DO_NOT_WAIT);

    //
    // Do the same with the Direct3D 9 Device.
    //

    // Dequeue surface.
    hr = m_pD3D9Consumer->Dequeue(surfaceID9,
                                  (void**)&pSurface9,
                                  &metaData,
                                  &metaDataSize, 0);
    // Only continue if we got a surface.
    if (SUCCEEDED(hr)))
    {
        // Process the surface.
        ProcessD3D9(pSurface9);

        // Present the surface using the meta data.
        PresentD3D9(pSurface9, metaData, metaDataSize);

        // Enqueue surface.
        m_pD3D9Producer->Enqueue(pSurface9, NULL, 0,
                                 SURFACE_QUEUE_FLAG_DO_NOT_WAIT);
    }
    // Flush the queue to check if any surfaces completed.
    m_pD3D9Producer->Flush(NULL,SURFACE_QUEUE_FLAG_DO_NOT_WAIT);
}

Una soluzione più complessa potrebbe controllare il valore restituito dall'accodamento e dallo scaricamento per determinare se lo scaricamento è necessario.

Tre dispositivi

L'estensione degli esempi precedenti per coprire più dispositivi è semplice. Il codice seguente esegue l'inizializzazione. Dopo aver creato gli oggetti Producer/Consumer, il codice da usare è lo stesso. Questo esempio include tre dispositivi e quindi tre code. Le superfici passano da Direct3D 9 a Direct3D 10 a Direct3D 11.

SURFACE_QUEUE_DESC Desc;
Desc.Width        = 640;
Desc.Height       = 480;
Desc.Format       = DXGI_FORMAT_R16G16B16A16_FLOAT;
Desc.NumSurfaces  = 2;
Desc.MetaDataSize = sizeof(UINT);
Desc.Flags        = 0;

SURFACE_QUEUE_CLONE_DESC Desc;
Desc.MetaDataSize = 0;
Desc.Flags        = 0;

CreateSurfaceQueue(&Desc, m_pD3D9Device, &m_11to9Queue);
m_11to9Queue->Clone(&Desc, &m_9to10Queue);
m_11to9Queue->Clone(&Desc, &m_10to11Queue);

Come accennato in precedenza, la clonazione funziona allo stesso modo, indipendentemente dalla coda clonata. Ad esempio, la seconda chiamata Clone potrebbe essere stata disattivata dall'oggetto m_9to10Queue.

// Open for m_p9to10Queue.
m_p9to10Queue->OpenProducer(m_pD3D9Device, &m_pD3D9Producer);
m_p9to10Queue->OpenConsumer(m_pD3D10Device, &m_pD3D10Consumer);

// Open for m_p10to11Queue.
m_p10to11Queue->OpenProducer(m_pD3D10Device, &m_pD3D10Producer);
m_p10to11Queue->OpenConsumer(m_pD3D11Device, &m_pD3D11Consumer);

// Open for m_p11to9Queue.
m_p11to9Queue->OpenProducer(m_pD3D11Device, &m_pD3D11Producer);
m_p11to9Queue->OpenConsumer(m_pD3D9Device, &m_pD3D9Consumer);

Conclusione

È possibile creare soluzioni che usano l'interoperabilità per sfruttare la potenza di più API DirectX. L'interoperabilità dell'API grafica Windows offre ora un runtime di gestione della superficie comune DXGI 1.1. Questo runtime abilita il supporto per la condivisione della superficie sincronizzata nelle API appena sviluppate, ad esempio Direct3D 11, Direct3D 10.1 e Direct2D. I miglioramenti dell'interoperabilità tra le nuove API e le API esistenti consentono la migrazione delle applicazioni e la compatibilità con le versioni precedenti. Le API consumer Direct3D 9Ex e DXGI 1.1 possono interagire, come illustrato con il meccanismo di sincronizzazione fornito tramite il codice helper di esempio in MSDN Code Gallery.