Direct3D 장치 관리자

Microsoft Direct3D 디바이스 관리자를 사용하면 두 개 이상의 개체가 동일한 Microsoft Direct3D 9 디바이스를 공유할 수 있습니다. 하나의 개체는 Direct3D 9 디바이스의 소유자 역할을 합니다. 디바이스를 공유하려면 디바이스 소유자가 Direct3D 디바이스 관리자를 만듭니다. 다른 개체는 디바이스 소유자로부터 디바이스 관리자에 대한 포인터를 가져온 다음 디바이스 관리자를 사용하여 Direct3D 디바이스에 대한 포인터를 가져올 수 있습니다. 디바이스를 사용하는 모든 개체는 배타적 잠금을 보유하므로 다른 개체가 동시에 디바이스를 사용할 수 없습니다.

참고

Direct3D 장치 관리자 Direct3D 9 디바이스만 지원합니다. DXGI 디바이스는 지원하지 않습니다.

 

Direct3D 디바이스 관리자를 만들려면 DXVA2CreateDirect3DDeviceManager9를 호출합니다. 이 함수는 재설정 토큰과 함께 디바이스 관리자의 IDirect3DDeviceManager9 인터페이스에 대한 포인터를 반환합니다. 재설정 토큰을 사용하면 Direct3D 디바이스 소유자가 디바이스 관리자에서 디바이스를 설정(및 다시 설정)할 수 있습니다. 디바이스 관리자를 초기화하려면 IDirect3DDeviceManager9::ResetDevice를 호출합니다. 다시 설정 토큰과 함께 Direct3D 디바이스에 대한 포인터를 전달합니다.

다음 코드에서는 디바이스 관리자를 만들고 초기화하는 방법을 보여줍니다.

HRESULT CreateD3DDeviceManager(
    IDirect3DDevice9 *pDevice, 
    UINT *pReset, 
    IDirect3DDeviceManager9 **ppManager
    )
{
    UINT resetToken = 0;

    IDirect3DDeviceManager9 *pD3DManager = NULL;

    HRESULT hr = DXVA2CreateDirect3DDeviceManager9(&resetToken, &pD3DManager);

    if (FAILED(hr))
    {
        goto done;
    }

    hr = pD3DManager->ResetDevice(pDevice, resetToken);

    if (FAILED(hr))
    {
        goto done;
    }

    *ppManager = pD3DManager;
    (*ppManager)->AddRef();

    *pReset = resetToken;


done:
    SafeRelease(&pD3DManager);
    return hr;
}

디바이스 소유자는 다른 개체가 IDirect3DDeviceManager9 인터페이스에 대한 포인터를 가져올 수 있는 방법을 제공해야 합니다. 표준 메커니즘은 IMFGetService 인터페이스를 구현하는 것입니다. 서비스 GUID가 MR_VIDEO_ACCELERATION_SERVICE.

여러 개체 간에 디바이스를 공유하려면 각 개체(디바이스 소유자 포함)가 다음과 같이 디바이스 관리자를 통해 디바이스에 액세스해야 합니다.

  1. IDirect3DDeviceManager9::OpenDeviceHandle을 호출하여 디바이스에 대한 핸들을 가져옵니다.
  2. 디바이스를 사용하려면 IDirect3DDeviceManager9::LockDevice 를 호출하고 디바이스 핸들을 전달합니다. 메서드는 IDirect3DDevice9 인터페이스에 대한 포인터를 반환합니다. 메서드는 fBlock 매개 변수의 값에 따라 차단 모드 또는 비차단 모드에서 호출할 수 있습니다.
  3. 디바이스 사용을 마쳤으면 IDirect3DDeviceManager9::UnlockDevice를 호출합니다. 이 메서드를 사용하면 디바이스를 다른 개체에서 사용할 수 있습니다.
  4. 종료하기 전에 IDirect3DDeviceManager9::CloseDeviceHandle 을 호출하여 디바이스 핸들을 닫습니다.

디바이스 잠금을 유지하면 다른 개체가 디바이스를 사용할 수 없으므로 디바이스를 사용하는 동안에만 디바이스 잠금을 유지해야 합니다.

디바이스 소유자는 일반적으로 원래 디바이스가 손실되었기 때문에 ResetDevice를 호출하여 언제든지 다른 디바이스로 전환할 수 있습니다. 모니터 해상도 변경, 전원 관리 작업, 컴퓨터 잠금 및 잠금 해제 등 다양한 이유로 디바이스 손실이 발생할 수 있습니다. 자세한 내용은 Direct3D 설명서를 참조하세요.

ResetDevice 메서드는 이전에 연 모든 디바이스 핸들을 무효화합니다. 디바이스 핸들이 유효하지 않으면 LockDevice 메서드는 DXVA2_E_NEW_VIDEO_DEVICE 반환합니다. 이 경우 다음 코드와 같이 핸들을 닫고 OpenDeviceHandle 을 다시 호출하여 새 디바이스 핸들을 가져옵니다.

다음 예제에서는 디바이스 핸들을 열고 디바이스를 잠그는 방법을 보여줍니다.

HRESULT LockDevice(
    IDirect3DDeviceManager9 *pDeviceManager,
    BOOL fBlock,
    IDirect3DDevice9 **ppDevice, // Receives a pointer to the device.
    HANDLE *pHandle              // Receives a device handle.   
    )
{
    *pHandle = NULL;
    *ppDevice = NULL;

    HANDLE hDevice = 0;

    HRESULT hr = pDeviceManager->OpenDeviceHandle(&hDevice);

    if (SUCCEEDED(hr))
    {
        hr = pDeviceManager->LockDevice(hDevice, ppDevice, fBlock);
    }

    if (hr == DXVA2_E_NEW_VIDEO_DEVICE)
    {
        // Invalid device handle. Try to open a new device handle.
        hr = pDeviceManager->CloseDeviceHandle(hDevice);

        if (SUCCEEDED(hr))
        {
            hr = pDeviceManager->OpenDeviceHandle(&hDevice);
        }

        // Try to lock the device again.
        if (SUCCEEDED(hr))
        {
            hr = pDeviceManager->LockDevice(hDevice, ppDevice, TRUE); 
        }
    }

    if (SUCCEEDED(hr))
    {
        *pHandle = hDevice;
    }
    return hr;
}

DirectX 비디오 가속 2.0