Reputation: 46
I am trying to set up the correct context for hardware-accelerated h264 decoding and rendering using D3D11 - and failing at the very beginning, on the CreateSwapChainForHwnd() call.
These are the versions of the interfaces I'm using:
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;
This is the device creation code:
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
Up until this point, everything works, but I'm posting it just in case there's a mistake cascading down to the malfunctioning call.
This is my swap chain descriptor:
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;
Do note I have tried the following options in various (non-exhaustive) permutations:
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
And this is the call that fails:
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
));
Other things I have tried:
different COM interface versions: d3d11_1 through 6, though I may have misused the combinations of IDXGIFactoryN with ID3D11DeviceM and IDXGISwapChainX
using m_adapter[0] (which is Intel HD Graphics 530)
Printed debug info:
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.
Additional info:
Windows 10 build 17763.195
Nvidia GTX 960m, supported feature levels: 9_1 through 11_0
Intel HD Graphics 530, supported feature levels: 9_1 through 12_1
Visual Studio D3D11 example apps compile and run correctly, however they use UWP instead of Win32 for presentation (could hWnd be at fault? How do I test it?)
With both adapters, the resulting acceptedFeatureLevel after CreateDevice is the highest supported one.
I've gone through a few pages of google and SO searches trying to find similar issues, and none of the suggested solutions work for me.
Given the memory access exception returned from the debug mode, I'm suspecting a bad COM interface pointer? If that's the case, I'm assuming it happens after the vtable indirection layer because the address indicated is very very far away from any of my COM interface pointers, as can be seen above in the debug output. Is it possible to trace the function pointers after the vtable indirection, in order to verify if any of them correspond to the bad memory access?
Upvotes: 1
Views: 2675
Reputation: 46
Alright, this is a temporary answer because it is the result of shotgun debugging, I have simply tried other permutations of options but I still have no idea why the previous ones failed.
The results of my experimentation:
Any combination I tried with DXGI_FORMAT_B8G8R8X8_UNORM failed, I have to use DXGI_FORMAT_B8G8R8A8_UNORM
Any combination I tried with DXGI_SCALING_ASPECT_RATIO_STRETCH
failed, I have to use DXGI_SCALING_STRETCH
I have not found any explanation in the MSDN for this behavior, the failing options seem viable as far as I can understand this.
Edit:
Thank you very much Chuck Walbourn for the explanations:
DXGI_FORMAT_B8G8R8X8_UNORM
is not a viable backbuffer format at my target feature levels as per MSDN supported formats tables (I had actually consulted those tables without ever realizing they scrolled sideways facepalm...)
DXGI_SCALING_ASPECT_RATIO_STRETCH
is only compatible with CreateSwapChainForCoreWindow
or CreateSwapChainForComposition
, not Win32 window handles and associated methods (cannot find an MSDN source for that)
Upvotes: 1