共用方式為


初始化 Direct3D 11

總結

示範如何將 Direct3D 9 初始化程式代碼轉換為 Direct3D 11,包括如何取得 Direct3D 裝置和裝置內容的句柄,以及如何使用 DXGI 來設定交換鏈結。 將簡單的 Direct3D 9 應用程式移植到 DirectX 11 和通用 Windows 平臺 (UWP) 的第 1 部分 逐步解說。

初始化 Direct3D 裝置

在 Direct3D 9 中,我們透過呼叫 IDirect3D9::CreateDevice來建立 Direct3D 裝置的控制代碼。 我們首先取得 IDirect3D9 介面 的指標,並指定了一些參數來控制 Direct3D 裝置和交換鏈的組態。 執行此動作之前,我們會呼叫 GetDeviceCaps,以確保我們沒有要求裝置執行它無法執行的動作。

Direct3D 9

UINT32 AdapterOrdinal = 0;
D3DDEVTYPE DeviceType = D3DDEVTYPE_HAL;
D3DCAPS9 caps;
m_pD3D->GetDeviceCaps(AdapterOrdinal, DeviceType, &caps); // caps bits

D3DPRESENT_PARAMETERS params;
ZeroMemory(&params, sizeof(D3DPRESENT_PARAMETERS));

// Swap chain parameters:
params.hDeviceWindow = m_hWnd;
params.AutoDepthStencilFormat = D3DFMT_D24X8;
params.BackBufferFormat = D3DFMT_X8R8G8B8;
params.MultiSampleQuality = D3DMULTISAMPLE_NONE;
params.MultiSampleType = D3DMULTISAMPLE_NONE;
params.SwapEffect = D3DSWAPEFFECT_DISCARD;
params.Windowed = true;
params.PresentationInterval = 0;
params.BackBufferCount = 2;
params.BackBufferWidth = 0;
params.BackBufferHeight = 0;
params.EnableAutoDepthStencil = true;
params.Flags = 2;

m_pD3D->CreateDevice(
    0,
    D3DDEVTYPE_HAL,
    m_hWnd,
    64,
    &params,
    &m_pd3dDevice
    );

在 Direct3D 11 中,裝置內容和圖形基礎結構會視為與裝置本身分開。 初始化分為多個步驟。

首先,我們會建立裝置。 我們會取得裝置所支援的功能層級清單,這會通知我們需要知道的 GPU 大部分資訊。 此外,我們不需要建立介面來存取 Direct3D。 相反地,我們使用 D3D11CreateDevice 核心 API。 這讓我們獲得裝置及其即時上下文的參考。 設備上下文用來設定管線狀態並生成渲染命令。

建立 Direct3D 11 裝置和內容之後,我們可以利用 COM 指標功能來取得最新版本的介面,其中包括額外的功能,而且一律建議使用。

附註 D3D_FEATURE_LEVEL_9_1(對應至著色器模型 2.0)是您 Microsoft 市集遊戲所需支援的最低層級。 (如果您的遊戲的 Arm 套件不支援 9_1,則認證將會失敗。)如果您的遊戲也包含支援著色器模型 3 功能的繪圖路徑,則您應該在陣列中包含 D3D_FEATURE_LEVEL_9_3。

 

Direct3D 11

// This flag adds support for surfaces with a different color channel 
// ordering than the API default. It is required for compatibility with
// Direct2D.
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;

#if defined(_DEBUG)
// If the project is in a debug build, enable debugging via SDK Layers.
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

// This example only uses feature level 9.1.
D3D_FEATURE_LEVEL featureLevels[] = 
{
    D3D_FEATURE_LEVEL_9_1
};

// Create the Direct3D 11 API device object and a corresponding context.
ComPtr<ID3D11Device> device;
ComPtr<ID3D11DeviceContext> context;
D3D11CreateDevice(
    nullptr, // Specify nullptr to use the default adapter.
    D3D_DRIVER_TYPE_HARDWARE,
    nullptr,
    creationFlags,
    featureLevels,
    ARRAYSIZE(featureLevels),
    D3D11_SDK_VERSION, // UWP apps must set this to D3D11_SDK_VERSION.
    &device, // Returns the Direct3D device created.
    nullptr,
    &context // Returns the device immediate context.
    );

// Store pointers to the Direct3D 11.2 API device and immediate context.
device.As(&m_d3dDevice);

context.As(&m_d3dContext);

建立交換鏈

