One of the most obvious issues is that this is going to give the wrong size for the data type size for CheckFeatureSupport.
A union is going to be the smallest size that can fit all of the members. This means that sizeof(mixedArray)
(and by extension sizeof(ma[n])
) would be 8 bytes in size. This is due to D3D11_FEATURE_DATA_FORMAT_SUPPORT
, D3D11_FEATURE_DATA_FORMAT_SUPPORT2
and D3D11_FEATURE_DATA_THREADING
having two 4 byte members. But this would not be usable for D3D11_FEATURE_DATA_DOUBLES
, since this is a single 4 byte member. Once D3D11_FEATURE_DATA_D3D11_OPTIONS
is added, the union will increase to 56 bytes, which is much larger than D3D11 is expecting.
One very important thing to note is that when developing for Direct3D, the debug layer is the most useful debugging tool that is available.
int wmain()
{
using Microsoft::WRL::ComPtr;
ComPtr<ID3D11Device> d3d11_device;
ComPtr<ID3D11DeviceContext> d3d11_devctx;
UINT d3d11_flags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
D3D_FEATURE_LEVEL fl = D3D_FEATURE_LEVEL_11_1;
D3D_FEATURE_LEVEL out_fl{};
#ifdef _DEBUG
d3d11_flags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
if (FAILED(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, d3d11_flags, &fl, 1, D3D11_SDK_VERSION, d3d11_device.ReleaseAndGetAddressOf(), &out_fl, d3d11_devctx.ReleaseAndGetAddressOf())))
{
return -1;
}
D3D11_FEATURE_DATA_D3D11_OPTIONS opts{};
//The size parameter is deliberately too large.
d3d11_device->CheckFeatureSupport(D3D11_FEATURE::D3D11_FEATURE_D3D11_OPTIONS, &opts, sizeof(D3D11_FEATURE_DATA_D3D11_OPTIONS)+4);
return 0;
}
This deliberately incorrect code will have:
D3D11 ERROR: ID3D11Device::CheckFeatureSupport: Feature D3D11_FEATURE_D3D11_OPTIONS requires FeatureSupportDataSize to be the sizeof( D3D11_FEATURE_DATA_D3D11_OPTIONS ), which equals 56; but 60 was passed instead. [ STATE_GETTING ERROR #2097314: DEVICE_CHECKFEATURESUPPORT_MISMATCHED_DATA_SIZE]
D3D11 ERROR: ID3D11Device::CheckFeatureSupport: Returning E_INVALIDARG, meaning the parameters were invalid. [ STATE_GETTING ERROR #2097315: DEVICE_CHECKFEATURESUPPORT_INVALIDARG_RETURN]
in the debugger output. This is documented in the CheckFeatureSupport documentation:
"Returns S_OK if successful; otherwise, returns E_INVALIDARG if an unsupported data type is passed to the pFeatureSupportData parameter or a size mismatch is detected for the FeatureSupportDataSize parameter."
So because of how unions work, this will never work as intended.
To give an easier to test example.
union u
{
signed char a;
short b;
int c;
long long d;
};
int wmain()
{
auto fmt_string = std::format(L"{}\n", sizeof(u));
fputws(fmt_string.c_str(), stdout);
return 0;
}
Using sizeof(u)
or any variation that will get the size of the union is used, then this union will always return 8. This is because the size of long long
is 8 bytes. This is true even if the 1 byte member is the intended target.