-1

I am trying to create a swapchain from a dll. My process creates a window, initializes Direct3D11 and loads the dll.

It works perfectly fine when the process creates a non fullscreen window. But as soon as the process creates a fullscreen window I get an access violation when calling D3D11CreateDeviceAndSwapChain from the dll.

The call occurs in a separate thread. (not from the dllmain thread.)

Now unfortunately I can't even debug properly since breakpoints freeze the fullscreen window and it is on top of my debugger window.

What causes the access violation?

EDIT: I have done some static analysis of dxgi.dll and found that when creating the swapchain it checks for a series of extended and basic window styles. Also I noticed that it should print a debug message before crashing so I hooked up a remote debugger to capture it. The message just says what I already knew:

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: ]

The error code is: DXGI_ERROR_INVALID_CALL

So why does intializing direct3d work from my executable but using the window it creates in my dll doesn't?

EDIT2: Apparently calling D3D11CreateDeviceAndSwapChain with DXGI_SWAP_CHAIN_DESC::Windowed set to FALSE in the executable changes the window styles causing the next call to D3D11CreateDeviceAndSwapChain to fail.

CODE SNIPPET:

    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;
    }
James
  • 49
  • 1
  • 5
  • Instead of using ``D3D11CreateDeviceAndSwapChain`` you may find it is easier to use & debug if you create the device and then the swapchain in two steps. See [this blog post](https://walbourn.github.io/anatomy-of-direct3d-11-create-device/). – Chuck Walbourn Aug 10 '20 at 21:52

1 Answers1

0

Calling D3D11CreateDeviceAndSwapChain with DXGI_SWAP_CHAIN_DESC::Windowed set to FALSE in the executable changes the window styles causing the next call to D3D11CreateDeviceAndSwapChain to fail.

James
  • 49
  • 1
  • 5