[Vulkan] Fix failing allocation on iGPUs (#24736)
If memory requests for HOST_LOCAL memory fail, try to allocate
HOST_VISIBLE/mappable memory.
This is a workaround for what probably would need some refactoring in
the vulkan allocator.
Fixes https://github.com/iree-org/iree/issues/24717
Co-Authored-By: Claude
---------
Signed-off-by: Tobias Fuchs <fuchs@roofline.ai>
diff --git a/runtime/src/iree/hal/drivers/vulkan/allocator.c b/runtime/src/iree/hal/drivers/vulkan/allocator.c
index 5d78da7..0494004 100644
--- a/runtime/src/iree/hal/drivers/vulkan/allocator.c
+++ b/runtime/src/iree/hal/drivers/vulkan/allocator.c
@@ -887,29 +887,17 @@
return score;
}
-static bool iree_hal_vulkan_allocator_resolve_memory_placement(
+// Scans the physical device's memory types for the highest-scoring one that
+// provides |required_type| and can satisfy the requested usage.
+static bool iree_hal_vulkan_allocator_select_memory_type(
const iree_hal_vulkan_allocator_t* allocator,
- uint32_t allowed_memory_type_bits, iree_hal_buffer_params_t* params,
+ uint32_t allowed_memory_type_bits, const iree_hal_buffer_params_t* params,
+ iree_hal_memory_type_t required_type, iree_hal_buffer_params_t* out_params,
iree_hal_vulkan_allocator_memory_placement_t* out_placement) {
- memset(out_placement, 0, sizeof(*out_placement));
- if (!iree_hal_vulkan_allocator_normalize_queue_affinity(allocator, params)) {
- return false;
- }
- if (!iree_device_size_is_valid_alignment(params->min_alignment)) {
- return false;
- }
-
- const iree_hal_memory_type_t required_type =
- params->type & ~IREE_HAL_MEMORY_TYPE_OPTIMAL;
const VkPhysicalDeviceMemoryProperties* memory_properties =
&allocator->memory_properties2.memoryProperties;
-
bool found = false;
int best_score = 0;
- iree_hal_buffer_params_t best_params = *params;
- iree_hal_vulkan_allocator_memory_placement_t best_placement;
- memset(&best_placement, 0, sizeof(best_placement));
-
for (uint32_t i = 0; i < memory_properties->memoryTypeCount; ++i) {
if (!iree_all_bits_set(allowed_memory_type_bits, 1u << i)) continue;
const VkMemoryType* vk_memory_type = &memory_properties->memoryTypes[i];
@@ -933,20 +921,61 @@
if (!found || score > best_score) {
found = true;
best_score = score;
- best_params = candidate_params;
- best_params.type = memory_type;
- best_placement = (iree_hal_vulkan_allocator_memory_placement_t){
+ *out_params = candidate_params;
+ out_params->type = memory_type;
+ *out_placement = (iree_hal_vulkan_allocator_memory_placement_t){
.memory_type_index = i,
.memory_property_flags = vk_memory_type->propertyFlags,
.memory_type = memory_type,
};
}
}
+ return found;
+}
- if (!found) return false;
- *params = best_params;
- *out_placement = best_placement;
- return true;
+static bool iree_hal_vulkan_allocator_resolve_memory_placement(
+ const iree_hal_vulkan_allocator_t* allocator,
+ uint32_t allowed_memory_type_bits, iree_hal_buffer_params_t* params,
+ iree_hal_vulkan_allocator_memory_placement_t* out_placement) {
+ memset(out_placement, 0, sizeof(*out_placement));
+ if (!iree_hal_vulkan_allocator_normalize_queue_affinity(allocator, params)) {
+ return false;
+ }
+ if (!iree_device_size_is_valid_alignment(params->min_alignment)) {
+ return false;
+ }
+
+ const iree_hal_memory_type_t required_type =
+ params->type & ~IREE_HAL_MEMORY_TYPE_OPTIMAL;
+ iree_hal_buffer_params_t resolved_params = *params;
+
+ if (iree_hal_vulkan_allocator_select_memory_type(
+ allocator, allowed_memory_type_bits, params, required_type,
+ &resolved_params, out_placement)) {
+ *params = resolved_params;
+ return true;
+ }
+
+ // Unified-memory fallback. iree_hal_vulkan_memory_type_from_vk only reports
+ // HOST_LOCAL for host-visible, non-device-local memory, so unified-memory
+ // devices (integrated GPUs, software rasterizers) that expose a single
+ // device-local + host-visible type never satisfy a strict host-local request.
+
+ // Skip the fallback if the caller didn't ask for host-local
+ if (!iree_all_bits_set(required_type, IREE_HAL_MEMORY_TYPE_HOST_LOCAL)) {
+ return false;
+ }
+ // Retry requiring only host-visible (i.e. mappable)
+ const iree_hal_memory_type_t host_visible_type =
+ (required_type & ~IREE_HAL_MEMORY_TYPE_HOST_LOCAL) |
+ IREE_HAL_MEMORY_TYPE_HOST_VISIBLE | IREE_HAL_MEMORY_TYPE_HOST_COHERENT;
+ if (iree_hal_vulkan_allocator_select_memory_type(
+ allocator, allowed_memory_type_bits, params, host_visible_type,
+ &resolved_params, out_placement)) {
+ *params = resolved_params;
+ return true;
+ }
+ return false;
}
static iree_status_t iree_hal_vulkan_allocator_align_allocation_size(