What notes are you referring to beyond what I see on the screen which does not say this.
The issue, as far as I can tell is not one of physical or virtual access, it is one of API.
I am NOT a Metal expert, but this is my understanding:
Metal wants you to use Handles (essentially indices into a table of address ranges) not raw pointers. This is not because raw pointers won't, in some sense, "work", it's because the Metal API depends on being told how and when blocks of data are being used.
This is because the L1 caches are not coherent, and *SW conventions* are required to handle coherency.
After every unit of work (called a "kick", but you can think of this as a shader) the L1 caches are flushed to L2, so that subsequent shaders that depend on the results of this shader, but which may run on a different core, can see the work that was done.
This mechanism for flushing data from L1 to L2 is very sophisticated in terms of flushing the minimum amount of data, and in terms of scheduling non-dependent kicks to execute at the same time that flushing is happening, BUT it depends on knowing which address ranges are used in what way by each kick – ie which address ranges were read, which were written.
If you start passing around raw pointers without informing Metal of how the associated data ranges are being used, you will lose this flushing/coherence.
This is not an issue for Vulkan, or more precisely it's a DIFFERENT issue, because Vulkan has a different model of who is responsible for flushing L1 caches. Apple's solution is not wrong, it's just different from Vulkan's, and assumes different packaging of the information about who is responsible for flushing what data ranges when.
It's like Apple is Java or Swift, with memory management happening behind the scenes – but you don't use raw pointers – while Vulkan is like C with manual calls to malloc and free.
Corrections welcome if I got anything wrong!
What you describe may be one potential technical reason why Metal does not offer unified virtual memory, although I am not 100% convinced the cache flushing works exactly as you describe. Metal indeed requires you to tell it which memory objects are in use during a pass, but not the exact pointer range. There is nothing preventing you from allocating one huge Metal buffer and doing all your sub-allocations from there. In fact, that’s the preferred way since every buffer incurs additional overhead (and Metal gives you the heaps API to simplify these things). In summary, the system must already have a way to track which parts of the cache need flushing and so my guess is that the “use” APIs are there primarily to ensure that the resources are in memory and bound to the appropriate page tables. Vulkan doesn’t need the “use” API because all resources are explicitly assumed to be resident anyway, unlike Metal.
From the API consumer perspective the issue is that the CPU and the GPU use different virtual address spaces. And anyway, the buffer handle is just the GPU virtual address. It’s even called GPU address in the API and you can write valid GPU pointers from the CPU using these APIs. Real handles are used for textures and samplers and they indeed encode offsets into the per-process descriptor tables (same system Nvidia uses).