Render a triangle underneath the text

This commit is contained in:
Bob Shelline 2020-10-30 18:48:10 -06:00
parent 289070ef0f
commit 4972e03405
8 changed files with 190 additions and 37 deletions

45
Cargo.lock generated
View file

@ -69,6 +69,12 @@ dependencies = [
"winapi 0.3.9", "winapi 0.3.9",
] ]
[[package]]
name = "anyhow"
version = "1.0.33"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1fd36ffbb1fb7c834eac128ea8d0e310c5aeb635548f9d58861e1308d46e71c"
[[package]] [[package]]
name = "approx" name = "approx"
version = "0.3.2" version = "0.3.2"
@ -329,6 +335,15 @@ dependencies = [
"bitflags", "bitflags",
] ]
[[package]]
name = "cmake"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0e56268c17a6248366d66d4a47a3381369d068cce8409bb1716ed77ea32163bb"
dependencies = [
"cc",
]
[[package]] [[package]]
name = "cocoa" name = "cocoa"
version = "0.20.2" version = "0.20.2"
@ -1016,6 +1031,12 @@ version = "0.22.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724" checksum = "aaf91faf136cb47367fa430cd46e37a788775e7fa104f8b4bcb3861dc389b724"
[[package]]
name = "glob"
version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574"
[[package]] [[package]]
name = "glyph_brush" name = "glyph_brush"
version = "0.7.0" version = "0.7.0"
@ -2374,9 +2395,12 @@ dependencies = [
name = "roc_editor" name = "roc_editor"
version = "0.1.0" version = "0.1.0"
dependencies = [ dependencies = [
"anyhow",
"bumpalo", "bumpalo",
"env_logger 0.7.1", "env_logger 0.7.1",
"fs_extra",
"futures", "futures",
"glob",
"glyph_brush", "glyph_brush",
"im", "im",
"im-rc", "im-rc",
@ -2404,6 +2428,7 @@ dependencies = [
"roc_types", "roc_types",
"roc_unify", "roc_unify",
"roc_uniq", "roc_uniq",
"shaderc",
"target-lexicon", "target-lexicon",
"tokio", "tokio",
"wgpu", "wgpu",
@ -2855,6 +2880,26 @@ dependencies = [
"opaque-debug", "opaque-debug",
] ]
[[package]]
name = "shaderc"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "50b8aeaae10b9bda5cba66736a7e265f67698e912e1cc6a4678acba286e22be9"
dependencies = [
"libc",
"shaderc-sys",
]
[[package]]
name = "shaderc-sys"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5b12d7c62d6732884c9dfab587503fa3a795b108df152415a89da23812d4737e"
dependencies = [
"cmake",
"libc",
]
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.2.1" version = "1.2.1"

View file

@ -63,3 +63,9 @@ maplit = "1.0.1"
indoc = "0.3.3" indoc = "0.3.3"
quickcheck = "0.8" quickcheck = "0.8"
quickcheck_macros = "0.8" quickcheck_macros = "0.8"
[build-dependencies]
anyhow = "1.0"
fs_extra = "1.1"
glob = "0.3"
shaderc = "0.6"

81
editor/build.rs Normal file
View file

@ -0,0 +1,81 @@
use anyhow::*;
use glob::glob;
use std::fs::{read_to_string, write};
use std::path::PathBuf;
// Build script for shaders used from:
// https://sotrh.github.io/learn-wgpu/beginner/tutorial3-pipeline/#compiling-shaders-and-include-spirv
struct ShaderData {
src: String,
src_path: PathBuf,
spv_path: PathBuf,
kind: shaderc::ShaderKind,
}
impl ShaderData {
pub fn load(src_path: PathBuf) -> Result<Self> {
let extension = src_path
.extension()
.context("File has no extension")?
.to_str()
.context("Extension cannot be converted to &str")?;
let kind = match extension {
"vert" => shaderc::ShaderKind::Vertex,
"frag" => shaderc::ShaderKind::Fragment,
"comp" => shaderc::ShaderKind::Compute,
_ => bail!("Unsupported shader: {}", src_path.display()),
};
let src = read_to_string(src_path.clone())?;
let spv_path = src_path.with_extension(format!("{}.spv", extension));
Ok(Self {
src,
src_path,
spv_path,
kind,
})
}
}
fn main() -> Result<()> {
// Collect all shaders recursively within /src/
let mut shader_paths = [
glob("./src/**/*.vert")?,
glob("./src/**/*.frag")?,
glob("./src/**/*.comp")?,
];
// This could be parallelized
let shaders = shader_paths
.iter_mut()
.flatten()
.map(|glob_result| ShaderData::load(glob_result?))
.collect::<Vec<Result<_>>>()
.into_iter()
.collect::<Result<Vec<_>>>()?;
let mut compiler = shaderc::Compiler::new().context("Unable to create shader compiler")?;
// This can't be parallelized. The [shaderc::Compiler] is not
// thread safe. Also, it creates a lot of resources. You could
// spawn multiple processes to handle this, but it would probably
// be better just to only compile shaders that have been changed
// recently.
for shader in shaders {
// This tells cargo to rerun this script if something in /src/ changes.
println!("cargo:rerun-if-changed={:?}", shader.src_path);
let compiled = compiler.compile_into_spirv(
&shader.src,
shader.kind,
&shader.src_path.to_str().unwrap(),
"main",
None,
)?;
write(shader.spv_path, compiled.as_binary_u8())?;
}
Ok(())
}

View file

@ -1,10 +0,0 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(location = 0) in vec4 vertex_color;
layout(location = 0) out vec4 fragment_color;
void main() {
fragment_color = vertex_color;
}

View file

@ -1,25 +0,0 @@
#version 450
#extension GL_ARB_separate_shader_objects : enable
layout(push_constant) uniform PushConstants {
vec4 color;
vec2 pos;
vec2 scale;
} push_constants;
layout(location = 0) out vec4 vertex_color;
void main() {
vec2 position;
if (gl_VertexIndex == 0) {
position = vec2(0.0, -0.5);
} else if (gl_VertexIndex == 1) {
position = vec2(-0.5, 0.5);
} else if (gl_VertexIndex == 2) {
position = vec2(0.5, 0.5);
}
vec2 pos = position * push_constants.scale;
vertex_color = push_constants.color;
gl_Position = vec4((pos + push_constants.pos), 0.0, 1.0);
}

View file

@ -76,7 +76,6 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
// Prepare swap chain // Prepare swap chain
let render_format = wgpu::TextureFormat::Bgra8UnormSrgb; let render_format = wgpu::TextureFormat::Bgra8UnormSrgb;
let mut size = window.inner_size(); let mut size = window.inner_size();
let mut swap_chain = device.create_swap_chain( let mut swap_chain = device.create_swap_chain(
&surface, &surface,
&wgpu::SwapChainDescriptor { &wgpu::SwapChainDescriptor {
@ -88,6 +87,43 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
}, },
); );
// Prepare Triangle Pipeline
let triangle_vs_module =
device.create_shader_module(wgpu::include_spirv!("shaders/rect.vert.spv"));
let triangle_fs_module =
device.create_shader_module(wgpu::include_spirv!("shaders/rect.frag.spv"));
let triangle_pipeline_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: None,
bind_group_layouts: &[],
push_constant_ranges: &[],
});
let triangle_pipeline = device.create_render_pipeline(&wgpu::RenderPipelineDescriptor {
label: None,
layout: Some(&triangle_pipeline_layout),
vertex_stage: wgpu::ProgrammableStageDescriptor {
module: &triangle_vs_module,
entry_point: "main",
},
fragment_stage: Some(wgpu::ProgrammableStageDescriptor {
module: &triangle_fs_module,
entry_point: "main",
}),
// Use the default rasterizer state: no culling, no depth bias
rasterization_state: None,
primitive_topology: wgpu::PrimitiveTopology::TriangleList,
color_states: &[wgpu::TextureFormat::Bgra8UnormSrgb.into()],
depth_stencil_state: None,
vertex_state: wgpu::VertexStateDescriptor {
index_format: wgpu::IndexFormat::Uint16,
vertex_buffers: &[],
},
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
});
// Prepare glyph_brush // Prepare glyph_brush
let inconsolata = let inconsolata =
ab_glyph::FontArc::try_from_slice(include_bytes!("../Inconsolata-Regular.ttf"))?; ab_glyph::FontArc::try_from_slice(include_bytes!("../Inconsolata-Regular.ttf"))?;
@ -182,7 +218,7 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
// Clear frame // Clear frame
{ {
let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor { let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor { color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view, attachment: &frame.view,
resolve_target: None, resolve_target: None,
@ -198,6 +234,9 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
}], }],
depth_stencil_attachment: None, depth_stencil_attachment: None,
}); });
render_pass.set_pipeline(&triangle_pipeline);
render_pass.draw(0..3, 0..1);
} }
glyph_brush.queue(Section { glyph_brush.queue(Section {

View file

@ -0,0 +1,7 @@
#version 450
layout(location = 0) out vec4 outColor;
void main() {
outColor = vec4(1.0, 0.0, 0.0, 1.0);
}

View file

@ -0,0 +1,10 @@
#version 450
out gl_PerVertex {
vec4 gl_Position;
};
void main() {
vec2 position = vec2(gl_VertexIndex, (gl_VertexIndex & 1) * 2) - 1;
gl_Position = vec4(position, 0.0, 1.0);
}