memory

package
v0.19.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 1, 2026 License: MIT Imports: 5 Imported by: 0

Documentation

Overview

Package memory provides GPU memory allocation for Vulkan backend.

Architecture

The memory subsystem is organized in layers:

┌─────────────────────────────────────────────────────────┐
│                    GpuAllocator                         │
│  (High-level API: Alloc/Free, memory type selection)    │
├─────────────────────────────────────────────────────────┤
│                   MemoryTypePool                        │
│  (Per memory-type pools, dedicated allocation logic)    │
├─────────────────────────────────────────────────────────┤
│                   BuddyAllocator                        │
│  (Power-of-2 block management, O(log n) operations)     │
├─────────────────────────────────────────────────────────┤
│                   Vulkan Memory API                     │
│  (vkAllocateMemory, vkFreeMemory, vkMapMemory)          │
└─────────────────────────────────────────────────────────┘

Buddy Allocator

Implements classic buddy allocation algorithm:

  • Memory divided into power-of-2 blocks
  • Blocks split recursively until desired size reached
  • Adjacent "buddy" blocks merged on free
  • O(log n) allocation and deallocation
  • Minimal external fragmentation

Memory Type Selection

Vulkan exposes multiple memory types with different properties:

  • DEVICE_LOCAL: Fast GPU access, no CPU access
  • HOST_VISIBLE: CPU can map and access
  • HOST_COHERENT: No flush/invalidate needed
  • HOST_CACHED: CPU reads are cached

The allocator selects optimal memory type based on usage flags.

Allocation Strategies

  • Pooled: Small/medium allocations suballocated from large blocks
  • Dedicated: Large allocations (>32MB) get their own VkDeviceMemory
  • External: Memory imported from outside (not managed by allocator)

Thread Safety

GpuAllocator is thread-safe. Internal synchronization via mutex. Individual MemoryBlock handles are not thread-safe.

Index

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoSuitableMemoryType indicates no memory type matches requirements.
	ErrNoSuitableMemoryType = errors.New("allocator: no suitable memory type")

	// ErrAllocationFailed indicates Vulkan memory allocation failed.
	ErrAllocationFailed = errors.New("allocator: allocation failed")

	// ErrInvalidBlock indicates an invalid memory block.
	ErrInvalidBlock = errors.New("allocator: invalid memory block")
)
View Source
var (
	// ErrOutOfMemory indicates no suitable block is available.
	ErrOutOfMemory = errors.New("buddy: out of memory")

	// ErrInvalidSize indicates the requested size is invalid.
	ErrInvalidSize = errors.New("buddy: invalid size (zero or too large)")

	// ErrDoubleFree indicates an attempt to free an unallocated block.
	ErrDoubleFree = errors.New("buddy: double free or invalid block")

	// ErrInvalidConfig indicates invalid allocator configuration.
	ErrInvalidConfig = errors.New("buddy: invalid configuration")
)

Functions

This section is empty.

Types

type AllocationRequest added in v0.2.0

type AllocationRequest struct {
	// Size is the required allocation size in bytes.
	Size uint64

	// Alignment is the required alignment (must be power of 2).
	// Use 0 or 1 for no specific alignment beyond block size.
	Alignment uint64

	// Usage specifies how the memory will be used.
	Usage UsageFlags

	// MemoryTypeBits is a bitmask of allowed memory type indices.
	// Typically from VkMemoryRequirements.memoryTypeBits.
	MemoryTypeBits uint32
}

AllocationRequest describes a memory allocation request.

type AllocatorConfig added in v0.2.0

type AllocatorConfig struct {
	// BlockSize is the size of memory blocks allocated from Vulkan.
	// Default: 64MB. Must be power of 2.
	BlockSize uint64

	// MinAllocationSize is the minimum allocation granularity.
	// Default: 256 bytes. Must be power of 2.
	MinAllocationSize uint64

	// DedicatedThreshold is the size above which allocations
	// get their own VkDeviceMemory instead of suballocation.
	// Default: 32MB.
	DedicatedThreshold uint64

	// MaxBlocksPerHeap limits memory blocks per heap.
	// Default: 8 (512MB per heap with 64MB blocks).
	MaxBlocksPerHeap int
}

AllocatorConfig configures the GPU memory allocator.

func DefaultConfig added in v0.2.0

func DefaultConfig() AllocatorConfig

DefaultConfig returns sensible default configuration.

type AllocatorStats added in v0.2.0

type AllocatorStats struct {
	TotalAllocated       uint64 // Total memory allocated from Vulkan
	TotalUsed            uint64 // Total memory in use
	PooledAllocations    uint64 // Number of pooled allocations
	DedicatedAllocations uint64 // Number of dedicated allocations
	AllocationCount      uint64 // Total active allocations
}

