D3D11 CreateSwapChainForHwnd失败,出现DXGI_ERROR_INVALID_CALL或E_INVALIDARG

时间:2019-10-28 05:44:07

标签: c++ direct3d11

我正在尝试使用D3D11为硬件加速的h264解码和渲染设置正确的上下文-并在一开始就失败,调用CreateSwapChainForHwnd()。

这些是我正在使用的接口的版本:

usecols=[1, 6, 26]

这是设备创建代码:

std::vector<IDXGIAdapter1*> m_adapters;
Microsoft::WRL::ComPtr<IDXGIFactory2> m_dxgiFactory;
Microsoft::WRL::ComPtr<ID3D11Device3> m_device;
Microsoft::WRL::ComPtr<ID3D11DeviceContext> m_deviceContext;
Microsoft::WRL::ComPtr<IDXGISwapChain1> m_swapChain;

到目前为止,一切正常,但是我将其发布,以防万一发生错误而导致故障通话。

这是我的交换链描述符:

    D3D_FEATURE_LEVEL targetFeatures[] = { 
        D3D_FEATURE_LEVEL_12_1,
        D3D_FEATURE_LEVEL_12_0,
        D3D_FEATURE_LEVEL_11_1, 
        D3D_FEATURE_LEVEL_11_0,
        D3D_FEATURE_LEVEL_10_1,
        D3D_FEATURE_LEVEL_10_0,
        D3D_FEATURE_LEVEL_9_3
    };
    D3D_FEATURE_LEVEL acceptedFeatureLevel;

    UINT deviceFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT; // this is needed for compatibility with direct2d
#ifdef _DEBUG
    deviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif

    ComPtr<ID3D11Device> dev;

    IF_FAILED_RETURN(D3D11CreateDevice(
        m_adapters[1],              // TODO pick adapter, hardcoded for GTX 960m here
        D3D_DRIVER_TYPE_UNKNOWN, // CreateDevice does not accept constraint on defined adapter
        nullptr,                       // DLL for a software rasterizer
        deviceFlags,
        targetFeatures,
        ARRAYSIZE(targetFeatures),
        D3D11_SDK_VERSION,
        &dev,
        &acceptedFeatureLevel,
        &m_deviceContext
    ));

    IF_FAILED_RETURN(dev.As(&m_device)); // cast to ID3D11Device3

请注意,我已经尝试了各种(非穷举性)排列的以下选项:

    DXGI_SWAP_CHAIN_DESC1 swapDesc = { 0 };
    swapDesc.Width = uiWidth;
    swapDesc.Height = uiHeight;
    swapDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
    swapDesc.Stereo = false;
    swapDesc.SampleDesc.Count = 1;
    swapDesc.SampleDesc.Quality = 0;
    swapDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    swapDesc.BufferCount = 2;
    swapDesc.SwapEffect = DXGI_SWAP_EFFECT_SEQUENTIAL;
    swapDesc.Flags = 0
        //| DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH
        //| DXGI_SWAP_CHAIN_FLAG_FULLSCREEN_VIDEO
        ;
    swapDesc.Scaling = DXGI_SCALING_ASPECT_RATIO_STRETCH;
    swapDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;

这是失败的呼叫:

DXGI_ALPHA_MODE_IGNORE
DXGI_SCALING_STRETCH // this is the one that causes E_INVALIDARG instead of DXGI_ERROR_INVALID_CALL
DXGI_SCALING_NONE
DXGI_SWAP_EFFECT_DISCARD // and the FLIP variants
DXGI_FORMAT_B8G8R8X8_UNORM

我尝试过的其他事情:

  • 不同的COM接口版本:d3d11_1至6,尽管我可能滥用了IDXGIFactoryN与ID3D11DeviceM和IDXGISwapChainX的组合

  • 使用m_adapter [0](这是Intel HD Graphics 530)

打印的调试信息:

    ComPtr<IUnknown> unkDev;
    IF_FAILED_RETURN(m_device.As(&unkDev));

    IF_FAILED_RETURN(m_dxgiFactory->CreateSwapChainForHwnd(
        unkDev.Get(),
        hWnd,
        &swapDesc,
        nullptr, // DXGI_SWAP_CHAIN_FULLSCREEN_DESC nullptr because we're trying windowed first
        nullptr, // do not restrict output to a specific IDXGIOutput
        &m_swapChain
    ));

其他信息:

  • Windows 10内部版本17763.195

  • Nvidia GTX 960m,支持的功能级别:9_1至11_0

  • Intel HD Graphics 530,支持的功能级别:9_1至12_1

  • Visual Studio D3D11示例应用程序可以正确编译并运行,但是它们使用UWP而不是Win32进行演示(可能会出错吗?如何对其进行测试?)

使用两个适配器,CreateDevice之后得到的acceptedFeatureLevel是受支持的最高适配器。

我已经浏览了几页的google和SO搜索,试图找到类似的问题,但是没有建议的解决方案对我有用。

鉴于调试模式返回的内存访问异常,我怀疑是错误的COM接口指针?如果是这种情况,我假设它发生在vtable间接层之后,因为指示的地址与我的任何COM接口指针都非常遥远,如上面的调试输出所示。是否可以在vtable间接访问之后跟踪函数指针,以验证它们是否与错误的内存访问相对应?

1 个答案:

答案 0 :(得分:1)

好的,这是一个临时性的答案,因为它是of弹枪调试的结果,我只是尝试了其他选项的排列,但我仍然不知道为什么以前的选项会失败。

我的实验结果:

  • 我尝试使用DXGI_FORMAT_B8G8R8的任何组合 X 8_UNORM失败,我必须使用DXGI_FORMAT_B8G8R8 A 8_UNORM

  • 我尝试与DXGI_SCALING_ASPECT_RATIO_STRETCH进行的任何组合都失败了,我必须使用DXGI_SCALING_STRETCH

我在MSDN中没有找到有关此行为的任何解释,据我所知,失败的选项似乎是可行的。

编辑:

非常感谢Chuck Walbourn的解释:

    按照MSDN supported formats tables
  • DXGI_FORMAT_B8G8R8X8_UNORM在我的目标功能级别上不是可行的后缓冲格式(我实际上查阅了那些表,却没有意识到它们可以横向滚动 facepalm ...)

  • DXGI_SCALING_ASPECT_RATIO_STRETCH仅与CreateSwapChainForCoreWindowCreateSwapChainForComposition兼容,而不与Win32窗口句柄和相关方法兼容(无法找到该MSDN源代码)