Questions & Answers
These questions were asked by the audience during our tour.
Project
Licence
What is the LambdaCube 3D project licence?
The whole project is licensed under BSD3.
Community
Where can I bounce ideas and advice around?
Join to the lambdacube3d-discuss google group.
Project goals
What are your long-term goals with the project?
We plan to use LambdaCube 3D for application development.
What kind of applications would you like to develop with LambdaCube 3D?
It could be a mobile game or a data visualisation tool.
Is LambdaCube 3D only for graphics programming?
Currently yes, it is. General purpose GPU programming is planned.
Development plan
When will be the language stable?
We consider the following phases of completeness (ordered list):
- having a tutorial and documentation
- releases on HackageDB and Stackage
- pilot mobile application written with LambdaCube 3D
After completing these phases, we plan to write more and more applications and validate the language against real world use cases until LambdaCube 3D will be announced stable.
What’s the next big feature to add?
Planned features
- Various language extensions:
PatternSynonyms
,ScopedTypeVariables
, typed holes - Compute shaders
- Nested data parallelism
- FRP system
Will the compiler be independent?
The compiler is already in a separate GitHub repository. We intend to make the compiler as general purpose as possible, given the constraint that its main purpose is to compile a graphics DSL for CPU+GPU. This means for example that the type family reductions wired into the compiler will be moved into the libraries. Also we would like to experiment with a language extension which would specialise error messages for the problem domain and make this machinery independent from the actual problem domain.
Other
Who sponsors you?
Two of us work on the project full time, living on spared money. One of us work on the project in his spare time.
Are you looking for sponsors?
We would like to be independent.
Usage
Documentation
Where can I find the documentation for the language?
There is only a rough language specification at the moment. The documentation pages are exposed in the homepage: We plan to improve the documentation gradually and a tutorial planned also. Get back to the development history to see the progress.
Development with LambdaCube 3D
How is the time input treated in the demos?
The time
variable is a Float
-typed input value which is supposed to be updated by the user application. Input values are constants during the rendering of a frame.
Conceptually this means that we treat the screen frames as a set of individual images and there is no way to express connection between the images with the type system at the moment. We plan to add some kind of FRP system to LambdaCube 3D which will be reflected in the type of time
too.
Is it possible to see the generated shader code?
The generated shader code is part of the IR (Intermediate Representation) which is the output of the LambdaCube compiler. In the online editor IR is shown on a separate tab next to the canvas.
How do you support debugging?
Currently we use native debugging tools on different platforms. It is possible to add a debugger for the intermediate representation of LambdaCube 3D. It is also possible to add a debugger for the LambdaCube 3D language.
Language
Would it be possible to guarantee execution time limits with the type system?
Probably it is possible, it would be a nice area to explore later. Now we focus on simpler features.
What do you use type families for in the domain specific operations?
I expect usability errors with structural records plus type classes. Does they play well together?
We don’t have enough experience yet to answer this question. We plan to use structural records more and more in our Prelude and see the consequences.
Does LambdaCube support scene graph?
Related work
How does this language compare to Elm?
Elm focuses on FRP and web programming. LambdaCube 3D targets computer graphics on multiple platforms.
Elm has a different philosophy regarding language features: be newcomer friendly and avoid advanced type system constructs like type classes and GADTs. On the contrary, LambdaCube 3D aims to use these powerful constructs.
LambdaCube3D try to reuse syntax and type system constructs from Haskell. Elm explores new areas instead.
Why are you developing a separate DSL instead of a Haskell EDSL?
Csaba spent several years experimenting with EDSLs, as the previous versions of LambdaCube 3D were implemented as DSLs embedded in GHC Haskell. Based on this experience, we decided to make the next iteration of the language an independent DSL for several reasons:
Independence of Haskell
Our ultimate goal is to create a graphics pipeline language that can be easily integrated into any other system. Requiring potential users to install GHC (and the inevitable torrent of dependencies) or learn Haskell with the ecosystem of tools around GHC is an absolute showstopper for most people who are mainly interested in getting graphics work done.
Full control over the type system
We are not limited by Haskell’s type system, so we can create our own that matches the domain much better. With Haskell, we had to jump through elaborate hoops to be able to capture all the constraints we wanted to, and the error messages tended to be quite dreadful as a consequence (think C++ templates). We don’t want a compromise where we sacrifice either domain modelling accuracy or usability, and a separate language allows us to reach a much sweeter spot.
Full control over syntax
Syntax absolutely matters. Unfortunately, Haskell’s record syntax makes it rather unpleasant to use as a shading language, where we often need to deal with structs, vectors, and swizzling. Besides, we want to keep our options open with respect to syntax.
Better integration between the interactive system and the compiler
Since we roll our own parser and type checker, we are free to evolve the API that allows the editor to have a continuous conversation with the compiler based on the feature requirements. While it is possible to get some feedback from GHC for a better editing experience, the setup that makes this happen tends to be way too complicated for our purposes.
Compilation performance
We can get much better compilation performance, because we can inspect assignments and don’t have to do silly things like recover sharing. Speedy compilation absolutely matters to us (it’s really non-negotiable if we are to compete with existing graphics programming tools), and that’s just not going to happen with an EDSL compiled with GHC – not just because of GHC’s performance, but the inherent extra complexity in dealing with EDSLs.
Full control over the runtime system
The role of LambdaCube is to provide a thin layer over the GPU, therefore its runtime must be as lightweight as possible. Due to the real-time nature of graphics applications, we need to make sure that allocations are well-behaved, and ideally we should be able to get by entirely without garbage collection – or at least tell the user if using some feature leads to dynamic allocations. We also intend to provide easy to use profiling services eventually. Finally, the runtime system should be so small and simple that it’s trivial to port to any new platform.
Rapid iterative development
The LambdaCube compiler and runtime are implemented in a few thousand lines, all of which is written by us. Due to some of the features we need in the final product, we would need to work within the depths of GHC itself, or wait for GHC bugs to be fixed (this is an issue for us due to our heavy use of cutting edge language extensions).
To sum it up, in many ways going the Haskell EDSL way would either make the result suboptimal compared to our vision, or it would be at least an order of magnitude more work to achieve what we want. For instance, several of the above mentioned issues could be solved by improving GHC. However, that’s suddenly a lot bigger undertaking than working on our tiny isolated project, and it would also be a distraction from our own goals that would slow us down considerably. Besides, the option is always there to backport the DSL’s innovations to the EDSL implementation if there’s demand to do so.
Implementation
Compiler
Is the generated byte code Turing-complete?
It is probably not Turing-complete hence the system generates static pipeline structure at the moment. We haven’t proved it though.
If the pipeline has infinite loop, will the compiler stuck?
In the current system the yes. That will be fixed in a later version.
Does the compiler decide what to run on the CPU and on the GPU? How?
The language has builtin primitives to mimic the GPU functionality. The parameters of these builtin functions (e.g. vertex and fragment shader function) are executed in the GPU hardware.
Performance
Are the shaders generated for every frame?
No, shaders are generated compile time. This means that all shaders should be known at compile time, i.e. only static pipelines are supported. We plan to support dynamic pipelines (pipeline which depend on user input) later.
If you use LambdaCube from a JavaScript or C++ application, then the application has to load the pipeline through a LambdaCube backend. The backend allocates every necessary OpenGL resources for pipeline execution, then it can be used to render several frames.
Do you have performance comparisons against C++ and native OpenGL?
We know that performance is crucial for 3D graphics programming. Currently the focus is on language design, later it will shift to compiler optimizations with performance benchmarks.
Is it OK to deal with performance later?
Csaba has experience with doing computer graphics in C++. We keep performance in mind during making design decisions.
Is it possible to get good performance for a high-level language like LambdaCube 3D?
We believe that modern compilers should automate as much boring programming tasks as possible while keeping good performance. You can see LambdaCube 3D as an experiment achieving this goal.
Source code
What is the code-base size?
Figures as of 5th June, 2015
Component | Sources |
---|---|
Compiler | 4.6 kLOC Haskell |
Prelude modules | 0.7 kLOC LambdaCube 3D |
OpenGL 3.3 backend | 2.7 kLOC Haskell |
WebGL backend | 1.9 kLOC PureScript |
Why do you use PureScript instead of Elm?
- There are more libraries for PureScript than for Elm.
- PureScript has a better JavaScript FFI.
- It was easier to port our existing Haskell library to PureScript because its syntax stays closer to Haskell.
- PureScript has no runtime environment.
Why don’t you use GHCJS?
GHCJS can be used in the following cases:
- WebGL backend implementation (an interpreter for LambdaCube’s intermediate representation)
- running the compiler in the browser
We would like to keep the WebGL interpreter as lightweight as possible, the code generated by GHCJS is too big for this.
We tried GHCJS to run the compiler in the browser. It was running, but it was 13x slower than the native code. We will experiment with it later again.
Is any code reused from GHC?
In short, no. The compiler is written from scratch. As the benefit of this decision we can use the latest technology and theory advancements.
Which editor do you use in the browser?
It is Ace editor, an open-source editor written in JavaScript. PureScript has an Ace interface.