Tuesday, May 5, 2026

Month 1 - Blog 2 - Gateware Development

 The past two weeks have been hectic to say the least. Being filled with development and preparing for my presentation, my nerves were definitely on the line. Since my ongoing task was to create samples for the new GSamples repository, I added some more tasks for samples expanding on the following Gateware modules:
- GMatrix
- GVector
- GQuaternion
- GDaemon
- GThreadShared
- GConcurrent


So far most of theses samples have been merged into the main GSamples repository which is very exciting. They didn't come with the fun hiccups of learning more about CMake, like with GAudio and GBufferedInput, but did offer more learning into how threading and concurrency work. 

Developing GDaemon's sample created an interesting point about the documentation provided in the Gateware Doxygen resource. My assumption was to make a daemon, then add event responders to the daemon. This ended up not being the intended functionality and needed to be swapped out for something more focused on GDaemon itself. Swapping to demonstrate the Fibonacci Sequence using a daemon seemed more suitable, so one daemon was used to run iterations of the sequence while another toggled the sequence daemon on and off. Both of these daemons had event responders to print out the status of the daemons, while also running at specific intervals.


The rest of the samples went smoothly, with little to no issues arising. This helped the fact that I had to work on my GNodeFactory Proposal Presentation. This was a requirement of the CSMS degree in which I had to get the project approved by the Committee members. The past week I worked with Lari to present my materials to the Gateware Maintainers, which was insightful. They provided a ton of feedback which I tried to incorporate as best I could into the upcoming presentation. After the meeting with Lari and the maintainers, I had my meeting with the Committee. They really liked the project and were interested in a ton of the unit testing and research ideology. Overall I think the past two weeks have been really fun, not only for my confidence, but for learning more with modern systems.

Thursday, April 23, 2026

Month 1 - Blog 1 - Gateware Development

So being onboarded into Gateware was fun to say the least. My tasks for onboarding into Gateware were simple at first, recursively clone the repositories and verify they build. Since I have a dual-boot machine I can test Linux (Ubuntu) and Windows implementations fairly quickly. Mac on the other hand wanted to cause a bit of trouble by not being updateable. After eventually getting the required software installed and validated everything was cloned properly, I started working on the GSamples. 

GSamples is a new repository that aims to help developers who are unfamiliar with how Gateware operates into showing how to utilize the library. There were some samples already provided such as the GVulkanSurface and GOpenGLSurface which helped give me a jumpstart into what was expected. The first sample I was to work on was for the audio interfaces GSound and GMusic. As I started to make the samples, I found that isPlaying wasn't implemented into the main API which was what I used to identify if the sample should stop or continue playing. Since the Audio Interfaces needed a running application to continue playing the sound, this created a bit of a snag. Though thankfully Alex Cusaac mentioned opting to use sleep_for and yield instead. 

So safe to say I was out of the clear for the time being. Turns out testing all available platforms is really important. The audio I happened to use for the sample had a formatting issue which exposed an underlying offset bit read in the GMusic implementation. With that fix pushed, I was able to continue validating the GMusic and GSound samples. These samples helped me understand how the Gateware Developers use a Continuous Integration / Continuous Development (CI/CD) Pipeline to always test and push updated releases.

While I wasn't familiar with CI/CD I have grown to like this format of development. The next couple of samples I worked on were GInput and GBuffered Input. Since I wanted to print out the ASCII equivalent of the key pressed, CI/CD allowed me to pull the latest version of Gateware and implement that fix. 

My future work with Gateware will be to inevitably incorporate the GNodeFactory module. This module will help manage large 3D Transformation Hierarchies like scene graphs. For now I am researching into how I can parallelize and optimize operations in the factory before implementing them. To accomplish this task, I was requested to look into GConcurrent, GThreadShared, and GDaemon. These modules in Gateware are also on the coding chopping block for samples to create. Additionally GVector, GMatrix, GQuaternion are also going to be implemented over the next two weeks. 

Wednesday, February 18, 2026

Month 2 - Part 1

Over the past week I was working on a Vulkan validation error that was caused by some weird environment setup on my machine. The error was complaining about not knowing what a specific struct type was when chaining features on in our CreateVkDevice() method in this section of the code:


