D3D12 can use IDXGIOutputDuplication::AcquireNextFrame?

Mingkun Ma 1 Reputation point
2022-01-18T10:08:07.05+00:00

I want to use ID3D12Device to create to IDXGIOutput , but ID3D12Device cant queryinterface to get IDXGIDevice2. I found ID3D12Device can create ID3D11Device by d3d11on12.h , but it will return DXGI_ERROR_ACCESS_LOST error when call IDXGIOutputDuplication::AcquireNextFrame. I want to know if IDXGIOutputDuplication::AcquireNextFrame support d3d12.

Below is the initialization code:
ComPtr<ID3D12Device> pDevice12;
ComPtr<ID3D12CommandQueue> pDevice12CommandQueue;

    ComPtr<ID3D11Device> pDevice11;
    ComPtr<ID3D11DeviceContext> pDevice11Context;
    ComPtr<ID3D11Texture2D> pDopTex2D;

    std::shared_ptr<DDAImpl> pDDACapture = nullptr;

    HRESULT hr = S_OK;
    /// Driver types supported
    D3D_DRIVER_TYPE DriverTypes[] =
    {
        D3D_DRIVER_TYPE_HARDWARE,
        D3D_DRIVER_TYPE_WARP,
        D3D_DRIVER_TYPE_REFERENCE,
    };
    UINT NumDriverTypes = ARRAYSIZE(DriverTypes);

    /// Feature levels supported
    D3D_FEATURE_LEVEL FeatureLevels[] =
    {
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_1
    };
    UINT NumFeatureLevels = ARRAYSIZE(FeatureLevels);
    D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_0;

    HRESULT res = D3D12CreateDevice(nullptr, FeatureLevel, IID_PPV_ARGS(pDevice12.GetAddressOf()));

    CHECK_FAIL_AND_RETURN(res, D3D12CreateDevice)

    D3D12_COMMAND_QUEUE_DESC queueDesc = { D3D12_COMMAND_LIST_TYPE_DIRECT };
    //queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
    //queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
    res = pDevice12->CreateCommandQueue(&queueDesc, IID_PPV_ARGS(pDevice12CommandQueue.GetAddressOf()));
    CHECK_FAIL_AND_RETURN(res, CreateCommandQueue)

    //ComPtr<IDXGIDevice2> pDevice2;
    //res = pDevice12->QueryInterface(__uuidof(IDXGIDevice2), (void**)pDevice2.GetAddressOf());
    //CHECK_FAIL_AND_RETURN(res, IDXGIDevice2)

    res = D3D11On12CreateDevice(pDevice12.Get(),
        D3D11_CREATE_DEVICE_BGRA_SUPPORT | D3D11_CREATE_DEVICE_VIDEO_SUPPORT,
        FeatureLevels,
        NumFeatureLevels,
        reinterpret_cast<IUnknown**>(pDevice12CommandQueue.GetAddressOf()),
        1,
        0,
        pDevice11.GetAddressOf(),
        pDevice11Context.GetAddressOf(),
        nullptr);

    CHECK_FAIL_AND_RETURN(res, D3D11On12CreateDevice);
    if (pDevice11) {
        printf("Get Device success \n");
    }


    //HRESULT res;
    //InitDXGI_ON_11(pDevice11.GetAddressOf(), pDevice11Context.GetAddressOf());

    if (pDevice11 && pDevice11Context) {
        pDDACapture = std::make_shared<DDAImpl>(pDevice11.Get(), pDevice11Context.Get());
        res = pDDACapture->Init();
        CHECK_FAIL_AND_RETURN(res, DDAImpl->init);
    }

    int frames = 10;
    while (frames > 0) {
        res = pDDACapture->GetCapturedFrame(pDopTex2D.GetAddressOf(), 17);
        if (res == DXGI_ERROR_WAIT_TIMEOUT) {
            continue;
        }
        else {

            std::cout << "######################capture a frame success" << std::endl;
        }
        frames -= 1;
    }
Windows development | Windows API - Win32
0 comments No comments

4 answers

