Efulefu
Efulefu

Reputation: 46

D3D11 CreateSwapChainForHwnd fails with either DXGI_ERROR_INVALID_CALL or E_INVALIDARG

I am trying to set up the correct context for hardware-accelerated h264 decoding and rendering using D3D11 - and failing at the very beginning, on the CreateSwapChainForHwnd() call.

These are the versions of the interfaces I'm using:

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;

This is the device creation code:

    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

Up until this point, everything works, but I'm posting it just in case there's a mistake cascading down to the malfunctioning call.

This is my swap chain descriptor:

    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;

Do note I have tried the following options in various (non-exhaustive) permutations:

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

And this is the call that fails:

    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
    ));

Other things I have tried:

Printed debug info:

D3D11 INFO: Create ID3D11Context: Name="unnamed", Addr=0x000002A9D30B9260, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097225: CREATE_CONTEXT]
D3D11 INFO: Create ID3DDeviceContextState: Name="unnamed", Addr=0x000002A9D30F31D0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #3145735: CREATE_DEVICECONTEXTSTATE]
D3D11 INFO: Create ID3D11BlendState: Name="unnamed", Addr=0x000002A9D3100560, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097270: CREATE_BLENDSTATE]
D3D11 INFO: Create ID3D11DepthStencilState: Name="unnamed", Addr=0x000002A9D31007D0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097273: CREATE_DEPTHSTENCILSTATE]
D3D11 INFO: Create ID3D11RasterizerState: Name="unnamed", Addr=0x000002A9D3100A00, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097276: CREATE_RASTERIZERSTATE]
D3D11 INFO: Create ID3D11Sampler: Name="unnamed", Addr=0x000002A9D3100C70, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097267: CREATE_SAMPLER]
D3D11 INFO: Create ID3D11Query: Name="unnamed", Addr=0x000002A9D3100EC0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097279: CREATE_QUERY]
Exception thrown at 0x00007FFD7A185299 in H264Decoder.exe: Microsoft C++ exception: _com_error at memory location 0x000000BF7793E8E0.

Additional info:

With both adapters, the resulting acceptedFeatureLevel after CreateDevice is the highest supported one.

I've gone through a few pages of google and SO searches trying to find similar issues, and none of the suggested solutions work for me.

Given the memory access exception returned from the debug mode, I'm suspecting a bad COM interface pointer? If that's the case, I'm assuming it happens after the vtable indirection layer because the address indicated is very very far away from any of my COM interface pointers, as can be seen above in the debug output. Is it possible to trace the function pointers after the vtable indirection, in order to verify if any of them correspond to the bad memory access?

Upvotes: 1

Views: 2675

Answers (1)

Efulefu
Efulefu

Reputation: 46

Alright, this is a temporary answer because it is the result of shotgun debugging, I have simply tried other permutations of options but I still have no idea why the previous ones failed.

The results of my experimentation:

  • Any combination I tried with DXGI_FORMAT_B8G8R8X8_UNORM failed, I have to use DXGI_FORMAT_B8G8R8A8_UNORM

  • Any combination I tried with DXGI_SCALING_ASPECT_RATIO_STRETCH failed, I have to use DXGI_SCALING_STRETCH

I have not found any explanation in the MSDN for this behavior, the failing options seem viable as far as I can understand this.

Edit:

Thank you very much Chuck Walbourn for the explanations:

  • DXGI_FORMAT_B8G8R8X8_UNORM is not a viable backbuffer format at my target feature levels as per MSDN supported formats tables (I had actually consulted those tables without ever realizing they scrolled sideways facepalm...)

  • DXGI_SCALING_ASPECT_RATIO_STRETCH is only compatible with CreateSwapChainForCoreWindow or CreateSwapChainForComposition, not Win32 window handles and associated methods (cannot find an MSDN source for that)

Upvotes: 1

Related Questions