Skip to content

Notes for Contributors

grondag edited this page Jun 30, 2019 · 5 revisions

Contributions to Canvas are welcome!

Here are some things you should know about working with me:

1) You don't have to like my code but please avoid lecturing me about it.

I've been programming on and off for over 30 years, but I am relatively new to Java and to rendering. I tend to start with experiments and then refactor heavily. I also tend to adapt my style and approach to the situation or even to my mood that day. I am doing this for fun and motivation matters.

It's also important to remember that Canvas is a work in progress and changing rapidly. I tend to leave more "noise" in code that is still experimental or likely to be replaced.

2) I want contributors to have creative freedom.

The flip side of #1 is that I'm relatively flexible. If something bothers you and there is some practical benefit to changing it, there's a good chance I'll accept your PR and appreciate you for making Canvas better. For code you are contributing, I care mostly that it is clear, performant and functional. However, see Contribution Guidelines, below.

3) I value useful debate.

I will frequently stop and re-evaluate the problem space and alternative approaches, including some that may seem ridiculous or impractical at the outset. I appreciate contrary and radical points of view when they lead to better idea and outcomes. For me, this is never personal. I keep it respectful and avoid making personal attacks. I expect that will also. If you find it difficult to maintain that sort of detachment, then this may not be the project for you.

4) I am impatient to make things.

Debate is useful; shipping code is satisfying. I learn by doing, and a working, viable implementation beats a hypothetical solution. (Until that solution can be implemented!)

Point is: I tend to switch between Hmmm, what is best? and DO IT NOW! frequently and without notice. This isn't something I can change.

Contribution Guidelines

I don't have many rules, but here they are.

  1. By contributing, you grant perpetual and non-exclusive rights under the Apache 2.0 license agreement.

  2. All contributions must be your own or covered under the next rule.

  3. Many rendering problems have readily adaptable code available via a compatible license. If such code is not available in a library appropriate for inclusion, then excerpts or adaptations may be contributed with appropriate attribution and disclosures, per the source license.

  4. Smaller and more frequent PRs are generally preferable to big PRs that take a long time because the code base can change rapidly. "Dark launch" WIP commits will be considered for this reason - just don't break anything.

  5. If you know you'll be working on a big feature for an extended time, try to create isolation from the rest of the codebase via interfaces, possibly with some reorganization. Preliminary refactoring to prepare for such efforts is absolutely OK.

  6. Spaces not tabs - and that's one debate I'm not interesting in having. Code and build need to be compatible with both Eclipse and Idea.

  7. Use assert where units tests aren't viable (they usually aren't) and run your JVM in dev with the -ea parameter. This is mainly useful for catching race conditions and as a safety net when reasoning about complex state that is concurrently maintained.

Performance Recommendations

Performance is always a constraint in rendering code. The following practices are recommended:

Locality of Reference

Modern processors are so fast that memory bandwidth is almost the only thing that matters. Prevent cache misses and maximize register usage at almost any cost.

LOR is a big topic but in simplest terms this means using primitive types and arrays of primitive types with minimal indirection. FastUtil collections are usually a decent choice.

Move Non-rendering Work off the Client Thread

Because the main client thread owns the GL context, it is (mostly) the only thread that can do anything render related. For our purposes, it is the scarce resource.

Ideally we want the client thread to be preparing for draw calls and waiting for draw calls to complete, and nothing else.

Measure and Make it Configurable

Many optimizations vary in effectiveness with different hardware/software configurations. Measure performance via instrumentation and/or VisualVM and also provide a way to turn it off.

Avoid GL State Changes and Minimize Draw Calls

Also highly variable and situational. For an introduction to the concerns, see this stackexchange thread

Favor Static Invocation

Essentially a technique for avoiding indirection. Use minimal scoping (private when possible), final members, and concrete types or single-implementation interfaces. Calling static methods also works if the parameters re reasonable.

Favor Lock-Free Approaches to Concurrency

Another big topic and highly situational. Atomics can help but come with their own costs and limitations. Maintaining per-thread mutable data with immutable shared data is very good when workable.

Clone this wiki locally