Share via


Windows グラフィックス API 間のサーフェス共有

このトピックでは、Direct3D 11、Direct2D、DirectWrite、Direct3D 10、Direct3D 9Ex など、Windows グラフィックス API 間のサーフェス共有を使用した相互運用性の技術的な概要について説明します。 これらの API に関する実用的な知識が既にある場合、このペーパーは、Windows 7 または Windows Vista オペレーティング システム用に設計されたアプリケーションで、複数の API を使用して同じサーフェスにレンダリングするのに役立ちます。 このトピックでは、ベスト プラクティスのガイドラインと、追加のリソースへのポインターについても説明します。

Note

DirectX 11.1 ランタイムでの Direct2D とDirectWriteの相互運用性のために、Direct2D デバイスとデバイス コンテキストを使用して Direct3D 11 デバイスに直接レンダリングできます。

 

このトピックは、次のセクションで構成されています。

はじめに

このドキュメントでは、Windows グラフィックス API の相互運用性は、異なる API による同じレンダリング サーフェイスの共有を指します。 この種の相互運用性により、アプリケーションは複数の Windows グラフィックス API を利用して魅力的なディスプレイを作成し、既存の API との互換性を維持することで新しいテクノロジへの移行を容易にできます。

Windows 7 (および Windows 7 Interop Pack、Vista 7IP を使用した Windows Vista SP2) では、グラフィックス レンダリング API は、Direct3D 11、Direct2D、Direct3D 10.1、Direct3D 10.0、Direct3D 9Ex、Direct3D 9c 以前の Direct3D API、GDI+です。 Windows Imaging Component (WIC) と DirectWrite は画像処理に関連するテクノロジであり、Direct2D はテキスト レンダリングを実行します。 Direct3D 9c と Direct3D 9Ex に基づく DirectX Video Acceleration API (DXVA) は、ビデオ処理に使用されます。

Windows グラフィックス API が Direct3D ベースに向かって進化するにつれて、Microsoft は API 間の相互運用性を確保するためにより多くの労力を費やしています。 新しく開発された Direct3D API と Direct3D API に基づく上位レベルの API は、古い API との互換性をブリッジするために必要な場合にもサポートを提供します。 説明するために、Direct2D アプリケーションでは、Direct3D 10.1 デバイスを共有することで Direct3D 10.1 を使用できます。 また、Direct3D 11、Direct2D、および Direct3D 10.1 API はすべて DirectX Graphics Infrastructure (DXGI) 1.1 を利用できます。これにより、これらの API 間の相互運用性を完全にサポートする同期共有サーフェスが可能になります。 DXGI 1.1 ベースの API は、DXGI 1.1 サーフェスから GDI デバイス コンテキストを取得することで、GDI および GDI+ と関連付けて相互運用します。 詳細については、MSDN で入手できる DXGI と GDI の相互運用性に関するドキュメントを参照してください。

同期されていないサーフェス共有は、Direct3D 9Ex ランタイムでサポートされています。 DXVA ベースのビデオ アプリケーションでは、Direct3D 9Ex ベースの DXVA 相互運用性ヘルパーと Direct3D 9Ex ベースの DXVA 相互運用性ヘルパーを使用してコンピューティング シェーダー用に Direct3D 11 を使用したり、2D コントロールまたはテキスト レンダリング用に Direct2D と相互運用したりできます。 WIC とDirectWrite GDI、Direct2D、および関連付けによって、他の Direct3D API と相互運用することもできます。

Direct3D 10.0、Direct3D 9c、および以前の Direct3D ランタイムは、共有サーフェスをサポートしていません。 システム メモリ コピーは、GDI または DXGI ベースの API との相互運用性のために引き続き使用されます。

このドキュメント内の相互運用性シナリオでは、同じアプリケーション ウィンドウではなく、共有レンダリング サーフェイスにレンダリングする複数のグラフィックス API が参照されることに注意してください。 同じウィンドウに合成されるさまざまなサーフェスをターゲットとする個別の API の同期は、このペーパーの範囲外です。

API 相互運用性の概要

Windows グラフィックス API のサーフェス共有相互運用性は、API 間シナリオと対応する相互運用性機能の観点から説明できます。 Windows 7 以降、Windows Vista SP2 と 7IP 以降では、新しい API と関連するランタイムには、Direct2D と関連テクノロジ (Direct3D 11 と DXGI 1.1) が含まれています。 GDI のパフォーマンスは Windows 7 でも向上しました。 Direct3D 10.1 は Windows Vista SP1 で導入されました。 次の図は、API 間の相互運用性のサポートを示しています。

Windows グラフィックス API 間の相互運用性のサポートの図

