[Mesa-dev] [PATCH v2 3/3] radv: add support for VK_EXT_memory_budget
Samuel Pitoiset
samuel.pitoiset at gmail.com
Tue Jan 8 15:19:15 UTC 2019
A simple Vulkan extension that allows apps to query size and
usage of all exposed memory heaps.
The different usage values are not really accurate because
they are per drm-fd, but they should be close enough.
v2: - add software counters for the different heaps in the winsys
- improve budget/usage computations based on these counters
Signed-off-by: Samuel Pitoiset <samuel.pitoiset at gmail.com>
---
src/amd/vulkan/radv_device.c | 72 +++++++++++++++++++
src/amd/vulkan/radv_extensions.py | 1 +
src/amd/vulkan/radv_radeon_winsys.h | 4 ++
src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c | 29 +++++++-
.../vulkan/winsys/amdgpu/radv_amdgpu_winsys.c | 6 ++
.../vulkan/winsys/amdgpu/radv_amdgpu_winsys.h | 4 ++
6 files changed, 115 insertions(+), 1 deletion(-)
diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c
index d1e47133d1f..f79d54296b4 100644
--- a/src/amd/vulkan/radv_device.c
+++ b/src/amd/vulkan/radv_device.c
@@ -1350,12 +1350,84 @@ void radv_GetPhysicalDeviceMemoryProperties(
*pMemoryProperties = physical_device->memory_properties;
}
+static void
+radv_get_memory_budget_properties(VkPhysicalDevice physicalDevice,
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT *memoryBudget)
+{
+ RADV_FROM_HANDLE(radv_physical_device, device, physicalDevice);
+ VkPhysicalDeviceMemoryProperties *memory_properties = &device->memory_properties;
+ uint64_t visible_vram_size = radv_get_visible_vram_size(device);
+ uint64_t vram_size = radv_get_vram_size(device);
+ uint64_t gtt_size = device->rad_info.gart_size;
+ uint64_t heap_budget, heap_usage;
+
+ /* For all memory heaps, the computation of budget is as follow:
+ * heap_budget = heap_size - global_heap_usage + app_heap_usage
+ *
+ * The Vulkan spec 1.1.97 says that the budget should include any
+ * currently allocated device memory.
+ *
+ * Note that the application heap usages are not really accurate (eg.
+ * in presence of shared buffers).
+ */
+ if (vram_size) {
+ heap_usage = device->ws->query_value(device->ws,
+ RADEON_ALLOCATED_VRAM);
+
+ heap_budget = vram_size -
+ device->ws->query_value(device->ws, RADEON_VRAM_USAGE) +
+ heap_usage;
+
+ memoryBudget->heapBudget[RADV_MEM_HEAP_VRAM] = heap_budget;
+ memoryBudget->heapUsage[RADV_MEM_HEAP_VRAM] = heap_usage;
+ }
+
+ if (visible_vram_size) {
+ heap_usage = device->ws->query_value(device->ws,
+ RADEON_ALLOCATED_VRAM_VIS);
+
+ heap_budget = visible_vram_size -
+ device->ws->query_value(device->ws, RADEON_VRAM_VIS_USAGE) +
+ heap_usage;
+
+ memoryBudget->heapBudget[RADV_MEM_HEAP_VRAM_CPU_ACCESS] = heap_budget;
+ memoryBudget->heapUsage[RADV_MEM_HEAP_VRAM_CPU_ACCESS] = heap_usage;
+ }
+
+ if (gtt_size) {
+ heap_usage = device->ws->query_value(device->ws,
+ RADEON_ALLOCATED_GTT);
+
+ heap_budget = gtt_size -
+ device->ws->query_value(device->ws, RADEON_GTT_USAGE) +
+ heap_usage;
+
+ memoryBudget->heapBudget[RADV_MEM_HEAP_GTT] = heap_budget;
+ memoryBudget->heapUsage[RADV_MEM_HEAP_GTT] = heap_usage;
+ }
+
+ /* The heapBudget and heapUsage values must be zero for array elements
+ * greater than or equal to
+ * VkPhysicalDeviceMemoryProperties::memoryHeapCount.
+ */
+ for (uint32_t i = memory_properties->memoryHeapCount; i < VK_MAX_MEMORY_HEAPS; i++) {
+ memoryBudget->heapBudget[i] = 0;
+ memoryBudget->heapUsage[i] = 0;
+ }
+}
+
void radv_GetPhysicalDeviceMemoryProperties2(
VkPhysicalDevice physicalDevice,
VkPhysicalDeviceMemoryProperties2KHR *pMemoryProperties)
{
radv_GetPhysicalDeviceMemoryProperties(physicalDevice,
&pMemoryProperties->memoryProperties);
+
+ VkPhysicalDeviceMemoryBudgetPropertiesEXT *memory_budget =
+ vk_find_struct(pMemoryProperties->pNext,
+ PHYSICAL_DEVICE_MEMORY_BUDGET_PROPERTIES_EXT);
+ if (memory_budget)
+ radv_get_memory_budget_properties(physicalDevice, memory_budget);
}
VkResult radv_GetMemoryHostPointerPropertiesEXT(
diff --git a/src/amd/vulkan/radv_extensions.py b/src/amd/vulkan/radv_extensions.py
index 9952bb9c1c6..491ed9d94c3 100644
--- a/src/amd/vulkan/radv_extensions.py
+++ b/src/amd/vulkan/radv_extensions.py
@@ -105,6 +105,7 @@ EXTENSIONS = [
Extension('VK_EXT_external_memory_dma_buf', 1, True),
Extension('VK_EXT_external_memory_host', 1, 'device->rad_info.has_userptr'),
Extension('VK_EXT_global_priority', 1, 'device->rad_info.has_ctx_priority'),
+ Extension('VK_EXT_memory_budget', 1, True),
Extension('VK_EXT_pci_bus_info', 2, True),
Extension('VK_EXT_sampler_filter_minmax', 1, 'device->rad_info.chip_class >= CIK'),
Extension('VK_EXT_scalar_block_layout', 1, 'device->rad_info.chip_class >= CIK'),
diff --git a/src/amd/vulkan/radv_radeon_winsys.h b/src/amd/vulkan/radv_radeon_winsys.h
index e9d541ab150..d9b46d89cf3 100644
--- a/src/amd/vulkan/radv_radeon_winsys.h
+++ b/src/amd/vulkan/radv_radeon_winsys.h
@@ -84,6 +84,9 @@ enum radeon_ctx_priority {
};
enum radeon_value_id {
+ RADEON_ALLOCATED_VRAM,
+ RADEON_ALLOCATED_VRAM_VIS,
+ RADEON_ALLOCATED_GTT,
RADEON_TIMESTAMP,
RADEON_NUM_BYTES_MOVED,
RADEON_NUM_EVICTIONS,
@@ -164,6 +167,7 @@ struct radeon_winsys_fence;
struct radeon_winsys_bo {
uint64_t va;
bool is_local;
+ bool vram_cpu_access;
};
struct radv_winsys_sem_counts {
uint32_t syncobj_count;
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
index a9bd55eac8f..19a4211dd8b 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_bo.c
@@ -249,6 +249,7 @@ radv_amdgpu_winsys_bo_virtual_bind(struct radeon_winsys_bo *_parent,
static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo)
{
struct radv_amdgpu_winsys_bo *bo = radv_amdgpu_winsys_bo(_bo);
+ struct radv_amdgpu_winsys *ws = bo->ws;
if (p_atomic_dec_return(&bo->ref_count))
return;
@@ -269,6 +270,14 @@ static void radv_amdgpu_winsys_bo_destroy(struct radeon_winsys_bo *_bo)
0, AMDGPU_VA_OP_UNMAP);
amdgpu_bo_free(bo->bo);
}
+
+ if (bo->initial_domain & RADEON_DOMAIN_VRAM)
+ ws->allocated_vram -= align64(bo->size, ws->info.gart_page_size);
+ if (bo->base.vram_cpu_access)
+ ws->allocated_vram_vis -= align64(bo->size, ws->info.gart_page_size);
+ if (bo->initial_domain & RADEON_DOMAIN_GTT)
+ ws->allocated_gtt -= align64(bo->size, ws->info.gart_page_size);
+
amdgpu_va_range_free(bo->va_handle);
FREE(bo);
}
@@ -344,8 +353,10 @@ radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws,
if (initial_domain & RADEON_DOMAIN_GTT)
request.preferred_heap |= AMDGPU_GEM_DOMAIN_GTT;
- if (flags & RADEON_FLAG_CPU_ACCESS)
+ if (flags & RADEON_FLAG_CPU_ACCESS) {
+ bo->base.vram_cpu_access = initial_domain & RADEON_DOMAIN_VRAM;
request.flags |= AMDGPU_GEM_CREATE_CPU_ACCESS_REQUIRED;
+ }
if (flags & RADEON_FLAG_NO_CPU_ACCESS)
request.flags |= AMDGPU_GEM_CREATE_NO_CPU_ACCESS;
if (flags & RADEON_FLAG_GTT_WC)
@@ -378,6 +389,14 @@ radv_amdgpu_winsys_bo_create(struct radeon_winsys *_ws,
bo->bo = buf_handle;
bo->initial_domain = initial_domain;
bo->is_shared = false;
+
+ if (initial_domain & RADEON_DOMAIN_VRAM)
+ ws->allocated_vram += align64(bo->size, ws->info.gart_page_size);
+ if (bo->base.vram_cpu_access)
+ ws->allocated_vram_vis += align64(bo->size, ws->info.gart_page_size);
+ if (initial_domain & RADEON_DOMAIN_GTT)
+ ws->allocated_gtt += align64(bo->size, ws->info.gart_page_size);
+
radv_amdgpu_add_buffer_to_global_list(bo);
return (struct radeon_winsys_bo *)bo;
error_va_map:
@@ -474,6 +493,8 @@ radv_amdgpu_winsys_bo_from_ptr(struct radeon_winsys *_ws,
bo->bo = buf_handle;
bo->initial_domain = RADEON_DOMAIN_GTT;
+ ws->allocated_gtt += align64(bo->size, ws->info.gart_page_size);
+
radv_amdgpu_add_buffer_to_global_list(bo);
return (struct radeon_winsys_bo *)bo;
@@ -538,6 +559,12 @@ radv_amdgpu_winsys_bo_from_fd(struct radeon_winsys *_ws,
bo->is_shared = true;
bo->ws = ws;
bo->ref_count = 1;
+
+ if (bo->initial_domain & RADEON_DOMAIN_VRAM)
+ ws->allocated_vram += align64(bo->size, ws->info.gart_page_size);
+ if (bo->initial_domain & RADEON_DOMAIN_GTT)
+ ws->allocated_gtt += align64(bo->size, ws->info.gart_page_size);
+
radv_amdgpu_add_buffer_to_global_list(bo);
return (struct radeon_winsys_bo *)bo;
error_va_map:
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c
index 9706c04e8cd..d3a57f6b4f3 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.c
@@ -72,6 +72,12 @@ static uint64_t radv_amdgpu_winsys_query_value(struct radeon_winsys *rws,
uint64_t retval = 0;
switch (value) {
+ case RADEON_ALLOCATED_VRAM:
+ return ws->allocated_vram;
+ case RADEON_ALLOCATED_VRAM_VIS:
+ return ws->allocated_vram_vis;
+ case RADEON_ALLOCATED_GTT:
+ return ws->allocated_gtt;
case RADEON_TIMESTAMP:
amdgpu_query_info(ws->dev, AMDGPU_INFO_TIMESTAMP, 8, &retval);
return retval;
diff --git a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h
index 80a1c6f2926..edec0a1ed78 100644
--- a/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h
+++ b/src/amd/vulkan/winsys/amdgpu/radv_amdgpu_winsys.h
@@ -52,6 +52,10 @@ struct radv_amdgpu_winsys {
pthread_mutex_t global_bo_list_lock;
struct list_head global_bo_list;
+
+ uint64_t allocated_vram;
+ uint64_t allocated_vram_vis;
+ uint64_t allocated_gtt;
};
static inline struct radv_amdgpu_winsys *
--
2.20.1
More information about the mesa-dev
mailing list