Module Sarek_vulkan.Vulkan_api_host

Pinned and registered host memory (specs/vulkan-async-api.md).

Two sources of a host range that a VkBuffer covers:

A copy between such a range and a device buffer is one vkCmdCopyBuffer with no staging buffer and no host memcpy: the DMA engine reads or writes the host pages. A copy whose host range lies inside a buffer's range uses it, whether or not it names the allocated or registered bytes exactly.

module Device = Vulkan_api_device
module Ffi = Vulkan_api_host_ffi
type import = {
  1. device : Device.t;
  2. base : nativeint;
    (*

    First covered byte: the mapped pointer of a driver allocation, or the first imported byte (a multiple of the alignment).

    *)
  3. length : int;
    (*

    Covered bytes.

    *)
  4. buffer : Vulkan_types.vk_buffer;
  5. memory : Vulkan_types.vk_device_memory;
}
type entry = {
  1. mutable import : import option;
  2. registered : bool;
}

One buffer per (device, address). import = None once the device is gone: a registered entry then stays as a tombstone so a late unregister succeeds quietly.

val entries : (int * nativeint, entry) Stdlib.Hashtbl.t
val owned_blocks : (nativeint, unit) Stdlib.Hashtbl.t

Live alloc_pinned blocks. A block is driver memory owned by the device that allocated it: it is unmapped when that device is destroyed, but stays listed until free_pinned, which then succeeds without touching it.

val lock : Stdlib.Mutex.t
val refuse : string -> 'a
val unavailable_reason : Device.t -> string
val alignment_of : Device.t -> int
val round_down : nativeint -> int -> nativeint
val round_up : int -> int -> int
val create_import_buffer : Device.t -> int -> Vulkan_types.vk_buffer
val import_requirements : Device.t -> Vulkan_types.vk_buffer -> unit Ctypes.ptr -> int * int

Memory type bits both the buffer and the host pointer allow, and the size the buffer requires.

val allocate_import : Device.t -> type_index:int -> length:int -> unit Ctypes_static.ptr -> Vulkan_types.vk_device_memory
val pick_import_type : Device.t -> int -> int
val import_range : Device.t -> addr:nativeint -> byte_size:int -> import

Import the pages covering the range from addr of byte_size bytes on device. The buffer's own size requirement must fit the rounded range.

val destroy_import : import -> unit

Launches and copies that name the import have completed (every copy through this module is synchronous), so the objects can go at once.

val release_import : import -> unit
val take_entry : Device.t -> nativeint -> entry option
val add_entry : Device.t -> nativeint -> entry -> unit
val release_entry : entry -> unit
val destroy_entry : entry -> unit
val find : Device.t -> addr:nativeint -> byte_size:int -> (Vulkan_types.vk_buffer * int) option

The buffer and byte offset that address the range from addr of byte_size bytes of host memory on device, when an import covers it.

val page_size : int lazy_t
val check_registrable : Device.t -> unit

A registered range is imported as the pages around it; the extension may ask for a coarser granule than a page, and rounding to it would import memory the process may not own.

val register : Device.t -> nativeint -> byte_size:int -> unit
val unregister : Device.t -> nativeint -> unit
val amd_device_memory_bits : int
val pinned_memory_type : Device.t -> int -> int option

The memory type for a pinned block, best first: HOST_VISIBLE | HOST_COHERENT | HOST_CACHED, then without HOST_CACHED, both not DEVICE_LOCAL; only then the DEVICE_LOCAL ones. On a discrete GPU the DEVICE_LOCAL host-visible type is the BAR window onto VRAM, write-combined and read at 0.03 GB/s; a UMA device has only DEVICE_LOCAL types.

val create_pinned_buffer : Device.t -> int -> Vulkan_types.vk_buffer
val allocate_mapped_memory : Device.t -> Vulkan_types.vk_buffer -> Vulkan_types.vk_device_memory * nativeint

Driver memory for buffer, bound and mapped. The mapping lasts until the memory is freed.

val allocate_pinned : Device.t -> byte_size:int -> import

A driver allocation of byte_size bytes, mapped: no host memory crosses to the driver, whatever the device or the import policy.

val alloc_pinned : Device.t -> byte_size:int -> nativeint

Driver-allocated, mapped host memory that DMA copies address directly.

val free_pinned : Device.t -> nativeint -> unit

Releases the block's buffer and memory, which unmaps it. A block whose device was destroyed has nothing left to release. The table is keyed by address, as core's is: if the address was handed out again after the device was destroyed, a late free of the old block cannot be told from a free of the new one. Free every block before destroying its device.