この図では、矢印は、接続されている API から同じサーフェスにアクセスできる相互運用性シナリオを示しています。 青い矢印は、Windows Vista で導入された相互運用性メカニズムを示します。 緑色の矢印は、新しい API の相互運用性のサポート、または古い API が新しい API と相互運用するのに役立つ機能強化を示しています。 たとえば、緑色の矢印は、デバイス共有、同期された共有サーフェスのサポート、Direct3D 9Ex/DXGI 同期ヘルパー、互換性のあるサーフェスから GDI デバイス コンテキストを取得することを表します。

相互運用性のシナリオ

Windows 7 および Windows Vista 7IP の時点で、Windows グラフィックス API のメインストリーム オファリングでは、同じ DXGI 1.1 サーフェスへの複数の API レンダリングがサポートされています。

Direct3D 11、Direct3D 10.1、Direct2D — 相互の相互運用性

Direct3D 11、Direct3D 10.1、Direct2D API (およびDirectWriteや WIC などの関連 API) は、Direct3D 10.1 デバイス共有または同期された共有サーフェスを使用して相互に相互運用できます。

Direct3D 10.1 デバイスと Direct2D の共有

Direct2D と Direct3D 10.1 の間のデバイス共有により、アプリケーションは両方の API を使用して、同じ基になる Direct3D デバイス オブジェクトを使用して、同じ DXGI 1.1 サーフェスにシームレスかつ効率的にレンダリングできます。 Direct2D では、Direct3D 10.1 と DXGI 1.1 のランタイム上に Direct2D が構築されているという事実を利用して、既存の Direct3D 10.1 デバイスを使用して Direct2D API を呼び出す機能が提供されます。 次のコード スニペットは、Direct2D がデバイスに関連付けられている DXGI 1.1 サーフェスから Direct3D 10.1 デバイス レンダー ターゲットを取得する方法を示しています。 Direct3D 10.1 デバイス レンダー ターゲットは、BeginDraw API と EndDraw API の間で Direct2D 描画呼び出しを実行できます。

// 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);

解説

  • 関連付けられている Direct3D 10.1 デバイスは、BGRA 形式をサポートしている必要があります。 そのデバイスは、パラメーター D3D10_CREATE_DEVICE_BGRA_SUPPORTを使用して D3D10CreateDevice1 を呼び出すことによって作成されました。 BGRA 形式は、Direct3D 10 機能レベル 9.1 以降でサポートされています。
  • アプリケーションでは、同じ Direct3D10.1 デバイスに関連付けられている複数の ID2D1RenderTargets を作成しないでください。
  • 最適なパフォーマンスを得るには、デバイスに関連付けられているテクスチャやサーフェスなど、常に少なくとも 1 つのリソースを保持します。

デバイス共有は、Direct3D 10.1 と Direct2D レンダリング API の両方で共有される 1 つのレンダリング デバイスのインプロセスシングルスレッド使用に適しています。 同期された共有サーフェスを使用すると、Direct3D 10.1、Direct2D、Direct3D 11 API で使用される複数のレンダリング デバイスのマルチスレッド、インプロセス、アウトプロセスの使用が可能になります。

Direct3D 10.1 と Direct2D の相互運用性のもう 1 つの方法は、ID3D1RenderTarget::CreateSharedBitmap を使用して IDXGISurface から ID2D1Bitmap オブジェクトを作成することです。 Direct3D10.1 シーンをビットマップに書き込み、Direct2D でレンダリングできます。 詳細については、「 ID2D1RenderTarget::CreateSharedBitmap メソッド」を参照してください。

Direct2D ソフトウェアのラスター化

Direct3D 10.1 を使用したデバイス共有は、Direct2D ソフトウェア レンダラーを使用する場合はサポートされません。たとえば、Direct2D レンダー ターゲットの作成時に D2D1_RENDER_TARGET_USAGE でD2D1_RENDER_TARGET_USAGE_FORCE_SOFTWARE_RENDERINGを指定するなどです。

Direct2D は WARP10 ソフトウェア ラスタライザーを使用して、デバイスを Direct3D 10 または Direct3D 11 と共有できますが、パフォーマンスは大幅に低下します。

DXGI 1.1 同期共有サーフェス

Direct3D 11、Direct3D 10.1、および Direct2D API はすべて DXGI 1.1 を使用します。これは、2 つ以上の Direct3D デバイスによって同じビデオ メモリ サーフェス (DXGISurface1) との間で読み取りと書き込みを同期する機能を提供します。 同期された共有サーフェスを使用するレンダリング デバイスは、Direct3D 10.1 または Direct3D 11 デバイスで、それぞれ同じプロセスまたはクロスプロセスで実行できます。