Direct3D 11 包含稱為 DirectX 圖形基礎結構 (DXGI) 的裝置 API。 DXGI 介面可讓我們(例如)控制交換鏈結的設定和設定共用裝置的方式。 在初始化 Direct3D 的此步驟中,我們將使用 DXGI 來建立交換鏈結。 由於我們建立了裝置,我們可以遵循介面鏈結回到 DXGI 適配卡。

Direct3D 裝置會實作 DXGI 的 COM 介面。 首先,我們需要取得該介面,並用它來要求裝載裝置的 DXGI 適配卡。 然後使用 DXGI 配接器來建立 DXGI 處理站。

注意 這些是 COM 介面,因此您的第一個回應可能是使用 QueryInterface。 您應該改用 Microsoft::WRL::ComPtr 智慧指標。 然後,只要呼叫 As() 方法,即可提供正確介面類型的空白 COM 指標。

 

Direct3D 11

ComPtr<IDXGIDevice2> dxgiDevice;
m_d3dDevice.As(&dxgiDevice);

// Then, the adapter hosting the device;
ComPtr<IDXGIAdapter> dxgiAdapter;
dxgiDevice->GetAdapter(&dxgiAdapter);

// Then, the factory that created the adapter interface:
ComPtr<IDXGIFactory2> dxgiFactory;
dxgiAdapter->GetParent(
    __uuidof(IDXGIFactory2),
    &dxgiFactory
    );

既然我們有了 DXGI 工廠,就可以使用它來建立交換鏈。 讓我們定義交換鏈結參數。 我們需要指定表面格式;我們將選擇 DXGI_FORMAT_B8G8R8A8_UNORM,因為它與 Direct2D 相容。 我們將關閉顯示縮放比例、多重取樣和立體聲轉譯,因為它們不會在此範例中使用。 由於我們正在 CoreWindow 中直接執行,因此可以將寬度和高度設定為 0,並自動取得全螢幕值。

注意 務必將 SDKVersion 參數設定為 D3D11_SDK_VERSION,適用於 UWP 應用程式。

 

Direct3D 11

ComPtr<IDXGISwapChain1> swapChain;
dxgiFactory->CreateSwapChainForCoreWindow(
    m_d3dDevice.Get(),
    reinterpret_cast<IUnknown*>(window),
    &swapChainDesc,
    nullptr,
    &swapChain
    );
swapChain.As(&m_swapChain);

為了確保畫面轉譯的頻率不會超過螢幕的實際顯示能力,我們將畫面延遲設定為1,並使用 DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL。 這會節省電力,而且是商店認證的要求;我們將在本逐步解說的第 2 部分中進一步了解如何在螢幕上呈現。

注意 您可以使用多執行緒(例如,ThreadPool 工作項目)在渲染執行緒遭到封鎖時繼續其他工作。

 

Direct3D 11

dxgiDevice->SetMaximumFrameLatency(1);

現在我們可以設定用於轉譯的後端緩衝區。

將後台緩衝區設定為轉譯目標

首先,我們必須取得後備緩衝區的控制代碼。 (請注意,後端緩衝區是由 DXGI 交換鏈結所擁有,而在 DirectX 9 中,則由 Direct3D 裝置所擁有。然後,我們會指示 Direct3D 裝置使用它作為轉譯目標,方法是使用後台緩衝區建立轉譯目標 檢視

Direct3D 11

ComPtr<ID3D11Texture2D> backBuffer;
m_swapChain->GetBuffer(
    0,
    __uuidof(ID3D11Texture2D),
    &backBuffer
    );

// Create a render target view on the back buffer.
m_d3dDevice->CreateRenderTargetView(
    backBuffer.Get(),
    nullptr,
    &m_renderTargetView
    );

現在裝置情境現已開始發揮作用。 我們會告訴 Direct3D 通過裝置上下文介面來使用我們新建立的渲染目標視圖。 我們將擷取後台緩衝區的寬度和高度,以便將整個視窗作為檢視區的目標。 請注意,後台緩衝區會附加至交換鏈結,因此,如果視窗大小變更(例如,使用者將遊戲視窗拖曳到另一個監視器),後端緩衝區將需要重設大小,而且某些設定必須重做。

Direct3D 11

D3D11_TEXTURE2D_DESC backBufferDesc = {0};
backBuffer->GetDesc(&backBufferDesc);

CD3D11_VIEWPORT viewport(
    0.0f,
    0.0f,
    static_cast<float>(backBufferDesc.Width),
    static_cast<float>(backBufferDesc.Height)
    );

m_d3dContext->RSSetViewports(1, &viewport);

既然我們有設備控制代碼和全螢幕渲染目標,我們已經準備好載入和繪製幾何圖形。 繼續 第 2 部分:渲染