AllocatorStats contains allocator-wide statistics.

type BuddyAllocator

type BuddyAllocator struct {
	// contains filtered or unexported fields
}

BuddyAllocator implements the buddy memory allocation algorithm.

The allocator manages a contiguous region of memory by dividing it into power-of-2 sized blocks. When allocating, blocks are split recursively until the smallest fitting size is found. When freeing, adjacent "buddy" blocks are merged back together.

Time complexity: O(log n) for both allocation and deallocation. Space overhead: O(n) bits for tracking block states.

func NewBuddyAllocator

func NewBuddyAllocator(totalSize, minBlockSize uint64) (*BuddyAllocator, error)

NewBuddyAllocator creates a new buddy allocator.

Parameters:

  • totalSize: Total memory to manage (must be power of 2)
  • minBlockSize: Smallest allocatable unit (must be power of 2, <= totalSize)

Returns error if parameters are invalid.

func (*BuddyAllocator) Alloc

func (b *BuddyAllocator) Alloc(size uint64) (BuddyBlock, error)

Alloc allocates a block of at least the requested size.

The returned block size will be rounded up to the next power of 2, and at least minBlockSize. Returns ErrOutOfMemory if no suitable block is available, ErrInvalidSize if size is 0 or exceeds totalSize.

func (*BuddyAllocator) Free

func (b *BuddyAllocator) Free(block BuddyBlock) error

Free releases a previously allocated block.

Returns ErrDoubleFree if the block was not allocated or already freed.

func (*BuddyAllocator) Reset

func (b *BuddyAllocator) Reset()

Reset releases all allocations and resets the allocator to initial state.

func (*BuddyAllocator) Stats

func (b *BuddyAllocator) Stats() BuddyStats

Stats returns current allocator statistics.

type BuddyBlock

type BuddyBlock struct {
	Offset uint64 // Offset within the managed region
	Size   uint64 // Actual size (power of 2, >= requested)
	// contains filtered or unexported fields
}

BuddyBlock represents an allocated memory block.

type BuddyStats

type BuddyStats struct {
	TotalSize       uint64 // Total managed memory
	AllocatedSize   uint64 // Currently allocated
	AllocationCount uint64 // Number of active allocations
	PeakAllocated   uint64 // Peak allocated size
	TotalAllocated  uint64 // Cumulative allocated (for throughput)
	TotalFreed      uint64 // Cumulative freed
	SplitCount      uint64 // Number of block splits
	MergeCount      uint64 // Number of block merges
}

BuddyStats contains allocator statistics.

type DeviceMemoryProperties added in v0.2.0

type DeviceMemoryProperties struct {
	// MemoryTypes lists all available memory types.
	MemoryTypes []MemoryType

	// MemoryHeaps lists all available memory heaps.
	MemoryHeaps []MemoryHeap
}

DeviceMemoryProperties holds all memory properties for a device.

type GpuAllocator added in v0.2.0

type GpuAllocator struct {
	// contains filtered or unexported fields
}

GpuAllocator is the main GPU memory allocator.

Thread-safe. Use Alloc/Free for all allocations.

func NewGpuAllocator added in v0.2.0

func NewGpuAllocator(device vk.Device, cmds *vk.Commands, props DeviceMemoryProperties, config AllocatorConfig) (*GpuAllocator, error)

NewGpuAllocator creates a new GPU memory allocator.

Parameters:

  • device: Vulkan device handle
  • cmds: Vulkan commands for memory operations
  • props: Device memory properties from vkGetPhysicalDeviceMemoryProperties
  • config: Allocator configuration (use DefaultConfig() for defaults)

func (*GpuAllocator) Alloc added in v0.2.0

func (a *GpuAllocator) Alloc(req AllocationRequest) (*MemoryBlock, error)

Alloc allocates GPU memory.

For large allocations (>= DedicatedThreshold), creates a dedicated VkDeviceMemory. For smaller allocations, suballocates from a pool using buddy allocation.

func (*GpuAllocator) Destroy added in v0.2.0

func (a *GpuAllocator) Destroy()

Destroy releases all allocations and cleans up.

Call this before destroying the Vulkan device.

func (*GpuAllocator) Free added in v0.2.0

func (a *GpuAllocator) Free(block *MemoryBlock) error

Free releases a memory block.

func (*GpuAllocator) PoolStats added in v0.2.0

func (a *GpuAllocator) PoolStats(memTypeIndex uint32) (PoolStats, bool)

PoolStats returns statistics for a specific memory type pool.

func (*GpuAllocator) Selector added in v0.2.0

func (a *GpuAllocator) Selector() *MemoryTypeSelector

Selector returns the memory type selector.

