Skip to content

Commit

Permalink
More documentation
Browse files Browse the repository at this point in the history
  • Loading branch information
nanoqsh committed Feb 28, 2024
1 parent ff6671a commit 731bd99
Show file tree
Hide file tree
Showing 14 changed files with 68 additions and 53 deletions.
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ members = [
]

[workspace.package]
version = "0.3.0-alpha.1"
version = "0.3.0-rc"
edition = "2021"
license = "MIT"
authors = ["nanoqsh"]
Expand All @@ -25,9 +25,9 @@ repository = "https://github.com/nanoqsh/dunge"
rust-version = "1.76"

[workspace.dependencies]
dunge = { version = "=0.3.0-alpha.1", path = "dunge" }
dunge_macros = { version = "=0.3.0-alpha.1", path = "dunge_macros" }
dunge_shader = { version = "=0.3.0-alpha.1", path = "dunge_shader" }
dunge = { version = "=0.3.0-rc", path = "dunge" }
dunge_macros = { version = "=0.3.0-rc", path = "dunge_macros" }
dunge_shader = { version = "=0.3.0-rc", path = "dunge_shader" }
bytemuck = "1.13"
glam = "0.25"
env_logger = "0.11"
Expand Down
8 changes: 2 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,8 @@ let triangle = |vert: sl::InVertex<Vert>| {
```

As you can see from the snippet, the shader requires you to provide two things: the position of the vertex on the screen and the color of each fragment/pixel. The result is a `triangle` function, but if you ask for its type in the IDE you may notice that it is more complex than usual:
```rust
impl Fn(InVertex<Vert>) -> Out<
Ret<Compose<Ret<ReadVertex, Vec2<f32>>, Ret<NewVec<(f32, f32), Vs>, Vec2<f32>>>, Vec4<f32>>,
Ret<Compose<Ret<Fragment<Ret<ReadVertex, Vec3<f32>>>, Vec3<f32>>, f32>, Vec4<f32>>,
>
```

`impl Fn(InVertex<Vert>) -> Out<Ret<Compose<Ret<ReadVertex, Vec2<f32>>, Ret<NewVec<(f32, f32), Vs>, Vec2<f32>>>, Vec4<f32>>, Ret<Compose<Ret<Fragment<Ret<ReadVertex, Vec3<f32>>>, Vec3<f32>>, f32>, Vec4<f32>>>`

That's because this function doesn't actually compute anything. It is needed only to describe the method for computing what we need on GPU. During shader instantiation, this function is used to compile an actual shader. However, this saves us from having to write the shader in wgsl and allows to typecheck at compile time. For example, dunge checks that a vertex type in a shader matches with a mesh used during rendering. It also checks types inside the shader itself.

Expand Down
3 changes: 3 additions & 0 deletions dunge/src/draw.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use crate::state::Frame;

/// The draw stage.
pub trait Draw {
fn draw(&self, frame: Frame);
}
Expand All @@ -13,6 +14,8 @@ where
}
}

/// Helper function to create a [`Draw`]
/// implementer from a function.
pub fn draw<D>(draw: D) -> impl Draw
where
D: Fn(Frame),
Expand Down
13 changes: 10 additions & 3 deletions dunge/src/el.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,13 @@ use {
},
};

/// Code representing the location of a physical key.
pub type KeyCode = keyboard::KeyCode;

/// String type from `winit` crate.
pub type SmolStr = keyboard::SmolStr;

/// Describes a button of a mouse controller.
pub type MouseButton = event::MouseButton;

pub(crate) struct Loop(EventLoop<()>);
Expand Down Expand Up @@ -64,6 +69,7 @@ impl Loop {
}
}

/// The event loop error.
#[derive(Debug)]
pub enum LoopError {
EventLoop(EventLoopError),
Expand All @@ -90,9 +96,9 @@ impl error::Error for LoopError {

type Event = event::Event<()>;
type Target = event_loop::EventLoopWindowTarget<()>;
type Maybe = Option<Box<dyn error::Error>>;
type Failure = Option<Box<dyn error::Error>>;

fn handle<U>(cx: Context, view: View, mut upd: U) -> impl FnMut(Event, &Target) -> Maybe
fn handle<U>(cx: Context, view: View, mut upd: U) -> impl FnMut(Event, &Target) -> Failure
where
U: Update,
{
Expand Down Expand Up @@ -287,6 +293,7 @@ where
}
}

/// The main event loop control type.
pub struct Control {
view: View,
resized: Option<(u32, u32)>,
Expand Down Expand Up @@ -414,7 +421,7 @@ impl Flow for () {
}
}

/// The control flow object.
/// The control flow type.
pub enum Then {
/// Keep running the application.
Run,
Expand Down
29 changes: 13 additions & 16 deletions dunge/src/format.rs
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
use wgpu::TextureFormat;

/// The texture format type.
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
pub enum Format {
#[default]
SrgbAlpha,
SbgrAlpha,
RgbAlpha,
BgrAlpha,
RgbAlphaLin,
BgrAlphaLin,
Depth,
}

impl Format {
pub(crate) const fn bytes(self) -> u32 {
match self {
Self::RgbAlpha
| Self::BgrAlpha
| Self::RgbAlphaLin
| Self::BgrAlphaLin
| Self::Depth => 4,
Self::SrgbAlpha | Self::SbgrAlpha | Self::RgbAlpha | Self::BgrAlpha | Self::Depth => 4,
}
}

pub(crate) const fn wgpu(self) -> TextureFormat {
match self {
Self::RgbAlpha => TextureFormat::Rgba8UnormSrgb,
Self::BgrAlpha => TextureFormat::Bgra8UnormSrgb,
Self::RgbAlphaLin => TextureFormat::Rgba8Unorm,
Self::BgrAlphaLin => TextureFormat::Bgra8Unorm,
Self::SrgbAlpha => TextureFormat::Rgba8UnormSrgb,
Self::SbgrAlpha => TextureFormat::Bgra8UnormSrgb,
Self::RgbAlpha => TextureFormat::Rgba8Unorm,
Self::BgrAlpha => TextureFormat::Bgra8Unorm,
Self::Depth => TextureFormat::Depth32Float,
}
}

pub(crate) const fn from_wgpu(format: TextureFormat) -> Self {
match format {
TextureFormat::Rgba8UnormSrgb => Self::RgbAlpha,
TextureFormat::Bgra8UnormSrgb => Self::BgrAlpha,
TextureFormat::Rgba8Unorm => Self::RgbAlphaLin,
TextureFormat::Bgra8Unorm => Self::BgrAlphaLin,
TextureFormat::Rgba8UnormSrgb => Self::SrgbAlpha,
TextureFormat::Bgra8UnormSrgb => Self::SbgrAlpha,
TextureFormat::Rgba8Unorm => Self::RgbAlpha,
TextureFormat::Bgra8Unorm => Self::BgrAlpha,
TextureFormat::Depth32Float => Self::Depth,
_ => panic!("supported format"),
_ => panic!("unsupported format"),
}
}
}
2 changes: 1 addition & 1 deletion dunge/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,6 @@ pub use crate::init::from_element;

#[cfg(feature = "winit")]
pub use crate::{
el::{Control, Flow, Key, KeyCode, LoopError, SmolStr, Then},
el::{Control, Flow, Key, KeyCode, LoopError, MouseButton, SmolStr, Then},
update::{update, update_with, Update},
};
27 changes: 17 additions & 10 deletions dunge/src/state.rs
Original file line number Diff line number Diff line change
Expand Up @@ -108,18 +108,21 @@ impl State {
}
}

/// Current layer options.
#[derive(Clone, Copy, Default)]
pub struct Options {
clear_color: Option<Rgba>,
clear_depth: Option<f32>,
}

impl Options {
/// Sets clear color for the layer.
pub fn clear_color(mut self, clear: Rgba) -> Self {
self.clear_color = Some(clear);
self
}

/// Sets clear depth for the layer.
pub fn clear_depth(mut self, clear: f32) -> Self {
self.clear_depth = Some(clear);
self
Expand All @@ -132,6 +135,7 @@ impl From<Rgba> for Options {
}
}

/// The frame type for drawing and copying operations.
pub struct Frame<'v, 'e> {
target: Target<'v>,
encoder: &'e mut CommandEncoder,
Expand All @@ -151,13 +155,13 @@ impl Frame<'_, '_> {
);

assert!(
!layer.depth() || self.target.depthview.is_some(),
!layer.depth() || self.target.depthv.is_some(),
"the target for a layer with depth must contain a depth buffer",
);

let opts = opts.into();
let color_attachment = RenderPassColorAttachment {
view: self.target.colorview,
view: self.target.colorv,
resolve_target: None,
ops: Operations {
load: opts
Expand All @@ -183,7 +187,7 @@ impl Frame<'_, '_> {

let desc = RenderPassDescriptor {
color_attachments: &[Some(color_attachment)],
depth_stencil_attachment: self.target.depthview.map(depth_attachment),
depth_stencil_attachment: self.target.depthv.map(depth_attachment),
..Default::default()
};

Expand All @@ -199,28 +203,30 @@ impl Frame<'_, '_> {
}
}

/// A target for current frame.
#[derive(Clone, Copy)]
pub struct Target<'v> {
format: Format,
colorview: &'v TextureView,
depthview: Option<&'v TextureView>,
colorv: &'v TextureView,
depthv: Option<&'v TextureView>,
}

impl<'v> Target<'v> {
pub(crate) fn new(format: Format, colorview: &'v TextureView) -> Self {
pub(crate) fn new(format: Format, colorv: &'v TextureView) -> Self {
Self {
format,
colorview,
depthview: None,
colorv,
depthv: None,
}
}

fn with(mut self, depthview: &'v TextureView) -> Self {
self.depthview = Some(depthview);
fn with(mut self, depthv: &'v TextureView) -> Self {
self.depthv = Some(depthv);
self
}
}

/// Something that contains a [target](Target).
pub trait AsTarget {
fn as_target(&self) -> Target;
}
Expand All @@ -246,6 +252,7 @@ where
}
}

/// Pair of color and depth buffer.
#[derive(Clone, Copy)]
pub struct RenderBuffer<T, D> {
color: T,
Expand Down
5 changes: 5 additions & 0 deletions dunge/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,14 @@ use crate::{
state::Frame,
};

/// The update stage.
pub trait Update: Draw {
type Flow: Flow;
fn update(&mut self, ctrl: &Control) -> Self::Flow;
}

/// Helper function to create a [`Update`]
/// implementer from functions.
pub fn update<U, F, D>(mut upd: U, draw: D) -> impl Update
where
U: FnMut(&Control) -> F,
Expand All @@ -18,6 +21,8 @@ where
update_with((), move |(), ctrl| upd(ctrl), move |(), frame| draw(frame))
}

/// Same as [`undate`](fn@crate::update) but with
/// a state shared between two handlers.
pub fn update_with<S, U, F, D>(state: S, upd: U, draw: D) -> impl Update
where
U: FnMut(&mut S, &Control) -> F,
Expand Down
4 changes: 2 additions & 2 deletions dunge/src/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -186,10 +186,10 @@ impl View {
use wgpu::*;

const SUPPORTED_FORMATS: [Format; 4] = [
Format::SrgbAlpha,
Format::SbgrAlpha,
Format::RgbAlpha,
Format::BgrAlpha,
Format::RgbAlphaLin,
Format::BgrAlphaLin,
];

let surface = instance.create_surface(Arc::clone(&inner))?;
Expand Down
6 changes: 3 additions & 3 deletions dunge/tests/triangle_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ fn render() -> Result<(), Error> {
let texture = {
let gradient = Image::decode(include_bytes!("gradient.png"));
let data =
TextureData::new(&gradient.data, gradient.size, Format::RgbAlpha)?.with_bind();
TextureData::new(&gradient.data, gradient.size, Format::SrgbAlpha)?.with_bind();
cx.make_texture(data)
};

Expand All @@ -61,9 +61,9 @@ fn render() -> Result<(), Error> {
binder.into_binding()
};

let layer = cx.make_layer(&shader, Format::RgbAlpha);
let layer = cx.make_layer(&shader, Format::SrgbAlpha);
let view = {
let data = TextureData::empty(SIZE, Format::RgbAlpha)?
let data = TextureData::empty(SIZE, Format::SrgbAlpha)?
.with_draw()
.with_copy();

Expand Down
4 changes: 2 additions & 2 deletions dunge/tests/triangle_index.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,9 @@ fn render() -> Result<(), Error> {
let shader = cx.make_shader(triangle);
helpers::eq_lines(shader.debug_wgsl(), include_str!("triangle_index.wgsl"));

let layer = cx.make_layer(&shader, Format::RgbAlpha);
let layer = cx.make_layer(&shader, Format::SrgbAlpha);
let view = {
let data = TextureData::empty(SIZE, Format::RgbAlpha)?
let data = TextureData::empty(SIZE, Format::SrgbAlpha)?
.with_draw()
.with_copy();

Expand Down
4 changes: 2 additions & 2 deletions dunge/tests/triangle_instance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ fn render() -> Result<(), Error> {
let shader = cx.make_shader(triangle);
helpers::eq_lines(shader.debug_wgsl(), include_str!("triangle_instance.wgsl"));

let layer = cx.make_layer(&shader, Format::RgbAlpha);
let layer = cx.make_layer(&shader, Format::SrgbAlpha);
let view = {
let data = TextureData::empty(SIZE, Format::RgbAlpha)?
let data = TextureData::empty(SIZE, Format::SrgbAlpha)?
.with_draw()
.with_copy();

Expand Down
4 changes: 2 additions & 2 deletions dunge/tests/triangle_vertex.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,9 @@ fn render() -> Result<(), Error> {
let shader = cx.make_shader(triangle);
helpers::eq_lines(shader.debug_wgsl(), include_str!("triangle_vertex.wgsl"));

let layer = cx.make_layer(&shader, Format::RgbAlpha);
let layer = cx.make_layer(&shader, Format::SrgbAlpha);
let view = {
let data = TextureData::empty(SIZE, Format::RgbAlpha)?
let data = TextureData::empty(SIZE, Format::SrgbAlpha)?
.with_draw()
.with_copy();

Expand Down
4 changes: 2 additions & 2 deletions examples/ssaa/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,7 @@ pub fn run(window: dunge::window::Window) -> Result<(), Error> {
u32::max(height, 1) * SCREEN_FACTOR,
);

let data = TextureData::empty(size, Format::RgbAlpha)
let data = TextureData::empty(size, Format::SrgbAlpha)
.expect("non-zero size")
.with_draw()
.with_bind();
Expand Down Expand Up @@ -123,7 +123,7 @@ pub fn run(window: dunge::window::Window) -> Result<(), Error> {
cx.make_mesh(&data)
};

let triangle_layer = cx.make_layer(&triangle_shader, Format::RgbAlpha);
let triangle_layer = cx.make_layer(&triangle_shader, Format::SrgbAlpha);
let screen_layer = cx.make_layer(&screen_shader, window.format());

let upd = move |state: &mut State<_>, ctrl: &Control| {
Expand Down

0 comments on commit 731bd99

Please sign in to comment.