diff --git a/compiler/build/src/lib.rs b/compiler/build/src/lib.rs index 896bcc6c21..e2abf50874 100644 --- a/compiler/build/src/lib.rs +++ b/compiler/build/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod link; pub mod program; diff --git a/compiler/builtins/src/lib.rs b/compiler/builtins/src/lib.rs index 63a936ce39..ba07aa6f8c 100644 --- a/compiler/builtins/src/lib.rs +++ b/compiler/builtins/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod bitcode; pub mod std; diff --git a/compiler/can/src/def.rs b/compiler/can/src/def.rs index 95864ad67d..e58cb21df1 100644 --- a/compiler/can/src/def.rs +++ b/compiler/can/src/def.rs @@ -83,6 +83,7 @@ enum PendingDef<'a> { InvalidAlias, } +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #[derive(Clone, Debug, PartialEq)] #[allow(clippy::large_enum_variant)] pub enum Declaration { diff --git a/compiler/can/src/lib.rs b/compiler/can/src/lib.rs index 44c7bf3faa..158426477e 100644 --- a/compiler/can/src/lib.rs +++ b/compiler/can/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod annotation; pub mod builtins; diff --git a/compiler/collections/src/lib.rs b/compiler/collections/src/lib.rs index 79c906ee0c..5f54b3f3a1 100644 --- a/compiler/collections/src/lib.rs +++ b/compiler/collections/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod all; diff --git a/compiler/constrain/src/lib.rs b/compiler/constrain/src/lib.rs index d75e00643f..0e30c75a9c 100644 --- a/compiler/constrain/src/lib.rs +++ b/compiler/constrain/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod builtins; pub mod expr; diff --git a/compiler/fmt/src/lib.rs b/compiler/fmt/src/lib.rs index c03633bddf..db3530b0aa 100644 --- a/compiler/fmt/src/lib.rs +++ b/compiler/fmt/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod annotation; pub mod def; diff --git a/compiler/gen/src/lib.rs b/compiler/gen/src/lib.rs index c86b32f6a5..79649fe3fd 100644 --- a/compiler/gen/src/lib.rs +++ b/compiler/gen/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod llvm; diff --git a/compiler/gen/src/llvm/build.rs b/compiler/gen/src/llvm/build.rs index 00be57ef61..b2826ce354 100644 --- a/compiler/gen/src/llvm/build.rs +++ b/compiler/gen/src/llvm/build.rs @@ -3064,7 +3064,14 @@ fn run_low_level<'a, 'ctx, 'env>( let wrapper_struct = wrapper_struct.into_struct_value(); let elem_index = load_symbol(env, scope, &args[1]).into_int_value(); - list_get_unsafe(env, list_layout, elem_index, wrapper_struct) + list_get_unsafe( + env, + layout_ids, + parent, + list_layout, + elem_index, + wrapper_struct, + ) } ListSetInPlace => { let (list_symbol, list_layout) = load_symbol_and_layout(env, scope, &args[0]); diff --git a/compiler/gen/src/llvm/build_list.rs b/compiler/gen/src/llvm/build_list.rs index 6b7b3e99e1..1e27bd3d93 100644 --- a/compiler/gen/src/llvm/build_list.rs +++ b/compiler/gen/src/llvm/build_list.rs @@ -553,6 +553,8 @@ pub fn list_reverse<'a, 'ctx, 'env>( pub fn list_get_unsafe<'a, 'ctx, 'env>( env: &Env<'a, 'ctx, 'env>, + layout_ids: &mut LayoutIds<'a>, + parent: FunctionValue<'ctx>, list_layout: &Layout<'a>, elem_index: IntValue<'ctx>, wrapper_struct: StructValue<'ctx>, @@ -572,7 +574,11 @@ pub fn list_get_unsafe<'a, 'ctx, 'env>( let elem_ptr = unsafe { builder.build_in_bounds_gep(array_data_ptr, &[elem_index], "elem") }; - builder.build_load(elem_ptr, "List.get") + let result = builder.build_load(elem_ptr, "List.get"); + + increment_refcount_layout(env, parent, layout_ids, result, elem_layout); + + result } _ => { unreachable!( diff --git a/compiler/gen_dev/src/lib.rs b/compiler/gen_dev/src/lib.rs index d91bb8f59a..3417941a82 100644 --- a/compiler/gen_dev/src/lib.rs +++ b/compiler/gen_dev/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] use bumpalo::{collections::Vec, Bump}; diff --git a/compiler/load/src/lib.rs b/compiler/load/src/lib.rs index 52a7a2b7f8..977b57afef 100644 --- a/compiler/load/src/lib.rs +++ b/compiler/load/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod docs; pub mod effect_module; diff --git a/compiler/module/src/lib.rs b/compiler/module/src/lib.rs index 4c837c4275..50d5d356a4 100644 --- a/compiler/module/src/lib.rs +++ b/compiler/module/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod ident; diff --git a/compiler/mono/src/lib.rs b/compiler/mono/src/lib.rs index e44b3d7fae..188e856c93 100644 --- a/compiler/mono/src/lib.rs +++ b/compiler/mono/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod borrow; diff --git a/compiler/parse/src/lib.rs b/compiler/parse/src/lib.rs index 858070e101..adb36adf78 100644 --- a/compiler/parse/src/lib.rs +++ b/compiler/parse/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] #[macro_use] diff --git a/compiler/problem/src/lib.rs b/compiler/problem/src/lib.rs index 11610b6314..333c9990a8 100644 --- a/compiler/problem/src/lib.rs +++ b/compiler/problem/src/lib.rs @@ -1,13 +1,4 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod can; diff --git a/compiler/region/src/lib.rs b/compiler/region/src/lib.rs index 79c906ee0c..5f54b3f3a1 100644 --- a/compiler/region/src/lib.rs +++ b/compiler/region/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod all; diff --git a/compiler/reporting/src/lib.rs b/compiler/reporting/src/lib.rs index 12ef1d2a39..c8550d9966 100644 --- a/compiler/reporting/src/lib.rs +++ b/compiler/reporting/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod error; diff --git a/compiler/solve/src/lib.rs b/compiler/solve/src/lib.rs index 9718a929a9..3d093e2c1e 100644 --- a/compiler/solve/src/lib.rs +++ b/compiler/solve/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod module; diff --git a/compiler/types/src/lib.rs b/compiler/types/src/lib.rs index b98f1f9944..0ec67509c7 100644 --- a/compiler/types/src/lib.rs +++ b/compiler/types/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod boolean_algebra; pub mod builtin_aliases; diff --git a/compiler/unify/src/lib.rs b/compiler/unify/src/lib.rs index 2bb083f4bc..39437895b0 100644 --- a/compiler/unify/src/lib.rs +++ b/compiler/unify/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub mod unify; diff --git a/compiler/uniq/src/lib.rs b/compiler/uniq/src/lib.rs index 4838333e89..cb790d59e6 100644 --- a/compiler/uniq/src/lib.rs +++ b/compiler/uniq/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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, -// and encouraging shortcuts here creates bad incentives. I would rather temporarily -// re-enable this when working on performance optimizations than have it block PRs. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] pub use roc_can::expr::Expr::*; diff --git a/editor/src/lib.rs b/editor/src/lib.rs index c60a547fe0..7cfa033dc8 100644 --- a/editor/src/lib.rs +++ b/editor/src/lib.rs @@ -1,14 +1,5 @@ #![warn(clippy::all, clippy::dbg_macro)] -// I'm skeptical that clippy:large_enum_variant is a good lint to have globally enabled. -// -// It warns about a performance problem where the only quick remediation is -// to allocate more on the heap, which has lots of tradeoffs - including making it -// 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 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. +// See github.com/rtfeldman/roc/issues/800 for discussion of the large_enum_variant check. #![allow(clippy::large_enum_variant)] // Inspired by: @@ -20,12 +11,10 @@ use crate::buffer::create_rect_buffers; use crate::text::{build_glyph_brush, Text}; use crate::vertex::Vertex; -use cgmath::Ortho; +use ortho::{init_ortho, update_ortho_buffer, OrthoResources}; use std::error::Error; use std::io; use std::path::Path; -use wgpu::util::DeviceExt; -use wgpu::{BindGroup, BindGroupLayoutDescriptor, BindGroupLayoutEntry, Buffer, ShaderStage}; use winit::event; use winit::event::{Event, ModifiersState}; use winit::event_loop::ControlFlow; @@ -35,6 +24,7 @@ mod buffer; pub mod expr; pub mod file; mod keyboard_input; +mod ortho; pub mod pool; mod rect; pub mod text; @@ -51,31 +41,6 @@ pub fn launch(_filepaths: &[&Path]) -> io::Result<()> { Ok(()) } -#[repr(C)] -#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] -struct Uniforms { - // We can't use cgmath with bytemuck directly so we'll have - // to convert the Matrix4 into a 4x4 f32 array - ortho: [[f32; 4]; 4], -} - -impl Uniforms { - fn new(w: u32, h: u32) -> Self { - let ortho: cgmath::Matrix4 = Ortho:: { - left: 0.0, - right: w as f32, - bottom: h as f32, - top: 0.0, - near: -1.0, - far: 1.0, - } - .into(); - Self { - ortho: ortho.into(), - } - } -} - fn run_event_loop() -> Result<(), Box> { env_logger::init(); @@ -133,8 +98,7 @@ fn run_event_loop() -> Result<(), Box> { let mut swap_chain = gpu_device.create_swap_chain(&surface, &swap_chain_descr); - let (rect_pipeline, ortho_bind_group, ortho_buffer) = - make_rect_pipeline(&gpu_device, &swap_chain_descr); + let (rect_pipeline, ortho) = make_rect_pipeline(&gpu_device, &swap_chain_descr); let mut glyph_brush = build_glyph_brush(&gpu_device, render_format)?; @@ -179,33 +143,13 @@ fn run_event_loop() -> Result<(), Box> { }, ); - // update orthographic buffer according to new window size - let new_uniforms = Uniforms::new(size.width, size.height); - - let new_ortho_buffer = - gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Ortho uniform buffer"), - contents: bytemuck::cast_slice(&[new_uniforms]), - usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC, - }); - - // get a command encoder for the current frame - let mut encoder = - gpu_device.create_command_encoder(&wgpu::CommandEncoderDescriptor { - label: Some("Resize"), - }); - - // overwrite the new buffer over the old one - encoder.copy_buffer_to_buffer( - &new_ortho_buffer, - 0, - &ortho_buffer, - 0, - (std::mem::size_of::() * vec![new_uniforms].as_slice().len()) - as wgpu::BufferAddress, + update_ortho_buffer( + size.width, + size.height, + &gpu_device, + &ortho.buffer, + &cmd_queue, ); - - cmd_queue.submit(Some(encoder.finish())); } //Received Character Event::WindowEvent { @@ -260,7 +204,7 @@ fn run_event_loop() -> Result<(), Box> { if rect_buffers.num_rects > 0 { render_pass.set_pipeline(&rect_pipeline); - render_pass.set_bind_group(0, &ortho_bind_group, &[]); + render_pass.set_bind_group(0, &ortho.bind_group, &[]); render_pass.set_vertex_buffer(0, rect_buffers.vertex_buffer.slice(..)); render_pass.set_index_buffer(rect_buffers.index_buffer.slice(..)); render_pass.draw_indexed(0..rect_buffers.num_rects, 0, 0..1); @@ -300,41 +244,11 @@ fn run_event_loop() -> Result<(), Box> { fn make_rect_pipeline( gpu_device: &wgpu::Device, swap_chain_descr: &wgpu::SwapChainDescriptor, -) -> (wgpu::RenderPipeline, BindGroup, Buffer) { - let uniforms = Uniforms::new(swap_chain_descr.width, swap_chain_descr.height); - - // orthographic projection is used to transfrom pixel coords to the coordinate system used by wgpu - let ortho_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { - label: Some("Ortho uniform buffer"), - contents: bytemuck::cast_slice(&[uniforms]), - usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, - }); - - // bind groups consist of extra resources that are provided to the shaders - let ortho_bind_group_layout = gpu_device.create_bind_group_layout(&BindGroupLayoutDescriptor { - entries: &[BindGroupLayoutEntry { - binding: 0, - visibility: ShaderStage::VERTEX, - ty: wgpu::BindingType::UniformBuffer { - dynamic: false, - min_binding_size: None, - }, - count: None, - }], - label: Some("Ortho bind group layout"), - }); - - let ortho_bind_group = gpu_device.create_bind_group(&wgpu::BindGroupDescriptor { - layout: &ortho_bind_group_layout, - entries: &[wgpu::BindGroupEntry { - binding: 0, - resource: wgpu::BindingResource::Buffer(ortho_buffer.slice(..)), - }], - label: Some("Ortho bind group"), - }); +) -> (wgpu::RenderPipeline, OrthoResources) { + let ortho = init_ortho(swap_chain_descr.width, swap_chain_descr.height, gpu_device); let pipeline_layout = gpu_device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor { - bind_group_layouts: &[&ortho_bind_group_layout], + bind_group_layouts: &[&ortho.bind_group_layout], push_constant_ranges: &[], label: Some("Rectangle pipeline layout"), }); @@ -347,7 +261,7 @@ fn make_rect_pipeline( wgpu::include_spirv!("shaders/rect.frag.spv"), ); - (pipeline, ortho_bind_group, ortho_buffer) + (pipeline, ortho) } fn create_render_pipeline( diff --git a/editor/src/ortho.rs b/editor/src/ortho.rs new file mode 100644 index 0000000000..8acbe2a66e --- /dev/null +++ b/editor/src/ortho.rs @@ -0,0 +1,116 @@ +use cgmath::{Matrix4, Ortho}; +use wgpu::util::DeviceExt; +use wgpu::{ + BindGroup, BindGroupLayout, BindGroupLayoutDescriptor, BindGroupLayoutEntry, Buffer, + ShaderStage, +}; + +// orthographic projection is used to transfrom pixel coords to the coordinate system used by wgpu + +#[repr(C)] +#[derive(Debug, Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)] +struct Uniforms { + // We can't use cgmath with bytemuck directly so we'll have + // to convert the Matrix4 into a 4x4 f32 array + ortho: [[f32; 4]; 4], +} + +impl Uniforms { + fn new(w: u32, h: u32) -> Self { + let ortho: Matrix4 = Ortho:: { + left: 0.0, + right: w as f32, + bottom: h as f32, + top: 0.0, + near: -1.0, + far: 1.0, + } + .into(); + Self { + ortho: ortho.into(), + } + } +} + +// update orthographic buffer according to new window size +pub fn update_ortho_buffer( + inner_width: u32, + inner_height: u32, + gpu_device: &wgpu::Device, + ortho_buffer: &Buffer, + cmd_queue: &wgpu::Queue, +) { + let new_uniforms = Uniforms::new(inner_width, inner_height); + + let new_ortho_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Ortho uniform buffer"), + contents: bytemuck::cast_slice(&[new_uniforms]), + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_SRC, + }); + + // get a command encoder for the current frame + let mut encoder = gpu_device.create_command_encoder(&wgpu::CommandEncoderDescriptor { + label: Some("Resize"), + }); + + // overwrite the new buffer over the old one + encoder.copy_buffer_to_buffer( + &new_ortho_buffer, + 0, + ortho_buffer, + 0, + (std::mem::size_of::() * vec![new_uniforms].as_slice().len()) + as wgpu::BufferAddress, + ); + + cmd_queue.submit(Some(encoder.finish())); +} + +pub struct OrthoResources { + pub buffer: Buffer, + pub bind_group_layout: BindGroupLayout, + pub bind_group: BindGroup, +} + +pub fn init_ortho( + inner_width: u32, + inner_height: u32, + gpu_device: &wgpu::Device, +) -> OrthoResources { + let uniforms = Uniforms::new(inner_width, inner_height); + + let ortho_buffer = gpu_device.create_buffer_init(&wgpu::util::BufferInitDescriptor { + label: Some("Ortho uniform buffer"), + contents: bytemuck::cast_slice(&[uniforms]), + usage: wgpu::BufferUsage::UNIFORM | wgpu::BufferUsage::COPY_DST, + }); + + // bind groups consist of extra resources that are provided to the shaders + let ortho_bind_group_layout = gpu_device.create_bind_group_layout(&BindGroupLayoutDescriptor { + entries: &[BindGroupLayoutEntry { + binding: 0, + visibility: ShaderStage::VERTEX, + ty: wgpu::BindingType::UniformBuffer { + dynamic: false, + min_binding_size: None, + }, + count: None, + }], + label: Some("Ortho bind group layout"), + }); + + let ortho_bind_group = gpu_device.create_bind_group(&wgpu::BindGroupDescriptor { + layout: &ortho_bind_group_layout, + entries: &[wgpu::BindGroupEntry { + binding: 0, + resource: wgpu::BindingResource::Buffer(ortho_buffer.slice(..)), + }], + label: Some("Ortho bind group"), + }); + + OrthoResources { + buffer: ortho_buffer, + bind_group_layout: ortho_bind_group_layout, + bind_group: ortho_bind_group, + } +} diff --git a/examples/effect/thing/platform-dir/src/lib.rs b/examples/effect/thing/platform-dir/src/lib.rs index 905bf7113e..0f753acdb4 100644 --- a/examples/effect/thing/platform-dir/src/lib.rs +++ b/examples/effect/thing/platform-dir/src/lib.rs @@ -14,10 +14,18 @@ extern "C" { fn roc_main_size() -> i64; #[link_name = "roc__mainForHost_1_Fx_caller"] - fn call_Fx(function_pointer: *const u8, closure_data: *const u8, output: *mut u8) -> (); + fn call_Fx( + flags: &(), + function_pointer: *const u8, + closure_data: *const u8, + output: *mut u8, + ) -> (); #[link_name = "roc__mainForHost_1_Fx_size"] fn size_Fx() -> i64; + + #[link_name = "roc__mainForHost_1_Fx_result_size"] + fn size_Fx_result() -> i64; } #[no_mangle] @@ -48,13 +56,14 @@ pub fn roc_fx_getLine() -> RocStr { } unsafe fn call_the_closure(function_pointer: *const u8, closure_data_ptr: *const u8) -> i64 { - let size = size_Fx() as usize; + let size = size_Fx_result() as usize; alloca::with_stack_bytes(size, |buffer| { let buffer: *mut std::ffi::c_void = buffer; let buffer: *mut u8 = buffer as *mut u8; call_Fx( + &(), function_pointer, closure_data_ptr as *const u8, buffer as *mut u8, diff --git a/examples/task/platform/host.zig b/examples/task/platform/host.zig index c817591515..b622f90096 100644 --- a/examples/task/platform/host.zig +++ b/examples/task/platform/host.zig @@ -10,8 +10,11 @@ const Allocator = mem.Allocator; extern fn roc__mainForHost_1_exposed([*]u8) void; extern fn roc__mainForHost_1_size() i64; -extern fn roc__mainForHost_1_Fx_caller(*const u8, [*]u8, [*]u8) void; +extern fn roc__mainForHost_1_Fx_caller(*const u8, *const u8, [*]u8, [*]u8) void; extern fn roc__mainForHost_1_Fx_size() i64; +extern fn roc__mainForHost_1_Fx_result_size() i64; + +const Unit = extern struct {}; pub export fn main() u8 { const stdout = std.io.getStdOut().writer(); @@ -44,7 +47,7 @@ pub export fn main() u8 { } fn call_the_closure(function_pointer: *const u8, closure_data_pointer: [*]u8) void { - const size = roc__mainForHost_1_Fx_size(); + const size = roc__mainForHost_1_Fx_result_size(); const raw_output = std.heap.c_allocator.alloc(u8, @intCast(usize, size)) catch unreachable; var output = @ptrCast([*]u8, raw_output); @@ -52,7 +55,9 @@ fn call_the_closure(function_pointer: *const u8, closure_data_pointer: [*]u8) vo std.heap.c_allocator.free(raw_output); } - roc__mainForHost_1_Fx_caller(function_pointer, closure_data_pointer, output); + const flags: u8 = 0; + + roc__mainForHost_1_Fx_caller(&flags, function_pointer, closure_data_pointer, output); const elements = @ptrCast([*]u64, @alignCast(8, output)); diff --git a/examples/tea/platform/Pkg-Config.roc b/examples/tea/platform/Pkg-Config.roc index 719b1ac581..cbf8205cb7 100644 --- a/examples/tea/platform/Pkg-Config.roc +++ b/examples/tea/platform/Pkg-Config.roc @@ -13,7 +13,7 @@ platform folkertdev/foo mainForHost : { - init : ({} -> { model: I64, cmd : (Cmd.Cmd [ Line Str ]) as Fx }) as Init, + init : ({} -> { model: I64 as Model, cmd : (Cmd.Cmd [ Line Str ]) as Fx }) as Init, update : ([ Line Str ], I64 -> { model: I64, cmd : Cmd.Cmd [ Line Str ] } ) as Update } mainForHost = main diff --git a/examples/tea/platform/src/lib.rs b/examples/tea/platform/src/lib.rs index 11409beea2..3ed8a6c4e1 100644 --- a/examples/tea/platform/src/lib.rs +++ b/examples/tea/platform/src/lib.rs @@ -6,8 +6,7 @@ use roc_std::RocStr; use std::alloc::Layout; use std::time::SystemTime; -type Msg = RocStr; -type Model = i64; +type Model = *const u8; extern "C" { #[link_name = "roc__mainForHost_1_exposed"] @@ -32,8 +31,8 @@ extern "C" { #[link_name = "roc__mainForHost_1_Update_caller"] fn call_Update( - msg: &Msg, - model: &Model, + msg: Msg, + model: Model, function_pointer: *const u8, closure_data: *const u8, output: *mut u8, @@ -84,9 +83,7 @@ pub fn roc_fx_putChar(foo: i64) -> () { #[no_mangle] pub fn roc_fx_putLine(line: RocStr) -> () { - let bytes = line.as_slice(); - let string = unsafe { std::str::from_utf8_unchecked(bytes) }; - println!("{}", string); + println!("{}", unsafe { line.as_str() }); () } @@ -104,115 +101,139 @@ pub fn roc_fx_getLine() -> RocStr { unsafe fn run_fx(function_pointer: *const u8, closure_data_ptr: *const u8) -> Msg { let size = size_Fx_result() as usize; - alloca::with_stack_bytes(size, |buffer| { - let buffer: *mut std::ffi::c_void = buffer; - let buffer: *mut u8 = buffer as *mut u8; + let layout = Layout::array::(size).unwrap(); + let buffer = std::alloc::alloc(layout); - call_Fx( - function_pointer, - closure_data_ptr as *const u8, - buffer as *mut u8, - ); + call_Fx( + function_pointer, + closure_data_ptr as *const u8, + buffer as *mut u8, + ); - let output = &*(buffer as *mut RocCallResult<()>); + let output = &*(buffer as *mut RocCallResult<()>); - match output.into() { - Ok(()) => { - let mut bytes = *(buffer.add(8) as *const (u64, u64)); - let msg = std::mem::transmute::<(u64, u64), RocStr>(bytes); + match output.into() { + Ok(()) => Msg { msg: buffer.add(8) }, - msg - } - - Err(e) => panic!("failed with {}", e), - } - }) + Err(e) => panic!("failed with {}", e), + } } -unsafe fn run_init(function_pointer: *const u8, closure_data_ptr: *const u8) -> (Model, Msg) { +struct Msg { + msg: *mut u8, +} + +impl Msg { + unsafe fn alloc(size: usize) -> Self { + let size = size_Fx_result() as usize; + let layout = Layout::array::(size).unwrap(); + let msg = std::alloc::alloc(layout); + + Self { msg } + } +} + +impl Drop for Msg { + fn drop(&mut self) { + unsafe { + let size = size_Fx_result() as usize; + let layout = Layout::array::(size).unwrap(); + std::alloc::dealloc(self.msg.offset(-8), layout); + } + } +} + +struct ModelCmd { + buffer: *mut u8, + cmd_fn_ptr_ptr: *const u8, + cmd_closure_data_ptr: *const u8, + model: *const u8, +} + +impl ModelCmd { + unsafe fn alloc() -> Self { + let size = 8 + size_Fx() as usize + size_Model() as usize; + + let layout = Layout::array::(size).unwrap(); + let buffer = std::alloc::alloc(layout); + + let cmd_fn_ptr_ptr = buffer.add(8); + let cmd_closure_data_ptr = buffer.add(8 + 8); + let model = buffer.add(8 + size_Fx() as usize); + + Self { + buffer, + cmd_fn_ptr_ptr, + cmd_closure_data_ptr, + model, + } + } +} + +impl Drop for ModelCmd { + fn drop(&mut self) { + unsafe { + let size = 8 + size_Fx() as usize + size_Model() as usize; + let layout = Layout::array::(size).unwrap(); + std::alloc::dealloc(self.buffer, layout); + } + } +} + +unsafe fn run_init( + function_pointer: *const u8, + closure_data_ptr: *const u8, +) -> Result { + debug_assert_eq!(size_Init_result(), 8 + size_Fx() + size_Model()); let size = size_Init_result() as usize; - alloca::with_stack_bytes(size, |buffer| { - let buffer: *mut std::ffi::c_void = buffer; - let buffer: *mut u8 = buffer as *mut u8; + let model_cmd = ModelCmd::alloc(); + let buffer = model_cmd.buffer; - call_Init(function_pointer, 0 as *const u8, buffer as *mut u8); + call_Init(function_pointer, 0 as *const u8, buffer as *mut u8); - // cmd < model, so the command comes first - let output = &*(buffer as *mut RocCallResult<()>); + // cmd < model, so the command comes first + let output = &*(buffer as *mut RocCallResult<()>); - match output.into() { - Ok(_) => { - let offset = 8 + size_Fx(); - let model_ptr = buffer.add(offset as usize); - let model: i64 = *(model_ptr as *const i64); - - let cmd_fn_ptr_ptr = buffer.add(8) as *const i64; - let cmd_fn_ptr = (*cmd_fn_ptr_ptr) as *const u8; - let cmd_closure_data_ptr = buffer.add(16); - - let msg = run_fx(cmd_fn_ptr, cmd_closure_data_ptr); - - (model, msg) - } - - Err(e) => panic!("failed with {}", e), - } - }) + match output.into() { + Ok(_) => Ok(model_cmd), + Err(e) => Err(e.to_string()), + } } unsafe fn run_update( - msg: RocStr, + msg: Msg, model: Model, function_pointer: *const u8, closure_data_ptr: *const u8, -) -> (Model, Msg) { +) -> Result { + debug_assert_eq!(size_Update_result(), 8 + size_Fx() + size_Model()); let size = size_Update_result() as usize; - alloca::with_stack_bytes(size, |buffer| { - let buffer: *mut std::ffi::c_void = buffer; - let buffer: *mut u8 = buffer as *mut u8; + let model_cmd = ModelCmd::alloc(); + let buffer = model_cmd.buffer; - println!("let's try update!"); + call_Update( + msg, + model, + function_pointer, + closure_data_ptr, + buffer as *mut u8, + ); - call_Update( - &msg, - &model, - function_pointer, - closure_data_ptr, - buffer as *mut u8, - ); + // cmd < model, so the command comes first + let output = &*(buffer as *mut RocCallResult<()>); - // cmd < model, so the command comes first - let output = &*(buffer as *mut RocCallResult<()>); - - match output.into() { - Ok(_) => { - let offset = 8 + size_Fx(); - let model_ptr = buffer.add(offset as usize); - let model: i64 = *(model_ptr as *const i64); - - let cmd_fn_ptr_ptr = buffer.add(8) as *const i64; - let cmd_fn_ptr = (*cmd_fn_ptr_ptr) as *const u8; - let cmd_closure_data_ptr = buffer.add(16); - - let msg = run_fx(cmd_fn_ptr, cmd_closure_data_ptr); - - (model, msg) - } - - Err(e) => panic!("failed with {}", e), - } - }) + match output.into() { + Ok(_) => Ok(model_cmd), + Err(e) => Err(e.to_string()), + } } -#[no_mangle] -pub fn rust_main() -> isize { - let start_time = SystemTime::now(); - +fn run_roc() -> Result<(), String> { let size = unsafe { roc_main_size() } as usize; let layout = Layout::array::(size).unwrap(); - let answer = unsafe { + unsafe { let buffer = std::alloc::alloc(layout); roc_main(buffer); @@ -221,101 +242,62 @@ pub fn rust_main() -> isize { match output.into() { Ok((init_fn_ptr, update_fn_ptr)) => { - // let closure_data_ptr = buffer.offset(16); + //let closure_data_ptr = buffer.offset(16); let closure_data_ptr = 0 as *const u8; - let (mut model, mut msg) = - run_init(init_fn_ptr as *const u8, closure_data_ptr as *const u8); + let model_cmd = + &mut run_init(init_fn_ptr as *const u8, closure_data_ptr as *const u8).unwrap(); for _ in 0..5 { - let result = run_update( + let model = model_cmd.model; + let cmd_fn_ptr = *(model_cmd.cmd_fn_ptr_ptr as *const usize) as *const u8; + let msg = run_fx(cmd_fn_ptr, model_cmd.cmd_closure_data_ptr); + + let mut result = run_update( msg, model, update_fn_ptr as *const u8, closure_data_ptr as *const u8, - ); + ) + .unwrap(); - model = result.0; - msg = result.1; + std::mem::swap(model_cmd, &mut result); + + // implictly drops `result` and `msg` } std::alloc::dealloc(buffer, layout); - - model + Ok(()) } Err(msg) => { std::alloc::dealloc(buffer, layout); - panic!("Roc failed with message: {}", msg); + Err(msg.to_string()) } } - }; - let end_time = SystemTime::now(); - let duration = end_time.duration_since(start_time).unwrap(); - - println!( - "Roc closure took {:.4} ms to compute this answer: {:?}", - duration.as_secs_f64() * 1000.0, - // truncate the answer, so stdout is not swamped - answer - ); - - // Exit code - 0 + } } -/* #[no_mangle] -pub fn old_rust_main() -> isize { - println!("Running Roc closure"); +pub fn rust_main() -> isize { let start_time = SystemTime::now(); - let size = unsafe { roc_main_size() } as usize; - let layout = Layout::array::(size).unwrap(); - let answer = unsafe { - let buffer = std::alloc::alloc(layout); - - roc_main(buffer); - - let output = &*(buffer as *mut RocCallResult<()>); - - match output.into() { - Ok(()) => { - let function_pointer = { - // this is a pointer to the location where the function pointer is stored - // we pass just the function pointer - let temp = buffer.offset(8) as *const i64; - - (*temp) as *const u8 - }; - - let closure_data_ptr = buffer.offset(16); - - let result = - call_the_closure(function_pointer as *const u8, closure_data_ptr as *const u8); - - std::alloc::dealloc(buffer, layout); - - result - } - Err(msg) => { - std::alloc::dealloc(buffer, layout); - - panic!("Roc failed with message: {}", msg); - } - } - }; let end_time = SystemTime::now(); let duration = end_time.duration_since(start_time).unwrap(); - println!( - "Roc closure took {:.4} ms to compute this answer: {:?}", - duration.as_secs_f64() * 1000.0, - // truncate the answer, so stdout is not swamped - answer - ); + match run_roc() { + Ok(answer) => { + println!( + "Roc closure took {:.4} ms to compute this answer: {:?}", + duration.as_secs_f64() * 1000.0, + answer + ); + } + Err(e) => { + eprintln!("Roc failed with message {:?}", e); + } + } // Exit code 0 } -*/ diff --git a/roc_std/src/lib.rs b/roc_std/src/lib.rs index 50f9fcbd86..e01ee0ce44 100644 --- a/roc_std/src/lib.rs +++ b/roc_std/src/lib.rs @@ -390,6 +390,12 @@ impl RocStr { unsafe { core::slice::from_raw_parts(self.elements, self.length) } } } + #[allow(clippy::missing_safety_doc)] + pub unsafe fn as_str(&self) -> &str { + let slice = self.as_slice(); + + core::str::from_utf8_unchecked(slice) + } } impl From<&str> for RocStr {