我正在学习Metal,并尝试使用屏幕外渲染来实现后期效果。为此,我将场景绘制到in this question之类的渲染目标。
然后我想将纹理绘制到帧缓冲区(currentDrawable)。
我想我的纹理已经可以绘制了,可以使用了。但是,当我将纹理绘制到帧缓冲区时,我看到了垃圾。看来纹理尚未准备好。为了解决这个问题,我为屏幕外命令缓冲区调用waitUntilCompleted。它有助于。 但是据苹果公司documentation:
确保发送到单个命令队列的所有命令缓冲区都按命令缓冲区入队的顺序执行。
因此,我希望可以不调用阻塞函数waitUntilCompleted
而实现。但这对我不起作用。参见示例:
var device = MTLDevice.SystemDefault;
var commandQueue = device.CreateCommandQueue();
//Create texture for renderTarget
var textDesc = MTLTextureDescriptor.CreateTexture2DDescriptor(pixelFormat, Width, Height, 1);
textDesc.Usage = MTLTextureUsage.RenderTarget | MTLTextureUsage.ShaderRead;
textDesc.StorageMode = MTLStorageMode.Private;
IMTLTexture texture = device.CreateTexture(textDesc);
var textPassDesc = new MTLRenderPassDescriptor();
textPassDesc.ColorAttachments[0].LoadAction = MTLLoadAction.Clear;
textPassDesc.ColorAttachments[0].StoreAction = MTLStoreAction.Store;
textPassDesc.ColorAttachments[0].Texture = texture;
var commandBuffer = commandQueue.CommandBuffer();
var commandEncoder = commandBuffer.CreateRenderCommandEncoder(textPassDesc);
//Drawing scene. I guess It's not interesting now
{
...
}
//Finish command
commandEncoder.EndEncoding();
commandBuffer.Commit();
//The main goal of the question, can I escape this calling ?
commandBuffer.WaitUntilCompleted();
var finalPassDesc = MTKView.CurrentRenderPassDescriptor;
commandBuffer = commandQueue.CommandBuffer();
commandEncoder = commandBuffer.CreateRenderCommandEncoder(finalPassDesc);
//Drawing the frame with texture
{
commandEncoder.SetFragmentTexture(texture, 0);
commandEncoder.SetFragmentSamplerState(defaultSamplerState, 0);
...
}
commandEncoder.EndEncoding();
commandBuffer.PresentDrawable(MTKView.CurrentDrawable);
commandBuffer.Commit();
使用金属进行屏幕外渲染的正确方法是什么?