Ok, I still can't get it to work. The CreateSwapChain call stopped working once the DXGI_SWAP_CHAIN_DESC has been filled with the MSAA parameters determined with CheckFeatureSupport. The error is DXGI_ERROR_INVALID_CALL which should indicate an invalid parameter, I'm lost.
The significant code is the following, I hope it is another silly mistake and I thank in advance whoever will try to help me.
//create device
D3D12CreateDevice(nullptr, //default adapter
m_featureLevel, //12.1
IID_PPV_ARGS(&m_device));
//create graphics command queue
D3D12_COMMAND_QUEUE_DESC commandQueueDesc{};
commandQueueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
commandQueueDesc.Priority = D3D12_COMMAND_QUEUE_PRIORITY_NORMAL;
commandQueueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
commandQueueDesc.NodeMask = 0;
m_device->CreateCommandQueue(&commandQueueDesc, IID_PPV_ARGS(&m_commandQueue));
//create swap chain
DXGI_SWAP_CHAIN_DESC swapChainDesc{};
ZeroMemory(&swapChainDesc, sizeof(DXGI_SWAP_CHAIN_DESC));
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = m_rtvFormat;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = FRAMES_COUNT;
swapChainDesc.OutputWindow = getWindowHandle();
swapChainDesc.Windowed = TRUE;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
swapChainDesc.Flags = 0;
D3D12_FEATURE_DATA_MULTISAMPLE_QUALITY_LEVELS msaaQualityDesc{};
//msaaQualityDesc is filled with the method discussed before...
swapChainDesc.SampleDesc.Count = msaaQualityDesc.SampleCount;
swapChainDesc.SampleDesc.Quality = msaaQualityDesc.NumQualityLevels-1;
ComPtr<IDXGIFactory4> factory{ nullptr };
CreateDXGIFactory1(IID_PPV_ARGS(&factory));
ComPtr<IDXGISwapChain> swapChain{ nullptr };
factory->CreateSwapChain(m_commandQueue.Get(),
&swapChainDesc, &swapChain); //this fails