Skip to content

Commit f713ae2

Browse files
committed
Complement image reading functions for Atomic/Cell
1 parent 6a4ea72 commit f713ae2

File tree

1 file changed

+176
-59
lines changed

1 file changed

+176
-59
lines changed

texel/src/image/unaligned.rs

Lines changed: 176 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -18,20 +18,66 @@ mod sealed {
1818
}
1919

2020
pub trait Loadable {
21-
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, into: usize);
22-
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, into: usize);
23-
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize);
21+
fn load_from_buf(&mut self, buffer: &buf, what: Range<usize>, at: usize);
22+
fn load_from_cell(&mut self, buffer: &cell_buf, what: Range<usize>, at: usize);
23+
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, at: usize);
2424
}
2525

2626
pub trait Storable {
27-
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, into: usize);
28-
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, into: usize);
29-
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize);
27+
fn store_to_buf(&self, buffer: &mut buf, what: Range<usize>, at: usize);
28+
fn store_to_cell(&self, buffer: &cell_buf, what: Range<usize>, at: usize);
29+
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, at: usize);
30+
}
31+
32+
/// So we can abstract over the invocations of `Loadable::load_from_{buf,cell,atomic}`.
33+
pub(crate) trait LoadSource {
34+
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize);
35+
}
36+
37+
/// So we can abstract over the invocations of `Storable::store_to_{buf,cell,atomic}`.
38+
pub(crate) trait StoreTarget {
39+
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize);
40+
}
41+
42+
impl LoadSource for &'_ buf {
43+
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize) {
44+
into.load_from_buf(self, what, at)
45+
}
46+
}
47+
48+
impl LoadSource for &'_ cell_buf {
49+
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize) {
50+
into.load_from_cell(self, what, at)
51+
}
52+
}
53+
54+
impl LoadSource for &'_ atomic_buf {
55+
fn load(&mut self, into: &mut dyn Loadable, what: Range<usize>, at: usize) {
56+
into.load_from_atomic(self, what, at)
57+
}
58+
}
59+
60+
impl StoreTarget for &'_ mut buf {
61+
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize) {
62+
into.store_to_buf(self, what, at)
63+
}
64+
}
65+
66+
impl StoreTarget for &'_ cell_buf {
67+
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize) {
68+
into.store_to_cell(self, what, at)
69+
}
70+
}
71+
72+
impl StoreTarget for &'_ atomic_buf {
73+
fn store(&mut self, into: &dyn Storable, what: Range<usize>, at: usize) {
74+
into.store_to_atomic(self, what, at)
75+
}
3076
}
3177
}
3278

3379
use core::{cell::Cell, ops::Range};
34-
use sealed::{LayoutEngineCore, Loadable, Storable};
80+
use sealed::{Loadable, Storable};
3581

3682
use crate::buf::{atomic_buf, buf, cell_buf};
3783
use crate::image::{
@@ -40,18 +86,21 @@ use crate::image::{
4086
use crate::layout::{Bytes, Layout};
4187
use crate::texels;
4288

89+
/// A buffer with layout, not aligned to any particular boundary.
4390
pub struct DataRef<'lt, Layout = Bytes> {
4491
data: &'lt [u8],
4592
layout: Layout,
4693
offset: usize,
4794
}
4895

96+
/// A mutable buffer with layout, not aligned to any particular boundary.
4997
pub struct DataMut<'lt, Layout = Bytes> {
5098
data: &'lt mut [u8],
5199
layout: Layout,
52100
offset: usize,
53101
}
54102

103+
/// A cell buffer with layout, not aligned to any particular boundary.
55104
pub struct DataCells<'lt, Layout = Bytes> {
56105
data: &'lt [Cell<u8>],
57106
layout: Layout,
@@ -145,6 +194,22 @@ impl<'lt, L> DataRef<'lt, L> {
145194
let len = buffer.len().min(core::mem::size_of_val(self.data));
146195
buffer[..len].copy_from_slice(self.data);
147196
}
197+
198+
/// An adapter reading from the data as one contiguous chunk.
199+
///
200+
/// See [`WholeLayout`] for more explanations.
201+
pub fn as_source(&self) -> AsCopySource<'_, WholeLayout<'_, L>>
202+
where
203+
L: Layout,
204+
{
205+
AsCopySource {
206+
inner: &self.data,
207+
engine: WholeLayout {
208+
inner: &self.layout,
209+
offset: self.offset,
210+
},
211+
}
212+
}
148213
}
149214

