From c8833703b267e13158b7ff251202caa8dd43562f Mon Sep 17 00:00:00 2001 From: Karol Herbst Date: Mon, 6 Jan 2025 07:13:55 +0100 Subject: [PATCH] rusticl/mesa: rework image and sampler view creation APIs The mesa crate should just provide the means of creating those, but the logic of what to create shouldn't be there. The passed in arguments also heavily vary, and this way we can be explicit about what variants needs what inputs. Reviewed-by: @LingMan Part-of: --- src/gallium/frontends/rusticl/core/memory.rs | 48 ++--- .../frontends/rusticl/mesa/pipe/resource.rs | 164 ++++++++++++------ 2 files changed, 135 insertions(+), 77 deletions(-) diff --git a/src/gallium/frontends/rusticl/core/memory.rs b/src/gallium/frontends/rusticl/core/memory.rs index f32b9ac4f15..3d8bd9babf0 100644 --- a/src/gallium/frontends/rusticl/core/memory.rs +++ b/src/gallium/frontends/rusticl/core/memory.rs @@ -1597,39 +1597,41 @@ impl Image { pub fn sampler_view<'c>(&self, ctx: &'c QueueContext) -> CLResult> { let res = self.get_res_of_dev(ctx.dev)?; - let size = self.size.try_into().map_err(|_| CL_OUT_OF_RESOURCES)?; - // If resource is a buffer, the image was created from a buffer. Use - // strides and dimensions of the image then. - let app_img_info = if res.is_buffer() && self.mem_type == CL_MEM_OBJECT_IMAGE2D { - Some(self.buffer_2d_info()?) + let template = if res.is_buffer() && self.mem_type == CL_MEM_OBJECT_IMAGE2D { + res.pipe_sampler_view_template_2d_buffer(self.pipe_format, &self.buffer_2d_info()?) + } else if res.is_buffer() { + // we need to pass in the size of the buffer, not the width. + let size = self.size.try_into().map_err(|_| CL_OUT_OF_RESOURCES)?; + res.pipe_sampler_view_template_1d_buffer(self.pipe_format, size) } else { - None + res.pipe_sampler_view_template() }; - PipeSamplerView::new(ctx, res, self.pipe_format, size, app_img_info.as_ref()) - .ok_or(CL_OUT_OF_HOST_MEMORY) + PipeSamplerView::new(ctx, res, &template).ok_or(CL_OUT_OF_HOST_MEMORY) } pub fn image_view(&self, dev: &Device, read_write: bool) -> CLResult { let res = self.get_res_of_dev(dev)?; - let size = self.size.try_into().map_err(|_| CL_OUT_OF_RESOURCES)?; - // If resource is a buffer, the image was created from a buffer. Use - // strides and dimensions of the image then. - let app_img_info = if res.is_buffer() && self.mem_type == CL_MEM_OBJECT_IMAGE2D { - Some(self.buffer_2d_info()?) + if res.is_buffer() && self.mem_type == CL_MEM_OBJECT_IMAGE2D { + Ok(res.pipe_image_view_2d_buffer( + self.pipe_format, + read_write, + self.pipe_image_host_access(), + &self.buffer_2d_info()?, + )) + } else if res.is_buffer() { + let size = self.size.try_into().map_err(|_| CL_OUT_OF_RESOURCES)?; + Ok(res.pipe_image_view_1d_buffer( + self.pipe_format, + read_write, + self.pipe_image_host_access(), + size, + )) } else { - None - }; - - Ok(res.pipe_image_view( - self.pipe_format, - read_write, - self.pipe_image_host_access(), - size, - app_img_info.as_ref(), - )) + Ok(res.pipe_image_view(read_write, self.pipe_image_host_access())) + } } } diff --git a/src/gallium/frontends/rusticl/mesa/pipe/resource.rs b/src/gallium/frontends/rusticl/mesa/pipe/resource.rs index d7a9cd9b28d..7d3be624c42 100644 --- a/src/gallium/frontends/rusticl/mesa/pipe/resource.rs +++ b/src/gallium/frontends/rusticl/mesa/pipe/resource.rs @@ -124,45 +124,42 @@ impl PipeResource { self.as_ref().flags & PIPE_RESOURCE_FLAG_RUSTICL_IS_USER != 0 } - pub fn pipe_image_view( + pub fn pipe_image_view(&self, read_write: bool, host_access: u16) -> PipeImageView { + debug_assert!(!self.is_buffer()); + + let pipe = self.as_ref(); + let shader_access = if read_write { + PIPE_IMAGE_ACCESS_READ_WRITE + } else { + PIPE_IMAGE_ACCESS_WRITE + } as u16; + + let mut tex = pipe_image_view__bindgen_ty_1__bindgen_ty_1::default(); + tex.set_level(0); + tex.set_first_layer(0); + if pipe.target() == pipe_texture_target::PIPE_TEXTURE_3D { + tex.set_last_layer((pipe.depth0 - 1).into()); + } else { + tex.set_last_layer(pipe.array_size.saturating_sub(1).into()); + } + + PipeImageView::new(pipe_image_view { + resource: self.pipe(), + format: pipe.format(), + access: host_access, + shader_access: shader_access, + u: pipe_image_view__bindgen_ty_1 { tex: tex }, + }) + } + + pub fn pipe_image_view_1d_buffer( &self, format: pipe_format, read_write: bool, host_access: u16, size: u32, - app_img_info: Option<&AppImgInfo>, ) -> 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 { - offset: 0, - row_stride: app_img_info.row_stride as u16, - width: app_img_info.width as u16, - height: app_img_info.height as u16, - }, - } - } else if self.is_buffer() { - pipe_image_view__bindgen_ty_1 { - buf: pipe_image_view__bindgen_ty_1__bindgen_ty_2 { - offset: 0, - size: size, - }, - } - } else { - let mut tex = pipe_image_view__bindgen_ty_1__bindgen_ty_1::default(); - tex.set_level(0); - tex.set_first_layer(0); - 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); - } - - pipe_image_view__bindgen_ty_1 { tex: tex } - }; + debug_assert!(self.is_buffer()); let shader_access = if read_write { PIPE_IMAGE_ACCESS_READ_WRITE @@ -170,44 +167,106 @@ impl PipeResource { PIPE_IMAGE_ACCESS_WRITE } as u16; - let access = if app_img_info.is_some() { - PIPE_IMAGE_ACCESS_TEX2D_FROM_BUFFER + PipeImageView::new(pipe_image_view { + resource: self.pipe(), + format: format, + access: host_access, + shader_access: shader_access, + u: pipe_image_view__bindgen_ty_1 { + buf: pipe_image_view__bindgen_ty_1__bindgen_ty_2 { + offset: 0, + size: size, + }, + }, + }) + } + + pub fn pipe_image_view_2d_buffer( + &self, + format: pipe_format, + read_write: bool, + host_access: u16, + app_img_info: &AppImgInfo, + ) -> PipeImageView { + debug_assert!(self.is_buffer()); + + let shader_access = if read_write { + PIPE_IMAGE_ACCESS_READ_WRITE } else { - 0 + PIPE_IMAGE_ACCESS_WRITE } as u16; PipeImageView::new(pipe_image_view { resource: self.pipe(), format: format, - access: access | host_access, + access: PIPE_IMAGE_ACCESS_TEX2D_FROM_BUFFER as u16 | host_access, shader_access: shader_access, - u: u, + u: pipe_image_view__bindgen_ty_1 { + tex2d_from_buf: pipe_image_view__bindgen_ty_1__bindgen_ty_3 { + offset: 0, + row_stride: app_img_info.row_stride as u16, + width: app_img_info.width as u16, + height: app_img_info.height as u16, + }, + }, }) } - pub fn pipe_sampler_view_template( + pub fn pipe_sampler_view_template(&self) -> pipe_sampler_view { + debug_assert!(!self.is_buffer()); + + let mut res = pipe_sampler_view::default(); + unsafe { + u_sampler_view_default_template(&mut res, self.pipe(), self.as_ref().format()); + } + + res + } + + pub fn pipe_sampler_view_template_1d_buffer( &self, format: pipe_format, size: u32, - app_img_info: Option<&AppImgInfo>, ) -> pipe_sampler_view { + debug_assert!(self.is_buffer()); + let mut res = pipe_sampler_view::default(); unsafe { u_sampler_view_default_template(&mut res, self.pipe(), format); } - if let Some(app_img_info) = app_img_info { - res.u.tex2d_from_buf.offset = 0; - res.u.tex2d_from_buf.row_stride = app_img_info.row_stride as u16; - res.u.tex2d_from_buf.width = app_img_info.width as u16; - res.u.tex2d_from_buf.height = app_img_info.height as u16; + // write the entire union field because u_sampler_view_default_template might have left it + // in an undefined state. + res.u.buf = pipe_sampler_view__bindgen_ty_2__bindgen_ty_2 { + offset: 0, + size: size, + }; - res.set_is_tex2d_from_buf(true); - } else if res.target() == pipe_texture_target::PIPE_BUFFER { - res.u.buf.offset = 0; - res.u.buf.size = size; + res + } + + pub fn pipe_sampler_view_template_2d_buffer( + &self, + format: pipe_format, + app_img_info: &AppImgInfo, + ) -> pipe_sampler_view { + debug_assert!(self.is_buffer()); + + let mut res = pipe_sampler_view::default(); + unsafe { + u_sampler_view_default_template(&mut res, self.pipe(), format); } + // write the entire union field because u_sampler_view_default_template might have left it + // in an undefined state. + res.u.tex2d_from_buf = pipe_sampler_view__bindgen_ty_2__bindgen_ty_3 { + offset: 0, + row_stride: app_img_info.row_stride as u16, + width: app_img_info.width as u16, + height: app_img_info.height as u16, + }; + res.set_is_tex2d_from_buf(true); + res } } @@ -233,16 +292,13 @@ impl<'c, 'r> PipeSamplerView<'c, 'r> { pub fn new( ctx: &'c PipeContext, res: &'r PipeResource, - format: pipe_format, - size: u32, - app_img_info: Option<&AppImgInfo>, + template: &pipe_sampler_view, ) -> Option { - let template = res.pipe_sampler_view_template(format, size, app_img_info); let view = unsafe { ctx.pipe().as_ref().create_sampler_view.unwrap()( ctx.pipe().as_ptr(), res.pipe(), - &template, + template, ) };