What was happening was the requested API got set to 1.3 but 1.4 was defined so when it would hit the #if defined(VK_API_VERSION_1_4) it would try to chain on the 1.4 feature struct but was using the 1.3 validation layers which were too old to recognize this newer struct.

Validation layers in Vulkan are meant as a debug tool to tell you when your pipeline/set up is off and helps debug issues early before they become a problem in release. Despite the message, everything got set up correctly and I couldn't reproduce the issue reliably so Lari and I decided that it would be best to move on as it was probably a user error in how I set up the project and my environment variables.

I then moved on to an issue reported to us by Justin Edwards:
VUID-VkDeviceCreateInfo-pNext-02830(ERROR / SPEC): msgNum: 555635515 - Validation Error: [ VUID-VkDeviceCreateInfo-pNext-02830 ] Object 0: handle = 0x25a8407cc70, type = VK_OBJECT_TYPE_INSTANCE; | MessageID = 0x211e533b | vkCreateDevice(): If the pNext chain includes a VkPhysicalDeviceVulkan12Features structure, then it must not include a VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES structure

Which is complaining about 12 including the VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_DESCRIPTOR_INDEXING_FEATURES structure which comes from this part in our code:


Where before we didn't have the:

#if defined(VK_API_VERSION_1_2)

features12.descriptorIndexing = VK_TRUE;

#else


but with the new if define we're basically saying if we're on 1.2 or higher then we don't want to add that flag which ended up fixing the issue.

To ensure this fix was working we asked Justin for his exact setup and I created a test case mimicking this which looks like:


Which also accounts for the other versions of Vulkan. This test reproduced his errors without the fix and didn't produce them with it which proved our fix was working. He then downloaded the new Gateware version and tested it, confirming that it cleared that error but still produced this:

I'll be looking into what's causing this validation error along with tackling these tasks:

Which should provide some good learning opportunities for me.

Sunday, February 8, 2026

Month 1 - Part 2

Over the past couple of weeks I've been working on a Vulkan issue that could happen if the user had Vulkan tooling installed that was on a lower version of the API than their drivers claimed they could support. I figured this out when I tried to build the project requesting Vulkan SDK v1.3.296.0 while my drivers supported 1.4+. The error message I got was:

VUID-VkDeviceCreateInfo-pNext-pNext(ERROR / SPEC): msgNum: -1876993556 - Validation Error: [ VUID-VkDeviceCreateInfo-pNext-pNext ] | MessageID = 0x901f59ec | vkCreateDevice(): pCreateInfo->pNext chain includes a structure with unknown VkStructureType (55). This error is based on the Valid Usage documentation for version 296 of the Vulkan header. It is possible that you are using a struct from a private extension or an extension that was added to a later version of the Vulkan header, in which case the use of pCreateInfo->pNext is undefined and may not work correctly with validation enabled. The Vulkan spec states: Each pNext member of any structure (including this one) in the pNext chain must be either NULL or a pointer to a valid struct for extending VkDeviceCreateInfo

Which basically means "I don't know what VkStructureType (55) is because it's not defined on this API version."

I eventually figured out that we were chaining feature structs up to the highest available version the users machine could run instead of what we intend to target. I fixed this by choosing the minimum version between what we intend to target and what the driver supports and then using this as a check before chaining feature structs. The code snippet for this is below:


1. We get the device properties so we can see which API version our graphics drivers support

2. We check this against our requested API version and take the minimum

3. We use this as a gate for feature chaining so we don't chain anything over the requested API version

That's all of my updates for now!

Saturday, January 24, 2026

Month 1 - Part 1 - Implementing IntersectOBBToOBB

 Over the past few weeks I've gotten introduced to the Gateware project and started contributing. I've discovered a new Vulkan bug (by accident), implemented a function that outputs an OBB given a transform, and began implementation on another function that finds the minimum penetration distance between two intersecting oriented bounding boxes and returns it to the user. I've learned a lot during this time which I will share in the following post. 

During my first week I focused on getting my environment set up, reading through the code base and trying to compile. Given that this was my first time compiling and running the project I expected all tests to pass. Much to my surprise I was greeted with my first test failure. The issue was related to Vulkan and wasn't reproducible on others machines. After some debugging with Lari we found that it was related to the newer versions of Vulkan. We decided to table this for now as I was just getting started with the project and it worked fine on recent versions of the Vulkan SDK. 

