PCIe is a networking protocol between multiple entities that send each other read and write requests into their respective address spaces. When requests are generated is defined by the devices on the bus. The exchange of TLPs is fully symmetric, so the format is the same whether the CPU writes to an expansion card, an expansion card starts a DMA transfer, or two expansion cards talk to each other.
The CPU and memory are connected to the root complex, which is basically a regular PCIe node that presents the system memory as the addressable address space (in modern implementations, with a protection/translation layer similar to the MMU), as well as a few special addresses that cause interrupts to be sent to the CPU when written to; there are also special TLP packets that correspond to the traditional ("legacy") PCI interrupts.
The same mechanism also works for the GPU, except that the GPU will not understand legacy interrupts. You can simply access video memory in parallel to the GPU, but writing to a command register will generate an interrupt inside the GPU, which redirects the instruction flow.
The PCIe device and the GPU are typically integrated on a single chip to optimize accesses to the graphics RAM, but logically these are different functional units.
Flow control is implemented using credits, on the link layer (so below TLPs). On a direct link, each side advertises how much buffer space is left for packets of a certain type, and the next packet can be sent if sufficient space is available (so packets are never split).