Vulkan Startup Code

I’ve been studying books, code examples, tutorials, and frankly anything I can get my hands on regarding Vulkan. What follows is a bit of what I’ve learned in the process.

The first thing I bumped into is that Vulkan uses different shaders than OpenGL does. Or perhaps more accurately, almost the same shaders, but with restrictions and rules all over, and in a different format. OpenGL uses GLSL (OpenGL Shader Language), a C-like text based language, for shaders. Vulkan uses a compiler that turns GLSL that follows special rules into SPIR-V (Standard Portable Intermediate Representation for Vulkan) which is a binary (byte code) based language. The trick here is learning to understand enough about GLSL and SPIR-V that you can figure out what all the compiler errors you get when trying to compile your shaders mean.

The next thing I figured out is that getting through all the start up code for Vulkan is borderline nightmarish. OpenGL magically hides a lot of things in the drivers. This includes everything from the GLSL compiler and linker to the hidden state that lets the whole thing work with relatively few methods. That means that the start up code for OpenGL is a relatively lean process that involves compiling a couple shaders with the driver and linking them together into a shader program and not too much else. In contrast, to get Vulkan up and running is about a zillion lines of code that involves at least a dozen different types of objects that have to be picked over and assembled together.

I’m working on crafting this Vulkan start up code into my graphics engine. At this point it has been a lot of work and research, which I admit has slowed down my posting here, but I swear I am plugging along and I suspect I have a long way to go still. Please try to bear with me.

Java Bump

Somewhere in my travels on the interwebs, I came to realize that OpenJDK version 10 was already at “end of life” because version 11 had come out and was deemed the LTS version (long term support). This meant that version 10, while obviously still functional, wasn’t a great choice. It also meant version 11 could be the version I settle down on for a long time to come (several years at least it sounds like). Related to this was the additional good news that there were no changes to the code required to keep the project compiling properly.

Then came the issue of the Java documentation. Since the last time I talked about Java, the “no longer free” thing Oracle was doing to the licence for Java has come to pass. This came with some baggage I wasn’t fully prepared for. I’d already dealt with switching to OpenJDK, I’d already made sure I had OpenJFX available, but I’d simply assumed that the online Java API documentation would still be available for download. This was a requirement due to my desire to be able to work on the project fully offline if I had to.

This is where it gets kind of weird. OpenJDK doesn’t include or produce the JavaDocs for the API. I didn’t think this would be a problem because they should still be available from Oracle and those should be close enough to accurate to cover any needs I was likely to have. I headed over to Oracle’s site, clicked the “I accept” radio button for the documentation license like I had a hundred times before, clicked the download link, and was taken to an Oracle single sign on page.

Ok, no problem, I can apparently just make an Oracle account. I don’t particularly want to do so, but at least I seem to have a path forward. I start filling in the form to create an account and realize that they are asking me required questions about my work phone number, company, and job title. At this point I have become suspicious that I’m not really supposed to be signing up for an account as a person, so I pull the rip cord and start trying to come up with another way to get the docs. This is pretty frustrating because they won’t let me download the documentation that they clearly provide on their live site for free.

It stands to reason, at least in my head, that I should be able to generate the JavaDocs for the API on my own if I can locate the source code for the JDK. As it turns out this is a very simple thing to do. It’s available as a separate download on the OpenJDK site (assuming you live in a country where downloading it is allowed). That meant I just needed to unzip it and try to figure out how to configure the javadoc tool to build the API docs I want.

Due to Java modules, this actually proved to be a bit more complex than I thought it would. I’m an old hand at Java and I like and use packages all the time, but modules never seemed to really offer much value to me so I never spent any time learning how they work. New information to me was that when they are in use (as they are for the OpenJDK project) they pretty considerably change the way JavaDocs are generated.

After quite a bit of reading the documentation for how to make JavaDocs on code with modules, I finally managed to come up with this:

> cd src      // the place I extracted the source code to
> ..\bin\javadoc -d ..\docs --module-source-path=. --module-path=. --module=java.base -html5

I ran it and in about a minute I had an epic pile of documentation sitting in my docs directory and I was officially ready to go. Hopefully this helps someone else too, or perhaps it will just help me again later, which is also great.

Graphics Engine

I’m writing my graphics engine, again. I was probably supposed to be writing tests for my on-going code audit, but they are boring and I don’t want to right now. (So there.) The alternative path I’m following is to start over with my graphics engine coding. This has resulted in a handful of changes.

First, the entire previous attempt at an OpenGL based graphics engine has been balled up and thrown into the temporary package com.qubekwest.graphics.old so I can use it for reference, but where it doesn’t get confusingly mixed in with the new stuff I’m writing. Second, I have switched entirely to Vulkan (from OpenGL) for my graphics library of choice. That decision comes with some serious baggage.

