It turns out that QXL is essential. I must have checked incorrectly whether it works after removing it. Without QXL, there is no image from the GPU, just a black screen. After adding it back, the graphics card outputs an image (the monitor name is now displayed instead of vDisplay). I’m not entirely sure what’s going on here, but I’m satisfied with the result.
Thanks @perrine for the script and suggestions.
I finally got around to testing again with a new VM and with QXL… Sadly, I cannot (simply) use BIOS instead of UEFI, because my existing Windows installation was done on a bare metal M.2 drive from a UEFI system. While I could attempt to convert the disk partition style, I’m not willing to risk potential data loss.
The only thing left to try is a fresh Windows install relying on virtualized storage, but that would only be for more testing.
It seems I’ll again hold off on GPU passthrough until getting another M.2 drive for a fresh Windows install.