Yeah, sadly most GUI systems are still depressingly single threaded by nature. It is possible to run windows in different threads in Windows, but usually it's not worth the effort.
That said though, pure processing and rendering of GUI should never be a performance bottleneck. As soon as you know you have to perform a lengthy operation in response to user input, that should be offloaded to a background thread. Your GUI thread should *only* be used for GUI, and that should be reasonably lightweight.
Rendering in general is a single threaded bottleneck on a lot of systems. OpenGL is restricted to simple uploading of resources, and even that can be broken depending on the platform. DX11 provides support for setting up command buffers in worker threads, but it's so horribly broken in pretty much all driver implementations it's not worth bothering with. DX12 is better in that respect, but it's still quite restricted. Metal is about the same, if I remember correctly (it's been a while). Vulkan, I have no idea, but I guess it's similar to DX12 in this respect. Thankfully, GPUs are a hell of a lot faster these days. :)
But then again, most graphics intensive applications keep the main thread just for rendering and push all other processing off into worker threads.
Re: Thread Affinity: That *can* make things slower, but if you have a large(ish) set of data that you know will be accessed in a certain manner, thrashing your L1 and L2 caches as worker threads are bounced all over the CPU *will* make things slower. There's a time and a place for setting thread affinity. The trick is knowing when and when not to. :)