首页 > 解决方案 > 是什么导致全屏模式下“D3D11CreateDeviceAndSwapChain”出现访问冲突?

问题描述

我正在尝试从 dll 创建交换链。我的进程创建一个窗口,初始化 Direct3D11 并加载 dll。

当该过程创建非全屏窗口时,它工作得非常好。但是,一旦该过程创建了一个全屏窗口,我在从 dll 调用 D3D11CreateDeviceAndSwapChain 时就会遇到访问冲突。

调用发生在单独的线程中。(不是来自 dllmain 线程。)

现在不幸的是,我什至无法正确调试,因为断点冻结了全屏窗口并且它位于我的调试器窗口的顶部。

是什么导致访问冲突?

编辑:我对 dxgi.dll 进行了一些静态分析,发现在创建交换链时它会检查一系列扩展和基本窗口样式。我还注意到它应该在崩溃之前打印一条调试消息,所以我连接了一个远程调试器来捕获它。该消息只是说明了我已经知道的内容:

DXGI ERROR: IDXGIFactory::CreateSwapChain: The specified output window has a style that is incompatible with DXGI. Output windows must have at least one of:
WS_POPUP
WS_BORDER
WS_CAPTION
WS_SYSMENU
WS_MAXIMIZEBOX
WS_MINIMIZEBOX
WS_THICKFRAME
WS_EX_CLIENTEDGE
WS_EX_CONTEXTHELP
WS_EX_DLGMODALFRAME
WS_EX_TOOLWINDOW
WS_EX_WINDOWEDGE
or not have WS_EX_TOPMOST. [ MISCELLANEOUS ERROR #78: ]

错误代码是:DXGI_ERROR_INVALID_CALL

那么为什么从我的可执行文件初始化direct3d但使用它在我的dll中创建的窗口却不行呢?

EDIT2:显然调用 D3D11CreateDeviceAndSwapChain 并在可执行文件中将 DXGI_SWAP_CHAIN_DESC::Windowed 设置为 FALSE 会更改窗口样式,从而导致对 D3D11CreateDeviceAndSwapChain 的下一次调用失败。

代码片段:

    IDXGISwapChain* swapChain;
    ID3D11Device* device;
    ID3D11DeviceContext* deviceContext;

    DXGI_SWAP_CHAIN_DESC desc;
    ZeroMemory(&desc, sizeof(desc));

    desc.BufferCount = 1;
    desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
    desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
    desc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
    desc.OutputWindow = FindWindowW(L"Window Title", NULL);
    desc.SampleDesc.Count = 1;
    desc.Windowed = ((GetWindowLongPtr(desc.OutputWindow, GWL_STYLE) & WS_POPUP) != 0) ? false : true;
    desc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
    desc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
    desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;

    desc.BufferDesc.Width = 1;
    desc.BufferDesc.Height = 1;
    desc.BufferDesc.RefreshRate.Numerator = 0;
    desc.BufferDesc.RefreshRate.Denominator = 1;


    if (!desc.OutputWindow)
    {
        return nullptr;
    }

    D3D_FEATURE_LEVEL featureLevel;
    const D3D_FEATURE_LEVEL featureLevelArray[] = { D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, };

    if (FAILED(D3D11CreateDeviceAndSwapChain(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, D3D11_CREATE_DEVICE_DEBUG, featureLevelArray, ARRAYSIZE(featureLevelArray), D3D11_SDK_VERSION, &desc, &swapChain, &device, &featureLevel, &deviceContext)))
    {
        return nullptr;
    }

标签: c++access-violationdirect3d11

解决方案


在可执行文件中将 DXGI_SWAP_CHAIN_DESC::Windowed 设置为 FALSE 时调用 D3D11CreateDeviceAndSwapChain 会更改窗口样式,从而导致对 D3D11CreateDeviceAndSwapChain 的下一次调用失败。


推荐阅读