アプリケーションでは、Direct2D レンダー ターゲット オブジェクトから Direct3D 10.1 デバイスを取得することで、同期された共有サーフェスを使用して、Direct3D 11 や Direct3D 10.1 などの DXGI 1.1 ベースのデバイス間、または Direct3D 11 と Direct2D の間で相互運用できます。

Direct3D 10.1 以降の API で DXGI 1.1 を使用するには、DXGI 1.1 ファクトリ オブジェクトから列挙された DXGI 1.1 アダプター オブジェクトを使用して Direct3D デバイスが作成されていることを確認します。 CreateDXGIFactory1 を呼び出して IDXGIFactory1 オブジェクトを作成し、EnumAdapters1 を呼び出して IDXGIAdapter1 オブジェクトを列挙します。 IDXGIAdapter1 オブジェクトは、D3D10CreateDevice または D3D10CreateDeviceAndSwapChain 呼び出しの一部として渡す必要があります。 DXGI 1.1 API の詳細については、 DXGI のプログラミング ガイドを参照してください。

API

D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX
同期された共有リソースを作成するときは、D3D10_RESOURCE_MISC_FLAGでD3D10_RESOURCE_MISC_SHARED_KEYEDMUTEXを設定します。

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
IDXGIKeyedMutex::AcquireSync および ReleaseSync API を使用して、作成されたリソースを同期できるようにします。 次のリソース作成 Direct3D 10.1 API では、すべて D3D10_RESOURCE_MISC_FLAG パラメーターを受け取り、新しいフラグをサポートするように拡張されています。

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

一覧表示されている関数のいずれかが D3D10_RESOURCE_MISC_SHARED_KEYEDMUTEX フラグを設定して呼び出された場合、返されるインターフェイスに対して IDXGIKeyedMutex インターフェイスを照会できます。このインターフェイスは、AcquireSync API と ReleaseSync API を実装して、サーフェスへのアクセスを同期します。 サーフェスを作成するデバイスと、サーフェスを開く他のデバイス (OpenSharedResource を使用) は、サーフェスへのレンダリング コマンドの前に IDXGIKeyedMutex::AcquireSync を呼び出し、レンダリングが完了したときに IDXGIKeyedMutex::ReleaseSync を呼び出す必要があります。
WARP および REF デバイスは、共有リソースをサポートしていません。 WARP または REF デバイスでこのフラグを持つリソースを作成しようとすると、create メソッドはE_OUTOFMEMORYエラー コードを返します。
IDXGIKEYEDMUTEX インターフェイス
DXGI 1.1 の新しいインターフェイス IDXGIKeyedMutex は、キー付きミューテックスを表します。これにより、複数のデバイスで使用される共有リソースへの排他的アクセスが許可されます。 このインターフェイスとその 2 つのメソッド (AcquireSync と ReleaseSync) のリファレンス ドキュメントについては、「 IDXGIKeyedMutex」を参照してください。

サンプル: 2 つの Direct3D 10.1 デバイス間の同期サーフェス共有

次の例は、2 つの Direct3D 10.1 デバイス間でサーフェスを共有する方法を示しています。 同期された共有サーフェスは、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;

同じ Direct3D10.1 デバイスは、AcquireSync を呼び出し、ReleaseSync を呼び出して他のデバイスのレンダリング用のサーフェスを解放することで、レンダリング用の同期された共有サーフェスを取得できます。 同期された共有サーフェスを他の Direct3D デバイスと共有しない場合、作成者は、同じキー値を使用して取得および解放することで、同期された共有サーフェスを取得および解放できます (レンダリングの開始と終了)。

// 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;

2 つ目の Direct3D10.1 デバイスは、AcquireSync を呼び出し、ReleaseSync を呼び出して最初のデバイスのレンダリング用のサーフェスを解放することで、レンダリング用の同期された共有サーフェスを取得できます。 デバイス 2 は、デバイス 1 による ReleaseSync 呼び出しで指定されたものと同じキー値を使用して、同期された共有サーフェスを取得できることに注意してください。

// 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;

同じサーフェスを共有する追加のデバイスでは、次の呼び出しに示すように、追加のキーを使用して、サーフェスの取得と解放を順番に行うことができます。

// 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);
...

実際のアプリケーションは、常に中間サーフェスにレンダリングされ、その後共有サーフェスにコピーされ、1 つのデバイスがサーフェスを共有する別のデバイスで待機するのを防ぐことに注意してください。

Direct2D および Direct3D 11 での同期された共有サーフェスの使用

同様に、Direct3D 11 と Direct3D 10.1 API の間で共有する場合、同期された共有サーフェスは、いずれかの API デバイスから作成し、プロセス内またはプロセス外で他の API デバイスと共有できます。

