Compartir a través de


Inicializar Direct3D 11

Resumen

Muestra cómo convertir el código de inicialización de Direct3D 9 en Direct3D 11, incluido cómo obtener identificadores en el dispositivo Direct3D y el contexto del dispositivo y cómo usar DXGI para configurar una cadena de intercambio. Parte 1 del tutorial Puerto de una aplicación sencilla de Direct3D 9 a DirectX 11 y Plataforma universal de Windows (UWP).

Inicialización del dispositivo Direct3D

En Direct3D 9, creamos un identificador para el dispositivo Direct3D llamando a IDirect3D9::CreateDevice. Empezamos obteniendo un puntero a la interfaz IDirect3D9 y especificamos una serie de parámetros para controlar la configuración del dispositivo Direct3D y la cadena de intercambio. Antes de hacerlo, llamamos GetDeviceCaps para asegurarnos de que no estábamos pidiendo al dispositivo que hiciera algo que no podía hacer.

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

En Direct3D 11, el contexto del dispositivo y la infraestructura de gráficos se consideran independientes del propio dispositivo. La inicialización se divide en varios pasos.

En primer lugar, creamos el dispositivo. Se obtiene una lista de los niveles de características que admite el dispositivo: esto informa a la mayoría de lo que necesitamos saber sobre la GPU. Además, no es necesario crear una interfaz solo para acceder a Direct3D. En su lugar, usamos la API principal D3D11CreateDevice. Esto nos proporciona un identificador para el dispositivo y el contexto inmediato del dispositivo. El contexto del dispositivo se usa para establecer el estado de canalización y generar comandos de representación.

Después de crear el dispositivo y el contexto de Direct3D 11, podemos aprovechar la funcionalidad de puntero COM para obtener la versión más reciente de las interfaces, que incluyen funcionalidad adicional y siempre se recomiendan.

Nota D3D_FEATURE_LEVEL_9_1 (que corresponde al modelo de sombreador 2.0) es el nivel mínimo que requiere tu juego de Microsoft Store para admitir. (Los paquetes arm de tu juego producirán un error en la certificación si no admites 9_1). Si tu juego también incluye una ruta de representación para las características del modelo de sombreador 3, debes incluir D3D_FEATURE_LEVEL_9_3 en la matriz.

 

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

Creación de una cadena de intercambio

Direct3D 11 incluye una API de dispositivo denominada infraestructura de gráficos directX (DXGI). La interfaz DXGI nos permite controlar (por ejemplo) cómo se configura la cadena de intercambio y se configuran los dispositivos compartidos. En este paso para inicializar Direct3D, vamos a usar DXGI para crear una cadena de intercambio. Como hemos creado el dispositivo, podemos seguir una cadena de interfaz de nuevo al adaptador DXGI.

El dispositivo Direct3D implementa una interfaz COM para DXGI. En primer lugar, necesitamos obtener esa interfaz y usarla para solicitar el adaptador DXGI que hospeda el dispositivo. A continuación, usamos el adaptador DXGI para crear una fábrica DXGI.

Nota Estas son interfaces COM para que la primera respuesta sea usar QueryInterface. Debe usar punteros inteligentes Microsoft::WRL::ComPtr en su lugar. A continuación, simplemente llame al método As(), proporcionando un puntero COM vacío del tipo de interfaz correcto.

 

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

Ahora que tenemos la fábrica DXGI, podemos usarla para crear la cadena de intercambio. Vamos a definir los parámetros de la cadena de intercambio. Es necesario especificar el formato de superficie; elegiremos DXGI_FORMAT_B8G8R8A8_UNORM porque es compatible con Direct2D. Desactivaremos el escalado de pantalla, el muestreo múltiple y la representación estéreo porque no se usan en este ejemplo. Puesto que estamos ejecutando directamente en CoreWindow, podemos dejar el ancho y alto establecido en 0 y obtener valores de pantalla completa automáticamente.

Nota Establezca siempre el parámetro SDKVersion en D3D11_SDK_VERSION para aplicaciones para UWP.

 

Direct3D 11

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

Para asegurarnos de que no estamos representando con más frecuencia que la pantalla en realidad, establecemos la latencia de fotogramas en 1 y usamos DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL. Esto ahorra energía y es un requisito de certificación de almacén; obtendrá más información sobre cómo presentar a la pantalla en la parte 2 de este tutorial.

Nota Puede usar multithreading (por ejemplo, elementos de trabajo ThreadPool ) para continuar con otro trabajo mientras el subproceso de representación está bloqueado.

 

Direct3D 11

dxgiDevice->SetMaximumFrameLatency(1);

Ahora podemos configurar el búfer de copia de seguridad para la representación.

Configuración del búfer de reserva como destino de representación

En primer lugar, tenemos que obtener un identificador para el búfer de reserva. (Tenga en cuenta que el búfer de reserva es propiedad de la cadena de intercambio DXGI, mientras que en DirectX 9 era propiedad del dispositivo Direct3D). A continuación, se indica al dispositivo Direct3D que lo use como destino de representación mediante la creación de una vista de destino de representación mediante el búfer de reserva.

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

Ahora el contexto del dispositivo entra en juego. Indicamos a Direct3D que use nuestra vista de destino de representación recién creada mediante la interfaz de contexto del dispositivo. Recuperaremos el ancho y alto del búfer de reserva para que podamos tener como destino toda la ventana como nuestra ventanilla. Tenga en cuenta que el búfer atrás está conectado a la cadena de intercambio, por lo que si el tamaño de la ventana cambia (por ejemplo, el usuario arrastra la ventana del juego a otro monitor), el búfer de reserva tendrá que cambiarse de tamaño y algunas configuraciones deberán rehacerse.

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

Ahora que tenemos un identificador de dispositivo y un destino de representación de pantalla completa, estamos listos para cargar y dibujar geometría. Continúe con la parte 2: Representación.