Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 3 additions & 11 deletions src/pipeline/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -154,18 +154,10 @@ pub const STAGES_COUNT: usize = Stage::GammaCompressSrgb as usize + 1;
impl PixmapRef<'_> {
#[inline(always)]
pub(crate) fn gather(&self, index: u32x8) -> [PremultipliedColorU8; highp::STAGE_WIDTH] {
let index: [u32; 8] = bytemuck::cast(index);
let pixels = self.pixels();
[
pixels[index[0] as usize],
pixels[index[1] as usize],
pixels[index[2] as usize],
pixels[index[3] as usize],
pixels[index[4] as usize],
pixels[index[5] as usize],
pixels[index[6] as usize],
pixels[index[7] as usize],
]
// safety: callers clamp indices to [0, w*h) via gather_ix.
let gathered = unsafe { u32x8::gather_u32(pixels.as_ptr() as *const u32, index) };

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can't we use bytemuck::cast_slice here? I would love to avoid as much unsafe as possible.

bytemuck::cast(gathered)
}
}

Expand Down
28 changes: 28 additions & 0 deletions src/wide/u32x8_t.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,34 @@ impl u32x8 {
}
}
}

/// Gathers 8 u32s from `base[index[i]]`.
///
/// # Safety
/// Each lane in `index` must be a valid offset (in u32 units) into the
/// buffer at `base`. avx2 `vpgatherdd` faults on oob; the scalar fallback
/// indexes a raw slice and would UB on oob too.
#[inline(always)]
pub unsafe fn gather_u32(base: *const u32, index: Self) -> Self {
cfg_if::cfg_if! {
if #[cfg(all(feature = "simd", target_feature = "avx2"))] {
let vindex: __m256i = cast(index);
Self(_mm256_i32gather_epi32::<4>(base as *const i32, vindex))
} else {
let ix: [u32; 8] = bytemuck::cast(index);
bytemuck::cast([
*base.add(ix[0] as usize),
*base.add(ix[1] as usize),
*base.add(ix[2] as usize),
*base.add(ix[3] as usize),
*base.add(ix[4] as usize),
*base.add(ix[5] as usize),
*base.add(ix[6] as usize),
*base.add(ix[7] as usize),
])
}
}
}
}

impl core::ops::Not for u32x8 {
Expand Down
Loading