You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust Vulkano库创建可导入PNG像素的GPU纹理图像失败求解

问题:Vulkano创建可接收PNG像素的GPU图像失败

我在用Vulkan的Rust绑定库Vulkano把PNG图像上传到GPU时,创建图像失败。当前使用的是commit为94f50f18bd25971ea123adb8b5782ad65a8f085c的版本(后续需要做OpenGL互操作),我的代码如下:

let extent = [width, height, 1];
let format = Format::R8G8B8A8_UNORM;
let image = Image::new(
    memory_allocator.clone(),
    ImageCreateInfo {
        image_type: ImageType::Dim2d,
        format,
        extent,
        usage: ImageUsage::TRANSFER_DST | ImageUsage::SAMPLED,
        ..Default::default()
    },
    AllocationCreateInfo {
        memory_type_filter: MemoryTypeFilter {
            required_flags: MemoryPropertyFlags::HOST_VISIBLE,
            preferred_flags: MemoryPropertyFlags::DEVICE_LOCAL,
            not_preferred_flags: MemoryPropertyFlags::empty(),
        },
        ..Default::default()
    },
)
.unwrap();

运行时报错:

called Result::unwrap() on an Err value: a non-validation error occurred: allocating memory for the image failed

我修改创建参数后出现了其他错误,请问怎么正确创建能接收PNG解码后的原始像素、并能用于采样器做纹理映射的图像?


解决方案

1. 修正内存分配逻辑错误

你的错误核心是同时要求内存必须HOST_VISIBLE且偏好DEVICE_LOCAL,但多数设备的DEVICE_LOCAL内存并不支持HOST_VISIBLE属性,直接导致内存分配失败。

如果需要从CPU上传像素数据,正确流程是分两步:

  • 创建一块HOST_VISIBLE+HOST_COHERENT的临时staging图像,用来存放解码后的PNG像素
  • 创建一块DEVICE_LOCAL的目标图像(用于采样),通过Vulkan传输命令把数据从staging图像复制到目标图像

2. 完整实现代码示例

步骤1:创建Staging图像(CPU上传用)

let staging_image = Image::new(
    memory_allocator.clone(),
    ImageCreateInfo {
        image_type: ImageType::Dim2d,
        format: Format::R8G8B8A8_UNORM,
        extent: [width, height, 1],
        usage: ImageUsage::TRANSFER_SRC, // 标记为传输源
        ..Default::default()
    },
    AllocationCreateInfo {
        memory_type_filter: MemoryTypeFilter {
            required_flags: MemoryPropertyFlags::HOST_VISIBLE | MemoryPropertyFlags::HOST_COHERENT,
            preferred_flags: MemoryPropertyFlags::empty(),
            ..Default::default()
        },
        ..Default::default()
    },
).unwrap();

步骤2:上传PNG像素到Staging图像

假设png_pixels是解码后的RGBA格式字节数组:

let mut mapping = staging_image.write().unwrap();
mapping.copy_from_slice(png_pixels);

步骤3:创建目标图像(采样用)

let target_image = Image::new(
    memory_allocator.clone(),
    ImageCreateInfo {
        image_type: ImageType::Dim2d,
        format: Format::R8G8B8A8_UNORM,
        extent: [width, height, 1],
        usage: ImageUsage::TRANSFER_DST | ImageUsage::SAMPLED, // 接收传输+可采样
        ..Default::default()
    },
    AllocationCreateInfo {
        memory_type_filter: MemoryTypeFilter {
            required_flags: MemoryPropertyFlags::DEVICE_LOCAL,
            preferred_flags: MemoryPropertyFlags::empty(),
            ..Default::default()
        },
        ..Default::default()
    },
).unwrap();

步骤4:提交数据复制命令

用命令缓冲区完成staging到目标图像的数据复制:

let command_buffer = AutoCommandBufferBuilder::primary(
    &command_buffer_allocator,
    queue.queue_family_index(),
    CommandBufferUsage::OneTimeSubmit,
)
.unwrap()
.copy_image_to_image(
    CopyImageToImageInfo {
        src: staging_image.as_view().unwrap(),
        dst: target_image.as_view().unwrap(),
        regions: [ImageCopy {
            src_subresource: ImageSubresourceLayers {
                aspect: ImageAspect::COLOR,
                mip_level: 0,
                base_array_layer: 0,
                layer_count: 1,
            },
            src_offset: [0, 0, 0],
            dst_subresource: ImageSubresourceLayers {
                aspect: ImageAspect::COLOR,
                mip_level: 0,
                base_array_layer: 0,
                layer_count: 1,
            },
            dst_offset: [0, 0, 0],
            extent: [width, height, 1],
        }],
        ..Default::default()
    },
)
.build()
.unwrap();

// 提交命令并等待执行完成
let _ = queue.submit(SubmitInfo::new().command_buffers(&[command_buffer])).unwrap();
queue.wait_idle().unwrap();

3. 关键注意事项

  • 不要强行要求DEVICE_LOCAL内存同时具备HOST_VISIBLE属性,这在多数硬件上不支持,必须用staging资源中转
  • staging图像必须添加HOST_COHERENT标志,写入内存后无需手动flush就能让GPU读取到数据
  • 目标图像的usage必须包含TRANSFER_DST才能接收复制数据,SAMPLED保证能被采样器绑定使用

内容的提问来源于stack exchange,提问作者Mutant Bob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 17:37:16