Direct2D を使用するアプリケーションは、Direct3D 10.1 デバイスを共有し、同期された共有サーフェスを使用して、同じプロセスまたは異なるプロセスに属しているかどうかに関係なく、Direct3D 11 またはその他の Direct3D 10.1 デバイスと相互運用できます。 ただし、単一プロセスのシングルスレッド アプリケーションの場合、デバイス共有は、Direct2D と Direct3D 10 または Direct3D 11 の間の相互運用性の最も高いパフォーマンスと効率的な方法です。

ソフトウェア ラスタライザー

同期された共有サーフェスは、アプリケーションがグラフィックス ハードウェア アクセラレーションを使用する代わりに、参照ラスタライザーや WARP を含む Direct3D または Direct2D ソフトウェア ラスタライザーを使用する場合はサポートされません。

Direct3D 9Ex と DXGI ベースの API の相互運用性

Direct3D 9Ex API には、他の API が共有サーフェスから読み取ることができるように、サーフェス共有の概念が含まれていました。 Direct3D 9Ex 共有サーフェイスに読み取りと書き込みを共有するには、アプリケーション自体に手動同期を追加する必要があります。

Direct3D 9Ex 共有サーフェスと手動同期ヘルパー

Direct3D 9Ex と Direct3D 10 または 11 の相互運用性の最も基本的なタスクは、最初のデバイス (デバイス A) から 2 番目の (デバイス B) に 1 つのサーフェスを渡すことです。これにより、デバイス B がサーフェス上のハンドルを取得すると、デバイス A のレンダリングが完了することが保証されます。 そのため、デバイスBは心配なくこの表面を使用することができます。 これは、従来のプロデューサーとコンシューマーの問題によく似ています。このディスカッションでは、その方法で問題をモデル化します。 サーフェスを使用し、それを放棄する最初のデバイスはプロデューサー (デバイス A)、最初に待機しているデバイスはコンシューマー (デバイス B) です。 実際のアプリケーションはこれよりも高度であり、複数のプロデューサー/コンシューマーの構成要素を連結して目的の機能を作成します。

プロデューサー コンシューマーの構成要素は、サーフェスのキューを使用してヘルパーに実装されます。 サーフェスはプロデューサーによってエンキューされ、コンシューマーによってデキューされます。 ヘルパーには、ISurfaceQueue、ISurfaceProducer、ISurfaceConsumer の 3 つの COM インターフェイスが導入されています。

High-Level ヘルパーの概要

ISurfaceQueue オブジェクトは、共有サーフェスを使用するための構成要素です。 初期化された Direct3D デバイスと、固定数の共有サーフェスを作成するための説明を使用して作成されます。 queue オブジェクトは、リソースの作成とコードのオープンを管理します。 サーフェスの数と種類は固定されています。サーフェスが作成されると、アプリケーションはサーフェスを追加または削除できません。

ISurfaceQueue オブジェクトの各インスタンスは、生産デバイスから使用するデバイスにサーフェスを送信するために使用できる一方向の通りを提供します。 このような一方向の道路を複数使用して、特定のアプリケーションのデバイス間でサーフェス共有シナリオを有効にすることができます。

作成/オブジェクトの有効期間
キュー オブジェクトを作成するには、CreateSurfaceQueue または ISurfaceQueue の Clone メソッドの 2 つの方法があります。 インターフェイスは COM オブジェクトであるため、標準の COM 有効期間管理が適用されます。
プロデューサー/コンシューマー モデル
エンキュー (): プロデューサーはこの関数を呼び出して、サーフェスで実行されていることを示します。これにより、別のデバイスで使用できるようになります。 この関数から戻ると、プロデューサー デバイスはサーフェスに対する権限を持たなくなり、使用を続けるのは安全ではありません。
Dequeue (): 使用しているデバイスは、この関数を呼び出して共有サーフェスを取得します。 API は、デキューされたサーフェスを使用する準備ができていることを保証します。
メタデータ
API では、メタデータと共有サーフェスの関連付けがサポートされています。
Enqueue() には、使用するデバイスに渡される追加のメタデータを指定するオプションがあります。 メタデータは、作成時に既知の最大値未満である必要があります。
Dequeue() は、必要に応じてバッファーとバッファーのサイズへのポインターを渡すことができます。 キューは、対応するエンキュー呼び出しのメタデータをバッファーに格納します。
複製
各 ISurfaceQueue オブジェクトは、一方向の同期を解決します。 この API を使用するアプリケーションの大部分では、閉じたシステムを使用すると想定しています。 2 つのデバイスがサーフェスを送受信する最も単純な閉じたシステムには、2 つのキューが必要です。 ISurfaceQueue オブジェクトには Clone() メソッドがあり、同じ大きなパイプラインの一部である複数のキューを作成できます。
Clone は、既存の ISurfaceQueue オブジェクトから新しい ISurfaceQueue オブジェクトを作成し、その間で開いているすべてのリソースを共有します。 結果のオブジェクトは、ソース キューとまったく同じサーフェスを持ちます。 複製されたキューは、互いに異なるメタデータ サイズを持つことができます。
Surfaces
ISurfaceQueue は、そのサーフェスの作成と管理を担当します。 任意のサーフェスをエンキューすることはできません。 さらに、サーフェスにはアクティブな "所有者" が 1 つだけ必要です。特定のキュー上にあるか、特定のデバイスで使用されている必要があります。 複数のキューに配置することも、デバイスがエンキューされた後もサーフェスを引き続き使用することは無効です。

