I'm trying to create a DXGI swapchain for a window created by SDL2 (v2.0.18), but every time I call the IDXGIFactory5::CreateSwapChainForHwnd
method, I get the E_INVALIDARG
error.
Steps I'm Following
First, I create the SDL window.
Then I go about creating the swapchain, following these steps:
- Determine the index of the adapter containing the window
- Create a D3D11Device
- Create a DXGI swapchain using said device via the CreateSwapChainForHwnd method, passing the underlying HWND handle in the SDL_Window structure
I'll now share the code I'm using to accomplish these steps
Creating the SDL window
int posX = 0, int posY = 0, int width = 1920, int height = 1080;
// Init video subsystem
if (SDL_InitSubSystem(SDL_INIT_VIDEO) != 0) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_InitSubSystem(SDL_INIT_VIDEO) failed: %s",
SDL_GetError());
return false;
}
window = SDL_CreateWindow("H264 HW Decoding with D3D11 Rendering to SDL window",
posX,
posY,
width,
height,
SDL_WINDOW_ALLOW_HIGHDPI
);
if (!window) {
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_CreateWindow() failed: %s",
SDL_GetError());
SDL_QuitSubSystem(SDL_INIT_VIDEO);
}
Determine the index of the adapter containing the window
if (!SDL_DXGIGetOutputInfo(SDL_GetWindowDisplayIndex(params->window),
&adapterIndex, &outputIndex))
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"SDL_DXGIGetOutputInfo() failed: %s",
SDL_GetError());
return false;
}
Create a D3D11Device
IDXGIFactory5* Factory = nullptr;
bool success = false;
IDXGIAdapter1* adapter = nullptr;
HRESULT hr;
hr = CreateDXGIFactory2(DXGI_CREATE_FACTORY_DEBUG ,__uuidof(IDXGIFactory5), (void**)&Factory);
assert(!FAILED(hr));
hr = Factory->EnumAdapters1(adapterIndex, &adapter);
if (FAILED(hr))
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGIFactory::EnumAdapters1() failed: %x",
hr);
goto Exit;
}
hr = adapter->GetDesc1(&adapterDesc);
if (FAILED(hr))
{
SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
"IDXGIAdapter::GetDesc() failed: %x",
hr);
goto Exit;
}
if (adapterDesc.Flags & DXGI_ADAPTER_FLAG_SOFTWARE)
{
// Skip the WARP device. We know it will fail.
goto Exit;
}
hr = D3D11CreateDevice(adapter,
D3D_DRIVER_TYPE_UNKNOWN,
nullptr,
D3D11_CREATE_DEVICE_DEBUG | D3D11_CREATE_DEVICE_BGRA_SUPPORT,
nullptr,
0,
D3D11_SDK_VERSION,
&Device,
nullptr,
&DeviceContext);
Create a DXGI swapchain using said device via the CreateSwapChainForHwnd method, passing the underlying HWND handle in the SDL_Window structure
// Fill the swapchain description structure
DXGI_SWAP_CHAIN_DESC1 swapChainDesc = {0};
swapChainDesc.Stereo = FALSE;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Scaling = DXGI_SCALING_STRETCH;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
swapChainDesc.Flags = 0;
swapChainDesc.BufferCount = 5;
// Use the current window size as the swapchain size
SDL_GetWindowSize(window, (int*)&swapChainDesc.Width, (int*)&swapChainDesc.Height);
swapChainDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
// Get the HWND from SDL
SDL_SysWMinfo info;
SDL_VERSION(&info.version);
SDL_GetWindowWMInfo(params->window, &info);
SDL_assert(info.subsystem == SDL_SYSWWINDOWS);
assert(IsWindow(info.info.win.window));
// Create the swapchain and associate it to the SDL window
IDXGISwapChain1* swapChain;
hr = Factory->CreateSwapChainForHwnd(Device,
info.info.win.window,
&swapChainDesc,
nullptr,
nullptr,
&swapChain);
Debug Layer Output
I've turned the DXGI debug layer on, and this is the output from it
D3D11 INFO: Create ID3D11Context: Name="unnamed", Addr=0x000001B3F7978990, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097225: CREATE_CONTEXT]
D3D11 INFO: Create ID3DDeviceContextState: Name="unnamed", Addr=0x000001B3F7996B50, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #3145735: CREATE_DEVICECONTEXTSTATE]
D3D11 INFO: Create ID3D11BlendState: Name="unnamed", Addr=0x000001B3F79963A0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097270: CREATE_BLENDSTATE]
D3D11 INFO: Create ID3D11DepthStencilState: Name="unnamed", Addr=0x000001B3F79965E0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097273: CREATE_DEPTHSTENCILSTATE]
D3D11 INFO: Create ID3D11RasterizerState: Name="unnamed", Addr=0x000001B3F79A1F00, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097276: CREATE_RASTERIZERSTATE]
D3D11 INFO: Create ID3D11Sampler: Name="unnamed", Addr=0x000001B3F79A2140, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097267: CREATE_SAMPLER]
D3D11 INFO: Create ID3D11Query: Name="unnamed", Addr=0x000001B3F79A2380, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097279: CREATE_QUERY]
D3D11 INFO: Create ID3D11Fence: Name="unnamed", Addr=0x000001B3F79A2600, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #3146250: CREATE_FENCE]
D3D11 INFO: Destroy ID3D11Fence: Name="unnamed", Addr=0x000001B3F79A2600 [ STATE_CREATION INFO #3146252: DESTROY_FENCE]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA034FF0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA035430, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA035870, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA035CB0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA0360F0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA0870F0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA08B540, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA08B980, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA08C1D0, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA08C610, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #2097234: CREATE_TEXTURE2D]
D3D11 INFO: Create ID3D11Fence: Name="unnamed", Addr=0x000001B3FA04E870, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #3146250: CREATE_FENCE]
D3D11 INFO: Create ID3D11Fence: Name="unnamed", Addr=0x000001B3FA090370, ExtRef=1, IntRef=0 [ STATE_CREATION INFO #3146250: CREATE_FENCE]
D3D11 INFO: Destroy ID3D11Fence: Name="unnamed", Addr=0x000001B3FA04E870 [ STATE_CREATION INFO #3146252: DESTROY_FENCE]
D3D11 INFO: Destroy ID3D11Fence: Name="unnamed", Addr=0x000001B3FA090370 [ STATE_CREATION INFO #3146252: DESTROY_FENCE]
Exception thrown at 0x00007FFD803AFE7C in decode_video_ffmpeg_example.exe: Microsoft C++ exception: _com_error at memory location 0x00000079E9AFEF88.
Exception thrown at 0x00007FFD803AFE7C in decode_video_ffmpeg_example.exe: Microsoft C++ exception: _com_error at memory location 0x00000079E9AFF000.
D3D11 INFO: Destroy ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA034FF0 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA035430 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA035870 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA035CB0 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="unnamed", Addr=0x000001B3FA0360F0 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="DXGI cross-adapter flip proxy (dGPU opened)", Addr=0x000001B3FA0870F0 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="DXGI cross-adapter flip proxy (dGPU opened)", Addr=0x000001B3FA08B540 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="DXGI cross-adapter flip proxy (dGPU opened)", Addr=0x000001B3FA08B980 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="DXGI cross-adapter flip proxy (dGPU opened)", Addr=0x000001B3FA08C1D0 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
D3D11 INFO: Destroy ID3D11Texture2D: Name="DXGI cross-adapter flip proxy (dGPU opened)", Addr=0x000001B3FA08C610 [ STATE_CREATION INFO #2097236: DESTROY_TEXTURE2D]
The DirectX11 debug layer output is juts the following message
E_INVALIDARG One or more arguments are invalid.
Things I've already tried
- Using different versions of the DXGI factory (
IDXGIFactory2
andIDXGIFactory3
) - Creating different types of
D3D11Device
(likeD3D_DRIVER_TYPE_HARDWARE
andD3D_DRIVER_TYPE_REFERENCE
) - Instead of calling
SDL_CreateWindow
, creating a native window with these style flagsWS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX
, and then creating the SDL window using theSDL_CreateWindowFrom
function - Following this tutorial from Microsoft, where the
CreateSwapchainForHwnd
is used. This program gives me no problems; the method executes successfully and the window is displayed correctly - Changing the values set in the
DXGI_SWAP_CHAIN_DESC1
structure (output format, swap effect, scaling, buffer count, window size)
My Environment
OS: Windows 11
Processor: AMD Ryzen 9 5900HX with Radeon Graphics
Graphic Adapters: NVIDIA RTX3060 Laptop GPU; AMD Radeon Graphics (integrated)