rusticl/mesa: add thread-safe wrapper for pipe_image_views
In theory a pipe_image_view can outlive the pipe_resource it's referring to, so we have to make sure that doesn't happen. Signed-off-by: Karol Herbst <kherbst@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/26040>
This commit is contained in:
@@ -520,7 +520,8 @@ impl PipeContext {
|
||||
unsafe { self.pipe.as_ref().sampler_view_destroy.unwrap()(self.pipe.as_ptr(), view) }
|
||||
}
|
||||
|
||||
pub fn set_shader_images(&self, images: &[pipe_image_view]) {
|
||||
pub fn set_shader_images(&self, images: &[PipeImageView]) {
|
||||
let images = PipeImageView::slice_to_pipe(images);
|
||||
unsafe {
|
||||
self.pipe.as_ref().set_shader_images.unwrap()(
|
||||
self.pipe.as_ptr(),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
use mesa_rust_gen::*;
|
||||
|
||||
use std::ptr;
|
||||
use std::{mem, ptr};
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
pub struct PipeResource {
|
||||
@@ -12,6 +12,37 @@ pub struct PipeResource {
|
||||
unsafe impl Send for PipeResource {}
|
||||
unsafe impl Sync for PipeResource {}
|
||||
|
||||
/// A thread safe wrapper around [pipe_image_view]. It's purpose is to increase the reference count
|
||||
/// on the [pipe_resource] this view belongs to.
|
||||
#[repr(transparent)]
|
||||
pub struct PipeImageView {
|
||||
pub(super) pipe: pipe_image_view,
|
||||
}
|
||||
|
||||
impl PipeImageView {
|
||||
fn new(pipe: pipe_image_view) -> Self {
|
||||
unsafe { pipe_resource_reference(&mut ptr::null_mut(), pipe.resource) }
|
||||
Self { pipe: pipe }
|
||||
}
|
||||
|
||||
pub fn slice_to_pipe(slice: &[PipeImageView]) -> &[pipe_image_view] {
|
||||
// SAFETY: `PipeImageView` is a transparent wrapper around `pipe_image_view`, so transmute
|
||||
// on the slice is safe.
|
||||
unsafe { mem::transmute(slice) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for PipeImageView {
|
||||
fn drop(&mut self) {
|
||||
unsafe { pipe_resource_reference(&mut self.pipe.resource, ptr::null_mut()) }
|
||||
}
|
||||
}
|
||||
|
||||
// SAFETY: pipe_image_view is just static data around a pipe_resource, which itself is a thread-safe
|
||||
// type.
|
||||
unsafe impl Send for PipeImageView {}
|
||||
unsafe impl Sync for PipeImageView {}
|
||||
|
||||
// Image dimensions provide by application to be used in both
|
||||
// image and sampler views when image is created from buffer
|
||||
#[derive(PartialEq, Eq)]
|
||||
@@ -85,7 +116,8 @@ impl PipeResource {
|
||||
read_write: bool,
|
||||
host_access: u16,
|
||||
app_img_info: Option<&AppImgInfo>,
|
||||
) -> pipe_image_view {
|
||||
) -> PipeImageView {
|
||||
let pipe = PipeResource::as_ref(self);
|
||||
let u = if let Some(app_img_info) = app_img_info {
|
||||
pipe_image_view__bindgen_ty_1 {
|
||||
tex2d_from_buf: pipe_image_view__bindgen_ty_1__bindgen_ty_3 {
|
||||
@@ -99,17 +131,17 @@ impl PipeResource {
|
||||
pipe_image_view__bindgen_ty_1 {
|
||||
buf: pipe_image_view__bindgen_ty_1__bindgen_ty_2 {
|
||||
offset: 0,
|
||||
size: self.as_ref().width0,
|
||||
size: pipe.width0,
|
||||
},
|
||||
}
|
||||
} else {
|
||||
let mut tex = pipe_image_view__bindgen_ty_1__bindgen_ty_1::default();
|
||||
tex.set_level(0);
|
||||
tex.set_first_layer(0);
|
||||
if self.as_ref().target() == pipe_texture_target::PIPE_TEXTURE_3D {
|
||||
tex.set_last_layer((self.as_ref().depth0 - 1).into());
|
||||
} else if self.as_ref().array_size > 0 {
|
||||
tex.set_last_layer((self.as_ref().array_size - 1).into());
|
||||
if pipe.target() == pipe_texture_target::PIPE_TEXTURE_3D {
|
||||
tex.set_last_layer((pipe.depth0 - 1).into());
|
||||
} else if pipe.array_size > 0 {
|
||||
tex.set_last_layer((pipe.array_size - 1).into());
|
||||
} else {
|
||||
tex.set_last_layer(0);
|
||||
}
|
||||
@@ -129,13 +161,13 @@ impl PipeResource {
|
||||
0
|
||||
} as u16;
|
||||
|
||||
pipe_image_view {
|
||||
PipeImageView::new(pipe_image_view {
|
||||
resource: self.pipe(),
|
||||
format: format,
|
||||
access: access | host_access,
|
||||
shader_access: shader_access,
|
||||
u: u,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn pipe_sampler_view_template(
|
||||
|
||||
Reference in New Issue
Block a user