这是我的情景:
在MTKView
(以及其中的单个命令缓冲区)中,我有MTLTexture
,这是MTLComputeEncoder
操作的结果。
draw
上的MTKView
方法被称为dispatch_get_global_queue
的高优先级实例。在drawRect
的{{1}}的尾端,我“挖出”该纹理并将其设置为不同MTKView
上的属性。然后我调度一个低优先级线程来调用该视图的MTKView
方法,将原始纹理的一个区域复制到第二个draw
,同时调用最终的MTKView
调用 - 所有这些都是不同的命令缓冲区。同时,原始presentDrawable
结束MTKView
方法,并自行调用draw
。
我应该提及这些presentDrawable
都配置了MTKViews
和isPaused=YES
。
这一切都运行得相当不错,但我偶尔会遇到“enableSetNeedsDisplay=NO
”警告或偶尔崩溃导致某些无法识别的线程崩溃:
[CAMetalLayerDrawable texture] should not be called after presenting the drawable
如果我删除/注释掉辅助“scoop”并重绘原始纹理,则不会发生崩溃。
有没有更可接受的方法来实现这一目标?可能使用QuartzCore`-[CAMetalDrawable present]:
0x7fff881cf471 <+0>: pushq %rbp
0x7fff881cf472 <+1>: movq %rsp, %rbp
0x7fff881cf475 <+4>: movq %rdi, %rax
0x7fff881cf478 <+7>: movq 0x15f25ce1(%rip), %rcx ; CAMetalDrawable._priv
0x7fff881cf47f <+14>: movq (%rax,%rcx), %rcx
0x7fff881cf483 <+18>: movq 0x20(%rcx), %rdi <---- crashes here
0x7fff881cf487 <+22>: xorps %xmm0, %xmm0
0x7fff881cf48a <+25>: movq %rax, %rsi
0x7fff881cf48d <+28>: popq %rbp
0x7fff881cf48e <+29>: jmp 0x7fff881cf493 ; layer_private_present(_CAMetalLayerPrivate*, CAMetalDrawable*, double, unsigned int)
显式复制提供的纹理的内容?
更清晰的代码是一个明智的想法,可能:
这是主MTLBlitCommandEncoder
的{{1}}方法,由drawRect
驱动:
MTKView
在次要视图中:
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
答案 0 :(得分:1)
我不确定你是否意识到创建自己的纹理并渲染它是既可接受又常见的。您不必渲染视图或图层的可绘制纹理。
创建自己的纹理以进行渲染,然后,就目前的步骤而言,从纹理渲染到可绘制的纹理。
请注意,根据您正在做的事情,您可能需要旋转三个左右的纹理池。您需要关注的问题是Metal是否仍在从纹理中读取,因此在读取之前不要写入。