简体   繁体   中英

Metal equivalent for glCopyTexImage2d

I need to grab the texture of whatever is drawn to the frame buffer, in other words, whatever is appearing below the effect that i'm about to draw. Use case is to feed this texture to a shader that performs distortion to it.

what i've tried so far using MTLBlitCommandEncoder.

auto commandQueue = [device newCommandQueue];
auto commandBuffer = [commandQueue commandBuffer];
[commandBuffer enqueue];
id<MTLRenderCommandEncoder> renderEncoder = [commandBuffer renderCommandEncoderWithDescriptor:mtlDescriptor];

// perform encoding

[renderEncoder endEncoding];

// now after several render passes i need to commit all the rendering for behind the effect, 
// so that the texture i am grabbing will omit whatever is about to be drawn after this point

[commandBuffer commit];
[commandBuffer waitUntilCompleted];

Next, i have to create a new command buffer, because if i don't do so i will get an error when i call addCompletedHandler after this commit. I suppose a command buffer cannot commit more than once right?

auto commandBuffer = [commandQueue commandBuffer];

id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
[blitEncoder enqueue];

[blitEncoder copyFromTexture:drawable.texture sourceSlice:0 sourceLevel:level sourceOrigin:region.origin sourceSize:region.size toTexture:_mtlTexture destinationSlice:0 destinationLevel:level destinationOrigin:{xOffset, yOffset, 0}];

[blitEncoder endEncoding];
.
// continue with more other render encoding

This can run without any assert error. But the problem is that the depth test is appearing incorrectly. The effect appears to be drawn behind the models that it should be above (when i'm using just 1 command buffer without performing blit it renders correct). i am using this settings that i suppose whatever written to the depth texture will be preserved?

mtlDescritpor.depthAttachment.loadAction = MTLLoadActionLoad;
mtlDescritpor.depthAttachment.storeAction = MTLStoreActionStore;

Can anyone point to me where went wrong?

EDIT: i have tried using 2 command buffers, one after another, without performing blit, and the depth is also appearing wrong.

Does it mean depth test just can't work when it's a new command buffer? Or is there a more recommended implementation for what i'm trying to achieve? I can't seem to find any examples..

EDIT2: after more testing, it appears that there is a very inconsistent behaviour, even when using just 1 command buffer. Some time the effect renders below (incorrect), sometimes correctly. (part of it should be rendering above as tested on OpenGL) When i comment off a line of code or add more lines of code, the result will change randomly. I am currently using depthCompareFunction MTLCompareFunctionLessEqual . If i change to MTLCompareFunctionNotEqual , everything will always be on drawn on top, which is also wrong.

So i realise i have been under the wrong impression of having the need to execute a commit first, in order to have what was drawn up till that point to be 'saved' to the texture.

Based on this info here https://github.com/gfx-rs/gfx/issues/2232 It is as though whatever render encoding performed is already drawn to the texture. So having 2 command buffers is not necessary at all.

As for the depth test issue, it was my mistake of not setting the viewport znear and zfar for the MTLRenderCommandEncoder to be same as the models'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM