From 89868992ab7aed09c3f8de34f0b40ae60686aabe Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Thu, 5 Oct 2023 14:39:55 +0200 Subject: [PATCH] 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 Part-of: --- .../frontends/rusticl/mesa/pipe/context.rs | 3 +- .../frontends/rusticl/mesa/pipe/resource.rs | 50 +++++++++++++++---- 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/src/gallium/frontends/rusticl/mesa/pipe/context.rs b/src/gallium/frontends/rusticl/mesa/pipe/context.rs index 0d0faeda33a..d7ded5f04f0 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/context.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/context.rs @@ -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(), diff --git a/src/gallium/frontends/rusticl/mesa/pipe/resource.rs b/src/gallium/frontends/rusticl/mesa/pipe/resource.rs index b7c2ae4a2a0..565c90c7074 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/resource.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/resource.rs @@ -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(