checkpoint

This commit is contained in:
Blaž Hrastnik 2022-04-14 17:46:10 +09:00
parent 8dc9ad7997
commit fa4dfba043
No known key found for this signature in database
GPG Key ID: 1238B9C4AD889640
5 changed files with 292 additions and 28 deletions

109
Cargo.lock generated
View File

@ -52,6 +52,12 @@ version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c5d78ce20460b82d3fa150275ed9d55e21064fc7951177baacf86a145c4a4b1f"
[[package]]
name = "arrayvec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b"
[[package]]
name = "arrayvec"
version = "0.7.2"
@ -136,9 +142,23 @@ checksum = "72feb31ffc86498dacdbd0fcebb56138e7177a8cc5cea4516031d15ae85a742e"
[[package]]
name = "bytemuck"
version = "1.8.0"
version = "1.9.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e851ca7c24871e7336801608a4797d7376545b6928a10d32d75685687141ead"
checksum = "cdead85bdec19c194affaeeb670c0e41fe23de31459efd1c174d049269cf02cc"
dependencies = [
"bytemuck_derive",
]
[[package]]
name = "bytemuck_derive"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "562e382481975bc61d11275ac5e62a19abd00b0547d99516a415336f183dcd0e"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "byteorder"
@ -595,6 +615,15 @@ dependencies = [
"thiserror",
]
[[package]]
name = "euclid"
version = "0.22.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b52c2ef4a78da0ba68fbe1fd920627411096d2ac478f7f4c9f3a54ba6705bade"
dependencies = [
"num-traits",
]
[[package]]
name = "fern"
version = "0.6.1"
@ -604,6 +633,15 @@ dependencies = [
"log",
]
[[package]]
name = "float_next_after"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4fc612c5837986b7104a87a0df74a5460931f1c5274be12f8d0f40aa2f30d632"
dependencies = [
"num-traits",
]
[[package]]
name = "fnv"
version = "1.0.7"
@ -1033,6 +1071,7 @@ dependencies = [
name = "helix-ui"
version = "0.1.0"
dependencies = [
"bytemuck",
"console_error_panic_hook",
"env_logger",
"glam",
@ -1040,6 +1079,7 @@ dependencies = [
"helix-view",
"image",
"instant",
"lyon",
"pollster",
"resource",
"swash",
@ -1296,6 +1336,56 @@ dependencies = [
"url",
]
[[package]]
name = "lyon"
version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf0510ed5e3e2fb80f3db2061ef5ca92d87bfda1a624bb1eacf3bd50226e4cbb"
dependencies = [
"lyon_algorithms",
"lyon_tessellation",
]
[[package]]
name = "lyon_algorithms"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8037f716541ba0d84d3de05c0069f8068baf73990d55980558b84d944c8a244a"
dependencies = [
"lyon_path",
"sid",
]
[[package]]
name = "lyon_geom"
version = "0.17.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ce99ce77c22bfd8f39a95b9c749dffbfc3e2491ea30c874764c801a8b1485489"
dependencies = [
"arrayvec 0.5.2",
"euclid",
"num-traits",
]
[[package]]
name = "lyon_path"
version = "0.17.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b0a59fdf767ca0d887aa61d1b48d4bbf6a124c1a45503593f7d38ab945bfbc0"
dependencies = [
"lyon_geom",
]
[[package]]
name = "lyon_tessellation"
version = "0.17.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7230e08dd0638048e46f387f255dbe7a7344a3e6705beab53242b5af25635760"
dependencies = [
"float_next_after",
"lyon_path",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
@ -1935,6 +2025,15 @@ dependencies = [
"libc",
]
[[package]]
name = "sid"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bd5ac56c121948b4879bba9e519852c211bcdd8f014efff766441deff0b91bdb"
dependencies = [
"num-traits",
]
[[package]]
name = "signal-hook"
version = "0.3.13"
@ -2476,7 +2575,7 @@ version = "0.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b97cd781ff044d6d697b632a2e212032c2e957d1afaa21dbf58069cbb8f78567"
dependencies = [
"arrayvec",
"arrayvec 0.7.2",
"js-sys",
"log",
"naga",
@ -2497,7 +2596,7 @@ version = "0.12.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c4688c000eb841ca55f7b35db659b78d6e1cd77d7caf8fb929f4e181f754047d"
dependencies = [
"arrayvec",
"arrayvec 0.7.2",
"bitflags",
"cfg_aliases",
"codespan-reporting",
@ -2520,7 +2619,7 @@ version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93b1a9400e8d7f32dd4dd909bb9a391015d70633d639775ddd3f14d1104bc970"
dependencies = [
"arrayvec",
"arrayvec 0.7.2",
"ash",
"bit-set",
"bitflags",

View File

@ -13,7 +13,8 @@ members = [
]
default-members = [
"helix-term"
"helix-term",
"helix-ui"
]
resolver = "2"

View File

@ -20,9 +20,10 @@ instant = "0.1.12"
swash = { git = "https://github.com/dfrg/swash" }
# parley = { git = "https://github.com/dfrg/parley" }
# lyon = "0.17.10"
lyon = "0.17.10"
wgpu = "0.12"
pollster = "0.2"
glam = "0.20"
env_logger = "0.6"
bytemuck = { version = "1.9.1", features = ["derive"] }

View File

@ -5,6 +5,8 @@
window::Window,
};
use wgpu::util::DeviceExt;
// new femto-like framework:
// wgpu renderer
// kurbo, (alternative is euclid + lyon)
@ -25,6 +27,28 @@
Attributes, CacheKey, Charmap, FontRef,
};
use lyon::{
math::{point, Transform},
path::{builder::*, Path},
tessellation::{BuffersBuilder, FillOptions, FillTessellator, FillVertex, VertexBuffers},
};
use bytemuck::{Pod, Zeroable};
// Vertex for lines drawn by lyon
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
struct Vertex {
position: [f32; 2],
// color: [f32; 4], // Use this when I want more colors
}
#[repr(C)]
#[derive(Clone, Copy, Debug, Pod, Zeroable)]
struct View {
size: [f32; 2],
}
pub struct Font {
// Full content of the font file
data: Vec<u8>,
@ -71,7 +95,8 @@ pub fn as_ref(&self) -> FontRef {
}
}
}
fn font() {
fn font() -> VertexBuffers<Vertex, u16> {
let font = Font::from_file("assets/fonts/Inter Variable/Inter.ttf", 0).unwrap();
let font = font.as_ref();
@ -114,6 +139,8 @@ fn font() {
// c.glyphs
});
// -- Scaling
let mut context = ScaleContext::new();
let mut scaler = context
.builder(font)
@ -124,33 +151,79 @@ fn font() {
let glyph_id = font.charmap().map('Q');
let outline = scaler.scale_outline(glyph_id).unwrap();
append_outline((), outline.verbs(), outline.points());
// -- Tesselation
// -- Scaling
// let mut encoder = Path::builder().transformed(Transform::new(
// 0.01, 0., //
// 0., 0.01, //
// 0., 0.,
// ));
let mut encoder = Path::builder();
append_outline(&mut encoder, outline.verbs(), outline.points());
let path = encoder.build();
let mut geometry: VertexBuffers<Vertex, u16> = VertexBuffers::new();
let mut tessellator = FillTessellator::new();
{
// Compute the tessellation.
tessellator
.tessellate_path(
&path,
&FillOptions::default(),
&mut BuffersBuilder::new(&mut geometry, |vertex: FillVertex| Vertex {
position: vertex.position().to_array(),
}),
)
.unwrap();
}
println!("{:?}", geometry);
geometry
}
fn append_outline(_encoder: (), verbs: &[Verb], points: &[Vector]) {
fn append_outline<T: lyon::path::builder::PathBuilder>(
encoder: &mut T,
verbs: &[Verb],
points: &[Vector],
) {
let mut i = 0;
for verb in verbs {
println!("{:?}", verb);
match verb {
Verb::MoveTo => {
//
let p = points[i];
// TODO: can MoveTo appear halfway through?
encoder.begin(point(p.x, p.y));
i += 1;
}
Verb::LineTo => {
//
let p = points[i];
encoder.line_to(point(p.x, p.y));
i += 1;
}
Verb::QuadTo => {
//
let p1 = points[i];
let p2 = points[i + 1];
encoder.quadratic_bezier_to(point(p1.x, p1.y), point(p2.x, p2.y));
i += 2;
}
Verb::CurveTo => {
//
let p1 = points[i];
let p2 = points[i + 1];
let p3 = points[i + 2];
encoder.cubic_bezier_to(point(p1.x, p1.y), point(p2.x, p2.y), point(p3.x, p3.y));
i += 3;
}
Verb::Close => {
//
encoder.close();
}
}
}
}
async fn run(event_loop: EventLoop<()>, window: Window) {
let size = window.inner_size();
let instance = wgpu::Instance::new(wgpu::Backends::all());
@ -186,10 +259,62 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
source: wgpu::ShaderSource::Wgsl(Cow::Borrowed(include_str!("shader.wgsl"))),
});
// ---
let geometry = font();
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(&geometry.vertices),
usage: wgpu::BufferUsages::VERTEX,
});
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(&geometry.indices),
usage: wgpu::BufferUsages::INDEX,
});
//
let data = View { size: [0.0, 0.0] };
let uniform_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Uniform Buffer"),
contents: bytemuck::cast_slice(&[data]),
usage: wgpu::BufferUsages::UNIFORM | wgpu::BufferUsages::COPY_DST,
});
let uniform_bind_group_layout =
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
entries: &[wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Uniform,
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
}],
label: Some("uniform_bind_group_layout"),
});
let uniform_bind_group = device.create_bind_group(&wgpu::BindGroupDescriptor {
layout: &uniform_bind_group_layout,
entries: &[wgpu::BindGroupEntry {
binding: 0,
resource: uniform_buffer.as_entire_binding(),
}],
label: Some("uniform_bind_group"),
});
//
let pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
bind_group_layouts: &[&uniform_bind_group_layout], // &texture_bind_group_layout
push_constant_ranges: &[], // TODO: could use push constants for uniforms but that's not available on web
});
let swapchain_format = surface.get_preferred_format(&adapter).unwrap();
@ -200,7 +325,11 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
vertex: wgpu::VertexState {
module: &shader,
entry_point: "vs_main",
buffers: &[],
buffers: &[wgpu::VertexBufferLayout {
array_stride: std::mem::size_of::<Vertex>() as wgpu::BufferAddress,
step_mode: wgpu::VertexStepMode::Vertex,
attributes: &wgpu::vertex_attr_array![0 => Float32x2],
}],
},
fragment: Some(wgpu::FragmentState {
module: &shader,
@ -223,7 +352,7 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
surface.configure(&device, &config);
font();
//
event_loop.run(move |event, _, control_flow| {
// Have the closure take ownership of the resources.
@ -253,6 +382,20 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
.create_view(&wgpu::TextureViewDescriptor::default());
let mut encoder =
device.create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
// TODO: need to use queue.write_buffer or staging_belt to write to it
// Pass the current window size in
let dpi_factor = window.scale_factor();
let size = window.inner_size();
let winit::dpi::LogicalSize { width, height } = size.to_logical::<f32>(dpi_factor);
let data = View {
size: [width, height],
};
queue.write_buffer(&uniform_buffer, 0, bytemuck::cast_slice(&[data]));
{
let mut rpass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
label: None,
@ -260,14 +403,20 @@ async fn run(event_loop: EventLoop<()>, window: Window) {
view: &view,
resolve_target: None,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color::GREEN),
load: wgpu::LoadOp::Clear(wgpu::Color::BLACK),
store: true,
},
}],
depth_stencil_attachment: None,
});
// rpass.set_viewport();
rpass.set_pipeline(&render_pipeline);
rpass.draw(0..3, 0..1);
rpass.set_bind_group(0, &uniform_bind_group, &[]);
rpass.set_index_buffer(index_buffer.slice(..), wgpu::IndexFormat::Uint16);
rpass.set_vertex_buffer(0, vertex_buffer.slice(..));
rpass.draw_indexed(0..(geometry.indices.len() as u32), 0, 0..1);
}
queue.submit(Some(encoder.finish()));

View File

@ -1,11 +1,25 @@
// struct Vertex {
// [[location(0)]] position: vec2<f32>;
// };
struct View {
size: vec2<f32>;
};
[[group(0), binding(0)]]
var<uniform> view: View;
[[stage(vertex)]]
fn vs_main([[builtin(vertex_index)]] in_vertex_index: u32) -> [[builtin(position)]] vec4<f32> {
let x = f32(i32(in_vertex_index) - 1);
let y = f32(i32(in_vertex_index & 1u) * 2 - 1);
return vec4<f32>(x, y, 0.0, 1.0);
fn vs_main([[location(0)]] input: vec2<f32>) -> [[builtin(position)]] vec4<f32> {
// TODO: scale by hidpi factor?
return vec4<f32>(
input.xy / view.size.xy * 2.0 * 1.5,
0.0, 1.0
);
}
[[stage(fragment)]]
fn fs_main() -> [[location(0)]] vec4<f32> {
return vec4<f32>(1.0, 0.0, 0.0, 1.0);
return vec4<f32>(1.0, 1.0, 1.0, 1.0);
}