func (*GpuAllocator) Stats added in v0.2.0

func (a *GpuAllocator) Stats() AllocatorStats

Stats returns current allocator statistics.

type MemoryBlock added in v0.2.0

type MemoryBlock struct {
	// Memory is the Vulkan device memory handle.
	Memory vk.DeviceMemory

	// Offset is the byte offset within the device memory.
	Offset uint64

	// Size is the allocated size in bytes.
	Size uint64

	// MappedPtr holds the mapped pointer if memory is mapped.
	// Set by Map(), cleared by Unmap().
	MappedPtr uintptr
	// contains filtered or unexported fields
}

MemoryBlock represents an allocated memory region.

func (*MemoryBlock) IsDedicated added in v0.2.0

func (b *MemoryBlock) IsDedicated() bool

IsDedicated returns true if this is a dedicated allocation.

func (*MemoryBlock) MemoryTypeIndex added in v0.2.0

func (b *MemoryBlock) MemoryTypeIndex() uint32

MemoryTypeIndex returns the Vulkan memory type index.

type MemoryHeap added in v0.2.0

type MemoryHeap struct {
	// Size is the total heap size in bytes.
	Size uint64

	// Flags contains VkMemoryHeapFlags.
	Flags vk.MemoryHeapFlags
}

MemoryHeap describes a Vulkan memory heap.

type MemoryPool added in v0.2.0

type MemoryPool struct {
	// contains filtered or unexported fields
}

MemoryPool manages allocations for a single memory type.

type MemoryType added in v0.2.0

type MemoryType struct {
	// PropertyFlags contains VkMemoryPropertyFlags.
	PropertyFlags vk.MemoryPropertyFlags

	// HeapIndex is the index of the memory heap.
	HeapIndex uint32
}

MemoryType describes a Vulkan memory type.

type MemoryTypeSelector added in v0.2.0

type MemoryTypeSelector struct {
	// contains filtered or unexported fields
}

MemoryTypeSelector selects optimal memory types for allocations.

func NewMemoryTypeSelector added in v0.2.0

func NewMemoryTypeSelector(props DeviceMemoryProperties) *MemoryTypeSelector

NewMemoryTypeSelector creates a selector from device memory properties.

func (*MemoryTypeSelector) GetHeapSize added in v0.2.0

func (s *MemoryTypeSelector) GetHeapSize(heapIndex uint32) uint64

GetHeapSize returns the size of the specified heap.

func (*MemoryTypeSelector) GetMemoryType added in v0.2.0

func (s *MemoryTypeSelector) GetMemoryType(index uint32) (MemoryType, bool)

GetMemoryType returns the memory type at the given index.

func (*MemoryTypeSelector) IsDeviceLocal added in v0.2.0

func (s *MemoryTypeSelector) IsDeviceLocal(typeIndex uint32) bool

IsDeviceLocal returns true if the memory type is device local.

func (*MemoryTypeSelector) IsHostVisible added in v0.2.0

func (s *MemoryTypeSelector) IsHostVisible(typeIndex uint32) bool

IsHostVisible returns true if the memory type is host visible.

func (*MemoryTypeSelector) SelectMemoryType added in v0.2.0

func (s *MemoryTypeSelector) SelectMemoryType(req AllocationRequest) (uint32, bool)

SelectMemoryType finds the best memory type for the given request.

Returns the memory type index and true if found, or 0 and false if no suitable type exists.

type PoolStats added in v0.2.0

type PoolStats struct {
	BlockCount      int    // Number of VkDeviceMemory allocations
	TotalSize       uint64 // Total allocated from Vulkan
	UsedSize        uint64 // Currently used by suballocations
	AllocationCount uint64 // Number of active suballocations
}

PoolStats contains memory pool statistics.

type UsageFlags added in v0.2.0

type UsageFlags uint32

UsageFlags specifies intended memory usage. These flags help select the optimal memory type.

const (
	// UsageFastDeviceAccess indicates memory primarily accessed by GPU.
	// Prefers DEVICE_LOCAL memory.
	UsageFastDeviceAccess UsageFlags = 1 << iota

	// UsageHostAccess indicates memory needs CPU access.
	// Requires HOST_VISIBLE memory.
	UsageHostAccess

	// UsageUpload indicates memory used for CPU->GPU transfers.
	// Prefers HOST_VISIBLE + HOST_COHERENT, avoids HOST_CACHED.
	UsageUpload

	// UsageDownload indicates memory used for GPU->CPU readback.
	// Prefers HOST_VISIBLE + HOST_CACHED.
	UsageDownload

	// UsageTransient indicates memory for short-lived allocations.
	// May use LAZILY_ALLOCATED if available.
	UsageTransient
)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL