In the past week I’ve been working on the last two tasks for dirty rects:
The first one was implementing a system that allowed to clip a draw call and only render a portion of what’s supposed to be drawn, I implemented this in three different ways, based on the type of the draw call:
Blitting draw calls were implemented with a scissor rectangle logic inside the blitting module: this allows the clipping to be very fast as the clipped parts are skipped completely.
Rasterization draw calls are implemented in a different way: this time the scissor rectangle function is implemented on a pixel level, which means that every pixel is checked to be within the scissor rect before being written to the color buffer: this allows the dirty rects system to ignore everything that is outside the dirty region and thus manages to not cover regions that shouldn’t be touched that frame.
Clear buffers draw calls are clipped with a special function inside FrameBuffer that only clears a region of the screen instead of clearing everything.
This covers the implementation of the first sub task: the second one was to detect which regions of the screen changed and output a list of rectangles that need to be updated.
This task was implemented by keeping a copy of the previous frame draw calls and comparing the current frame draw calls with the previous one: this comparison tries to find the first difference between the two lists and then marks as dirty every rectangle that is covered by subsequent draw calls.
Once this list is obtained with this method I also use a simple merging algorithm to avoid re-rendering of the same region with overlapping rectangles and also to reduce the number of draw calls.
What happens after I have this information can be described with the following pseudocode:
foreach (drawCall in currentFrame.drawCalls) { foreach (dirtyRegion in currentFrame.dirtyRegions) { if (drawCall.dirtyRegion.intersects(dirtyRegion)) { drawCall.execute(dirtyRegion); } } }
There’s only one problem with this implementation: I have found that EMI intro sequence is not detected properly and causes some glitches whereas everything else works fine.
From what I’ve seen though this method isn’t helping the overall engine performance by much: as most of the time is spent in 3D rasterization this system doesn’t cope well with animated models that change very frequently and fails to be effective.
I will keep you updated with how this progresses in the next blog posts, stay tuned for more info!