gltrace: Support writable coherent buffers

For all writable coherent buffers we create respective shadow
memory of the same size aligned to page.

When memory is being mapped we save GL memory pointer and return
readonly shadow memory with the offset.

When write into shadow memory is caught we remove protection from
the respective page, mark page as dirty and add this shadow memory
to the dirty list in the current context.

When removing protection if previous page is also dirty we double
the number of page to remove protection from.
Thus reducing amount of page exceptions to log(n) where n is
a number of consecutive pages being written to.

On all draw and unpack functions all dirty memory shadows are
being commited to corresponding gl memory and made protected again.

When fence become signaled we sync all readable buffers.

Current shortcomings:
- Buffer's contents may be changed from shaders however this
  wouldn't be reflected in shadow memory and if the same page
  is changed on CPU side and on GPU side even if offsets are
  different the data on the GPU will be overwtitten.

- Small changes in buffer result in full page write.

- All readable-writable buffers are synced back to cpu on
  fence signal instead of only potentially changed ones.

Signed-off-by: Danylo Piliaiev <danylo.piliaiev@globallogic.com>
5 files changed