bevy/crates/bevy_crevice/src/std140/writer.rs
François 79d36e7c28 Prepare crevice for vendored release (#3394)
# Objective

- Our crevice is still called "crevice", which we can't use for a release
- Users would need to use our "crevice" directly to be able to use the derive macro

## Solution

- Rename crevice to bevy_crevice, and crevice-derive to bevy-crevice-derive
- Re-export it from bevy_render, and use it from bevy_render everywhere
- Fix derive macro to work either from bevy_render, from bevy_crevice, or from bevy

## Remaining

- It is currently re-exported as `bevy::render::bevy_crevice`, is it the path we want?
- After a brief suggestion to Cart, I changed the version to follow Bevy version instead of crevice, do we want that?
- Crevice README.md need to be updated
- in the `Cargo.toml`, there are a few things to change. How do we want to change them? How do we keep attributions to original Crevice?
```
authors = ["Lucien Greathouse <me@lpghatguy.com>"]
documentation = "https://docs.rs/crevice"
homepage = "https://github.com/LPGhatguy/crevice"
repository = "https://github.com/LPGhatguy/crevice"
```


Co-authored-by: François <8672791+mockersf@users.noreply.github.com>
Co-authored-by: Carter Anderson <mcanders1@gmail.com>
2021-12-23 22:49:12 +00:00

163 lines
4.0 KiB
Rust

use std::io::{self, Write};
use std::mem::size_of;
use bytemuck::bytes_of;
use crate::internal::align_offset;
use crate::std140::{AsStd140, Std140, WriteStd140};
/**
Type that enables writing correctly aligned `std140` values to a buffer.
`Writer` is useful when many values need to be laid out in a row that cannot be
represented by a struct alone, like dynamically sized arrays or dynamically
laid-out values.
## Example
In this example, we'll write a length-prefixed list of lights to a buffer.
`std140::Writer` helps align correctly, even across multiple structs, which can
be tricky and error-prone otherwise.
```glsl
struct PointLight {
vec3 position;
vec3 color;
float brightness;
};
buffer POINT_LIGHTS {
uint len;
PointLight[] lights;
} point_lights;
```
```
use bevy_crevice::std140::{self, AsStd140};
#[derive(AsStd140)]
struct PointLight {
position: mint::Vector3<f32>,
color: mint::Vector3<f32>,
brightness: f32,
}
let lights = vec![
PointLight {
position: [0.0, 1.0, 0.0].into(),
color: [1.0, 0.0, 0.0].into(),
brightness: 0.6,
},
PointLight {
position: [0.0, 4.0, 3.0].into(),
color: [1.0, 1.0, 1.0].into(),
brightness: 1.0,
},
];
# fn map_gpu_buffer_for_write() -> &'static mut [u8] {
# Box::leak(vec![0; 1024].into_boxed_slice())
# }
let target_buffer = map_gpu_buffer_for_write();
let mut writer = std140::Writer::new(target_buffer);
let light_count = lights.len() as u32;
writer.write(&light_count)?;
// Crevice will automatically insert the required padding to align the
// PointLight structure correctly. In this case, there will be 12 bytes of
// padding between the length field and the light list.
writer.write(lights.as_slice())?;
# fn unmap_gpu_buffer() {}
unmap_gpu_buffer();
# Ok::<(), std::io::Error>(())
```
*/
pub struct Writer<W> {
writer: W,
offset: usize,
}
impl<W: Write> Writer<W> {
/// Create a new `Writer`, wrapping a buffer, file, or other type that
/// implements [`std::io::Write`].
pub fn new(writer: W) -> Self {
Self { writer, offset: 0 }
}
/// Write a new value to the underlying buffer, writing zeroed padding where
/// necessary.
///
/// Returns the offset into the buffer that the value was written to.
pub fn write<T>(&mut self, value: &T) -> io::Result<usize>
where
T: WriteStd140 + ?Sized,
{
value.write_std140(self)
}
/// Write an iterator of values to the underlying buffer.
///
/// Returns the offset into the buffer that the first value was written to.
/// If no values were written, returns the `len()`.
pub fn write_iter<I, T>(&mut self, iter: I) -> io::Result<usize>
where
I: IntoIterator<Item = T>,
T: WriteStd140,
{
let mut offset = self.offset;
let mut iter = iter.into_iter();
if let Some(item) = iter.next() {
offset = item.write_std140(self)?;
}
for item in iter {
item.write_std140(self)?;
}
Ok(offset)
}
/// Write an `Std140` type to the underlying buffer.
pub fn write_std140<T>(&mut self, value: &T) -> io::Result<usize>
where
T: Std140,
{
let padding = align_offset(self.offset, T::ALIGNMENT);
for _ in 0..padding {
self.writer.write_all(&[0])?;
}
self.offset += padding;
let value = value.as_std140();
self.writer.write_all(bytes_of(&value))?;
let write_here = self.offset;
self.offset += size_of::<T>();
Ok(write_here)
}
/// Write a slice of values to the underlying buffer.
#[deprecated(
since = "0.6.0",
note = "Use `write` instead -- it now works on slices."
)]
pub fn write_slice<T>(&mut self, slice: &[T]) -> io::Result<usize>
where
T: AsStd140,
{
self.write(slice)
}
/// Returns the amount of data written by this `Writer`.
pub fn len(&self) -> usize {
self.offset
}
}