ggml-vulkan: probe vkGetBufferDeviceAddress before enabling BDA
Some Vulkan drivers (observed on Adreno, Qualcomm build 923a446bf8,
driver date 09/05/24) report bufferDeviceAddress support in
VkPhysicalDeviceVulkan12Features but crash with SIGSEGV when
vkGetBufferDeviceAddress is actually called:
Fatal signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0
#01 ggml_vk_create_buffer+4084
#02 ggml_vk_create_buffer_device+148
#03 ggml_backend_vk_buffer_type_alloc_buffer+240
#07 whisper_model_load+5996
The crash occurs inside ggml_vk_create_buffer when
device->device.getBufferAddress() is called — the driver-internal
function pointer dereferences null.
After creating the logical device, verify that the function pointer
resolves via vkGetDeviceProcAddr and that a test call returns a
non-zero address. If either check fails, disable
buffer_device_address so all guarded code paths skip BDA.
This commit is contained in:
parent
76684141a5
commit
a80d3d31a3
|
|
@ -5379,6 +5379,63 @@ static vk_device ggml_vk_get_device(size_t idx) {
|
|||
// Queues
|
||||
ggml_vk_create_queue(device, device->compute_queue, compute_queue_family_index, 0, { vk::PipelineStageFlagBits::eComputeShader | vk::PipelineStageFlagBits::eTransfer }, false);
|
||||
|
||||
// Verify vkGetBufferDeviceAddress actually works — some drivers
|
||||
// (e.g. certain Adreno builds) report bufferDeviceAddress support
|
||||
// in the feature bits but crash (SIGSEGV) when the function is
|
||||
// actually called. Probe it here and disable if broken.
|
||||
if (device->buffer_device_address) {
|
||||
PFN_vkGetBufferDeviceAddress pfn = (PFN_vkGetBufferDeviceAddress)
|
||||
vkGetDeviceProcAddr(device->device, "vkGetBufferDeviceAddress");
|
||||
if (pfn == nullptr) {
|
||||
GGML_LOG_WARN("ggml_vulkan: vkGetBufferDeviceAddress proc addr is null, disabling BDA\n");
|
||||
device->buffer_device_address = false;
|
||||
} else {
|
||||
// Create a tiny test buffer and verify the call returns non-zero
|
||||
VkBufferCreateInfo test_bci = {};
|
||||
test_bci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
|
||||
test_bci.size = 256;
|
||||
test_bci.usage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT;
|
||||
VkBuffer test_buf = VK_NULL_HANDLE;
|
||||
if (vkCreateBuffer(device->device, &test_bci, nullptr, &test_buf) == VK_SUCCESS) {
|
||||
VkMemoryRequirements test_req;
|
||||
vkGetBufferMemoryRequirements(device->device, test_buf, &test_req);
|
||||
VkPhysicalDeviceMemoryProperties test_mem_props;
|
||||
vkGetPhysicalDeviceMemoryProperties(device->physical_device, &test_mem_props);
|
||||
uint32_t test_mtype = UINT32_MAX;
|
||||
for (uint32_t j = 0; j < test_mem_props.memoryTypeCount; j++) {
|
||||
if (test_req.memoryTypeBits & (1u << j)) { test_mtype = j; break; }
|
||||
}
|
||||
if (test_mtype != UINT32_MAX) {
|
||||
VkMemoryAllocateFlagsInfo test_flags = {};
|
||||
test_flags.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_FLAGS_INFO;
|
||||
test_flags.flags = VK_MEMORY_ALLOCATE_DEVICE_ADDRESS_BIT;
|
||||
VkMemoryAllocateInfo test_alloc = {};
|
||||
test_alloc.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
test_alloc.pNext = &test_flags;
|
||||
test_alloc.allocationSize = test_req.size;
|
||||
test_alloc.memoryTypeIndex = test_mtype;
|
||||
VkDeviceMemory test_mem = VK_NULL_HANDLE;
|
||||
if (vkAllocateMemory(device->device, &test_alloc, nullptr, &test_mem) == VK_SUCCESS) {
|
||||
vkBindBufferMemory(device->device, test_buf, test_mem, 0);
|
||||
VkBufferDeviceAddressInfo test_addr = {};
|
||||
test_addr.sType = VK_STRUCTURE_TYPE_BUFFER_DEVICE_ADDRESS_INFO;
|
||||
test_addr.buffer = test_buf;
|
||||
VkDeviceAddress addr = pfn(device->device, &test_addr);
|
||||
if (addr == 0) {
|
||||
GGML_LOG_WARN("ggml_vulkan: vkGetBufferDeviceAddress returned 0, disabling BDA\n");
|
||||
device->buffer_device_address = false;
|
||||
}
|
||||
vkFreeMemory(device->device, test_mem, nullptr);
|
||||
} else {
|
||||
GGML_LOG_WARN("ggml_vulkan: BDA test alloc failed, disabling BDA\n");
|
||||
device->buffer_device_address = false;
|
||||
}
|
||||
}
|
||||
vkDestroyBuffer(device->device, test_buf, nullptr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Shaders
|
||||
// Disable matmul tile sizes early if performance low or not supported
|
||||
for (uint32_t i = 0; i < GGML_TYPE_COUNT; ++i) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue