7
$\begingroup$

I have a memory that is persistently mapped. It is both HOST_VISIBLE and HOST_COHERENT but not DEVICE_LOCAL. (My physical device offers no memory that is exclusively HOST_VISIBLE without also being HOST_COHERENT.)

This memory contains vertex buffers. I send commands every frame to draw those buffers. Some of those, I change the content every frame, and others more rarely.

I believe buffers somehow need to be transfered by the driver into the GPU before it can draw them, yes? Here, I never need to invalidate/flush anything because the memory is HOST_COHERENT. How does the driver know what to update/transfer and when? Does it have to a way to detect parts where I change stuff, or does it compulsively retransfer data every frame?

$\endgroup$

2 Answers 2

8
$\begingroup$

How does the driver know what to update/transfer and when?

It doesn't. There is no transfer or update in that fashion.

All memory allocated through a Vulkan device represents memory that some device operations can read directly. If a Vulkan device advertises that it can use visible/coherent memory as source vertex data for rendering operations, that does not mean that some kind of upload is going on to make this happen. The device is reading that data from the memory you write to. The vkFlushMappedRange function merely expunges writes from CPU cache lines, so that they actually reach the memory.

Memory that is host-coherent and host-visible would represent memory that either:

  1. Is not cached by the CPU, and therefore the GPU sees the memory as it is. This also means that CPU writes and reads tend to be slow.

  2. The GPU can directly access the CPU's caches, to one degree or another.

Usually, #2 happens when the GPU is on-die with the CPU. Which would also mean that this would be device-local memory. Since you've said that it isn't device-local, odds are good that it is simply not cached. It may use write-combining (which improves the efficiency of sequential writes), but CPU writes otherwise are delivered as they are. Given that the memory does not seem to include "cached" in its description, I'd say #1 is the most likely.

Note that just because you don't need to explicitly flush memory does not change the fact that you still need a dependency between the CPU operation writing that data and the GPU command(s) that read it. This would generally be some from of event with a memory dependency.

$\endgroup$
3
$\begingroup$

I don't think this kind of under-the-hood data transfer should happen in low-level APIs like Vulkan. The GPU is capable of reading directly from host memory, via the PCIe interconnect. So when you render from a host memory buffer, it should dynamically "pull" the vertices referenced by the draw call.

I'm not sure exactly how host coherence works with this, but my guess is the CPU's memory controller is probably smart enough to snoop PCIe read requests, and do the right thing with regard to the CPU caches.

If you wanted to transfer the data into GPU memory first, I think you would have to implement that yourself, by allocating some device-local memory and doing a copy into it. (For a vertex buffer that's pretty much consumed linearly once per frame, there's probably no benefit to doing that, but it could be worthwhile for a buffer that's updated more rarely, or that has a more random access pattern.)

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.