 So yeah, today I want to talk about some recent work Rafe and I have been doing on doing 2D graphics and application, like GUI application development in Rust. This talk is going to be in about three and a half parts. First we're going to do kind of the standard Rust evangelism section, where I try and convince you all to try Rust or whatever you're next trying anything for. Then we're going to talk a little bit about the specific tools that have been built. And then Rafe is going to talk briefly about some exciting new rendering strategies he has. Hopefully we'll have time for a demo. I really like Rust. This is kind of like one of the many little short, punchy Rust promo bits. And I'm going to try and go through these piecewise. Fast, live, and productive. We'll start with fast. So I want to clarify quickly, we'll talk about fast. We're talking about run time fast. Rust generates fast code. It generates fast binaries. Oh yeah, so I'm doing this thing again where I'm looking at the next slide section, not the current slide section. And this is important in application development. It's important if you want to be avoiding UI lagginess. It's important because it frees you up. It gives you those resources to create better experiences and to do more with the user for the user. Rust is also fast in the sense that it gives you really direct C level access to hardware, to system level APIs. This is in contrast with something like Go Java, where you have kind of like mediating layers that are sort of trying to provide access to those services for you. And then Rust is also fast in kind of this slightly harder to explain way. But Rust makes a lot of things harder, but there are things you probably didn't want to do. So one of the examples of this, famously there's a sign at Mozilla in the Mozilla San Francisco office that says, it must be this hall to write multi-threaded code, and the sign is about nine feet up in the sky. And the reason the multi-threaded code is hard to write is that sharing state across threads safely is very hard to do, and it's just a common source of bugs. One of the things that Rust does is it makes it so that you don't have to basically jump through some hoops to guarantee to the compiler that when you are sharing state across threads, you're doing it in a way that is safe. Things are behind you, Texas. Things are like you're using a Tom, I don't think you would believe, but it allows you to then do aggressive multi-threaded things with these guarantees. And one of the most popular or one of the most famous current Rust projects is RepGrap, which is a grep replacement that's very, very fast. And most of its speed wins over grep or over other grep-like tools come from its ability to exploit the fact that modern hardware has lots of cores. And even some of it still has hyper-threading enabled. And then I want to talk about the reliability. The big part of the reliability, anything I'm going to focus on, anything that most people maybe know about Rust or are scared of about Rust, is this idea of ownership. And what this means is that in Rust, so Rust has no garbage collection, we talked about that earlier, but it also affords you like C-level performance, though you're having to write a bunch of like malloc and free stuff. You're not manually managing management. Manually managing memory. And the way that that happens is you have this idea of ownership where some piece of memory is owned by some function or some scope within a function. And when it goes out of scope, it's free. And so basically, there's a continuation of this, is that there's also enforced exclusivity. So I want to look through a bit of sample code. This is Rust code. This is an example of a bug I've written before in other languages where I have a readable collection. Here I've got a little vector. And I'm going to iterate through that vector. And then somewhere inside my iteration, I'm going to change the vector I'm trying to iterate through. And this will probably seg-fold in like C++ because you're going to out of bounds or you're going to have some access error. And if I try and compile this in Rust, I get this. Where the compiler can tell that I am trying to mutably access this thing that I have an outstanding reference to. It will just not let me run this program. And this is just a really conceptually powerful. It just saves you from whole classes of bugs. And in general, ownership, and here I'm kind of lumping in a bunch of other language features that Rust provides, like bounds checking and things, but ownership prevents large swabs of memory errors. There was an audit in Firefox of their last 100 odd critical CDEs, critical security vulnerabilities, and about 72 of them would have been impossible to write a Rust. The others, still possible, but 72 is good. Yeah, dangling pointers and use that for free, that stuff that ownership handles, there's also things like preventing buffer overflows, null pointer referencing, these are all things. You have to really go out of your way to write these bugs. You still can if you want to, but you have to try. And kind of the takeaway for this to me is that sort of by encoding a lot of this that like tiny stuff in the type system, you let the compiler keep track of things that otherwise the programmer would have to keep track of. So if anybody's worked on like big C or C++ projects, a lot of your mental state becomes, or a lot of your mental space is taken up with a state of keeping track of like who owns what memory. And the kind of the concept for us is that like, let's just tell the compiler who owns what memory and it can keep track of that for us and we can worry about like what our program is supposed to be doing. So this is really the more fun stuff. And the rest gives you this all this low level performancey things, but also gives you a lot of language features that feel like a much higher level language. I don't even feel is right, but it provides high level abstractions. And importantly it provides these abstractions that still produce this fast C-ish code. I'm going to go through a couple of these. A really big one is the trait system. Traits are like interfaces in Java or protocols in Swift. They describe some set of behavior. And here's a concrete example. Here is a shape trait. And so this is basically just an abstract electronic idea of shapeness. What is a shape path? Well it's got some area. It like encloses some area. It has a perimeter. It has a bounding box like the smallest rectangle that can enclose all of its points. It has up here at the top this sort of an implementationy thing but has this ability to be turned into a path so you can draw it. Now why don't we walk through kind of what that looked like concretely. A circle is a very simple shape. It has a center and it has a radius. And so if we implement the shape trait for circle this is all like real rust code. Spoiler, it's actually this is in production ish production ish. And here's like my grade school geometry. The line radius is pi r squared and perimeter is 2 pi r. And so what this gives us is a way to work with rust really powerful generic system. So we can write functions like this where this is a function fill that takes as an argument anything that implements this shape trait. And importantly like this isn't doing a dynamic dispatch or anything. It's doing a circle and we can call this fill method and it will just fill that circle because the circle knows its area and the circle can like hit test itself and tell you what pixels should be filled. We can also take also I should mention this canvas thing is just some arbitrary like drawing context it could be implemented for like WebGL or it could be implemented for GTK on like Backbyte or Vulkan that you're drawing to. So here we can like make a circle and we can pass it to this call or this function this method. We can make a rectangle pass it to that same method and so this is what it looks like to us writing it and it's important that or like the thing to note is that we're not having to write like fill, rect and fill circle and give them like these special quick implementations that take advantage of the particular properties of these particular shapes. And then this is kind of what the compiler does for us because it actually knows that these these shapes things actually have concrete implementations and it can go in a compile time generate code that is specific and is fast for each given shape and do all that for us. I think the the million dollar word is model morphization compile time model morphization and so we get this stuff that's kind of like in the fast code we'd have to write this by hand traditionally and SQL just templating is similar there's other things but this basically gives us the fast code generation without the like burdensome having to write it all by hand and then another abstraction Rust provides is an interesting example it's kind of like a graphic there's lots of these but I just want to touch on a couple it's iterator and so iterator is a trait that comes it's built in it's like part of the standard library and an iterator is kind of like a generator Python it's some entity that you can call repeatedly and it will produce values and so I was a little deceptive earlier when I showed you this little part of shape and the shape here and this thing I showed you it's returning up like a busy a path which you would assume is some object that has like some collection of elements or something and it's probably a keep allocated you can probably move it around actually this code really looks like this and this is like maybe a little hairy but it's not so bad what this says is that when you define shape for circle say you also have to say that you provide with it some thing that implements iterator and instead of returning a busy a path you return this iterator and so here for circle we can imagine there's some struct just like the circle path iterator and when you able shape for circle we say that that's the type of this thing and that's what we return we can do the same for wrapped and then so here I'm going to look at concretely because this is kind of the crux of those sort of abstractors that Rust provides and the way that it's a good choice if you're currently thinking of something like C++ is this iterator structure has a copy of our current one and a rect is just four sides and it has an index which is what step of iteration we're at and then when we actually go to use this all we're doing is we call this next function here repeatedly until it returns none those are it's returning like drawing instructions in the classic like post script sense and so all we do is we increment our internal counter and then for each sort of whatever our current step is we say either like it's the first step it's like oh move to our first point and then we just you know for four line segments call you to draw four lines and then when we're done we're done and really importantly this never allocates this is can compile compile down to like some kind of like branch like some nest that's like a big if else and like anytime you've used a GUI application and like you've been dragging something and your cursor is stuttered the reason it's done that probably is because you were like something was getting allocated under the covers there are other things other like reasons that could happen but that's a very very common one and so the ability to do things like this like zero allocations is actually really powerful if you're doing a low level graphics program and the fact that like the fact that I could fit this entire implementation of something that is kind of pretty easy on a slide in like 50 odd point type is like pretty it feels good to me it doesn't feel good to you talk later so yeah this is really the big takeaway is that things like iterator and the trait system let us write these high level feeling things that compile down to really fast low level C there's a last thing I want to add actually that list of three and this is like very subjective but I feel it's really important and it's that I kind of like started writing in Rust by accident about three years ago now maybe two and a half and it's just been really fun I've really enjoyed myself a large part of that is that the language itself that's like there's excellent tooling things are easy to build things are easy to write and run unit tests little things like that it's easy to like manage dependencies but also is really interesting in the way that the language kind of gets out of your way and lets you like work on work on like focusing on like designing your program and solving the problems that you're trying to solve and less on like wrestling with your tooling and another big big part of it is the community and Rust kind of importantly there's no like emperor figure everything is run through working groups all design decisions are go through like a RFC like a request for comments process language changes are largely consensus or like certainly consensus of within a working group and there's just like a real thoughtfulness and care that is has been taken towards building a community and it's really one of the the warmest open source spaces I've been around and I don't know it's absolutely a plus like a thing that I can't touch enough but it is really a part of the reason I enjoy language so I guess now we should actually talk more concretely about the stuff that's been working on now beat is a new so crate is a library in Rust language these are four libraries is a 2D graphics abstraction layer that is it provides the simple API where you have like a render context which is something that draws things and that can be implemented by various backings Kerbo provides descriptions and implementations for shapes and vectors and curves a lot of definitions earlier like that shape trait or part of Kerbo and sort of like it gets used by Pete Scribo is for like TextLayout and font resolution and like kind of low level WeedZ type stuff and then Druid is a 2D well no, Druid is a cross-platform GUI toolkit for like doing application development and realistically this graph actually in terms of dependencies it's more like this where is this thing being built and Pete is this like backing layer that provides the drawing abstractions and then these others who are kind of like provide like lower level like type definitions and implementations for things that you need if you're doing 2D graphics and importantly is all cross-platform and so Pete defines a general set of traits that are implemented for a given target platform currently these are the back ends for these three platforms like a Kerbo back end, Druid 2D for Windows and then a Web back end I think great contextual that I think it's using the canvas API and then Rafe has actually been recently working on something new that he'll talk about shortly which is metal and I couldn't help myself so maybe Rafe will talk with that for a few minutes absolutely thanks Paan so Pete Metal Pete Metal is an experimental GPU render it's really at this point it's really still a research prototype but I think it has some really interesting features that I'd like to talk about it's really about being fast that is the primary goal and I also wanted to kind of build it to be easier to fine tune especially like for quality of not taking shortcuts a lot of renders you have limited compute resource so you don't get things like gamma correction right and I think the other part of the Pete Metal design is to really move almost all of the processing off of the CPU and have all of the processing of the vector data and the rendering into pixels done by the GPU because there's so much more compute power available there and as a research question I was really trying to you know it's obvious that we have to move to the GPU to get performance as you get higher resolution screens and faster frame rates and is the traditional 2D API the kind of programming that we've been doing with PostScript and you know Cairo and Web Canvas is that still a valid programming model for building these user interfaces or should we be writing UI that builds triangle strips and writes shaders to generate those GUIs in a language that the GPU kind of understands more natively and I think that it's still early days with the prototype but I think I have satisfied myself that yes you can implement the traditional 2D graphics in-game model on the GPU and I'll just touch very lightly on how that's working and so part of the magic of heat metal is that it's doing all of its work in compute shaders traditional GPU techniques are based on rasterization and that's not how heat metal works and so there's a first compute shader it's a pipeline of two passes and the first one takes the vector image and splits it into tiles and then the second one takes those tiles and renders them into pixels and you start with some of you might recognize this image and so you're going to divide it you know typical typical 2D vector image and you're going to divide it into tiles and then for each one of those tiles that's going to have a number of elements in it and it's going to take those elements it's going to analyze that source image and it's going to create a command list so these are the operations that have to be done within that tile only so all of the other elements that are not in that tile you can reject while you're generating the command list for this tile and then in the second path of the pipeline you're going to execute that command list for each of those pixels in parallel which is something that GPUs can do really really well so as I say this is still a research prototype but the results so far are very promising like that Tiger on a high resolution display I'm rendering entirely on the GPU in about 2.7 milliseconds on this MacBook Pro hardware which I think is really encouraging like this is going to enable the hope is that this will enable very rich practical applications where you're not limited in the number of layers or the number of objects and you're still able to maintain a very fluid kind of 60 seconds interactivity you know this kind of feedback loop where the artist can be immediately seeing the results of the editing so we've talked about this infrastructure that we've been building and now I think it would be a good time to move to what are we building on top of that infrastructure and I think Colin can give it a little demo so yeah for the last little while Rick and I have been talking about a font editor and so about a week ago I started playing around I mean it took me a week before that to write something out of the car CFO files but about a week ago I started playing around with Druid to see how it would work and so here we have a very simple little toy we can like do terrible things we can do whatever we like we can't save, which is a blessing and yeah so this is going to be very much an exploration of prototyping and playing around but it's felt very good it makes me confident that certainly for things like a drawing tool that isn't using a lot of like system UI that this is definitely an approach that will produce results I want to show you one little thing which is I know there are a lot of non-graph designers here but this is how you make italics alright thank you very much