API の詳細

IsurfaceQueue

キューは、共有リソースの作成と保守を担当します。 また、Clone を使用して複数のキューをチェーンする機能も提供します。 キューには、生成デバイスと消費デバイスを開くメソッドがあります。 いつでも開くことができるのは、それぞれ 1 つだけです。

キューは、次の API を公開します。

API 説明
CreateSurfaceQueue ISurfaceQueue オブジェクト ("ルート" キュー) を作成します。
ISurfaceQueue::OpenConsumer デキューする使用デバイスのインターフェイスを返します。
ISurfaceQueue::OpenProducer エンキューする生成デバイスのインターフェイスを返します。
ISurfaceQueue::Clone ルート キュー オブジェクトとサーフェスを共有する ISurfaceQueue オブジェクトを作成します。

 

CreateSurfaceQueue

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

[メンバー]

[幅]、[ 高さ] 共有サーフェスの寸法。 共有サーフェスはすべて同じ寸法を持つ必要があります。
形式 共有サーフェスの形式。 すべての共有サーフェスの形式は同じである必要があります。 有効な形式は、使用されるデバイスによって異なります。デバイスのペアによって異なる形式の種類を共有できるためです。
NumSurfaces キューの一部であるサーフェスの数。 これは固定番号です。
MetaDataSize メタデータ バッファーの最大サイズ。
フラグ キューの動作を制御するためのフラグ。 「解説」を参照してください。

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

パラメーター

pDesc [in] 作成する共有サーフェス キューの説明。

pDevice [in] 共有サーフェスの作成に使用するデバイス。 これは、Windows Vista の機能のため、明示的なパラメーターです。 Direct3D 9 と Direct3D 10 の間で共有されるサーフェスの場合、サーフェスは Direct3D 9 で作成する必要があります。

ppQueue [out] 戻り値には、ISurfaceQueue オブジェクトへのポインターが含まれます。

戻り値

pDevice がリソースを共有できない場合、この関数は DXGI_ERROR_INVALID_CALLを返します。 この関数は、リソースを作成します。 失敗した場合は、エラーが返されます。 成功した場合は、S_OKを返します。

解説

キュー オブジェクトを作成すると、すべてのサーフェスも作成されます。 すべてのサーフェスは 2D レンダー ターゲットであると見なされ、D3D10_BIND_RENDER_TARGETフラグとD3D10_BIND_SHADER_RESOURCE フラグが設定された状態で作成されます (または、異なるランタイムに対応するフラグ)。

開発者は、キューに複数のスレッドがアクセスするかどうかを示すフラグを指定できます。 フラグが設定されていない場合 (Flags == 0)、キューは複数のスレッドで使用されます。 開発者はシングル スレッド アクセスを指定できます。これにより同期コードがオフになり、そのような場合のパフォーマンスが向上します。 複製された各キューには独自のフラグがあるため、システム内の異なるキューで異なる同期制御を行うことができます。

プロデューサーを開く

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

パラメーター

pDevice [in]

サーフェスをサーフェス キューにエンキューするプロデューサー デバイス。

ppProducer [out] オブジェクトをプロデューサー インターフェイスに返します。

戻り値

デバイスがサーフェスを共有できない場合は、DXGI_ERROR_INVALID_CALLを返します。

コンシューマーを開く

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

パラメーター
pDevice [in]
サーフェス キューからサーフェスをデキューするコンシューマー デバイス。 ppConsumer [out] オブジェクトをコンシューマー インターフェイスに返します。

戻り値

デバイスがサーフェスを共有できない場合は、DXGI_ERROR_INVALID_CALLを返します。

解説

この関数は、入力デバイスのキュー内のすべてのサーフェスを開き、キャッシュします。 Dequeue への後続の呼び出しは単にキャッシュに移動し、毎回サーフェスを再度開く必要はありません。

