I had to write a simplified spike to boil down what I was trying to ask, as the actual code is a few thousand lines and many files.
Basically, I’m using a “ModelManager” that returns an Rc<Model>
and a model can have a Material which has a typedefed image::RgbaImage
as a field. I’m saving the &[u8]
bytes (i think?, it’s behind the datastructure in the image crate) of the image data directly in the field. Essentially, I need access to this data. Ideally, I’m not loading from disk every time I need it. I’d also really like to avoid cloning it everywhere as well. Not really sure what to do here. I’m welcome to restructuring suggestions too.
Here’s the code, with the error:
use std::{
fs::{
metadata, File
}, io::Read, path::PathBuf,
rc::Rc,
};
use ash::vk::{
BufferCreateInfo,
BufferUsageFlags,
SharingMode,
};
use image::RgbaImage;
pub type TextureImage = RgbaImage;
struct Material {
texture: TextureImage,
}
struct Model {
//materials: Vec<Material>,
materials: Material,
}
impl Model {
fn new() -> Rc<Self> {
Rc::new(
Self{
materials: Material::new(&PathBuf::from("yolo")),
}
)
}
}
impl Material {
fn new(tex_loc: &PathBuf) -> Self {
let mut file = File::open(&tex_loc).map_err(|e| e.to_string()).unwrap();
let metadata = metadata(&tex_loc).map_err(|e| e.to_string()).unwrap();
let mut buffer = vec![0; metadata.len() as usize];
file.read(&mut buffer).map_err(|e| e.to_string()).unwrap();
let texture = image::load_from_memory(&buffer).map_err(|e| e.to_string()).unwrap()
.to_rgba8();
Material{texture}
}
}
fn main() {
let model = Model::new();
//let mat = Material::new(&PathBuf::from("yolo"));
let tex_image = &model.materials.texture;
let (width, height) = tex_image.dimensions();
//let image_extent = vk::Extent2D { width, height };
let image_data = tex_image.into_raw(); //Here's the error, copied below
let image_buffer_info = BufferCreateInfo {
size: (42 * image_data.len()) as u64,
usage: BufferUsageFlags::TRANSFER_SRC,
sharing_mode: SharingMode::EXCLUSIVE,
..Default::default()
};
}
Here’s the error:
error[E0507]: cannot move out of `*tex_image` which is behind a shared reference
--> spikes/src/bin/references.rs:55:22
|
55 | let image_data = tex_image.into_raw();
| ^^^^^^^^^ ---------- `*tex_image` moved due to this method call
| |
| move occurs because `*tex_image` has type `ImageBuffer<Rgba<u8>, Vec<u8>>`, which does not implement the `Copy` trait
|
I’m still fairly new to Rust but I fear my code is devolving into needless complication trying to get this to work. One thing I was thinking of doing is writing a “TextureManger” or something that maintains an Rc and letting that be a field in the Material.
TLDR; How do I maintain the TextureImage data such that I can use it multiple times without copying/cloning?