Memory Management¶
Blender is responsible for memory management in Vulkan. Most of this is implemented using the VMA library. This section describes how the memory on modern GPUs are organized and how this is utilized by Blender.
Memory Areas¶
In Vulkan there each device can have its own memory areas where each area has different characteristics. Some areas are directly accessible via the host, others are only visible by the GPU. There are areas that can be cached by the GPU and others not.
The layout for an Dedicated AMD VEGA GPUs looks like:
Area | GPU Capabilities | Host Capabilities | Size |
---|---|---|---|
#0 | Stored / Visible / Cached Fast Read Write | Most of VRAM | |
#1 | Visible / Cached | Stored / Visible Fast Write | |
#2 | Stored / Visible / Cached Fast Read Write | Visible Fast Write | 256MB |
#3 | Visible / Cached | Stored / Visible / Cached Fast Read Write |
Note
This can be differ for each platform. An Integrated GPU or CPU/GPU with shared memory model or different GPU architectures can have different areas. This area layout was taken from AMD VEGA.
Buffers and Images¶
Memory Usage Types¶
Depending on the usage of the buffer we can select the memory area we want to keep the data.
GPU_USAGE_STATIC
,GPU_USAGE_DYNAMIC
andGPU_USAGE_DEVICE_ONLY
will be loaded in an area that is fast for the GPU to access. These buffers are expected to be used multiple times.GPU_USAGE_STREAM
will be loaded in GPU and host visible memory. It is assumed that the data is only used once. Uploading to the GPU would already access it multiple times.
Todo
Current implementation uploads the data to host visible area, but eventually this should be as described above to improve performance.
Note
More information about this topic can be found at https://www.youtube.com/watch?v=K-2bxdmosH8
Staging buffers¶
One Fixed Size Staging buffer. Transfers from the GPU to HOST is always slow.
Todo
When would be add staging buffers
Unbinding from contexts¶
- Device should be aware of each available context.
- When memory is freed, it will be removed from each known context.
- A resource can be bound to multiple contexts. When a resource is freed it should be unbound from all contexts.
classDiagram
class VKDevice {
void context_register(VKContext *context)
void context_unregister(VKContext *context)
}
class VKContext {
}
class VKStateManager {
void unbind_image(Texture *texture)
void unbind_texture(Texture *texture)
void unbind_storage_buffer(VKBindableResource &resource)
void unbind_buffer(VKBindableResource &resource)
}
class VKBindSpace {
void bind(int binding, VKBindableResource &resource)
void apply_bindings()
void unbind(VKBindableResource&resource)
void unbind_all()
}
VKDevice "1" o--> "N" VKContext: contexts
VKContext "1" *--> "1" VKStateManager: state_manager
VKStateManager *--> VKBindSpace: images, textures, uniform_buffers, storage_buffers
Todo
move to shader resource management
classDiagram
class VKBindableResource {
void bind(int binding, BindType bind_type)
void unbind_from_active_context()
void unbind_from_all_contexts()
}
VKBindableResource <|-- VKStorageBuffer
VKBindableResource <|-- VKTexture
VKBindableResource <|-- VKUniformBuffer
VKBindableResource <|-- VKIndexBuffer
VKBindableResource <|-- VKVertexBuffer
When unbinding a resource, the resource will be unbound from the active context (if any)
When destoying the resource, the resource will be unbound from all registered contexts.