I have a constructor for my struct that creates a Texture2d
and a Sampler<'a, Texture2d>
where 'a
is the lifetime of the Texture2d
. I need to store the Sampler
in the struct I am constructing.
If I try to return a struct containing the Sampler<'a, Texture2d>
and then the Texture2d
goes out of scope, then the struct, which is called DefaultResourcePack<'a>
would contain a reference of lifetime 'a
after that lifetime is over, which wouldn't be valid. The compiler agrees with me - it's not compiling.
I attempt to solve this by giving the DefaultResourcePack
ownership of the Texture2d
and hoping that the compiler will recognize that the lifetimes are now valid, but the compiler is still complaining.
How can I solve this?
Here's the relevant code:
pub struct DefaultResourcePack<'a> {
regions: [TexRegion; SHEET_TEX_ID_COUNT],
sheet: Sampler<'a, Texture2d>,
simple_program: Program,
texture: Texture2d,
}
impl<'a> DefaultResourcePack<'a> {
fn new<F: Facade>(facade: &'a F) -> DefaultResourcePack<'a> {
// construct regions
let sheet_dim: f32 = 16.0;
let slot_size: f32 = 1.0 / sheet_dim;
let mut regions = [TexRegion::new(0.0, 0.0, 0.0, 0.0); SHEET_TEX_ID_COUNT];
for &id in &ALL_SHEET_TEX_ID {
let slot = sheet_tex_ord(id) as f32;
let ord = sheet_tex_ord(id);
regions[ord] = TexRegion::uvwh(
(slot % sheet_dim) * slot_size,
(slot - (slot % sheet_dim)) * slot_size,
slot_size,
slot_size,
)
}
// construct the sheet
let image = image::load_from_memory(DEF_TEX_SHEET_BYTES)
.expect("texture sheet load error")
.to_rgba();
let image_dim = image.dimensions();
let image = RawImage2d::from_raw_rgba_reversed(&image.into_raw(), image_dim);
let texture: Texture2d = Texture2d::new(facade, image).expect("texture creation error");
let sheet: Sampler<'a, Texture2d> =
Sampler::new(&texture).magnify_filter(MagnifySamplerFilter::Nearest);
// construct the program
let simple_program = Program::new(
facade,
ProgramCreationInput::SourceCode {
vertex_shader: SIMPLE_SHADER_V,
tessellation_control_shader: None,
tessellation_evaluation_shader: None,
geometry_shader: None,
fragment_shader: SIMPLE_SHADER_F,
transform_feedback_varyings: None,
outputs_srgb: false,
uses_point_size: false,
},
).expect("GLSL compilation error");
// construct the pack
DefaultResourcePack {
regions,
sheet,
simple_program,
texture,
}
}
}
Here's what the compiler says:
error[E0597]: `texture` does not live long enough
--> src\graphics\resourcepack.rs:164:63
|
164 | let sheet: Sampler<'a, Texture2d> = Sampler::new(&texture)
| ^^^^^^^ borrowed value does not live long enough
...
182 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the impl at 138:5...
--> src\graphics\resourcepack.rs:138:5
|
138 | / impl<'a> DefaultResourcePack<'a> {
139 | | fn new<F: Facade>(facade: &'a F) -> DefaultResourcePack<'a> {
140 | | // construct regions
141 | | let sheet_dim: f32 = 16.0;
... |
182 | | }
183 | | }
| |_____^