Assignment 4
Default
Missing Object
Different Effect
The write-up should also explain (in your own words) what the point of the assignment was and how you did it
The goal was to isolate Game logic from Graphics logic. The game should dictate what is actually drawn, the graphics should only care about drawing what it is told to draw. In addition to this, we want to take advantage of multi-threading by having graphics run on a separate thread from the game. One dude is preparing a write up of what to draw, while the second dude is just drawing what is on the write up. The dude that is drawing also has two separate write ups where he swaps with the other dude when he’s ready for the next drawing. All we did to accomplish this was create a submission interface in Graphics to cache data to be drawn on the next frame. Game logic would use this interface to determine what to draw on the next frame. And with the power of locking magic we avoid problems.
The write-up should contain detail about how you personally completed the assignment:
In terms of what we actually implemented on our own, we dictated the interface of our Graphics class as well as the storage of the render frame structure. I tried to simplify RenderObject submission as much as possible by requiring it to have both an effect and geometry. You can see the end result of my interface in figure 4 below. A user only has to create a render object and then submit that render object to dictate what is drawn with what effect. In dictating our render frame structure, I opted for a design in which I thought was cache efficient by storing the render objects directly alongside the other render frame data. Further on I will talk about why I may possibly regret this.
Specific Requirements:
The render structure we picked has the game submit data for caching and rendering in a single frame. One of the reasons in which we structured it this way was due to the fact that the game thread is supposed to run on a separate thread from the rendering thread. OpenGL requires that rendered objects be created on the same thread the context was created in. And so when submitting objects to be rendered from the Game side, they have to be temporarily cached for the render thread to access them. Also, in terms of simplicity and concurrent wisdom I believe, we want the render thread to determine the order in which render objects are actually created. Like always create objects after clearing color, but before swapping back and front buffer.
Compared to the last assignment, the only size change for my geometry and effect (Look at Table 1 below) is the possible addition of 4 bytes to the class. The reason for this change is the addition of the reference counter from the macro (uint16_t m_referenceCount") of two bytes. As a result of four byte alignment I believe, the byte additions can round up to 4 bytes.
- X86 Geometry went from 28 -> 32 due to 4 byte alignment
- X86 Effect went from 28 -> 32 due to 4 byte alignment
- 64 Geometry stayed 48 -> 48 due to previous alignment rounding it to 48
- 64 Effect went from 12 -> 16 due to 4 byte alignment
In terms of saving space and making things smaller, one could realign byte values to avoid rounding of 4 bytes if possible. Example: putting a 2 byte int next to another 2 byte int. This could especially be done with the 2 byte reference counter added. This was technically done for my 64 bit Geometry class. The addition of a 2 byte reference counter didn’t change the size of the class due to the class already being off by 2 bytes.
Looking at Table 2, you will find the sizes i calculated for my render frame caching structure. You will also find it strange for I have a variable total size calculated with an input of N (whereas N is the object limit of how many effect and object pairs my Graphics class can render). In setting up my structure, I opted to store my geometry and effect pointers directly alongside the other render frame logic, I made a conclusion that this would lead to better caching as a result of requiring less pointer accesses. Accessing data would hopefully cache other spacial data. I also figured I would directly control the size and limit of the frame with a macro (called “RENDER_OBJECT_LIMIT”) in my code, making this easy to control on potentially other platforms.
Looking back now though, I am unsure if there is actually any performance benefit for doing this at all. And that doing it this way is potentially more dangerous. Firstly, I now realize that there wouldn’t be that much of a cache benefit, I might get cache hits for accessing the first couple of non-RenderObjects in beginning, but this would be negligible. Secondly, I believe it’s abnormal to store large data structures on the stack (which is where the render frame structure is being stored I believe). I don’t know if there is any actual danger in storing large data structures on the stack, but I believe that most of the time such things are stored on the heap.
Credits:
I discussed the assignment with Bosan, Byreave, and Sumi.
Platform | Geometry | Effect |
---|---|---|
x86 | 32 bytes | 20 bytes |
64 bit | 16 bytes | 48 bytes |
Table 1: Class byte sizes
Platform | sDataRequiredToRenderAFrame Base Size | Size per sRenderObject | Total Size |
---|---|---|---|
x86 | 164 bytes | 8 bytes | Size = 168 + (8*N) |
64 bit | 168 bytes | 16 bytes | Size = 168 + (16*N) |
Table 2: Render Frame Sizes
Fig 1 : Submitting Background Color
Fig 2 : Submitting Effect Objects Part 1. Creating effect and geometry in Game Initialize.
Fig 3 : Submitting Effect Objects Part 2. sRenderObject, the structure that stores a Effect and Geometry pair for rendering.
Fig 4 : Submitting Effect Objects Part 3. Submission of render object via passing of sRenderObject.
Instructions:
Press left arrow key to hide the box.
Press right arrow key to modify the effect of the roof.
Press enter key to change the background color.