IDXGIXSurfaceQueue の複製

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

メンバーMetaDataSizeFlags の動作は、CreateSurfaceQueue の場合と同じです。

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

パラメーター

pDesc [in] 作成する Clone オブジェクトの説明を提供する構造体。 このパラメーターは初期化する必要があります。
ppQueue [out] 初期化されたオブジェクトを返します。

解説

ルートではない場合でも、既存のキュー オブジェクトから複製できます。

IDXGIXSurfaceConsumer

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

パラメーター
id [in]
使用するデバイスの 2D サーフェスの REFIID。

  • IDirect3DDevice9 の場合、REFIID は __uuidof(IDirect3DTexture9) である必要があります。
  • ID3D10Device の場合、REFIID は __uuidof(ID3D10Texture2D) である必要があります。
  • ID3D11Device の場合、REFIID は __uuidof(ID3D11Texture2D) である必要があります。

ppSurface [out] サーフェスへのポインターを返します。
pBuffer [in, out] 省略可能なパラメーターであり、 NULL でない場合、戻り値には、対応するエンキュー呼び出しで渡されたメタデータが含まれます。
pBufferSize [in, out] pBuffer のサイズ (バイト単位)。 pBuffer で返されるバイト数を返します。 エンキュー呼び出しでメタデータが提供されなかった場合、 pBuffer は 0 に設定されます。
dwTimeout [in] タイムアウト値を指定します。 詳細については、「備考」を参照してください。

戻り値

タイムアウト値が指定されていて、タイムアウト値の前に関数が戻らない場合、この関数はWAIT_TIMEOUTを返すことができます。 「解説」を参照してください。 使用可能なサーフェスがない場合、この関数は ppSurfaceNULL に設定し、 pBufferSize を 0 に設定し、戻り値を0x80070120 (WIN32_TO_HRESULT(WAIT_TIMEOUT)) で返します。

解説

キューが空の場合、この API はブロックできます。 dwTimeout パラメーターは、WaitForSingleObject などの Windows 同期 API と同じように機能します。 非ブロッキング動作の場合は、タイムアウト 0 を使用します。

ISurfaceProducer

このインターフェイスには、アプリがサーフェスをエンキューできるようにする 2 つのメソッドが用意されています。 サーフェスがエンキューされると、サーフェス ポインターは無効になり、安全に使用できなくなります。 アプリケーションがポインターを使用して実行する必要がある唯一のアクションは、それを解放することです。

メソッド 説明
ISurfaceProducer::Enqueue キュー オブジェクトにサーフェスをエンキューします。 この呼び出しが完了すると、プロデューサーはサーフェスを使用して完了し、サーフェスは別のデバイスの準備が整います。
ISurfaceProducer::Flush アプリケーションに非ブロッキング動作が必要な場合に使用されます。 詳細については、「解説」を参照してください。

 

Enqueue

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

パラメーター
pSurface [in]
エンキューする必要がある製造デバイスの表面。 このサーフェスは、同じキュー ネットワークからのデキューサーフェスである必要があります。 pBuffer [in] メタデータの渡しに使用される省略可能なパラメーター。 デキュー呼び出しに渡されるデータを指している必要があります。
BufferSize [in] pBuffer のサイズ (バイト単位)。
Flags [in] この関数の動作を制御する省略可能なパラメーター。 唯一のフラグはSURFACE_QUEUE_FLAG_ DO_NOT_WAITです。 「Flush の備考」を参照してください。 フラグが渡されない場合 (Flags == 0)、既定のブロック動作が使用されます。

戻り値

この関数は、SURFACE_QUEUE_FLAG_DO_NOT_WAIT フラグが使用されている場合にDXGI_ERROR_WAS_STILL_DRAWINGを返すことができます。

解説

  • この関数は、サーフェスをキューに配置します。 アプリケーションでSURFACE_QUEUE_FLAG_DO_NOT_WAITを指定しない場合、この関数はブロックされており、エンキューされたサーフェス上のすべてのレンダリングが完了するように GPU と CPU の同期を実行します。 この関数が成功すると、デキューにサーフェスを使用できるようになります。 非ブロッキング動作が必要な場合は、DO_NOT_WAIT フラグを使用します。 詳細については、Flush() を参照してください。
  • COM 参照カウントルールに従って、Dequeue によって返されるサーフェスは AddRef() になるため、アプリケーションはこれを行う必要はありません。 Enqueue を呼び出した後、アプリケーションはサーフェスを使用しなくなったため、サーフェスを解放する必要があります。

フラッシュ

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

パラメーター
Flags [in]
唯一のフラグはSURFACE_QUEUE_FLAG_ DO_NOT_WAITです。 「解説」を参照してください。 nSurfaces [out] 保留中でフラッシュされていないサーフェスの数を返します。