Sort by: Most helpful
  1. Mingkun Ma 1 Reputation point
    2022-01-19T09:29:43.11+00:00

    I found he had the same problem as me ( https://stackoverflow.com/questions/40165786/calling-duplicateoutput-with-d3d12device-fails-with-e-nointerface ). I tryed 11on12, I call IDXGIOutputDuplication::AcquireNextFrame and return AcquireNextFrame error. Does D3D12 not support duplicateoutput?

    Was this answer helpful?


  2. Xiaopo Yang - MSFT 12,736 Reputation points Microsoft External Staff
    2022-01-19T08:14:02.567+00:00

    I have written a sample to test. The result is that ID3D12Device object doesn't implement IDXGIDevice. But there is a workaround(GetAdapterLuid) to retrieve the IDXGIAdapter which is used to create D3D12 Device. And the IDXGIAdapter can be used to do something.

    void GetHardwareAdapter(IDXGIFactory4* pFactory, IDXGIAdapter1** ppAdapter)  
        {  
            *ppAdapter = nullptr;  
            for (UINT adapterIndex = 0; ; ++adapterIndex)  
            {  
                IDXGIAdapter1* pAdapter = nullptr;  
                if (DXGI_ERROR_NOT_FOUND == pFactory->EnumAdapters1(adapterIndex, &pAdapter))  
                {  
                    // No more adapters to enumerate.  
                    break;  
                }  
      
                // Check to see if the adapter supports Direct3D 12, but don't create the  
                // actual device yet.  
                if (SUCCEEDED(D3D12CreateDevice(pAdapter, D3D_FEATURE_LEVEL_11_0, _uuidof(ID3D12Device), nullptr)))  
                {  
                    *ppAdapter = pAdapter;  
                    return;  
                }  
                pAdapter->Release();  
            }  
        }  
      
        HRESULT CreateDirect3DDevice(IDXGIAdapter1* g)  
        {  
            CComPtr<IDXGIFactory4> factory;  
            HRESULT r = (CreateDXGIFactory1(IID_PPV_ARGS(&factory)));  
            if (SUCCEEDED(r))  
            {  
      
            }  
      
            CComPtr<ID3D12Device> lDevice;  
            /*if (false)  
            {  
                CComPtr<IDXGIAdapter> warpAdapter;  
                r = (factory->EnumWarpAdapter(IID_PPV_ARGS(&warpAdapter)));  
                r = (D3D12CreateDevice(  
                    warpAdapter,  
                    D3D_FEATURE_LEVEL_11_0,  
                    IID_PPV_ARGS(&lDevice)  
                ));  
            }  
            else*/  
            {  
                CComPtr<IDXGIAdapter1> hardwareAdapter;  
                GetHardwareAdapter(factory, &hardwareAdapter);  
      
                r = (D3D12CreateDevice(  
                    hardwareAdapter,  
                    D3D_FEATURE_LEVEL_11_0,  
                    IID_PPV_ARGS(&lDevice)  
                ));  
            }  
      
            CComPtr<IDXGIDevice> lDxgiDevice;  
            r = lDevice->QueryInterface(IID_PPV_ARGS(&lDxgiDevice));  
      
            LUID uid = lDevice->GetAdapterLuid();  
            CComPtr<IDXGIAdapter> adapter;  
            factory->EnumAdapterByLuid(uid, IID_PPV_ARGS(&adapter));  
      
            UINT Output = 0;  
            CComPtr<IDXGIOutput> lDxgiOutput;  
            r = adapter->EnumOutputs(  
                Output,  
                &lDxgiOutput);  
    }  
    

    166311-image.png

    166312-image.png

    Was this answer helpful?


  3. Mingkun Ma 1 Reputation point
    2022-01-19T07:03:24.817+00:00

    I cant QueryInterface using D3D12 Device

        ComPtr<IDXGIFactory4> factory;
        HRESULT res = CreateDXGIFactory2(0, IID_PPV_ARGS(&factory));
        CHECK_FAIL_AND_RETURN(res, CreateDXGIFactory2);
    
        ComPtr<IDXGIAdapter1> adpter;
        for (int index = 0; 
            factory->EnumAdapters1(index, adpter.GetAddressOf()) != DXGI_ERROR_NOT_FOUND; 
            ++index) {
    
            DXGI_ADAPTER_DESC1 desc;
            adpter->GetDesc1(&desc);
    
            printf("#####################\n");
    
            if (desc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE) {
                continue;
            }
    
            res = D3D12CreateDevice(adpter.Get(), D3D_FEATURE_LEVEL_11_1, __uuidof(ID3D12Device), nullptr);
            if (res == S_FALSE) {
                std::wstring str(desc.Description);
                if (-1 != str.find(L"NVIDIA", 0)) {
                    wprintf_s(L"Output Describe: %s\n", desc.Description);
                    break;
                }
            }
        }
    
        ComPtr<ID3D12Device> pD3D12Device;
        res = D3D12CreateDevice(adpter.Get(), D3D_FEATURE_LEVEL_11_1, __uuidof(ID3D12Device), reinterpret_cast<void**>(pD3D12Device.GetAddressOf()));
        CHECK_FAIL_AND_RETURN(res, D3D12CreateDevice ID3D12Device)
    
        ComPtr<IDXGIDevice> pIDXGDevice;
        res = pD3D12Device->QueryInterface(IID_PPV_ARGS(pIDXGDevice.GetAddressOf()));
        CHECK_FAIL_AND_RETURN(res, QueryInterface IDXGIDevice)
    

    Was this answer helpful?

    0 comments No comments

  4. Xiaopo Yang - MSFT 12,736 Reputation points Microsoft External Staff
    2022-01-19T01:36:37.96+00:00

    According to DXGI, DXGI is used by Direct3D 10, Direct3D 11 and Direct3D 12. There is a sample where D3D11 uses DXGI.

    Was this answer helpful?


Your answer

Answers can be marked as 'Accepted' by the question author and 'Recommended' by moderators, which helps users know the answer solved the author's problem.