150215
impl Storable for &'_ [u8] {
@@ -199,6 +264,38 @@ impl<'lt, L> DataMut<'lt, L> {
199264
let len = buffer.len().min(core::mem::size_of_val(self.data));
200265
self.data[..len].copy_from_slice(buffer);
201266
}
267+
268+
/// An adapter reading from the data as one contiguous chunk.
269+
///
270+
/// See [`WholeLayout`] for more explanations.
271+
pub fn as_source(&self) -> AsCopySource<'_, WholeLayout<'_, L>>
272+
where
273+
L: Layout,
274+
{
275+
AsCopySource {
276+
inner: &self.data,
277+
engine: WholeLayout {
278+
inner: &self.layout,
279+
offset: self.offset,
280+
},
281+
}
282+
}
283+
284+
/// An adapter writing to this buffer in one contiguous chunk.
285+
///
286+
/// See [`WholeLayout`] for more explanations.
287+
pub fn as_target(&mut self) -> AsCopyTarget<'_, WholeLayout<'_, L>>
288+
where
289+
L: Layout,
290+
{
291+
AsCopyTarget {
292+
inner: &mut self.data,
293+
engine: WholeLayout {
294+
inner: &self.layout,
295+
offset: self.offset,
296+
},
297+
}
298+
}
202299
}
203300

204301
impl Storable for &'_ mut [u8] {
@@ -279,7 +376,9 @@ impl<'lt, L> DataCells<'lt, L> {
279376
self.data.load_from_buf(buffer, 0..len, 0);
280377
}
281378

282-
/// Copy all bytes contained in this layout.
379+
/// An adapter reading from the data as one contiguous chunk.
380+
///
381+
/// See [`WholeLayout`] for more explanations.
283382
pub fn as_source(&self) -> AsCopySource<'_, WholeLayout<'_, L>>
284383
where
285384
L: Layout,
@@ -293,7 +392,9 @@ impl<'lt, L> DataCells<'lt, L> {
293392
}
294393
}
295394

296-
/// Copy all bytes contained in this layout.
395+
/// An adapter writing to this buffer in one contiguous chunk.
396+
///
397+
/// See [`WholeLayout`] for more explanations.
297398
pub fn as_target(&mut self) -> AsCopyTarget<'_, WholeLayout<'_, L>>
298399
where
299400
L: Layout,
@@ -327,7 +428,10 @@ impl Storable for &'_ [Cell<u8>] {
327428

328429
#[track_caller]
329430
fn store_to_atomic(&self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
330-
todo!()
431+
let len = what.len();
432+
let target = buffer.index(texels::U8.to_range(into..into + len).unwrap());
433+
let source = &self[what.start..what.end];
434+
texels::U8.store_atomic_from_cells(target, source);
331435
}
332436
}
333437

@@ -350,59 +454,25 @@ impl Loadable for &'_ [Cell<u8>] {
350454
fn load_from_atomic(&mut self, buffer: &atomic_buf, what: Range<usize>, into: usize) {
351455
let len = what.len();
352456
let source = buffer.index(texels::U8.to_range(into..into + len).unwrap());
353-
todo!()
457+
let target = &self[what.start..what.end];
458+
texels::U8.load_atomic_to_cells(source, target);
354459
}
355460
}
356461

