Skip to content

Commit f6379dd

Browse files
authored
docs: added most documentation
Wgpu Context now async + added docs
2 parents 64496c3 + 9df1a40 commit f6379dd

File tree

3 files changed

+68
-17
lines changed

3 files changed

+68
-17
lines changed

examples/demo/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
fn main() {
2+
let _ = ratatui::init();
3+
4+
ratatui::restore();
5+
}

src/lib.rs

Lines changed: 57 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -29,12 +29,25 @@
2929
3030
mod wgpu_context;
3131

32+
use pollster::FutureExt;
3233
use ratatui::layout::{Position, Rect};
3334
use ratatui::style::{Color, Style};
3435
use ratatui::widgets::StatefulWidget;
3536

3637
use crate::wgpu_context::WgpuContext;
3738

39+
/// `ShaderCanvas` is a unit struct which implements the `StatefulWidget` trait from Ratatui.
40+
/// It holds the logic for applying the result of GPU computation to the `Buffer` struct which
41+
/// Ratatui uses to display to the terminal.
42+
///
43+
/// ```rust,no_run
44+
/// let mut terminal = ratatui::init();
45+
/// let mut state = tui_shader::ShaderCanvasState::default();
46+
/// terminal.draw(|frame| {
47+
/// frame.render_stateful_widget(tui_shader::ShaderCanvas, frame.area(), &mut state);
48+
/// }).unwrap();
49+
/// ratatui::restore();
50+
/// ```
3851
pub struct ShaderCanvas;
3952

