Partager via


Initialiser Direct3D 11

Résumé

Montre comment convertir le code d’initialisation Direct3D 9 en Direct3D 11, notamment comment obtenir des handles vers l’appareil Direct3D et le contexte de l’appareil et comment utiliser DXGI pour configurer une chaîne d’échange. Partie 1 du port d’une application Direct3D 9 simple vers DirectX 11 et plateforme Windows universelle (UWP) pas à pas.

Initialiser l’appareil Direct3D

Dans Direct3D 9, nous avons créé un handle sur l’appareil Direct3D en appelant IDirect3D9 ::CreateDevice. Nous avons commencé par obtenir un pointeur vers l’interface IDirect3D9 et nous avons spécifié un certain nombre de paramètres pour contrôler la configuration de l’appareil Direct3D et la chaîne d’échange. Avant de le faire, nous avons appelé GetDeviceCaps pour vous assurer que nous n’étions pas en train de demander à l’appareil de faire quelque chose qu’il n’a pas pu faire.

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

Dans Direct3D 11, le contexte de l’appareil et l’infrastructure graphique sont considérés comme distincts de l’appareil lui-même. L’initialisation est divisée en plusieurs étapes.

Tout d’abord, nous créons l’appareil. Nous obtenons une liste des niveaux de fonctionnalités pris en charge par l’appareil . Cela indique la plupart de ce que nous devons savoir sur le GPU. En outre, nous n’avons pas besoin de créer une interface uniquement pour accéder à Direct3D. Au lieu de cela, nous utilisons l’API principale D3D11CreateDevice . Cela nous donne un handle pour l’appareil et le contexte immédiat de l’appareil. Le contexte de l’appareil est utilisé pour définir l’état du pipeline et générer des commandes de rendu.

Après avoir créé l’appareil et le contexte Direct3D 11, nous pouvons tirer parti des fonctionnalités de pointeur COM pour obtenir la version la plus récente des interfaces, qui incluent des fonctionnalités supplémentaires et sont toujours recommandées.

Notez D3D_FEATURE_LEVEL_9_1 (qui correspond au modèle de nuanceur 2.0) est le niveau minimal nécessaire à la prise en charge de votre jeu microsoft Store. (Les packages Arm de votre jeu échouent si vous ne prenez pas en charge 9_1.) Si votre jeu inclut également un chemin de rendu pour les fonctionnalités du modèle de nuanceur 3, vous devez inclure D3D_FEATURE_LEVEL_9_3 dans le tableau.

 

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

Créer une chaîne d’échange

Direct3D 11 inclut une API d’appareil appelée Infrastructure graphique DirectX (DXGI). L’interface DXGI nous permet de contrôler (par exemple) la configuration de la chaîne d’échange et la configuration des appareils partagés. À cette étape de l’initialisation de Direct3D, nous allons utiliser DXGI pour créer une chaîne d’échange. Étant donné que nous avons créé l’appareil, nous pouvons suivre une chaîne d’interface à l’adaptateur DXGI.

L’appareil Direct3D implémente une interface COM pour DXGI. Tout d’abord, nous devons obtenir cette interface et l’utiliser pour demander l’adaptateur DXGI hébergeant l’appareil. Ensuite, nous utilisons l’adaptateur DXGI pour créer une fabrique DXGI.

Notez qu’il s’agit d’interfaces COM afin que votre première réponse soit d’utiliser QueryInterface. Vous devez utiliser les pointeurs intelligents Microsoft ::WRL ::ComPtr à la place. Ensuite, appelez simplement la méthode As(), en fournissant un pointeur COM vide du type d’interface correct.

 

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

Maintenant que nous avons la fabrique DXGI, nous pouvons l’utiliser pour créer la chaîne d’échange. Définissons les paramètres de la chaîne d’échange. Nous devons spécifier le format de surface ; Nous choisirons DXGI_FORMAT_B8G8R8A8_UNORM car il est compatible avec Direct2D. Nous allons désactiver la mise à l’échelle de l’affichage, l’échantillonnage multiple et le rendu stéréo, car ils ne sont pas utilisés dans cet exemple. Étant donné que nous sommes en cours d’exécution directement dans un CoreWindow, nous pouvons laisser la largeur et la hauteur définies sur 0 et obtenir automatiquement des valeurs plein écran.

Remarque : Définissez toujours le paramètre SDKVersion sur D3D11_SDK_VERSION pour les applications UWP.

 

Direct3D 11

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

Pour nous assurer que nous ne rendons pas plus souvent que l’écran ne peut réellement s’afficher, nous définissons la latence d’image sur 1 et utilisons DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL. Cela permet d’économiser de l’énergie et est une exigence de certification de magasin ; Nous allons en savoir plus sur la présentation à l’écran dans la partie 2 de cette procédure pas à pas.

Notez que vous pouvez utiliser le multithreading (par exemple, les éléments de travail ThreadPool ) pour poursuivre d’autres tâches pendant que le thread de rendu est bloqué.

 

Direct3D 11

dxgiDevice->SetMaximumFrameLatency(1);

À présent, nous pouvons configurer la mémoire tampon de sauvegarde pour le rendu.

Configurer la mémoire tampon back en tant que cible de rendu

Tout d’abord, nous devons obtenir un handle vers la mémoire tampon de retour. (Notez que la mémoire tampon arrière appartient à la chaîne d’échange DXGI, tandis que dans DirectX 9, elle a été détenue par l’appareil Direct3D.) Ensuite, nous indiquez à l’appareil Direct3D de l’utiliser comme cible de rendu en créant une vue cible de rendu à l’aide de la mémoire tampon arrière.

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

Maintenant, le contexte de l’appareil entre en jeu. Nous disons à Direct3D d’utiliser notre vue cible de rendu nouvellement créée à l’aide de l’interface de contexte de l’appareil. Nous allons récupérer la largeur et la hauteur de la mémoire tampon arrière afin que nous puissions cibler toute la fenêtre en tant que fenêtre d’affichage. Notez que la mémoire tampon d’arrière-mémoire est attachée à la chaîne d’échange. Par conséquent, si la taille de la fenêtre change (par exemple, l’utilisateur fait glisser la fenêtre de jeu vers un autre moniteur) la mémoire tampon d’arrière-mémoire doit être redimensionnée et une configuration doit être annulée.

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

Maintenant que nous avons un handle d’appareil et une cible de rendu plein écran, nous sommes prêts à charger et dessiner la géométrie. Passez à la partie 2 : Rendu.