Bagikan melalui


Menginisialisasi Direct3D 11

Ringkasan

Menunjukkan cara mengonversi kode inisialisasi Direct3D 9 ke Direct3D 11, termasuk cara menangani ke perangkat Direct3D dan konteks perangkat dan cara menggunakan DXGI untuk menyiapkan rantai pertukaran. Bagian 1 dari Port, aplikasi Direct3D 9 sederhana ke panduan DirectX 11 dan Platform Windows Universal (UWP).

Menginisialisasi perangkat Direct3D

Di Direct3D 9, kami membuat handel ke perangkat Direct3D dengan memanggil IDirect3D9::CreateDevice. Kami mulai dengan mendapatkan pointer ke antarmuka IDirect3D9 dan kami menentukan sejumlah parameter untuk mengontrol konfigurasi perangkat Direct3D dan rantai pertukaran. Sebelum melakukan ini, kami memanggil GetDeviceCaps untuk memastikan kami tidak meminta perangkat untuk melakukan sesuatu yang tidak dapat dilakukannya.

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

Dalam Direct3D 11, konteks perangkat dan infrastruktur grafis dianggap terpisah dari perangkat itu sendiri. Inisialisasi dibagi menjadi beberapa langkah.

Pertama, kita membuat perangkat. Kami mendapatkan daftar tingkat fitur yang didukung perangkat - ini menginformasikan sebagian besar hal yang perlu kita ketahui tentang GPU. Selain itu, kita tidak perlu membuat antarmuka hanya untuk mengakses Direct3D. Sebagai gantinya, kita menggunakan API inti D3D11CreateDevice . Ini memberi kami pegangan ke perangkat dan konteks langsung perangkat. Konteks perangkat digunakan untuk mengatur status alur dan menghasilkan perintah penyajian.

Setelah membuat perangkat dan konteks Direct3D 11, kita dapat memanfaatkan fungsionalitas pointer COM untuk mendapatkan versi terbaru antarmuka, yang mencakup kemampuan tambahan dan selalu direkomendasikan.

Catatan D3D_FEATURE_LEVEL_9_1 (yang sesuai dengan model shader 2.0) adalah tingkat minimum permainan Microsoft Store Anda diperlukan untuk mendukung. (Paket Arm game Anda akan gagal sertifikasi jika Anda tidak mendukung 9_1.) Jika game Anda juga menyertakan jalur penyajian untuk fitur model shader 3, maka Anda harus menyertakan D3D_FEATURE_LEVEL_9_3 dalam array.

 

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

Membuat rantai pertukaran

Direct3D 11 mencakup API perangkat yang disebut infrastruktur grafis DirectX (DXGI). Antarmuka DXGI memungkinkan kita untuk (misalnya) mengontrol bagaimana rantai pertukaran dikonfigurasi dan menyiapkan perangkat bersama. Pada langkah ini dalam menginisialisasi Direct3D, kita akan menggunakan DXGI untuk membuat rantai pertukaran. Karena kami membuat perangkat, kita dapat mengikuti rantai antarmuka kembali ke adaptor DXGI.

Perangkat Direct3D mengimplementasikan antarmuka COM untuk DXGI. Pertama, kita perlu mendapatkan antarmuka itu dan menggunakannya untuk meminta adaptor DXGI yang menghosting perangkat. Kemudian kita menggunakan adaptor DXGI untuk membuat pabrik DXGI.

Catatan Ini adalah antarmuka COM sehingga respons pertama Anda mungkin menggunakan QueryInterface. Anda harus menggunakan penunjuk cerdas Microsoft::WRL::ComPtr sebagai gantinya. Kemudian cukup panggil metode As(), menyediakan pointer COM kosong dari jenis antarmuka yang benar.

 

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

Sekarang kita memiliki pabrik DXGI, kita dapat menggunakannya untuk membuat rantai pertukaran. Mari kita tentukan parameter rantai pertukaran. Kita perlu menentukan format permukaan; kita akan memilih DXGI_FORMAT_B8G8R8A8_UNORM karena kompatibel dengan Direct2D. Kami akan menonaktifkan penskalaan tampilan, multisampling, dan penyajian stereo karena tidak digunakan dalam contoh ini. Karena kita berjalan langsung di CoreWindow, kita dapat membiarkan lebar dan tinggi diatur ke 0 dan mendapatkan nilai layar penuh secara otomatis.

Catatan Selalu atur parameter SDKVersion ke D3D11_SDK_VERSION untuk aplikasi UWP.

 

Direct3D 11

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

Untuk memastikan kami tidak merender lebih sering daripada layar yang benar-benar dapat ditampilkan, kami mengatur latensi bingkai ke 1 dan menggunakan DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL. Ini menghemat daya dan merupakan persyaratan sertifikasi toko; kita akan mempelajari lebih lanjut tentang menyajikan ke layar di bagian 2 panduan ini.

Catatan Anda dapat menggunakan multithreading (misalnya, item kerja ThreadPool ) untuk melanjutkan pekerjaan lain saat utas penyajian diblokir.

 

Direct3D 11

dxgiDevice->SetMaximumFrameLatency(1);

Sekarang kita dapat mengatur buffer belakang untuk penyajian.

Mengonfigurasi buffer belakang sebagai target render

Pertama kita harus mendapatkan pegangan ke buffer belakang. (Perhatikan bahwa buffer belakang dimiliki oleh rantai pertukaran DXGI, sedangkan di DirectX 9 dimiliki oleh perangkat Direct3D.) Kemudian kami memberi tahu perangkat Direct3D untuk menggunakannya sebagai target render dengan membuat tampilan target render menggunakan buffer belakang.

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

Sekarang konteks perangkat mulai diputar. Kami memberi tahu Direct3D untuk menggunakan tampilan target render yang baru dibuat dengan menggunakan antarmuka konteks perangkat. Kami akan mengambil lebar dan tinggi buffer belakang sehingga kami dapat menargetkan seluruh jendela sebagai viewport kami. Perhatikan bahwa buffer belakang dilampirkan ke rantai pertukaran, jadi jika ukuran jendela berubah (misalnya, pengguna menyeret jendela permainan ke monitor lain) buffer belakang perlu diubah ukurannya dan beberapa pengaturan perlu direone ulang.

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

Sekarang setelah kita memiliki handel perangkat dan target render layar penuh, kita siap untuk memuat dan menggambar geometri. Lanjutkan ke Bagian 2: Penyajian.