4053
impl StatefulWidget for ShaderCanvas {
@@ -43,22 +56,23 @@ impl StatefulWidget for ShaderCanvas {
4356
let width = area.width;
4457
let height = area.height;
4558

46-
let raw_buffer = state.wgpu_context.execute(width, height);
59+
let raw_buffer = state.wgpu_context.execute(width, height).block_on();
4760

4861
for y in 0..height {
4962
for x in 0..width {
5063
let index = (y * (width + WgpuContext::row_padding(width)) + x) as usize;
51-
let pixel = raw_buffer[index];
64+
let value = raw_buffer[index];
65+
let position = (x, y);
5266
let character = match state.options.character_rule {
5367
CharacterRule::Always(character) => character,
54-
CharacterRule::Map(map) => map(pixel.into()),
68+
CharacterRule::Map(map) => map(Sample::new(value, position)),
5569
};
56-
let color = Color::Rgb(pixel[0], pixel[1], pixel[2]);
70+
let color = Color::Rgb(value[0], value[1], value[2]);
5771
let style = match state.options.style_rule {
5872
StyleRule::ColorFg => Style::new().fg(color),
5973
StyleRule::ColorBg => Style::new().bg(color),
6074
StyleRule::ColorFgAndBg => Style::new().fg(color).bg(color),
61-
StyleRule::Map(map) => map(pixel.into()),
75+
StyleRule::Map(map) => map(Sample::new(value, position)),
6276
};
6377
let cell = buf.cell_mut(Position::new(x, y)).unwrap();
6478
cell.set_style(style);
@@ -68,25 +82,45 @@ impl StatefulWidget for ShaderCanvas {
6882
}
6983
}
7084

85+
/// State struct for [`ShaderCanvas`].
86+
///
87+
/// This struct holds values that may want to be altered at runtime.
7188
#[derive(Debug, Default, Clone, Eq, PartialEq)]
7289
pub struct ShaderCanvasState {
7390
wgpu_context: WgpuContext,
7491
options: ShaderCanvasOptions,
7592
}
7693

7794
impl ShaderCanvasState {
95+
/// Creates a new [`ShaderCanvasState`] by passing in the path to the desired fragment shader.
96+
/// The shader must be written in WGSL. The [`ShaderCanvasOptions`] will be set to
97+
/// [`Self::default()`].
7898
pub fn new(path_to_fragment_shader: &str) -> Self {
7999
Self::new_with_options(path_to_fragment_shader, ShaderCanvasOptions::default())
80100
}
81101

102+
/// Creates a new [`ShaderCanvasState`] by passing in the path to the desired fragment shader.
103+
/// The shader must be written in WGSL. The [`ShaderCanvasOptions`] can be customized.
104+
///
105+
/// ```rust,no_run
106+
/// let state = tui_shader::ShaderCanvasState::new_with_options("path/to/shader.wgsl",
107+
/// tui_shader::ShaderCanvasOptions {
108+
/// style_rule: tui_shader::StyleRule::ColorFg,
109+
/// entry_point: String::from("fragment"),
110+
/// ..Default::default()
111+
/// }
112+
/// );
113+
/// ```
82114
pub fn new_with_options(path_to_fragment_shader: &str, options: ShaderCanvasOptions) -> Self {
83115
Self {
84-
wgpu_context: WgpuContext::new(path_to_fragment_shader, &options.entry_point),
116+
wgpu_context: WgpuContext::new(path_to_fragment_shader, &options.entry_point)
117+
.block_on(),
85118
options,
86119
}
87120
}
88121
}
89122

123+
/// Contains options to customize the behaviour of the ShaderCanvas.
90124
#[derive(Debug, Clone, Eq, PartialEq)]
91125
pub struct ShaderCanvasOptions {
92126
pub character_rule: CharacterRule,
@@ -104,6 +138,11 @@ impl Default for ShaderCanvasOptions {
104138
}
105139
}
106140

141+
/// Determines which character to use for Cell.
142+
/// [`CharacterRule::Always`] takes a single char and applies it to all Cells in the [`ShaderCanvas`].
143+
/// [`CharacterRule::Map`] takes a function as an argument and allows you to map the input [`Sample`] to
144+
/// a character. For example, one might use the transparency value from the shader ([Sample::a]) and map
145+
/// it to a different character depending on the value.
107146
#[derive(Debug, Clone, Eq, PartialEq)]
108147
pub enum CharacterRule {
109148
Always(char),
@@ -127,9 +166,14 @@ pub enum StyleRule {
127166

128167
pub struct Sample {
129168
value: [u8; 4],
169+
position: (u16, u16),
130170
}
131171

132172
impl Sample {
173+
fn new(value: [u8; 4], position: (u16, u16)) -> Self {
174+
Self { value, position }
175+
}
176+
133177
pub fn r(&self) -> u8 {
134178
self.value[0]
135179
}
@@ -145,11 +189,13 @@ impl Sample {
145189
pub fn a(&self) -> u8 {
146190
self.value[3]
147191
}
148-
}
149192

150-
impl From<[u8; 4]> for Sample {
151-
fn from(value: [u8; 4]) -> Self {
152-
Self { value }
193+
pub fn x(&self) -> u16 {
194+
self.position.0
195+
}
196+
197+
pub fn y(&self) -> u16 {
198+
self.position.1
153199
}
154200
}
155201

@@ -160,7 +206,7 @@ mod tests {
160206
#[test]
161207
fn default_wgsl_context() {
162208
let mut context = WgpuContext::default();
163-
let raw_buffer = context.execute(64, 64);
209+
let raw_buffer = context.execute(64, 64).block_on();
164210
assert!(raw_buffer.iter().all(|pixel| pixel == &[255, 0, 255, 255]));
165211
}
166212
}

src/wgpu_context.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,12 @@ pub struct WgpuContext {
2424
}
2525

2626
impl WgpuContext {
27-
pub fn new(path_to_fragment_shader: &str, entry_point: &str) -> Self {
27+
pub async fn new(path_to_fragment_shader: &str, entry_point: &str) -> Self {
2828
let instance = wgpu::Instance::default();
2929

3030
let adapter = instance
3131
.request_adapter(&wgpu::RequestAdapterOptions::default())
32-
.block_on()
32+
.await
3333
.unwrap();
3434

3535
let (device, queue) = adapter
@@ -42,7 +42,7 @@ impl WgpuContext {
4242
},
4343
None,
4444
)
45-
.block_on()
45+
.await
4646
.unwrap();
4747

4848
let vertex_shader =
@@ -188,7 +188,7 @@ impl WgpuContext {
188188
(bytes_per_row - row_size) / 4
189189
}
190190

191-
pub fn execute(&mut self, width: u16, height: u16) -> Vec<[u8; 4]> {
191+
pub async fn execute(&mut self, width: u16, height: u16) -> Vec<[u8; 4]> {
192192
if Self::bytes_per_row(width) != Self::bytes_per_row(self.width) || height != self.height {
193193
self.texture = Self::create_texture(&self.device, width.into(), height.into());
194194
self.output_buffer = Self::create_buffer(&self.device, width.into(), height.into());
@@ -259,7 +259,7 @@ impl WgpuContext {
259259
let (sender, receiver) = flume::bounded(1);
260260
buffer_slice.map_async(wgpu::MapMode::Read, move |r| sender.send(r).unwrap());
261261
self.device.poll(wgpu::Maintain::wait()).panic_on_timeout();
262-
receiver.recv_async().block_on().unwrap().unwrap();
262+
receiver.recv_async().await.unwrap().unwrap();
263263
let slice: Vec<[u8; 4]>;
264264
{
265265
let view = buffer_slice.get_mapped_range();
@@ -272,6 +272,6 @@ impl WgpuContext {
272272

273273
impl Default for WgpuContext {
274274
fn default() -> Self {
275-
Self::new("src/shaders/default_fragment.wgsl", "magenta")
275+
Self::new("src/shaders/default_fragment.wgsl", "magenta").block_on()
276276
}
277277
}

0 commit comments

Comments
 (0)