The next week consisted of implementing a function that would output to the user an oriented bounding box given a transform. An oriented bounding box consists of a center, extents (width, height and depth), and rotation. I was familiar with OBBs on a high level, but never worked with them directly before thus began my research. I learned about the difference between Axis-Aligned Bounding Boxes and Oriented Bounding Boxes and their different use cases. I learned what defined an Oriented Bounding Box and how, given a transform, one can generate the center, extent and rotation of a bounding box. This turned out to be pretty simple and my solution is as follows:

Luckily, Gateware's math library contains functions that already compute the data we need given a transform. This ended up being as easy as plugging the transform into these functions to get the center and rotation of the desired bounding box. The one extra step I needed to do was take the limits vector given by the user and scale it by half since the extents of the bounding box are half width, half height and half depth. After calculating these, I set the appropriate properties of the output bounding box and return SUCCESS to let the user know it was created. 

The great thing about Gateware is that we are required to practice test driven development which means my work was not finished there. I then proceeded to create test cases for this function which consisted of:

  1. Given an identity transform, we output a centered OBB
  2. Translating an identity transform and then creating the OBB correctly sets the OBB center
  3. Given a transform with rotation correctly sets the OBBs rotation
  4. Given non-uniform extents still produces the correct extents for the OBB
  5. Given zero limits will produce an OBB with zero extents

I then did the same for a double variant, added to the interface and added a fallback function. After this my work was complete! I submitted a merge request, received some feedback and finally merged into the main branch. It was an awesome feeling knowing my code, however small, was live and possibly being used by people building games.

After this I decided to move onto another OBB function. This time the function was supposed to return the minimum penetration distance between two intersecting OBBs. Again, I started with research. I found that in order to detect two intersecting OBBs I would need to implement something called Separate Axis Theorem which luckily is well documented but also much more complex than the method you would use to detect collision between two AABBs. I read Real-Time Collision Detection by Christer Ericson and started doing other research on topics that were fuzzy to me such as vector projection, cross products and how to use these to derive the information needed to complete this function. 

After a talk with Lari I decided to see if there was anything in the codebase that could help me finish this function. Low and behold, I found a little (not so little) piece of code that was commented out with the function name IntersectOBBToOBB. Well that's awesome, someone had already started this and not only that but the function was practically finished! This was a relief but at the same time I felt like I had wasted so much time looking elsewhere and holding up development which would turn into a learning for me. I decided to start dissecting this function and figure out why it wasn't working the way the author intended. 

Through debugging I found that we were initializing our out distance to 0.0f and then using this out distance in future comparisons when finding a new penetration depth in the form of (x < out distance) which meant that we were simply never updating out distance because the new penetration depth would never be less than the initialized zero! To solve this issue I created a variable local to the function that initialized to FLT_MAX. I then used this in our comparison so that the first time we found a new penetration distance it would be guaranteed to be less and on subsequent comparisons we would then be comparing against the current minimum penetration distance. There were a couple other issues that popped up after this but this was the root issue. We finally were returning the true minimum distance between these two objects.

I added some tests, clapped my hands together, but wait.. there was a failure. In one of my tests I simulate a separation of the two objects by moving the object by the minimum penetration distance found and then recheck for a collision, expecting no collision. The test was returning collision? After further inspection I realized it's because we add on an epsilon value to each axis. This epsilon value exists to prevent numerical instability when the boxes are near parallel. The problem with this is that we get an inflated projected radii so on the next call to the function (after we've separated the objects) our function will detect another collision even though the objects are geometrically separate. This is the issue I've been stuck on for the past week and I'm not sure what the best way to solve it is just yet. I don't want to just return an estimate as this could cause jitter for the user. I am currently researching open source physics libraries like box2d and qu3e to see how they handle similar situations as well as reading and watching material from other collision experts such as Dirk Gregorius, Erin Catto, and Randy Gaul in hopes to find an elegant solution to this problem. 

If I can't resolve this soon, I plan on tabling it while I tackle the original Vulkan issue I encountered during my first week of set up as this is a more pressing issue that is currently affecting users on newer Vulkan SDKs. On to the next week of development!