D3D11 CreateSwapChainForHwnd 失败并显示 DXGI_ERROR_INVALID_CALL 或 E_INVALIDARG
D3D11 CreateSwapChainForHwnd fails with either DXGI_ERROR_INVALID_CALL or E_INVALIDARG
我正在尝试使用 D3D11 为硬件加速的 h264 解码和渲染设置正确的上下文 - 但一开始就在 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 构建 17763.195
Nvidia GTX 960m,支持的功能级别:9_1 到 11_0
Intel HD Graphics 530,支持的功能级别:9_1 到 12_1
Visual Studio D3D11 示例应用程序编译并 运行 正确,但是它们使用 UWP 而不是 Win32 进行演示(hWnd 可能有问题吗?我如何测试它?)
对于这两个适配器,CreateDevice 之后生成的 acceptedFeatureLevel 是受支持的最高级别。
我浏览了几页 google 和 SO 搜索试图找到类似的问题,none 的建议解决方案对我有用。
鉴于从调试模式返回的内存访问异常,我怀疑是错误的 COM 接口指针?如果是这样的话,我假设它发生在 vtable 间接层之后,因为指示的地址与我的任何 COM 接口指针都非常非常远,如上面的调试输出所示。是否可以在 vtable 间接寻址之后跟踪函数指针,以验证它们是否对应于错误的内存访问?
好吧,这是一个临时答案,因为它是 shotgun 调试的结果,我只是尝试了其他选项排列,但我仍然不知道为什么以前的失败。
我的实验结果:
我用DXGI_FORMAT_B8G8R8X8_UNORM尝试的任何组合都失败了,我必须使用DXGI_FORMAT_B8G8R8A8_UNORM
我尝试使用 DXGI_SCALING_ASPECT_RATIO_STRETCH
的任何组合都失败了,我必须使用 DXGI_SCALING_STRETCH
我没有在 MSDN 中找到任何关于此行为的解释,据我所知,失败的选项似乎可行。
编辑:
非常感谢Chuck Walbourn的解释:
DXGI_FORMAT_B8G8R8X8_UNORM
根据 MSDN supported formats tables 在我的目标功能级别上不是可行的后备缓冲区格式(我实际上已经查阅了这些表格而没有意识到它们横向滚动 脸掌...)
DXGI_SCALING_ASPECT_RATIO_STRETCH
仅与 CreateSwapChainForCoreWindow
或 CreateSwapChainForComposition
兼容,不兼容 Win32 window 句柄和相关方法(找不到 MSDN 源) )
我正在尝试使用 D3D11 为硬件加速的 h264 解码和渲染设置正确的上下文 - 但一开始就在 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 构建 17763.195
Nvidia GTX 960m,支持的功能级别:9_1 到 11_0
Intel HD Graphics 530,支持的功能级别:9_1 到 12_1
Visual Studio D3D11 示例应用程序编译并 运行 正确,但是它们使用 UWP 而不是 Win32 进行演示(hWnd 可能有问题吗?我如何测试它?)
对于这两个适配器,CreateDevice 之后生成的 acceptedFeatureLevel 是受支持的最高级别。
我浏览了几页 google 和 SO 搜索试图找到类似的问题,none 的建议解决方案对我有用。
鉴于从调试模式返回的内存访问异常,我怀疑是错误的 COM 接口指针?如果是这样的话,我假设它发生在 vtable 间接层之后,因为指示的地址与我的任何 COM 接口指针都非常非常远,如上面的调试输出所示。是否可以在 vtable 间接寻址之后跟踪函数指针,以验证它们是否对应于错误的内存访问?
好吧,这是一个临时答案,因为它是 shotgun 调试的结果,我只是尝试了其他选项排列,但我仍然不知道为什么以前的失败。
我的实验结果:
我用DXGI_FORMAT_B8G8R8X8_UNORM尝试的任何组合都失败了,我必须使用DXGI_FORMAT_B8G8R8A8_UNORM
我尝试使用
DXGI_SCALING_ASPECT_RATIO_STRETCH
的任何组合都失败了,我必须使用DXGI_SCALING_STRETCH
我没有在 MSDN 中找到任何关于此行为的解释,据我所知,失败的选项似乎可行。
编辑:
非常感谢Chuck Walbourn的解释:
DXGI_FORMAT_B8G8R8X8_UNORM
根据 MSDN supported formats tables 在我的目标功能级别上不是可行的后备缓冲区格式(我实际上已经查阅了这些表格而没有意识到它们横向滚动 脸掌...)DXGI_SCALING_ASPECT_RATIO_STRETCH
仅与CreateSwapChainForCoreWindow
或CreateSwapChainForComposition
兼容,不兼容 Win32 window 句柄和相关方法(找不到 MSDN 源) )