glium/texture/
bindless.rs1use crate::texture::any::TextureAny;
65use crate::TextureExt;
66use crate::GlObject;
67
68use crate::ContextExt;
69use crate::gl;
70
71use std::marker::PhantomData;
72use std::ops::{Deref, DerefMut};
73
74use crate::program::BlockLayout;
75use crate::uniforms::AsUniformValue;
76use crate::uniforms::LayoutMismatchError;
77use crate::uniforms::UniformBlock;
78use crate::uniforms::UniformValue;
79use crate::uniforms::UniformType;
80use crate::uniforms::SamplerBehavior;
81
82pub struct ResidentTexture {
85 texture: Option<TextureAny>,
86 handle: gl::types::GLuint64,
87}
88
89impl ResidentTexture {
90 pub fn new(texture: TextureAny) -> Result<ResidentTexture, BindlessTexturesNotSupportedError> {
93 let handle = {
94 let mut ctxt = texture.get_context().make_current();
95
96 if !ctxt.extensions.gl_arb_bindless_texture {
97 return Err(BindlessTexturesNotSupportedError);
98 }
99
100 let handle = unsafe { ctxt.gl.GetTextureHandleARB(texture.get_id()) };
101 unsafe { ctxt.gl.MakeTextureHandleResidentARB(handle) };
102 ctxt.resident_texture_handles.push(handle);
103 handle
104 };
105
106 Ok(ResidentTexture {
108 texture: Some(texture),
109 handle,
110 })
111 }
112
113 #[inline]
115 pub fn into_inner(mut self) -> TextureAny {
116 self.into_inner_impl()
117 }
118
119 fn into_inner_impl(&mut self) -> TextureAny {
121 let texture = self.texture.take().unwrap();
122
123 {
124 let mut ctxt = texture.get_context().make_current();
125 unsafe { ctxt.gl.MakeTextureHandleNonResidentARB(self.handle) };
126 ctxt.resident_texture_handles.retain(|&t| t != self.handle);
127 }
128
129 texture
130 }
131}
132
133impl Deref for ResidentTexture {
134 type Target = TextureAny;
135
136 #[inline]
137 fn deref(&self) -> &TextureAny {
138 self.texture.as_ref().unwrap()
139 }
140}
141
142impl DerefMut for ResidentTexture {
143 #[inline]
144 fn deref_mut(&mut self) -> &mut TextureAny {
145 self.texture.as_mut().unwrap()
146 }
147}
148
149impl Drop for ResidentTexture {
150 #[inline]
151 fn drop(&mut self) {
152 self.into_inner_impl();
153 }
154}
155
156#[derive(Copy, Clone)]
158pub struct TextureHandle<'a> {
159 value: gl::types::GLuint64,
160 marker: PhantomData<&'a ResidentTexture>,
161}
162
163impl<'a> TextureHandle<'a> {
164 #[inline]
166 pub fn new(texture: &'a ResidentTexture, _: &SamplerBehavior) -> TextureHandle<'a> {
167 TextureHandle {
169 value: texture.handle,
170 marker: PhantomData,
171 }
172 }
173
174 #[inline]
176 pub fn set(&mut self, texture: &'a ResidentTexture, _: &SamplerBehavior) {
177 self.value = texture.handle;
179 }
180}
181
182impl<'a> AsUniformValue for TextureHandle<'a> {
183 #[inline]
184 fn as_uniform_value(&self) -> UniformValue<'_> {
185 unimplemented!();
187 }
188}
189
190impl<'a> UniformBlock for TextureHandle<'a> {
191 fn matches(layout: &BlockLayout, base_offset: usize)
192 -> Result<(), LayoutMismatchError>
193 {
194 if let BlockLayout::BasicType { ty, offset_in_buffer } = *layout {
195 match ty {
201 UniformType::Sampler1d => (),
202 UniformType::ISampler1d => (),
203 UniformType::USampler1d => (),
204 UniformType::Sampler2d => (),
205 UniformType::ISampler2d => (),
206 UniformType::USampler2d => (),
207 UniformType::Sampler3d => (),
208 UniformType::ISampler3d => (),
209 UniformType::USampler3d => (),
210 UniformType::Sampler1dArray => (),
211 UniformType::ISampler1dArray => (),
212 UniformType::USampler1dArray => (),
213 UniformType::Sampler2dArray => (),
214 UniformType::ISampler2dArray => (),
215 UniformType::USampler2dArray => (),
216 UniformType::SamplerCube => (),
217 UniformType::ISamplerCube => (),
218 UniformType::USamplerCube => (),
219 UniformType::Sampler2dRect => (),
220 UniformType::ISampler2dRect => (),
221 UniformType::USampler2dRect => (),
222 UniformType::Sampler2dRectShadow => (),
223 UniformType::SamplerCubeArray => (),
224 UniformType::ISamplerCubeArray => (),
225 UniformType::USamplerCubeArray => (),
226 UniformType::SamplerBuffer => (),
227 UniformType::ISamplerBuffer => (),
228 UniformType::USamplerBuffer => (),
229 UniformType::Sampler2dMultisample => (),
230 UniformType::ISampler2dMultisample => (),
231 UniformType::USampler2dMultisample => (),
232 UniformType::Sampler2dMultisampleArray => (),
233 UniformType::ISampler2dMultisampleArray => (),
234 UniformType::USampler2dMultisampleArray => (),
235 UniformType::Sampler1dShadow => (),
236 UniformType::Sampler2dShadow => (),
237 UniformType::SamplerCubeShadow => (),
238 UniformType::Sampler1dArrayShadow => (),
239 UniformType::Sampler2dArrayShadow => (),
240 UniformType::SamplerCubeArrayShadow => (),
241
242 _ => return Err(LayoutMismatchError::TypeMismatch {
243 expected: ty,
244 obtained: UniformType::Sampler2d, })
246 }
247
248 if offset_in_buffer != base_offset {
249 return Err(LayoutMismatchError::OffsetMismatch {
250 expected: offset_in_buffer,
251 obtained: base_offset,
252 });
253 }
254
255 Ok(())
256
257 } else if let BlockLayout::Struct { members } = layout {
258 if members.len() == 1 {
259 <TextureHandle<'_> as UniformBlock>::matches(&members[0].1, base_offset)
260
261 } else {
262 Err(LayoutMismatchError::LayoutMismatch {
263 expected: layout.clone(),
264 obtained: BlockLayout::BasicType {
265 ty: UniformType::Sampler2d, offset_in_buffer: base_offset,
267 }
268 })
269 }
270
271 } else {
272 Err(LayoutMismatchError::LayoutMismatch {
273 expected: layout.clone(),
274 obtained: BlockLayout::BasicType {
275 ty: UniformType::Sampler2d, offset_in_buffer: base_offset,
277 }
278 })
279 }
280 }
281
282 #[inline]
283 fn build_layout(base_offset: usize) -> BlockLayout {
284 BlockLayout::BasicType {
285 ty: UniformType::Sampler2d, offset_in_buffer: base_offset,
287 }
288 }
289}
290
291#[derive(Debug, Copy, Clone)]
295pub struct BindlessTexturesNotSupportedError;
296
297#[cfg(test)]
298mod test {
299 use std::mem;
300 use super::TextureHandle;
301
302 #[test]
303 fn texture_handle_size() {
304 assert_eq!(mem::size_of::<TextureHandle<'_>>(), 8);
305 }
306}