assertion failure in copyContentsToMemory with Metal Topic is solved

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


jwwalker
Goblin
Posts: 248
Joined: Thu Aug 12, 2021 10:06 pm
Location: San Diego, CA, USA
x 18

assertion failure in copyContentsToMemory with Metal

Post by jwwalker »

I want to copy pixels from a window, which presumably would use copyContentsToMemory. I couldn't find any sample code for that, so tried as best I could:

Code: Select all

Ogre::TextureGpu* texture = _ogreWindow->getTexture();
Ogre::TextureBox box( texture->getEmptyBox( 0 ) );
std::vector<unsigned char> buffer( box.getSizeBytes() );
Ogre::TextureBox dstBox( box );
dstBox.data = buffer.data();
texture->copyContentsToMemory( box, dstBox, Ogre::PFG_RGBA8_UNORM_SRGB );
In the copyContentsToMemory call, I get an assertion failure:

Code: Select all

-[MTLDebugBlitCommandEncoder validateCopyFromTexture:sourceSlice:sourceLevel:sourceOrigin:sourceSize:toBuffer:destinationOffset:destinationBytesPerRow:destinationBytesPerImage:options:]:851: failed assertion `sourceTexture must not be nil.'
This message happens when MetalAsyncTextureTicket::downloadFromGpu does this:

Code: Select all

[blitEncoder copyFromTexture:srcTextureMetal->getFinalTextureName()
				 sourceSlice:srcTextureBox.sliceStart + i
				 sourceLevel:mipLevel
				sourceOrigin:mtlOrigin
				  sourceSize:mtlSize
					toBuffer:mVboName
		   destinationOffset:destBytesPerImage * i
	  destinationBytesPerRow:destBytesPerRow
	destinationBytesPerImage:destBytesPerImage];
I verified in the debugger that in this call, the variable srcTextureMetal is not nil, but srcTextureMetal->getFinalTextureName() is nil. What's going on?
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5436
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1343

Re: assertion failure in copyContentsToMemory with Metal

Post by dark_sylinc »

This is a known issue.

If the source is a window, Metal has issues. Coincidentally I fixed this problem 2 days ago for Ogre 2.4. See the documentation in the comments.

It may be possible to do it in 2.2/2.3 by using a CompositorWorkspaceListener or FrameListener::frameRenderingQueued listener (i.e. download the data before swapBuffers gets called) but there's still the issue that mMetalLayer.framebufferOnly needs to be set to NO.

You can obtain it from MetalWindow::getCustomAttribute( "UIView", .... ) and access ((CAMetalLayer *)mMetalView.layer).framebufferOnly

A bit troublesome but if you do those 2 things (take screenshot before swapBuffers + set framebufferOnly to NO), it will work (or you can just upgrade to latest/experimental 2.4 and use the new functions)
jwwalker
Goblin
Posts: 248
Joined: Thu Aug 12, 2021 10:06 pm
Location: San Diego, CA, USA
x 18

Re: assertion failure in copyContentsToMemory with Metal

Post by jwwalker »

Thanks. I updated to the tip of the master branch and tried the new functions. It almost worked... the problem is that fragments that should be translucent (and that look correct in the actual window) are shown as fully transparent in the snapshot image, without any background objects or background color showing through. Here's an image from the window:

Image

And here's the result of trying to capture the image with my code:

Image

The gray and white checkerboard pattern is drawn behind images with an alpha channel by Apple's Preview app, so that's where my image file has become fully transparent.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5436
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1343

Re: assertion failure in copyContentsToMemory with Metal

Post by dark_sylinc »

I wouldn't be surprised the Window's alpha channel is full of garbage (since our shaders literally don't care what happens to it), causing this; and not limited to Metal

Probably the solution is to (after downloading the image) just overwrite the alpha channel with all 255u
jwwalker
Goblin
Posts: 248
Joined: Thu Aug 12, 2021 10:06 pm
Location: San Diego, CA, USA
x 18

Re: assertion failure in copyContentsToMemory with Metal

Post by jwwalker »

Thanks again! It turned out that I didn't need to clear the alpha bytes to 0xFF. When I created an NSBitmapImageRep from the data, passing the correct parameters made it ignore the alpha bytes.