357462
impl<E: LayoutEngine> AsCopySource<'_, E> {
358-
fn engine_to_buf_at(&self, buffer: &mut buf, offset: usize) {
359-
// Make sure we compile this once per iterator type. Then for instance there is only one
360-
// such instance for all LayoutEngine types instead of one per different layout
361-
#[inline(never)]
362-
fn ranges_to_buf_at(
363-
ranges: impl Iterator<Item = Range<usize>>,
364-
store: &dyn Storable,
365-
buffer: &mut buf,
366-
offset: usize,
367-
) {
368-
for range in ranges {
369-
store.store_to_buf(buffer, range, offset)
370-
}
371-
}
372-
373-
ranges_to_buf_at(self.engine.ranges(), self.inner, buffer, offset);
374-
}
375-
376-
fn engine_to_cell_buf_at(&self, buffer: &cell_buf, offset: usize) {
377-
// Make sure we compile this once per iterator type. Then for instance there is only one
378-
// such instance for all LayoutEngine types instead of one per different layout
463+
fn engine_to_buf_at(&self, buffer: impl sealed::StoreTarget, offset: usize) {
464+
// Make sure we compile this once per iterator type and buffer type combination. Then for
465+
// instance there is only one such instance for all LayoutEngine types instead of one per
466+
// different layout.
379467
#[inline(never)]
380468
fn ranges_to_buf_at(
381469
ranges: impl Iterator<Item = Range<usize>>,
382470
store: &dyn Storable,
383-
buffer: &cell_buf,
471+
mut buffer: impl sealed::StoreTarget,
384472
offset: usize,
385473
) {
386474
for range in ranges {
387-
store.store_to_cell(buffer, range, offset)
388-
}
389-
}
390-
391-
ranges_to_buf_at(self.engine.ranges(), self.inner, buffer, offset);
392-
}
393-
394-
fn engine_to_atomic_buf_at(&self, buffer: &atomic_buf, offset: usize) {
395-
// Make sure we compile this once per iterator type. Then for instance there is only one
396-
// such instance for all LayoutEngine types instead of one per different layout
397-
#[inline(never)]
398-
fn ranges_to_buf_at(
399-
ranges: impl Iterator<Item = Range<usize>>,
400-
store: &dyn Storable,
401-
buffer: &atomic_buf,
402-
offset: usize,
403-
) {
404-
for range in ranges {
405-
store.store_to_atomic(buffer, range, offset)
475+
buffer.store(store, range, offset)
406476
}
407477
}
408478

@@ -458,6 +528,21 @@ impl<E: LayoutEngine> AsCopySource<'_, E> {
458528
Some(buffer)
459529
}
460530

531+
/// Write to an image, changing the layout in the process.
532+
///
533+
/// Fails when allocated buffer does not fits the new data's layout.
534+
pub fn write_to_cell_image(
535+
&self,
536+
buffer: CellImage<impl Layout>,
537+
) -> Option<CellImage<E::Layout>>
538+
where
539+
E::Layout: Clone + Layout,
540+
{
541+
let buffer = buffer.try_with_layout(self.engine.layout().clone()).ok()?;
542+
self.engine_to_buf_at(buffer.as_capacity_cell_buf(), 0);
543+
Some(buffer)
544+
}
545+
461546
/// Write to a locally shared buffer with layout.
462547
///
463548
/// First verifies that the data will fit into the target. Then returns `Some` with a new
@@ -470,7 +555,22 @@ impl<E: LayoutEngine> AsCopySource<'_, E> {
470555
E::Layout: Clone + Layout,
471556
{
472557
let buffer = buffer.checked_with_layout(self.engine.layout().clone())?;
473-
self.engine_to_cell_buf_at(buffer.as_cell_buf(), 0);
558+
self.engine_to_buf_at(buffer.as_cell_buf(), 0);
559+
Some(buffer)
560+
}
561+
562+
/// Write to an image, changing the layout in the process.
563+
///
564+
/// Fails when allocated buffer does not fits the new data's layout.
565+
pub fn write_to_atomic_image(
566+
&self,
567+
buffer: AtomicImage<impl Layout>,
568+
) -> Option<AtomicImage<E::Layout>>
569+
where
570+
E::Layout: Clone + Layout,
571+
{
572+
let buffer = buffer.try_with_layout(self.engine.layout().clone()).ok()?;
573+
self.engine_to_buf_at(buffer.as_capacity_atomic_buf(), 0);
474574
Some(buffer)
475575
}
476576

@@ -486,24 +586,25 @@ impl<E: LayoutEngine> AsCopySource<'_, E> {
486586
E::Layout: Clone + Layout,
487587
{
488588
let buffer = buffer.checked_with_layout(self.engine.layout().clone())?;
489-
self.engine_to_atomic_buf_at(buffer.as_capacity_atomic_buf(), 0);
589+
self.engine_to_buf_at(buffer.as_capacity_atomic_buf(), 0);
490590
Some(buffer)
491591
}
492592
}
493593

494594
impl<E: LayoutEngine> AsCopyTarget<'_, E> {
495-
fn engine_from_buf_at(&mut self, buffer: &buf, offset: usize) {
496-
// Make sure we compile this once per iterator type. Then for instance there is only one
497-
// such instance for all LayoutEngine types instead of one per different layout
595+
fn engine_from_buf_at(&mut self, buffer: impl sealed::LoadSource, offset: usize) {
596+
// Make sure we compile this once per iterator type and buffer type combination. Then for
597+
// instance there is only one such instance for all LayoutEngine types instead of one per
598+
// different layout.
498599
#[inline(never)]
499600
fn ranges_from_buf_at(
500601
ranges: impl Iterator<Item = Range<usize>>,
501602
store: &mut dyn Loadable,
502-
buffer: &buf,
603+
mut buffer: impl sealed::LoadSource,
503604
offset: usize,
504605
) {
505606
for range in ranges {
506-
store.load_from_buf(buffer, range, offset)
607+
buffer.load(store, range, offset)
507608
}
508609
}
509610

@@ -517,4 +618,20 @@ impl<E: LayoutEngine> AsCopyTarget<'_, E> {
517618
pub fn read_from_ref(&mut self, buffer: ImageRef<'_, impl Layout>) {
518619
self.engine_from_buf_at(buffer.as_buf(), 0);
519620
}
621+
622+
/// Read out data from a borrowed buffer.
623+
///
624+
/// This reads data up to our layout. It does not interpret the data with the layout of
625+
/// the argument buffer.
626+
pub fn read_from_cell_ref(&mut self, buffer: CellImageRef<'_, impl Layout>) {
627+
self.engine_from_buf_at(buffer.as_cell_buf(), 0);
628+
}
629+
630+
/// Read out data from a borrowed buffer.
631+
///
632+
/// This reads data up to our layout. It does not interpret the data with the layout of
633+
/// the argument buffer.
634+
pub fn read_from_atomic_ref(&mut self, buffer: CellImageRef<'_, impl Layout>) {
635+
self.engine_from_buf_at(buffer.as_cell_buf(), 0);
636+
}
520637
}

0 commit comments

Comments
 (0)