戻り値

SURFACE_QUEUE_FLAG_DO_NOT_WAIT フラグが使用されている場合、この関数はDXGI_ERROR_WAS_STILL_DRAWINGを返すことができます。 この関数は、サーフェスが正常にフラッシュされた場合にS_OKを返します。 この関数は、サーフェスがフラッシュされなかった場合にのみDXGI_ERROR_WAS_STILL_DRAWINGを返します。 戻り値と nSurfaces は、実行された作業と、実行する作業が残っている場合にアプリケーションに示します。

解説

Flush は、エンキューの前の呼び出しで DO_NOT_WAIT フラグが使用された場合にのみ意味があります。それ以外の場合は、no-op になります。 エンキューの呼び出しで DO_NOT_WAIT フラグを使用した場合、エンキューはすぐに戻り、GPU と CPU の同期は保証されません。 サーフェスはエンキューされたと見なされますが、生成デバイスでは引き続き使用できませんが、デキューには使用できません。 デキューのサーフェスをコミットするには、Flush を呼び出す必要があります。 Flush は、現在エンキューされているすべてのサーフェスをコミットしようとします。 Flush にフラグが渡されない場合、キュー全体がブロックされ、クリアされ、キュー内のすべてのサーフェスがデキュー用に準備されます。 DO_NOT_WAIT フラグが使用されている場合、キューはサーフェスをチェックして、いずれかの準備ができているかどうかを確認します。この手順はブロックされません。 GPU と CPU の同期が完了したサーフェスは、コンシューマー デバイスの準備が整います。 まだ保留中のサーフェスは影響を受けません。 関数は、フラッシュする必要があるサーフェスの数を返します。

Note

Flush はキューのセマンティクスを中断しません。 API は、GPU-CPU 同期がいつ行われるかに関係なく、後でエンキューされるサーフェスの前に、最初にエンキューされたサーフェスがコミットされることを保証します。

 

Direct3D 9Ex および DXGI 相互運用ヘルパー: 使用方法

ほとんどのユース ケースには、多数のサーフェスを共有する 2 つのデバイスが含まれることが予想されます。 これは最も簡単なシナリオでもあるため、このペーパーでは、API を使用してこの目標を達成する方法について詳しく説明し、非ブロッキングバリエーションについて説明し、3 つのデバイスの初期化に関する簡単なセクションで終わります。

2 つのデバイス

このヘルパーを使用するアプリケーション例では、Direct3D 9Ex と Direct3D 11 を一緒に使用できます。 アプリケーションでは、両方のデバイスでコンテンツを処理し、Direct3D 9 を使用してコンテンツを表示できます。 処理とは、コンテンツのレンダリング、ビデオのデコード、コンピューティング シェーダーの実行などを意味します。 すべてのフレームについて、アプリケーションは最初に Direct3D 11 で処理し、次に Direct3D 9 で処理し、最後に Direct3D 9 を使用して処理します。 さらに、Direct3D 11 を使用した処理では、Direct3D 9 で使用する必要があるメタデータがいくつか生成されます。 このセクションでは、このシーケンスに対応する 3 つの部分 (初期化、メイン ループ、クリーンアップ) のヘルパーの使用方法について説明します。

初期化
初期化には、次の手順が含まれます。

  1. 両方のデバイスを初期化します。
  2. ルート キュー: m_11to9Queueを作成します。
  3. ルート キューから複製する: m_9to11Queue。
  4. 両方のキューで OpenProducer/OpenConsumer を呼び出します。

