mod sealed {
use crate::buf::{atomic_buf, buf, cell_buf};
use crate::layout::Layout;
use core::ops::Range;
pub trait LayoutEngineCore {
type Layout: Layout;
fn consume_layout(&mut self) -> Self::Layout;
fn buffer_ranges(&self) -> impl Iterator<Item = Range<usize>>;
fn image_offset(&self) -> usize;
}
pub trait Loadable {
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, at: usize);
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, at: usize);
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, at: usize);
}
pub trait Storable {
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, at: usize);
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, at: usize);
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, at: usize);
}
pub(crate) trait LoadSource {
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize);
}
pub(crate) trait StoreTarget {
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize);
}
impl LoadSource for &'_ buf {
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize) {
into.load_from_buf(self, what, at)
}
}
impl LoadSource for &'_ cell_buf {
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize) {
into.load_from_cell(self, what, at)
}
}
impl LoadSource for &'_ atomic_buf {
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize) {
into.load_from_atomic(self, what, at)
}
}
impl StoreTarget for &'_ mut buf {
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize) {
into.store_to_buf(self, what, at)
}
}
impl StoreTarget for &'_ cell_buf {
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize) {
into.store_to_cell(self, what, at)
}
}
impl StoreTarget for &'_ atomic_buf {
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize) {
into.store_to_atomic(self, what, at)
}
}
}
use core::{cell::Cell, ops::Range};
use sealed::{Loadable, Storable};
use crate::buf::{atomic_buf, buf, cell_buf, AtomicBuffer, Buffer, CellBuffer};
use crate::image::{
AtomicImage, AtomicImageRef, CellImage, CellImageRef, Image, ImageMut, ImageRef,
};
use crate::layout::{AlignedOffset, Bytes, Layout, Relocated};
use crate::{texels, BufferReuseError};
pub struct DataRef<'lt, Layout = Bytes> {
data: &'lt [u8],
layout: Layout,
offset: usize,
}
pub struct DataMut<'lt, Layout = Bytes> {
data: &'lt mut [u8],
layout: Layout,
offset: usize,
}
pub struct DataCells<'lt, Layout = Bytes> {
data: &'lt [Cell<u8>],
layout: Layout,
offset: usize,
}
pub struct AsCopySource<'lt, E> {
inner: &'lt dyn Storable,
engine: E,
}
pub struct AsCopyTarget<'lt, E> {
inner: &'lt mut dyn Loadable,
engine: E,
}
pub trait LayoutEngine: sealed::LayoutEngineCore {}
impl<'lt> DataRef<'lt, Bytes> {
pub fn new(data: &'lt [u8]) -> Self {
DataRef {
data,
layout: Bytes(core::mem::size_of_val(data)),
offset: 0,
}
}
}
impl<'lt, L> DataRef<'lt, L> {
pub fn with_layout_at(data: &'lt [u8], layout: L, start: usize) -> Option<Self>
where
L: Layout,
{
Some(data)
.filter(|data| {
if let Some(partial) = data.get(start..) {
<dyn Layout>::fits_data(&layout, partial)
} else {
false
}
})
.map(|data| DataRef {
data,
layout,
offset: Default::default(),
})
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: &self.data,
engine: RangeEngine::new(&self.layout, self.offset),
}
}
}
impl Storable for &'_ [u8] {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = &mut buffer.as_bytes_mut()[into..][..len];
let source = &self[what.start..what.end];
target.copy_from_slice(source);
}
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let source = &self[what.start..what.end];
texels::U8.store_cell_slice(target, source);
}
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let source = &self[what.start..what.end];
texels::U8.store_atomic_slice(target, source);
}
}
impl<'lt> DataMut<'lt, Bytes> {
pub fn new(data: &'lt mut [u8]) -> Self {
DataMut {
layout: Bytes(core::mem::size_of_val(data)),
data,
offset: 0,
}
}
}
impl<'lt, L> DataMut<'lt, L> {
pub fn with_layout_at(data: &'lt mut [u8], layout: L, start: usize) -> Option<Self>
where
L: Layout,
{
Some(data)
.filter(|data| {
if let Some(partial) = data.get(start..) {
<dyn Layout>::fits_data(&layout, partial)
} else {
false
}
})
.map(|data| DataMut {
data,
layout,
offset: start,
})
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: &self.data,
engine: RangeEngine::new(&self.layout, self.offset),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
inner: &mut self.data,
engine: RangeEngine::new(&self.layout, self.offset),
}
}
}
impl Storable for &'_ mut [u8] {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = &mut buffer.as_bytes_mut()[into..][..len];
let source = &self[what.start..what.end];
target.copy_from_slice(source);
}
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let target = &self[what.start..what.end];
texels::U8.store_cell_slice(source, target);
}
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let source = &self[what.start..what.end];
texels::U8.store_atomic_slice(target, source);
}
}
impl Loadable for &'_ mut [u8] {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_bytes()[into..][..len];
let target = &mut self[what.start..what.end];
target.copy_from_slice(source);
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let target = &mut self[what.start..what.end];
texels::U8.load_cell_slice(source, target);
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let target = &mut self[what.start..what.end];
texels::U8.load_atomic_slice(source, target);
}
}
impl<'lt> DataCells<'lt, Bytes> {
pub fn new(data: &'lt [Cell<u8>]) -> Self {
DataCells {
layout: Bytes(core::mem::size_of_val(data)),
data,
offset: 0,
}
}
}
impl<'lt, L> DataCells<'lt, L> {
pub fn with_layout_at(data: &'lt [Cell<u8>], layout: L, start: usize) -> Option<Self>
where
L: Layout,
{
Some(data)
.filter(|data| {
if let Some(partial) = data.get(start..) {
<dyn Layout>::fits_data(&layout, partial)
} else {
false
}
})
.map(|data| DataCells {
data,
layout,
offset: Default::default(),
})
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: &self.data,
engine: RangeEngine::new(&self.layout, self.offset),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
inner: &mut self.data,
engine: RangeEngine::new(&self.layout, self.offset),
}
}
}
impl Storable for &'_ [Cell<u8>] {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = &mut buffer.as_bytes_mut()[into..][..len];
let source = &self[what.start..what.end];
crate::texels::U8.load_cell_slice(source, target);
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let target = &self[what.start..what.end];
texels::U8.cell_memory_copy(source, target);
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let source = &self[what.start..what.end];
texels::U8.store_atomic_from_cells(target, source);
}
}
impl Loadable for &'_ [Cell<u8>] {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_bytes()[into..][..len];
let target = &self[what.start..what.end];
texels::U8.store_cell_slice(target, source);
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let target = &self[what.start..what.end];
texels::U8.cell_memory_copy(source, target);
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let target = &self[what.start..what.end];
texels::U8.load_atomic_to_cells(source, target);
}
}
impl<'buf, E: LayoutEngine> AsCopySource<'buf, E> {
pub fn and_relocated(self, offset: AlignedOffset) -> AsCopySource<'buf, RelocateEngine<E>>
where
E::Layout: Clone,
{
AsCopySource {
inner: self.inner,
engine: RelocateEngine {
inner: self.engine,
offset,
},
}
}
}
impl<E: LayoutEngine> AsCopySource<'_, E> {
fn engine_to_buf_at(&self, buffer: impl sealed::StoreTarget) {
#[inline(never)]
fn ranges_to_buf_at(
ranges: impl Iterator<Item = Range<usize>>,
store: &dyn Storable,
mut buffer: impl sealed::StoreTarget,
offset: usize,
) {
for range in ranges {
buffer.store(store, range, offset)
}
}
ranges_to_buf_at(
self.engine.buffer_ranges(),
self.inner,
buffer,
self.engine.image_offset(),
);
}
pub fn write_to_image(mut self, buffer: Image<Bytes>) -> Image<E::Layout> {
let mut buffer = buffer.with_layout(self.engine.consume_layout());
self.engine_to_buf_at(buffer.as_capacity_buf_mut());
buffer
}
pub fn write_to_mut<'data>(
mut self,
buffer: ImageMut<'data, Bytes>,
) -> Option<ImageMut<'data, E::Layout>> {
let mut buffer = buffer.with_layout(self.engine.consume_layout())?;
self.engine_to_buf_at(buffer.as_mut_buf());
Some(buffer)
}
pub fn write_to_cell_image(mut self, buffer: CellImage<Bytes>) -> Option<CellImage<E::Layout>>
where
E::Layout: Clone + Layout,
{
let buffer = buffer.try_with_layout(self.engine.consume_layout()).ok()?;
self.engine_to_buf_at(buffer.as_capacity_cell_buf());
Some(buffer)
}
pub fn write_to_cell_ref<'data>(
mut self,
buffer: CellImageRef<'data, Bytes>,
) -> Option<CellImageRef<'data, E::Layout>> {
let buffer = buffer.checked_with_layout(self.engine.consume_layout())?;
self.engine_to_buf_at(buffer.as_cell_buf());
Some(buffer)
}
pub fn write_to_atomic_image(
mut self,
buffer: AtomicImage<Bytes>,
) -> Option<AtomicImage<E::Layout>>
where
E::Layout: Clone + Layout,
{
let buffer = buffer.try_with_layout(self.engine.consume_layout()).ok()?;
self.engine_to_buf_at(buffer.as_capacity_atomic_buf());
Some(buffer)
}
pub fn write_to_atomic_ref<'data>(
mut self,
buffer: AtomicImageRef<'data, Bytes>,
) -> Option<AtomicImageRef<'data, E::Layout>>
where
E::Layout: Clone + Layout,
{
let buffer = buffer.checked_with_layout(self.engine.consume_layout())?;
self.engine_to_buf_at(buffer.as_capacity_atomic_buf());
Some(buffer)
}
}
impl Storable for Buffer {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_buf(&self.as_bytes(), buffer, what, into)
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_cell(&self.as_bytes(), buffer, what, into)
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_atomic(&self.as_bytes(), buffer, what, into)
}
}
impl Loadable for Buffer {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
<&'_ mut [u8]>::load_from_buf(&mut self.as_bytes_mut(), buffer, what, into)
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ mut [u8]>::load_from_cell(&mut self.as_bytes_mut(), buffer, what, into)
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ mut [u8]>::load_from_atomic(&mut self.as_bytes_mut(), buffer, what, into)
}
}
impl<L> Image<L> {
pub fn assign<E>(&mut self, mut data: AsCopySource<'_, E>)
where
E: LayoutEngine<Layout = L>,
L: Layout,
{
let layout = data.engine.consume_layout();
*self.layout_mut_unguarded() = layout;
self.ensure_layout();
data.engine_to_buf_at(self.as_capacity_buf_mut());
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
engine: RangeEngine::new(self.layout(), 0),
inner: self.inner.get_mut(),
}
}
}
impl Storable for &'_ buf {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_buf(&self.as_bytes(), buffer, what, into)
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_cell(&self.as_bytes(), buffer, what, into)
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_atomic(&self.as_bytes(), buffer, what, into)
}
}
impl Storable for &'_ mut buf {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_buf(&self.as_bytes(), buffer, what, into)
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_cell(&self.as_bytes(), buffer, what, into)
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ [u8]>::store_to_atomic(&self.as_bytes(), buffer, what, into)
}
}
impl Loadable for &'_ mut buf {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
<&'_ mut [u8]>::load_from_buf(&mut self.as_bytes_mut(), buffer, what, into)
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ mut [u8]>::load_from_cell(&mut self.as_bytes_mut(), buffer, what, into)
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ mut [u8]>::load_from_atomic(&mut self.as_bytes_mut(), buffer, what, into)
}
}
impl<L> ImageMut<'_, L> {
pub fn assign<E>(&mut self, mut data: AsCopySource<'_, E>) -> Result<(), BufferReuseError>
where
E: LayoutEngine<Layout = L>,
L: Layout,
{
let layout = data.engine.consume_layout();
self.try_set_layout(layout)?;
data.engine_to_buf_at(self.as_capacity_buf_mut());
Ok(())
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
engine: RangeEngine::new(self.layout(), 0),
inner: self.inner.get_mut(),
}
}
}
impl<L> ImageRef<'_, L> {
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
}
impl Storable for CellBuffer {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
<&'_ cell_buf>::store_to_buf(&&**self, buffer, what, into)
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ cell_buf>::store_to_cell(&&**self, buffer, what, into)
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ cell_buf>::store_to_atomic(&&**self, buffer, what, into)
}
}
impl Loadable for CellBuffer {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
<&'_ cell_buf>::load_from_buf(&mut &**self, buffer, what, into)
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ cell_buf>::load_from_cell(&mut &**self, buffer, what, into)
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ cell_buf>::load_from_atomic(&mut &**self, buffer, what, into)
}
}
impl<L> CellImage<L> {
pub fn assign<E>(&mut self, mut data: AsCopySource<'_, E>) -> Result<(), BufferReuseError>
where
E: LayoutEngine<Layout = L>,
L: Layout,
{
let layout = data.engine.consume_layout();
self.try_set_layout(layout)?;
data.engine_to_buf_at(self.as_capacity_cell_buf());
Ok(())
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
engine: RangeEngine::new(self.layout(), 0),
inner: self.inner.get_mut(),
}
}
}
impl Storable for &'_ cell_buf {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
let inner = self.as_texels(texels::U8).as_slice_of_cells();
<&'_ [Cell<u8>]>::store_to_buf(&inner, buffer, what, into)
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let inner = self.as_texels(texels::U8).as_slice_of_cells();
<&'_ [Cell<u8>]>::store_to_cell(&inner, buffer, what, into)
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let inner = self.as_texels(texels::U8).as_slice_of_cells();
<&'_ [Cell<u8>]>::store_to_atomic(&inner, buffer, what, into)
}
}
impl Loadable for &'_ cell_buf {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
let mut inner = self.as_texels(texels::U8).as_slice_of_cells();
<&'_ [Cell<u8>]>::load_from_buf(&mut inner, buffer, what, into)
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let mut inner = self.as_texels(texels::U8).as_slice_of_cells();
<&'_ [Cell<u8>]>::load_from_cell(&mut inner, buffer, what, into)
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let mut inner = self.as_texels(texels::U8).as_slice_of_cells();
<&'_ [Cell<u8>]>::load_from_atomic(&mut inner, buffer, what, into)
}
}
impl<L> CellImageRef<'_, L> {
pub fn assign<E>(&mut self, mut data: AsCopySource<'_, E>) -> Result<(), BufferReuseError>
where
E: LayoutEngine<Layout = L>,
L: Layout,
{
let layout = data.engine.consume_layout();
self.try_set_layout(layout)?;
data.engine_to_buf_at(self.as_capacity_cell_buf());
Ok(())
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
engine: RangeEngine::new(self.layout(), 0),
inner: self.inner.get_mut(),
}
}
}
impl Storable for AtomicBuffer {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
<&'_ atomic_buf>::store_to_buf(&&**self, buffer, what, into)
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ atomic_buf>::store_to_cell(&&**self, buffer, what, into)
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ atomic_buf>::store_to_atomic(&&**self, buffer, what, into)
}
}
impl Loadable for AtomicBuffer {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
<&'_ atomic_buf>::load_from_buf(&mut &**self, buffer, what, into)
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
<&'_ atomic_buf>::load_from_cell(&mut &**self, buffer, what, into)
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
<&'_ atomic_buf>::load_from_atomic(&mut &**self, buffer, what, into)
}
}
impl<L> AtomicImage<L> {
pub fn assign<E>(&mut self, mut data: AsCopySource<'_, E>) -> Result<(), BufferReuseError>
where
E: LayoutEngine<Layout = L>,
L: Layout,
{
let layout = data.engine.consume_layout();
self.try_set_layout(layout)?;
data.engine_to_buf_at(self.as_capacity_atomic_buf());
Ok(())
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
engine: RangeEngine::new(self.layout(), 0),
inner: self.inner.get_mut(),
}
}
}
impl Storable for &'_ atomic_buf {
#[track_caller]
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = &mut buffer.as_bytes_mut()[into..][..len];
let source = self.index(texels::U8.to_range(what).unwrap());
texels::U8.load_atomic_slice(source, target);
}
#[track_caller]
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let source = self.index(texels::U8.to_range(what).unwrap());
texels::U8.load_atomic_to_cells(source, target);
}
#[track_caller]
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let target = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let source = self.index(texels::U8.to_range(what).unwrap());
texels::U8.atomic_memory_move(source, target);
}
}
impl Loadable for &'_ atomic_buf {
#[track_caller]
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_bytes()[into..][..len];
let target = self.index(texels::U8.to_range(what).unwrap());
texels::U8.store_atomic_slice(target, source);
}
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = &buffer.as_texels(texels::U8).as_slice_of_cells()[into..][..len];
let target = self.index(texels::U8.to_range(what).unwrap());
texels::U8.store_atomic_from_cells(target, source);
}
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
let len = what.len();
let source = buffer.index(texels::U8.to_range(into..into + len).unwrap());
let target = self.index(texels::U8.to_range(what).unwrap());
texels::U8.atomic_memory_move(source, target);
}
}
impl<L> AtomicImageRef<'_, L> {
pub fn assign<E>(&mut self, mut data: AsCopySource<'_, E>) -> Result<(), BufferReuseError>
where
E: LayoutEngine<Layout = L>,
L: Layout,
{
let layout = data.engine.consume_layout();
self.try_set_layout(layout)?;
data.engine_to_buf_at(self.as_capacity_atomic_buf());
Ok(())
}
pub fn as_source(&self) -> AsCopySource<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopySource {
inner: self.inner.get(),
engine: RangeEngine::new(self.layout(), 0),
}
}
pub fn as_target(&mut self) -> AsCopyTarget<'_, RangeEngine<L>>
where
L: Clone + Layout,
{
AsCopyTarget {
engine: RangeEngine::new(self.layout(), 0),
inner: self.inner.get_mut(),
}
}
}
impl<E: LayoutEngine> AsCopyTarget<'_, E> {
fn engine_from_buf_at(&mut self, buffer: impl sealed::LoadSource) {
#[inline(never)]
fn ranges_from_buf_at(
ranges: impl Iterator<Item = Range<usize>>,
store: &mut dyn Loadable,
mut buffer: impl sealed::LoadSource,
offset: usize,
) {
for range in ranges {
buffer.load(store, range, offset)
}
}
ranges_from_buf_at(
self.engine.buffer_ranges(),
self.inner,
buffer,
self.engine.image_offset(),
);
}
pub fn read_from_ref(&mut self, buffer: ImageRef<'_, Bytes>) {
self.engine_from_buf_at(buffer.as_buf());
}
pub fn read_from_cell_ref(&mut self, buffer: CellImageRef<'_, Bytes>) {
self.engine_from_buf_at(buffer.as_cell_buf());
}
pub fn read_from_atomic_ref(&mut self, buffer: CellImageRef<'_, Bytes>) {
self.engine_from_buf_at(buffer.as_cell_buf());
}
}
pub struct RangeEngine<L> {
inner: Option<L>,
bytes: [Range<usize>; 1],
}
pub struct RelocateEngine<Inner: sealed::LayoutEngineCore> {
inner: Inner,
offset: AlignedOffset,
}
impl<L: Layout> LayoutEngine for RangeEngine<L> {}
impl<L: Layout> RangeEngine<L> {
fn new(layout: &L, offset: usize) -> Self
where
L: Clone,
{
let byte_len = layout.byte_len();
let bytes = [offset..offset + byte_len];
RangeEngine {
inner: Some(layout.clone()),
bytes,
}
}
}
impl<L: Layout> sealed::LayoutEngineCore for RangeEngine<L> {
type Layout = L;
fn consume_layout(&mut self) -> L {
self.inner
.take()
.expect("Protocol error, layout polled twice")
}
#[allow(refining_impl_trait)]
fn buffer_ranges(&self) -> core::iter::Cloned<core::slice::Iter<'_, Range<usize>>> {
(&self.bytes[..]).iter().cloned()
}
fn image_offset(&self) -> usize {
0
}
}
impl<I: sealed::LayoutEngineCore> LayoutEngine for RelocateEngine<I> {}
impl<I: sealed::LayoutEngineCore> sealed::LayoutEngineCore for RelocateEngine<I> {
type Layout = Relocated<I::Layout>;
fn consume_layout(&mut self) -> Self::Layout {
Relocated {
inner: self.inner.consume_layout(),
offset: self.offset,
}
}
fn buffer_ranges(&self) -> impl Iterator<Item = Range<usize>> {
self.inner.buffer_ranges()
}
fn image_offset(&self) -> usize {
self.inner.image_offset() + self.offset.get()
}
}