We keep a shadow copy of the GPU cache data in the render thread.
After all updates (patches) have been applied for this frame, scan
the rows of the texture for rows that have been modified.

Upload each dirty row to the GPU via a PBO to ensure that there
are no CPU-side stalls.

In the future, there's several more optimizations that can be made:
 * Batch consecutive row updates into a single PBO / upload call.
 * Perhaps track start/end of each row, to avoid a full row update for small changes.