Rust使用Erupt库调用Vulkan的device.map_memory(vkMapMemory)出现段错误
问题根因与修复方案
1. map_memory 输出指针传参错误(直接触发段错误)
你在调用map_memory时直接传入了空指针作为输出参数,Vulkan需要向该地址写入映射后的内存地址,写入空地址直接触发段错误。
修复代码:
unsafe { // 先声明存储映射地址的变量 let mut pointer: *mut std::ffi::c_void = std::ptr::null_mut(); device .map_memory( vertex_buffer_memory, 0, vertex_buffer_memory_reqs.size, None, // 传入变量的可变引用作为输出地址 &mut pointer, ) .expect("failed to map memory."); // 后续可通过pointer完成数据拷贝 }
2. 顶点缓冲区大小计算错误
原代码中std::mem::size_of_val(&vertices)计算的是Vec结构体本身的大小(通常为24字节,对应指针、长度、容量三个usize字段),不是存储顶点数据需要的实际缓冲区大小。
修复代码:
let vertex_buffer_size = (std::mem::size_of::<VertexV3>() * vertices.len()) as vk::DeviceSize;
3. 内存类型索引硬编码风险
你直接将memory_type_index硬编码为2,不同设备的内存类型布局差异极大,很可能选中不支持主机映射的内存类型,导致映射失败或异常。需要根据内存要求动态匹配合适的内存类型:
首先添加内存类型匹配辅助函数:
fn find_memory_type( memory_properties: vk::PhysicalDeviceMemoryProperties, required_bits: u32, required_flags: vk::MemoryPropertyFlags, ) -> Option<u32> { memory_properties.memory_types .iter() .enumerate() .find(|(i, memory_type)| { (required_bits & (1 << i)) != 0 && memory_type.property_flags.contains(required_flags) }) .map(|(i, _)| i as u32) }
分配内存时调用函数匹配合适的类型:
let memory_type_index = find_memory_type( physical_device_memory_properties, vertex_buffer_memory_reqs.memory_type_bits, vk::MemoryPropertyFlags::HOST_VISIBLE | vk::MemoryPropertyFlags::HOST_COHERENT, ).expect("Failed to find suitable memory type"); let vertex_buffer_memory_allocate_info = vk::MemoryAllocateInfoBuilder::new() .allocation_size(vertex_buffer_memory_reqs.size) .memory_type_index(memory_type_index);
额外注意事项
- 内存映射、数据拷贝完成后需要调用
device.unmap_memory(vertex_buffer_memory)释放映射 - 如果是静态顶点数据,建议走 staging 缓冲区拷贝到设备本地内存,运行时读写性能更好
内容的提问来源于stack exchange,提问作者kulicuu
相关产品推荐
相关产品推荐

