Merge remote-tracking branch 'origin/trunk' into editor-ir

This commit is contained in:
Folkert 2020-12-04 20:45:30 +01:00
commit 66748d3a50
250 changed files with 37730 additions and 10808 deletions

View file

@ -6,21 +6,27 @@
// long-term unclear which allocations *need* to happen for compilation's sake
// (e.g. recursive structures) versus those which were only added to appease clippy.
//
// Effectively optimizing data struture memory layout isn't a quick fix,
// Effectively optimizing data structure memory layout isn't a quick fix,
// and encouraging shortcuts here creates bad incentives. I would rather temporarily
// re-enable this when working on performance optimizations than have it block PRs.
#![allow(clippy::large_enum_variant)]
use crate::rect::Rect;
use crate::vertex::Vertex;
use std::error::Error;
use std::io;
use std::path::Path;
use wgpu::util::DeviceExt;
use wgpu_glyph::{ab_glyph, GlyphBrushBuilder, Section, Text};
use winit::event::{ElementState, ModifiersState, VirtualKeyCode};
use winit::event_loop::ControlFlow;
pub mod ast;
pub mod text_state;
pub mod bucket;
pub mod file;
mod rect;
pub mod text_state;
mod vertex;
/// The editor is actually launched from the CLI if you pass it zero arguments,
/// or if you provide it 1 or more files or directories to open on launch.
@ -42,34 +48,41 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
.build(&event_loop)
.unwrap();
let surface = wgpu::Surface::create(&window);
let instance = wgpu::Instance::new(wgpu::BackendBit::all());
let surface = unsafe { instance.create_surface(&window) };
// Initialize GPU
let (device, queue) = futures::executor::block_on(async {
let adapter = wgpu::Adapter::request(
&wgpu::RequestAdapterOptions {
let adapter = instance
.request_adapter(&wgpu::RequestAdapterOptions {
power_preference: wgpu::PowerPreference::HighPerformance,
compatible_surface: Some(&surface),
},
wgpu::BackendBit::all(),
)
.await
.expect("Request adapter");
adapter
.request_device(&wgpu::DeviceDescriptor {
extensions: wgpu::Extensions {
anisotropic_filtering: false,
},
limits: wgpu::Limits { max_bind_groups: 1 },
})
.await
.expect("Request adapter");
adapter
.request_device(
&wgpu::DeviceDescriptor {
features: wgpu::Features::empty(),
limits: wgpu::Limits::default(),
shader_validation: false,
},
None,
)
.await
.expect("Request device")
});
// Create staging belt and a local pool
let mut staging_belt = wgpu::util::StagingBelt::new(1024);
let mut local_pool = futures::executor::LocalPool::new();
let local_spawner = local_pool.spawner();
// Prepare swap chain
let render_format = wgpu::TextureFormat::Bgra8UnormSrgb;
let mut size = window.inner_size();
let mut swap_chain = device.create_swap_chain(
&surface,
&wgpu::SwapChainDescriptor {
@ -81,6 +94,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: &[Vertex::buffer_descriptor()],
},
sample_count: 1,
sample_mask: !0,
alpha_to_coverage_enabled: false,
});
// Prepare glyph_brush
let inconsolata =
ab_glyph::FontArc::try_from_slice(include_bytes!("../Inconsolata-Regular.ttf"))?;
@ -168,25 +218,80 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
});
// Get the next frame
let frame = swap_chain.get_next_texture().expect("Get next frame");
let frame = swap_chain
.get_current_frame()
.expect("Failed to acquire next swap chain texture")
.output;
// Test Rectangle
let test_rect_1 = Rect {
top: 0.9,
left: -0.8,
width: 0.2,
height: 0.3,
color: [0.0, 1.0, 1.0],
};
let test_rect_2 = Rect {
top: 0.0,
left: 0.0,
width: 0.5,
height: 0.5,
color: [1.0, 1.0, 0.0],
};
let mut rectangles = Vec::new();
rectangles.extend_from_slice(&test_rect_1.as_array());
rectangles.extend_from_slice(&test_rect_2.as_array());
let mut rect_index_buffers = Vec::new();
rect_index_buffers.extend_from_slice(&Rect::INDEX_BUFFER);
rect_index_buffers.extend_from_slice(&Rect::INDEX_BUFFER);
// Vertex Buffer for drawing rectangles
let vertex_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Vertex Buffer"),
contents: bytemuck::cast_slice(&rectangles),
usage: wgpu::BufferUsage::VERTEX,
});
// Index Buffer for drawing rectangles
let index_buffer = device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
label: Some("Index Buffer"),
contents: bytemuck::cast_slice(&rect_index_buffers),
usage: wgpu::BufferUsage::INDEX,
});
// Clear frame
{
let _ = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
let mut render_pass = encoder.begin_render_pass(&wgpu::RenderPassDescriptor {
color_attachments: &[wgpu::RenderPassColorAttachmentDescriptor {
attachment: &frame.view,
resolve_target: None,
load_op: wgpu::LoadOp::Clear,
store_op: wgpu::StoreOp::Store,
clear_color: wgpu::Color {
r: 0.007,
g: 0.007,
b: 0.007,
a: 1.0,
ops: wgpu::Operations {
load: wgpu::LoadOp::Clear(wgpu::Color {
r: 0.007,
g: 0.007,
b: 0.007,
a: 1.0,
}),
store: true,
},
}],
depth_stencil_attachment: None,
});
render_pass.set_pipeline(&triangle_pipeline);
render_pass.set_vertex_buffer(
0, // The buffer slot to use for this vertex buffer.
vertex_buffer.slice(..), // Use the entire buffer.
);
render_pass.set_index_buffer(index_buffer.slice(..));
render_pass.draw_indexed(
0..((&rect_index_buffers).len() as u32), // Draw all of the vertices from our test data.
0, // Base Vertex
0..1, // Instances
);
}
glyph_brush.queue(Section {
@ -209,10 +314,27 @@ fn run_event_loop() -> Result<(), Box<dyn Error>> {
// Draw the text!
glyph_brush
.draw_queued(&device, &mut encoder, &frame.view, size.width, size.height)
.draw_queued(
&device,
&mut staging_belt,
&mut encoder,
&frame.view,
size.width,
size.height,
)
.expect("Draw queued");
queue.submit(&[encoder.finish()]);
staging_belt.finish();
queue.submit(Some(encoder.finish()));
// Recall unused staging buffers
use futures::task::SpawnExt;
local_spawner
.spawn(staging_belt.recall())
.expect("Recall staging belt");
local_pool.run_until_stalled();
}
_ => {
*control_flow = winit::event_loop::ControlFlow::Wait;