我目前有一个MTLTexture
用于输入,并使用一组20-30个顶点逐段渲染。目前,这是在drawRect
的{{1}}处理程序的尾端完成的:
MTKView
然而,在做最后的[encoder setVertexBuffer:mBuff offset:0 atIndex:0]; // buffer of vertices
[encoder setVertexBytes:&_viewportSize length:sizeof(_viewportSize) atIndex:1];
[encoder setFragmentTexture:inputTexture atIndex:0];
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:_vertexInfo.metalVertexCount];
[encoder endEncoding];
[commandBuffer presentDrawable:self.currentDrawable];
[commandBuffer commit];
之前,我想拦截生成的纹理(我将把它的一个区域发送到一个单独的presentDrawable
)。换句话说,我需要在MTKView
调用后访问某种方式的输出MTLTexture
。
最有效的方法是什么?
一个想法是向中间输出drawPrimitives
引入额外的drawPrimitives
渲染。我不知道该怎么做,但我会在这个过程中挖出输出纹理。我怀疑这甚至可以在其他地方完成(即屏幕外)。
然后我会使用带有outputTexture的单个质量纹理四边形,然后在其上MTLTexture
发出第二个drawPrimitives
。该代码将存在于我以前的代码中。
Metal API中可能有一个简单的方法(我缺少),它允许我捕获presentDrawable
的输出纹理。
我已经考虑使用drawPrimitives
,但在某些MacOSX硬件上存在一些问题。
更新#1: idoogy ,这是您要求的代码:
这是我创建初始“亮度输出”纹理的地方......我们在顶点着色器中进行中飞行:
MTLBlitCommandEncoder
下面,我们在辅助视图的...
[encoder setFragmentTexture:brightnessOutput atIndex:0];
[encoder drawPrimitives:MTLPrimitiveTypeTriangle vertexStart:0 vertexCount:_vertexInfo.metalVertexCount];
[encoder endEncoding];
for (AltMonitorMTKView *v in self.downstreamOutputs). // ancillary MTKViews
[v setInputTexture:brightnessOutput];
__block dispatch_semaphore_t block_sema = d.hostedAssetsSemaphore;
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
dispatch_semaphore_signal(block_sema);
}];
[commandBuffer presentDrawable:self.currentDrawable];
[commandBuffer commit];
处理程序中使用drawRect
作为正在传输的纹理,显示它的子区域。我应该提一下,inputTexture
被配置为由MTKView
绘制而不是与内部计时器一起绘制:
setNeedsDisplay
以上代码似乎可以正常使用。话虽如此,我想我们在Xcode调试器中讲述了一个不同的故事。很明显,我浪费了大量的时间用这种方式做事......那个长命令缓冲区是辅助监视器视图,做了很多等待......
答案 0 :(得分:2)
这应该是可行的。在commit
上调用commandBuffer
之前,通过调用[commandBuffer addCompletedHandler:]
为命令缓冲区添加完成处理程序,然后在完成处理程序中,从renderPassDescriptor
中获取颜色附件。
renderPassDescriptor
包含当前要绘制的附件集,并由MTKView
自动配置。实际纹理每帧旋转,因为MTKView
使用三重缓冲来确保GPU的连续使用,但只要您在完成处理程序中,该特定附件将不会被释放以供将来使用框架,所以你可以安全地阅读,复制它等。
注意:确保快速合理地完成处理程序,否则帧速率会下降(因为MTKView
将快速耗尽渲染目标,并且只会坐在那里直到它们被释放)
这是一个让您入门的通用代码段:
// Grab the current render pass descriptor from MTKView so it's accessible from within the completion block:
__block MTLRenderPassDescriptor *renderPassDescriptor = self.renderPassDescriptor;
[commandBuffer addCompletedHandler:^(id<MTLCommandBuffer> commandBuffer) {
// This will be called once the GPU has completed rendering your frame.
// This is your output texture:
id <MTLTexture> outputTexture = renderPassDescriptor.colorAttachments[0].texture;
}];
[commandBuffer commit];