Skip to content
This repository has been archived by the owner on Oct 6, 2024. It is now read-only.

Commit

Permalink
Implement command queue
Browse files Browse the repository at this point in the history
  • Loading branch information
yutannihilation committed May 5, 2022
1 parent ffd7f34 commit da79c7f
Show file tree
Hide file tree
Showing 4 changed files with 175 additions and 23 deletions.
Binary file modified man/figures/README-unnamed-chunk-2-1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
127 changes: 123 additions & 4 deletions src/rust/src/graphics_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,27 @@ pub(crate) const DEFAULT_TOLERANCE: f32 = lyon::tessellation::FillOptions::DEFAU
// TODO: why can't we use std::u32::MAX...?
const LAYER_FACTOR: f32 = 256.0 / std::u32::MAX as f32;

#[derive(Debug, Clone)]
pub struct DrawCommand {
pub count: u32,
}

impl DrawCommand {
fn extend(&mut self, count: u32) {
self.count += count;
}
}

#[derive(Debug, Clone)]
pub enum WgpugdCommand {
// Draw tessellated polygons.
DrawPolygon(DrawCommand),
// Draw shapes represented by an SDF.
DrawSDF(DrawCommand),
// Set clipping range.
SetClipping,
}

struct VertexCtor {
color: u32,
layer: u32,
Expand Down Expand Up @@ -94,13 +115,33 @@ impl crate::WgpuGraphicsDevice {

let ctxt = VertexCtor::new(color, self.current_layer as _, transform);

stroke_tess
let count = stroke_tess
.tessellate_path(
path,
stroke_options,
&mut BuffersBuilder::new(&mut self.geometry, ctxt),
)
.unwrap();

match self.current_command {
// If the previous command was the same, squash them into one draw
// command.
Some(WgpugdCommand::DrawPolygon(ref mut cmd)) => {
cmd.extend(count.indices);
}
// If the previous command was different, push it to the command
// queue (if exists) and create a new command.
_ => {
let prev = self
.current_command
.replace(WgpugdCommand::DrawPolygon(DrawCommand {
count: count.indices,
}));
if let Some(prev_cmd) = prev {
self.command_queue.push(prev_cmd)
}
}
}
}

fn tesselate_path_fill(&mut self, path: &Path, fill_options: &FillOptions, color: i32) {
Expand All @@ -122,13 +163,33 @@ impl crate::WgpuGraphicsDevice {

let ctxt = VertexCtor::new(color, self.current_layer as _, transform);

fill_tess
let count = fill_tess
.tessellate_path(
path,
fill_options,
&mut BuffersBuilder::new(&mut self.geometry, ctxt),
)
.unwrap();

match self.current_command {
// If the previous command was the same, squash them into one draw
// command.
Some(WgpugdCommand::DrawPolygon(ref mut cmd)) => {
cmd.extend(count.indices);
}
// If the previous command was different, push it to the command
// queue (if exists) and create a new command.
_ => {
let prev = self
.current_command
.replace(WgpugdCommand::DrawPolygon(DrawCommand {
count: count.indices,
}));
if let Some(prev_cmd) = prev {
self.command_queue.push(prev_cmd)
}
}
}
}

fn tesselate_rect_stroke(
Expand All @@ -145,13 +206,33 @@ impl crate::WgpuGraphicsDevice {

let ctxt = VertexCtor::new(color, self.current_layer as _, glam::Affine2::IDENTITY);

stroke_tess
let count = stroke_tess
.tessellate_rectangle(
rect,
stroke_options,
&mut BuffersBuilder::new(&mut self.geometry, ctxt),
)
.unwrap();

match self.current_command {
// If the previous command was the same, squash them into one draw
// command.
Some(WgpugdCommand::DrawPolygon(ref mut cmd)) => {
cmd.extend(count.indices);
}
// If the previous command was different, push it to the command
// queue (if exists) and create a new command.
_ => {
let prev = self
.current_command
.replace(WgpugdCommand::DrawPolygon(DrawCommand {
count: count.indices,
}));
if let Some(prev_cmd) = prev {
self.command_queue.push(prev_cmd)
}
}
}
}

fn tesselate_rect_fill(
Expand All @@ -168,13 +249,33 @@ impl crate::WgpuGraphicsDevice {

let ctxt = VertexCtor::new(color, self.current_layer as _, glam::Affine2::IDENTITY);

fill_tess
let count = fill_tess
.tessellate_rectangle(
rect,
fill_options,
&mut BuffersBuilder::new(&mut self.geometry, ctxt),
)
.unwrap();

match self.current_command {
// If the previous command was the same, squash them into one draw
// command.
Some(WgpugdCommand::DrawPolygon(ref mut cmd)) => {
cmd.extend(count.indices);
}
// If the previous command was different, push it to the command
// queue (if exists) and create a new command.
_ => {
let prev = self
.current_command
.replace(WgpugdCommand::DrawPolygon(DrawCommand {
count: count.indices,
}));
if let Some(prev_cmd) = prev {
self.command_queue.push(prev_cmd)
}
}
}
}

// This handles polygon(), polyline(), and line().
Expand Down Expand Up @@ -350,6 +451,24 @@ impl DeviceDriver for crate::WgpuGraphicsDevice {
stroke_color: unsafe { std::mem::transmute(color) },
z: 1.0 - self.current_layer as f32 * LAYER_FACTOR,
});

match self.current_command {
// If the previous command was the same, squash them into one draw
// command.
Some(WgpugdCommand::DrawSDF(ref mut cmd)) => {
cmd.extend(1);
}
// If the previous command was different, push it to the command
// queue (if exists) and create a new command.
_ => {
let prev = self
.current_command
.replace(WgpugdCommand::DrawSDF(DrawCommand { count: 1 }));
if let Some(prev_cmd) = prev {
self.command_queue.push(prev_cmd)
}
}
}
}

fn rect(&mut self, from: (f64, f64), to: (f64, f64), gc: R_GE_gcontext, _: DevDesc) {
Expand Down
70 changes: 51 additions & 19 deletions src/rust/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ mod render_pipeline;
mod text;

use crate::file::FilenameTemplate;
use crate::graphics_device::WgpugdCommand;

use std::io::Write;
use std::{fs::File, path::PathBuf};
Expand Down Expand Up @@ -140,6 +141,8 @@ struct WgpuGraphicsDevice {

// On clipping or instanced rendering layer, increment this layer id
current_layer: usize,
current_command: Option<WgpugdCommand>,
command_queue: Vec<WgpugdCommand>,

// width and height in point
width: u32,
Expand Down Expand Up @@ -359,6 +362,8 @@ impl WgpuGraphicsDevice {
depth_texture_sampler,

current_layer: 0,
current_command: None,
command_queue: Vec::new(),

width,
height,
Expand All @@ -374,6 +379,11 @@ impl WgpuGraphicsDevice {
}

fn render(&mut self) -> extendr_api::Result<()> {
// TODO: do this more nicely...
if let Some(ref cmd) = self.current_command {
self.command_queue.push(cmd.clone());
}

let vertex_buffer = &self
.device
.create_buffer_init(&wgpu::util::BufferInitDescriptor {
Expand Down Expand Up @@ -408,8 +418,6 @@ impl WgpuGraphicsDevice {
}]),
);

let num_indices = self.geometry.indices.len() as u32;

let texture_view = self
.texture
.create_view(&wgpu::TextureViewDescriptor::default());
Expand Down Expand Up @@ -446,27 +454,51 @@ impl WgpuGraphicsDevice {
}),
});

render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &self.globals_bind_group, &[]);
render_pass.set_vertex_buffer(0, vertex_buffer.slice(..));
render_pass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint32);
render_pass.draw_indexed(0..num_indices, 0, 0..1);
let mut begin_id_polygon = 0_u32;
let mut last_id_polygon = 0_u32;
let mut begin_id_sdf = 0_u32;
let mut last_id_sdf = 0_u32;

