Read the post-processed framebuffer into an ImageData.
Returns a Promise so that the WebGPU port (which requires async
buffer.mapAsync() readback) can swap the implementation without
touching the call sites. Under WebGL2 the underlying read is
still synchronous; the Promise just wraps the result.
Subset of PostProcessingManager the screenshot path reads.