Vulkan offers a lot of cool things that make it better (in my opinion) than OpenGL. Some of these things make it faster and more powerful. Such as the all new way of telling the video card what to do from a multithreaded environment. This lets you use as many CPUs as your computer can throw at it without them getting in each other’s way. Another thing makes it vastly harder to learn. To give developers more control over how things work in Vulkan, they well, gave developers more control over how things work. To accomplish this, they make most of the things you want to do take way more steps than they used to. Finally, Vulkan comes with some fun things that make it require newer hardware (and/or newer drivers) than OpenGL. This one means Raspberry Pi is just not a valid development target anymore. At least not models 1B through 3B+, maybe the 4 will have Vulkan capable hardware.

I’m trying to build the concept of a graphics engine as cleanly as possible and in a way that would let me implement a second one in OpenGL in the future if I want. There are some decisions I’m trying to make as I go that I’m almost positive will be just flat wrong because I made them before I understood enough of what I was trying to do for real. Thus is the side effect of the learning curve I figure.

There are lots of semi-related things that go with this, such as the management of the main game loop and of accepting user input. Admittedly they are mostly only related because GLFW (Graphics Library Framework) includes stuff for creating windows, accepting input, and managing the game loop. I am likely to use all of those things, but I haven’t figured out if I’m going to call them all part of the “Graphics Engine” I’m building or treat them as separate entities glued together into a “Game Engine” or something. I guess we’ll see.

Code Audit (Round 2)

The code base has come a long way since my last code audit, and worse, I got lazy and never really finished the last one properly.  There are more sub-packages in the data package than there used to be, there are more classes in the math package, and in general just more.  Since the last time, Google Sheets finally added support for making text in a cell conveniently crooked, that’s helped too.  Now I get to track my progress in a spreadsheet instead of on hand labeled sheets of graph paper in my notebook.

This is actually a bit handy since I haven’t touched the code in nearly a year and I really need to relearn what I was doing in the code before I stopped.  I’m actually almost completely done with the code portion of the audit (added around 3500 lines of code) and I’ll be moving on to auditing the tests and coverage next.  I’m not going to lie, this process is tedious and boring, but I’m still feeling rather motivated to do it as I gear up for another big graphics push toward getting a cube on the screen.

Calendar Adjustments

As I ramp up my work on the project again, I am reading over and relearning a lot of code.  Today I got to the GameCalendar class and remembered that I had a bunch of changes I wanted to make before I’d stopped work on QubeKwest.  What I wasn’t sure of exactly, was what changes I wanted to make.  After a bit of consideration followed by a bunch of coding, here’s the things I’ve changed.

Tracking game ticks was a pointless complexity for the calendar system.  Thus it was removed and that of course means that the math ticks added into the calendar was removed too.  This makes several parts of the calendar easier to calculate and it also means that the internal workings of advancing the time for the calendar now only needs to happen roughly 1/53rd as often.  It’s not a lot of overhead, but I’ll take it.

Days were too short.  My brother and I have played a bit of Minecraft lately and been repeatedly frustrated by how short the days are.  While I’d already build days to be longer than they were in Minecraft, I decided I wanted to make them even longer, and a bit more asymmetrical in favor of daylight.  This table demonstrates what I’m talking about:

Part of Day   Minecraft   QK (Old)   QK (New)
-------------------------------------------------
Day            10 min     16 min     40 min      
Dusk          1.5 min      3 min      4 min
Night           7 min     10 min     12 min
Dawn          1.5 min      3 min      4 min
-------------------------------------------------
Total          20 min     32 min     60 min

This change adjusted how the game represents the current “wall clock time.”  In simple terms, the math is different for deciding what time of day it is.  The game will still represent the clock as a 24 hour clock of 60 minutes in each hour.  The length of a minute in the game has just increased.  (Now 2.5 seconds each.)

Seasons were too short.  Due to the length of months (16 days) it seemed incorrect to have seasons be only 2 months long.  Thus, I’ve changed to a 16 month calendar.  Now each of the 4 seasons is 4 months long.  I haven’t come up with names for any of the months, and I’m not even sure if I’m going to bother.

Moon phases still line up in the months the same way they did before.  This is because neither the length of a month nor the number of moon phases there are have been changed.  It doesn’t sound like a lot, but I was thankful for this break in the sweeping changes I was making.

Due to the collected changes, the timestamp format was adjusted to have a second digit for the day of the month. The resulting format is:

hh:mm YYYY-MM-DD

Calculating this was simplified by the removal of game ticks from the calendar, but it was an almost total rewrite for this method to accommodate that adjustment.  The best part is that the wall clock time and the timestamp are no longer only approximate values.  Since I now only track down to the minute level, the number of minutes involved is always exactly known.  No rounding errors any more.

Last but not least, the collection of constants used by the calendar were updated in both name and value to make using them a little cleaner.  It’s been a fun day that involved drawing in my notebook, coding, and correcting tests that I blew up with all these changes, but I’m also glad it’s all set now.