Инициализация Direct3D 11
Сводка
- Часть 1. Инициализация Direct3D 11
- Часть 2. Преобразование платформы отрисовки
- Часть 3. Перенос цикла игры
Показано, как преобразовать код инициализации Direct3D 9 в Direct3D 11, включая получение дескрипторов к устройству Direct3D и контексту устройства и настройке цепочки буферов с помощью DXGI. Часть 1 из простого приложения Direct3D 9 в DirectX 11 и универсальная платформа Windows (UWP).
Инициализация устройства Direct3D
В Direct3D 9 мы создали дескриптор на устройстве Direct3D, вызвав IDirect3D9::CreateDevice. Мы начали с получения указателя на интерфейс 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(¶ms, 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,
¶ms,
&m_pd3dDevice
);
В Direct3D 11 контекст устройства и графической инфраструктуры считаются отдельными от самого устройства. Инициализация делится на несколько шагов.
Сначала мы создадим устройство. Мы получаем список уровней функций, поддерживаемых устройством, — это сообщает больше всего о том, что нам нужно знать о GPU. Кроме того, нам не нужно создавать интерфейс только для доступа к Direct3D. Вместо этого мы используем основной API D3D11CreateDevice . Это дает нам дескриптор для устройства и непосредственного контекста устройства. Контекст устройства используется для задания состояния конвейера и создания команд отрисовки.
После создания устройства Direct3D 11 и контекста мы можем воспользоваться преимуществами функций указателя COM, чтобы получить последнюю версию интерфейсов, которая включает дополнительные возможности и всегда рекомендуется.
Обратите внимание , D3D_FEATURE_LEVEL_9_1 (который соответствует модели шейдера 2.0) является минимальным уровнем, который требуется для поддержки игры в Microsoft Store. (Пакеты 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 включает API устройств с именем инфраструктуры графики DirectX (DXGI). Интерфейс DXGI позволяет (например) управлять настройкой цепочки буферов и настройкой общих устройств. На этом шаге при инициализации Direct3D мы будем использовать DXGI для создания цепочки буферов. Так как мы создали устройство, мы можем следовать цепочке интерфейсов обратно к адаптеру DXGI.
Устройство Direct3D реализует COM-интерфейс для DXGI. Сначала необходимо получить этот интерфейс и использовать его для запроса адаптера 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. Отрисовка.