vkCreateDevice调用触发段错误,共享队列族配置问题求助
问题分析与修复方案
你的代码触发段错误主要有三个核心问题,结合你的vulkaninfo输出和代码逻辑,逐一修复如下:
1. 优先级数组的生命周期问题
你在循环内部定义的f32 queue_priority[32][32]是栈上的局部变量,每次循环迭代结束后这块内存就会被销毁,而pQueuePriorities指向的是这块无效内存。当vkCreateDevice访问这些野指针时,直接触发段错误。
修复:把优先级数组移到循环外部,确保其生命周期覆盖vkCreateDevice调用:
// 移到循环外,确保内存有效 f32 queue_priorities[32][32]; memset(queue_priorities, 0, sizeof(queue_priorities)); // 初始化所有优先级为0.0f
2. 队列族索引处理的逻辑错误
- 数组越界:计算
shared_queues的循环中,j < index_count时访问indices[j+1]会越界(j最大为index_count-1,j+1超出数组范围),导致读取垃圾数据,错误计算共享队列数量。 - 重复创建队列族信息:Vulkan要求每个队列族只需要一个
VkDeviceQueueCreateInfo,即使要从该族创建多个队列,也只需在同一个Info中设置queueCount即可,你的代码为同一个队列族创建了多个重复的Info,违反API规范。
修复:先收集并去重需要的队列族索引,再为每个唯一队列族创建单个Info:
// 收集需要的唯一队列族索引,避免重复 u32 unique_queue_families[32]; u32 unique_count = 0; // 添加图形队列族 unique_queue_families[unique_count++] = context->device.graphics_queue_index; // 添加显示队列族(如果不与图形共享且未存在) if (!present_shares_graphics_queue) { b8 exists = false; for (u32 i = 0; i < unique_count; i++) { if (unique_queue_families[i] == context->device.present_queue_index) { exists = true; break; } } if (!exists) unique_queue_families[unique_count++] = context->device.present_queue_index; } // 添加传输队列族(如果不与图形共享且未存在) if (!transfer_shares_graphics_queue) { b8 exists = false; for (u32 i = 0; i < unique_count; i++) { if (unique_queue_families[i] == context->device.transfer_queue_index) { exists = true; break; } } if (!exists) unique_queue_families[unique_count++] = context->device.transfer_queue_index; }
3. 队列创建信息数量错误
你原来的queue_quantity是累加共享队列数得到的,等于index_count,但实际需要传递给vkCreateDevice的是唯一队列族的数量,也就是unique_count,否则驱动会处理多余的无效队列创建信息。
修复:填充队列创建信息时,基于唯一队列族列表:
VkDeviceQueueCreateInfo queue_create_infos[32]; for (u32 i = 0; i < unique_count; i++) { u32 family_idx = unique_queue_families[i]; u32 queue_count = 0; // 统计当前队列族需要创建的队列数 if (family_idx == context->device.graphics_queue_index) queue_count++; if (family_idx == context->device.present_queue_index && !present_shares_graphics_queue) queue_count++; if (family_idx == context->device.transfer_queue_index && !transfer_shares_graphics_queue) queue_count++; // 填充队列创建信息 queue_create_infos[i].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queue_create_infos[i].pNext = NULL; queue_create_infos[i].flags = 0; queue_create_infos[i].queueFamilyIndex = family_idx; queue_create_infos[i].queueCount = queue_count; queue_create_infos[i].pQueuePriorities = queue_priorities[i]; } // 创建设备时,队列信息数量设为唯一队列族数量 VkDeviceCreateInfo device_create_info = {VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO}; device_create_info.queueCreateInfoCount = unique_count; device_create_info.pQueueCreateInfos = queue_create_infos; // 其他字段保持你的原有代码...
额外提示(结合你的硬件情况)
从vulkaninfo输出看,队列族0只有1个队列,但支持图形、传输、显示操作,队列族1有4个队列,支持计算、传输、显示。如果你的程序不需要大量并行计算,完全可以只使用队列族0的单个队列,同时处理图形、传输、显示任务,这样代码会更简洁,也符合硬件资源限制。
内容的提问来源于stack exchange,提问作者mango
相关产品推荐
相关产品推荐

