D3D11 CreateSwapChainForHwnd завершается неудачно с DXGI_ERROR_INVALID_CALL или E_INVALIDARG - PullRequest
0 голосов
/ 28 октября 2019

Я пытаюсь настроить правильный контекст для аппаратного ускорения декодирования и рендеринга h264 с использованием D3D11 - и в самом начале происходит сбой при вызове CreateSwapChainForHwnd ().

Это версии интерфейсов. Я использую:

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

И это вызов, который терпит неудачу:

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

Другие вещи, которые я пробовал:

  • разные версии интерфейса COM: от d3d11_1 до 6, хотяВозможно, я неправильно использовал комбинации IDXGIFactoryN с ID3D11DeviceM и IDXGISwapChainX

  • , используя m_adapter [0] (то есть Intel HD Graphics 530)

Напечатаноотладочная информация:

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.

Дополнительная информация:

  • Windows 10 build 17763.195

  • Nvidia GTX 960m, поддерживаемые уровни функций: 9_1до 11_0

  • Intel HD Graphics 530, поддерживаемые уровни функций: от 9_1 до 12_1

  • Примеры приложений Visual Studio D3D11 компилируются и работают правильно, однако онииспользовать UWP вместо Win32 для презентации (может ли быть hWnd виноват? Как мне проверить это?)

С обоими адаптерами результирующий acceptFeatureLevel после CreateDevice является самым поддерживаемым.

Я просмотрел несколько страниц Googleи SO ищет, пытаясь найти похожие проблемы, и ни одно из предложенных решений не работает для меня.

Учитывая исключение доступа к памяти, возвращаемое из режима отладки, я подозреваю, что указатель COM-интерфейса неверен? Если это так, я предполагаю, что это происходит после уровня косвенности vtable, потому что указанный адрес очень очень далек от любого из моих указателей интерфейса COM, как можно видеть выше в выходных данных отладки. Можно ли отследить указатели на функции после перенаправления vtable, чтобы проверить, соответствует ли какой-либо из них плохому доступу к памяти?

1 Ответ

0 голосов
/ 28 октября 2019

Хорошо, это временный ответ, потому что это результат отладки ружья, я просто попробовал другие варианты вариантов, но я до сих пор не знаю, почему предыдущие не дали результатов.

Результаты моих экспериментов:

  • Любая комбинация, которую я пробовал с DXGI_FORMAT_B8G8R8 X 8_UNORM, не удалась, я должен использовать DXGI_FORMAT_B8G8R8 A 8_UNORM

  • Любая комбинация, которую я пробовал с DXGI_SCALING_ASPECT_RATIO_STRETCH, не удалась, я должен использовать DXGI_SCALING_STRETCH

Я не нашел никакого объяснения в MSDN для этого поведения, кажутся ошибочные вариантынасколько я понимаю, это возможно.

Редактировать:

Большое спасибо Чак Уолбурн за объяснения:

  • DXGI_FORMAT_B8G8R8X8_UNORM не является подходящим форматом резервного буфера для моих целевых уровней функций в соответствии с таблицами поддерживаемых форматов MSDN (я на самом деле просматривал эти таблицы, даже не осознавая, что они прокручиваются вбок facepalm ... )

  • DXGI_SCALING_ASPECT_RATIO_STRETCH совместим только с CreateSwapChainForCoreWindow или CreateSwapChainForComposition, но не с дескрипторами окна Win32 и связанными методами (для этого не удается найти источник MSDN)

...