for cmd in self.command_queue.iter() {
match cmd {
WgpugdCommand::DrawPolygon(cmd) => {
last_id_polygon = begin_id_polygon + cmd.count;

render_pass.set_pipeline(&self.render_pipeline);
render_pass.set_bind_group(0, &self.globals_bind_group, &[]);
render_pass.set_vertex_buffer(0, vertex_buffer.slice(..));
render_pass
.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint32);
render_pass.draw_indexed(begin_id_polygon..last_id_polygon, 0, 0..1);

begin_id_polygon = last_id_polygon;
}
WgpugdCommand::DrawSDF(cmd) => {
last_id_sdf = begin_id_sdf + cmd.count;

render_pass.set_pipeline(&self.sdf_render_pipeline);
render_pass.set_bind_group(0, &self.globals_bind_group, &[]);
render_pass.set_vertex_buffer(0, self.sdf_vertex_buffer.slice(..));
render_pass.set_vertex_buffer(1, sdf_instance_buffer.slice(..));
render_pass.set_index_buffer(
self.sdf_index_buffer.slice(..),
wgpu::IndexFormat::Uint16,
);
render_pass.draw_indexed(
0..RECT_INDICES.len() as _,
0,
begin_id_sdf..last_id_sdf,
);

begin_id_sdf = last_id_sdf;
}
WgpugdCommand::SetClipping => {}
}
}

// reprintln!("{:?}", self.geometry.vertices);
// reprintln!("{:?}", self.sdf_instances);

render_pass.set_pipeline(&self.sdf_render_pipeline);
render_pass.set_bind_group(0, &self.globals_bind_group, &[]);
render_pass.set_vertex_buffer(0, self.sdf_vertex_buffer.slice(..));
render_pass.set_vertex_buffer(1, sdf_instance_buffer.slice(..));
render_pass
.set_index_buffer(self.sdf_index_buffer.slice(..), wgpu::IndexFormat::Uint16);
render_pass.draw_indexed(
0..RECT_INDICES.len() as _,
0,
0..self.sdf_instances.len() as _,
);

// Return the ownership. Otherwise the next operation on encoder would fail
drop(render_pass);

Expand Down
1 change: 1 addition & 0 deletions vignettes/articles/benchmark.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ autoplot(res)
```{r}
#| label: bench2
#| eval: false
set.seed(10)
dsamp <- diamonds[sample(nrow(diamonds), 1000), ]
Expand Down

0 comments on commit da79c7f

Please sign in to comment.