キュー名では、9 と 11 の数値を使用して、プロデューサーである API とコンシューマーを示します。コンシューマーキューへのm_producer したがって、m_11to9Queueは、Direct3D 11 デバイスが Direct3D 9 デバイスが使用するサーフェスを生成するキューを示します。 同様に、m_9to11Queueは、Direct3D 9 が Direct3D 11 で使用するサーフェスを生成するキューを示します。
ルート キューは最初はいっぱいで、複製されたすべてのキューは最初は空です。 これは、エンキューとデキューの最初のサイクルとメタデータの可用性を除き、アプリケーションにとって問題になりません。 デキューがメタデータを要求したが、何も設定されていない場合 (最初は何も存在しないか、エンキューが何も設定していないため)、dequeue はメタデータが受信されなかったことを確認します。

  1. 両方のデバイスを初期化します。

    m_pD3D9Device = InitializeD3D9ExDevice();
    m_pD3D11Device = InitializeD3D11Device();
    
  2. ルート キューを作成します。
    この手順では、サーフェスも作成されます。 サイズと形式の制限は、共有リソースの作成と同じです。 メタデータ バッファーのサイズは作成時に固定され、この場合は UINT を渡すだけです。
    キューは、固定数のサーフェスで作成する必要があります。 パフォーマンスはシナリオによって異なります。 複数のサーフェスを使用すると、デバイスがビジー状態の可能性が高くなります。 たとえば、サーフェスが 1 つしかない場合、2 つのデバイス間で並列化は行われません。 一方、サーフェスの数を増やすとメモリ占有領域が増加し、パフォーマンスが低下する可能性があります。 この例では、2 つのサーフェスを使用します。

    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. ルート キューを複製します。
    複製された各キューは同じサーフェスを使用する必要がありますが、異なるメタデータ バッファー サイズと異なるフラグを持つことができます。 この場合、Direct3D 9 から Direct3D 11 へのメタデータはありません。

    SURFACE_QUEUE_CLONE_DESC Desc;
    Desc.MetaDataSize = 0;
    Desc.Flags        = 0;
    
    m_11to9Queue->Clone(&Desc, &m_9to11Queue);
    
  4. プロデューサー デバイスとコンシューマー デバイスを開きます。
    アプリケーションは、Enqueue と Dequeue を呼び出す前に、この手順を実行する必要があります。 プロデューサーとコンシューマーを開くと、エンキュー/デキュー API を含むインターフェイスが返されます。

    // 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);
    

メイン ループ
キューの使用は、従来のプロデューサー/コンシューマーの問題の後にモデル化されます。 これは、デバイスごとの観点から考えてください。 各デバイスは、次の手順を実行する必要があります。デキューを使用しているキューからサーフェスを取得し、サーフェス上で処理してから、生成キューにエンキューします。 Direct3D 11 デバイスの場合、Direct3D 9 の使用はほぼ同じです。

// 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);
}

クリーンアップ
この手順は非常に簡単です。 Direct3D API をクリーンアップするための通常の手順に加えて、アプリケーションはリターン COM インターフェイスを解放する必要があります。

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

非ブロッキングの使用

前の例は、各デバイスに独自のスレッドがあるマルチスレッドの使用ケースに適しています。 この例では、ブロッキング バージョンの API を使用しています。タイムアウトには INFINITE、エンキューするフラグはありません。 ヘルパーを非ブロッキングの方法で使用する場合は、いくつかの変更のみを行う必要があります。 このセクションでは、1 つのスレッド上の両方のデバイスでの非ブロッキングの使用を示します。

初期化
初期化は、 フラグを除いて同じです。 アプリケーションはシングル スレッドであるため、作成にはそのフラグを使用します。 これにより、一部の同期コードがオフになり、パフォーマンスが向上する可能性があります。

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);

プロデューサー デバイスとコンシューマー デバイスを開くのは、ブロッキングの例と同じです。
キューの使用
さまざまなパフォーマンス特性を持つ非ブロッキングの方法でキューを使用する方法は多数あります。 次の例は単純ですが、過剰な回転とポーリングによりパフォーマンスが低下しています。 これらの問題にもかかわらず、この例ではヘルパーの使用方法を示しています。 このアプローチでは、常にループに入り、デキュー、プロセス、エンキュー、フラッシュを行います。 リソースが使用できないためにいずれかの手順が失敗した場合、アプリケーションは次のループを再試行するだけです。

// 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);
}

より複雑なソリューションでは、エンキューとフラッシュからの戻り値をチェックして、フラッシュが必要かどうかを判断できます。

3 つのデバイス

前の例を拡張して複数のデバイスをカバーするのは簡単です。 次のコードは、初期化を実行します。 プロデューサー/コンシューマー オブジェクトが作成された後、それらを使用するコードは同じです。 この例には 3 つのデバイスがあり、したがって 3 つのキューがあります。 サーフェスは Direct3D 9 から Direct3D 10 から 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);

前述のように、複製は、複製されるキューに関係なく、同じように動作します。 たとえば、2 番目の Clone 呼び出しは、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);

まとめ

相互運用性を使用して複数の DirectX API の機能を使用するソリューションを作成できます。 Windows グラフィックス API の相互運用性で、共通のサーフェス管理ランタイム DXGI 1.1 が提供されるようになりました。 このランタイムにより、Direct3D 11、Direct3D 10.1、Direct2D など、新しく開発された API 内での同期されたサーフェス共有のサポートが可能になります。 新しい API と既存の API 間の相互運用性の向上により、アプリケーションの移行と下位互換性が向上します。 Direct3D 9Ex および DXGI 1.1 コンシューマー API は、MSDN コード ギャラリーのサンプル ヘルパー コードを通じて提供される同期メカニズムで示されているように、相互運用できます。