Hi!
I see two issues. One is a performance standpoint, the other is your actual problem. I will start with your problem.
1. You did everything right but one thing. You seem to just declare Ogre::TextureBox destPb; without valid stuff in it?
Anyway, TextureBox manipulation can be tricky, so I do suggest Image2 to encapsulate your mCaptureData pointer and take care of the details. Also please note the pointer is created with OGRE_MALLOC_SIMD, this is important.
Code: Select all
Ogre::Image2 mImage;
Ogre::TextureGpu *mWindowTexture;
//At init (MAKE SURE THE RESOLUTION IS WHAT YOU EXPECT! Check for resolution changes!!!
const uint32 rowAlignment = 4u;
const size_t totalBytes = PixelFormatGpuUtils::calculateSizeBytes( mWindowTexture->getWidth(),
mWindowTexture->getHeight(),
mWindowTexture->getDepth(),
mWindowTexture->getNumSlices(),
mWindowTexture->getPixelFormat(),
mWindowTexture->getNumMipmaps(),
rowAlignment );
void *data = OGRE_MALLOC_SIMD( totalBytes, MEMCATEGORY_RESOURCE );
mImage.loadDynamicImage( data, true, mWindowTexture ); //We pass mWindowTexture just to grab its metadata instead of typing mWindowTexture->getWidth, getHeight, etc
//On frameEnd:
mAsyncTicket->download( mWindowTexture, 0, true );
//getData() just fabricates a TextureBox with the right offsets given the mip level and bytes per row, bytes per image, etc
//While it's nothing fancy, there are many details to be aware, so Image2 is a great helper encapsulation utility.
Ogre::TextureBox destPb = mImage.getData( 0 ); //Get mip 0
mSrcBox = mAsyncTicket->map(0);
destPb.copyFrom( mSrcBox );
mAsyncTicket->unmap();
That should work. If it doesn't and you're grabbing the render window directly and are using OpenGL, it could be a bug. Transferring the render window in GL3+ is tricky.
If you're using MSAA, then you may need to resolve it first (see Image2::convertFromTexture).
You
could use Image2::convertFromTexture which handles all cases: MSAA, non-msaa, cubemaps, 3D textures, etc.
However it won't be efficient (see next step).
It could be useful to use it to see if capturing works as intended, and to compare your code against convertFromTexture to see if you missed anything.
2. Now to the performance concerns. Your code is inefficient. You're issuing the ticket download, and immediately afterwards mapping it. That turns the async ticket into synchronous, and causes stalls.
You should have 3 mAsyncTicket, and cycle through them:
Code: Select all
On init:
idx = 0;
On frameInit:
//Read the data which we requested to download 3 fames ago
mSrcBox = mAsyncTicket[idx]->map(0);
destPb.copyFrom( mSrcBox );
mAsyncTicket[idx]->unmap();
On frameEnd:
idx = (idx + 1u) % mVaoManager->getDynamicBufferMultiplier();
//Request another download, which we'll read 3 frames later
mAsyncTicket[idx]->download( mWindowTexture, 0, false ); //No need for accurate tracking by doing it this way
In Ogre 2.1, the only way you could have asynchronous behavior is by cycling through 3 textures. Now there's no need for 3 textures, but you'll need 3 tickets.
Cheers
Matias