다음을 통해 공유


Direct3D 11 초기화

요약

Direct3D 디바이스 및 디바이스 컨텍스트에 대한 핸들 가져오기 방법과 DXGI를 사용한 스왑 체인 설정 방법을 포함한 Direct3D 9 초기화 코드의 Direct3D 11 변환 방법을 보여 줍니다. 간단한 Direct3D 9 앱을 DirectX 11 및 UWP(유니버설 Windows 플랫폼)로 포팅 연습 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 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에는 DXGI(DirectX 그래픽 인프라)라는 디바이스 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 팩터리를 사용했으므로 이를 사용하여 스왑 체인을 생성할 수 있습니다. 스왑 체인 매개 변수를 정의하겠습니다. 표면 형식을 지정해야 합니다. Direct2D와 호환되므로 DXGI_FORMAT_B8G8R8A8_UNORM을 선택하겠습니다. 이 예제에서는 사용되지 않으므로 디스플레이 크기 조정, 다중 샘플링, 스테레오 렌더링을 해제합니다. CoreWindow에서 직접 실행되므로 너비와 높이를 0으로 설정하고 전체 화면 값을 자동으로 가져올 수 있습니다.

참고 항상 SDKVersion 매개 변수를 UWP 앱에 대한 D3D11_SDK_VERSION으로 설정합니다.

 

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부: 렌더링으로 진행합니다.