rusticl: Enabling image fill for images created from buffers
authorAntonio Gomes <antoniospg100@gmail.com>
Tue, 6 Dec 2022 21:39:59 +0000 (18:39 -0300)
committerMarge Bot <emma+marge@anholt.net>
Tue, 7 Mar 2023 18:24:56 +0000 (18:24 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/20378>

src/gallium/frontends/rusticl/core/memory.rs
src/gallium/frontends/rusticl/mesa/pipe/context.rs

index 9e140a8..b9c1209 100644 (file)
@@ -762,12 +762,11 @@ impl Mem {
         assert!(!self.is_buffer());
 
         let res = self.get_res()?.get(&q.device).unwrap();
-        let bx = create_box(origin, region, self.mem_type)?;
         // make sure we allocate multiples of 4 bytes so drivers don't read out of bounds or
         // unaligned.
         // TODO: use div_ceil once it's available
-        let size = align(self.pixel_size().unwrap() as usize, size_of::<u32>());
-        let mut new_pattern: Vec<u32> = vec![0; size / size_of::<u32>()];
+        let pixel_size = align(self.pixel_size().unwrap() as usize, size_of::<u32>());
+        let mut new_pattern: Vec<u32> = vec![0; pixel_size / size_of::<u32>()];
 
         // we don't support CL_DEPTH for now
         assert!(pattern.len() == 4);
@@ -787,7 +786,18 @@ impl Mem {
             );
         }
 
-        ctx.clear_texture(res, &new_pattern, &bx);
+        // If image is created from a buffer, use clear_image_buffer instead
+        // for each row
+        if self.is_parent_buffer() {
+            let strides = (
+                self.image_desc.row_pitch()? as usize,
+                self.image_desc.slice_pitch()? as usize,
+            );
+            ctx.clear_image_buffer(res, &new_pattern, origin, region, strides, pixel_size);
+        } else {
+            let bx = create_box(origin, region, self.mem_type)?;
+            ctx.clear_texture(res, &new_pattern, &bx);
+        }
 
         Ok(())
     }
index 06bbe3d..835fff1 100644 (file)
@@ -123,6 +123,41 @@ impl PipeContext {
         }
     }
 
+    pub fn clear_image_buffer(
+        &self,
+        res: &PipeResource,
+        pattern: &[u32],
+        origin: &[usize; 3],
+        region: &[usize; 3],
+        strides: (usize, usize),
+        pixel_size: usize,
+    ) {
+        let (row_pitch, slice_pitch) = strides;
+        for z in 0..region[2] {
+            for y in 0..region[1] {
+                let pitch = [pixel_size, row_pitch, slice_pitch];
+                // Convoluted way of doing (origin + [0, y, z]) * pitch
+                let offset = (0..3)
+                    .map(|i| ((origin[i] + [0, y, z][i]) * pitch[i]) as u32)
+                    .sum();
+
+                // SAFETY: clear_buffer arguments are specified
+                // in bytes, so pattern.len() dimension value
+                // should be multiplied by pixel_size
+                unsafe {
+                    self.pipe.as_ref().clear_buffer.unwrap()(
+                        self.pipe.as_ptr(),
+                        res.pipe(),
+                        offset,
+                        (region[0] * pixel_size) as u32,
+                        pattern.as_ptr().cast(),
+                        (pattern.len() * pixel_size) as i32,
+                    )
+                };
+            }
+        }
+    }
+
     pub fn clear_texture(&self, res: &PipeResource, pattern: &[u32], bx: &pipe_box) {
         unsafe {
             self.pipe.as_ref().clear_texture.unwrap()(