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: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32903>
This commit is contained in:
Karol Herbst
2025-01-06 07:13:55 +01:00
committed by Marge Bot
parent 26df5938cf
commit c8833703b2
2 changed files with 135 additions and 77 deletions

View File

@@ -1597,39 +1597,41 @@ impl Image {
pub fn sampler_view<'c>(&self, ctx: &'c QueueContext) -> CLResult<PipeSamplerView<'c, '_>> {
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<PipeImageView> {
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()))
}
}
}

View File

@@ -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<Self> {
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,
)
};