问题标签 [metalkit]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
metal - METAL顶点/片段着色器“拦截”结果的最佳方法
我目前有一个MTLTexture
for 输入,并且正在使用一组 20-30 个顶点逐段渲染。drawRect
这目前是在我的处理程序的尾部完成的MTKView
:
但是,在进行最终处理之前,presentDrawable
我想截取生成的纹理(我将把它的一个区域发送到一个单独的区域MTKView
)。换句话说,我需要在通话MTLTexture
后访问某种形式的输出。drawPrimitives
最有效的方法是什么?
drawPrimitives
一个想法是向中间输出引入额外的渲染MTLTexture
。我不知道该怎么做,但我会在这个过程中舀出那个输出纹理。我怀疑这甚至会在其他地方完成(即屏幕外)。
drawPrimitives
然后我会使用带有该 outputTexture 的单个大型纹理四边形发出第二个,然后presentDrawable
在其上发出一个。该代码将存在于我之前的代码所在的位置。
Metal API 中可能有一个简单的方法(我缺少),它可以让我捕获drawPrimitives
.
我已经研究过使用,MTLBlitCommandEncoder
但在某些 MacOSX 硬件上存在一些问题。
更新#1: idoogy,这是您要求的代码:
这是我创建初始“亮度输出”纹理的地方......我们在顶点着色器中飞行:
下面,我们在辅助视图的drawRect
处理程序中,inputTexture
作为正在传输的纹理,显示它的一个子区域。我应该提到,这MTKView
被配置为作为一个结果绘制,setNeedsDisplay
而不是作为一个带有内部计时器的结果:
上面的代码似乎工作正常。话虽如此,我认为我们在 Xcode 调试器中讲述了一个不同的故事。很明显,我以这种方式浪费了大量时间......那个长命令缓冲区是辅助监视器视图,正在等待很多......
ios - 为 iOS 模拟器目标构建时忽略 .metal 文件
每当我构建一个包含 x86_64 目标(iOS 模拟器)的金属着色器的项目时,我都会收到依赖分析警告:
warning: no rule to process file '[File Path]/Shaders.metal' of type sourcecode.metal for architecture x86_64
我知道这不是一个大问题,但我喜欢在构建时让我的项目免受警告,这样当真正出现问题时,我实际上会注意到黄色警告三角形。
有什么快速的方法让 Xcode 忽略模拟器目标的金属文件?
metal - 闪烁的金属输出纹理...为什么?
我正在尝试在现有纹理的顶部放置许多叠加层(纹理)。在大多数情况下,这工作正常。
但是,对于我的生活,我无法弄清楚为什么在我drawRect
的MTKView
. 一切似乎都很好;theTexture
在循环放置叠加层后,我会(在内核着色器中)进行进一步处理。出于某种原因,我觉得这种编码提前结束了,而且还没有完成足够的工作。
澄清一下,一切开始都很好,但大约 5 秒后,闪烁开始并逐渐恶化。出于调试目的(现在,无论如何),循环只运行一次——只有一个覆盖元素。theTexture
每次开始之前,输入纹理 ( ) 都是真实的(使用 storageModeMTLStorageModeManaged
和 usage的描述符创建MTLTextureUsageUnknown
)。
我还尝试将编码器实例化/结束填充到循环中;没有不同。
有人可以帮我看看我做错了什么吗?
更新#1:
我附上了一个“好”框架的图像,显示了顶点区域(右下角)。我的编码器负责将绿色替代“图像”theTexture
以 30fps 的速度放置在视频帧的顶部,它确实这样做了。只是为了澄清,theTexture
为每一帧创建(来自 CoreVideo 像素缓冲区)。在这个编码器之后,我只从theTexture
内核着色器中读取来调整亮度——一切都很好。
我的问题必须存在于其他地方,因为视频帧停止流动(尽管音频继续播放),并且一旦插入此编码器,我最终会在 2 或 3 个先前的帧之间交替(因此,闪烁)。我现在相信我的视频像素缓冲区供应商无意中被这个“覆盖”供应商所取代。
如果我注释掉整个顶点渲染器,我的视频帧就会很好地流过;这不是我的视频帧供应商的问题。
更新#2:
这是我的渲染管道的声明:
这是用于创建的纹理描述符theTexture
:
由于这个原因,我没有包含AAPLVertex
和 顶点/片段函数:如果我只是在我的渲染代码中注释掉OverlayWrapper
循环(即,甚至不设置顶点缓冲区或绘制图元),视频帧仍然会闪烁。从该编码器“运行”的时间开始,视频仍在播放,但只有 2-3 帧左右在连续循环中播放。
我还在 之后添加了此代码,[... endEncoding]
并将纹理使用更改为MTLStorageModeManaged
- 仍然,没有骰子:
澄清一些事情:随后的计算机着色器theTexture
仅用于输入。这些是视频帧;因此,theTexture
每次都重新创建。在它经过这个渲染阶段之前,它有一个真正的“背景”
更新#3:
我得到了这个工作,如果通过非常规的方式。
我使用这个顶点着色器将我的叠加层渲染到新创建的空白纹理的透明背景上,特别是我loadAction
的MTLLoadActionClear
clearColor 为 (0,0,0,0)。
然后我将这个生成的纹理与我theTexture
的内核着色器混合。我不应该这样做,但它有效!
avplayer - 金属渲染循环优化
我正在寻找有关如何正确实现金属渲染循环的方向。我的渲染循环从AVPlayer
.
这是我当前的实现:
- A以 60hz 的频率
CVDisplayLink
查询播放器的。AVPlayerItemVideoOutput
如果有一个新帧,它会CVPixelBufferRef
被捕获/保存*作为MTKView
它将被渲染到的属性。(此时,之前捕获的视频帧被释放)。 - My
MTKView
设置为isPaused
和enableSetNeedsDisplay
toNO
。换句话说,内部计时器的MTKView
任务是定期调用其drawRect
方法。 - 在
drawRect
我首先将 new-arrived* 转换CVPixelBuffer
为 aMTLTexture
,然后出现一堆渲染阶段。 - 最后,我
presentDrawable
在方法结束时调用drawRect
。
*注意:对 的互斥访问CVPixelBufferRef
由一对 dispatch_semaphore_wait
和控制dispatch_semaphore_signal
。
这是一种正确的做事方式吗? 尽管偶尔会丢失一些帧,但它似乎相当高效。在时间方面,Metal 的 Xcode 分析告诉我,我MTLCommandBuffer
的运行时间通常不到 3 毫秒。
话虽如此,我看到了一些替代的可能性:
- 放弃
CVDisplayLink
实现并抓住其中的框架drawRect
- 反转渲染过程;显示之前捕获的帧并
MTLTexture
首先在drawRect
方法中渲染,然后commit
是 Metal 命令缓冲区并presentDrawable
立即调用。在那之后,捕获下一个视频帧并在下一次调用之前运行它的渲染阶段(在退出drawRect
之前这样做吗?)。drawRect
另一个问题:我的印象是CVDisplayLink
和drawRect
方法都没有在这个配置的主线程上运行。我感到困扰的是,每当我松开应用程序的一个菜单时,视频帧的传递就会出现明显的卡顿——这是主线程进行 UI 更新并阻塞的症状。NSCollectionView
当重新加载屏幕并在屏幕上显示其内容时,会观察到相同的行为。这让我相信我的假设是不正确的。如何MTKView
制作这些渲染循环来避免这些问题? 想知道整个打开/配置是否也AVPlayer
需要脱离主线程。
更新#1
我修复了鼠标悬停在任何项目上时会出现的“另一个问题”口吃问题。NSMenu
这是我的解决方案:
MTKView
用isPaused=YES
和配置每个enableSetNeedsDisplay=NO
。这意味着draw
视图需要显式调用才能呈现其内容。- 在
CVDisplayLink
回调中,发出对on a的draw
调用,因此:MTKView
dispatch_global_queue
metal - MPSCopyAllocator 无法初始化
在 Objective-C 中,我尝试使用这种方法对命令缓冲区进行就地编码。
我想创建一个新的 MPSCopyAllocator 。
我使用了文档中的以下代码。
但我在问题导航器中遇到了语义问题
MPSCopyAllocator 定义
创建 MPSCopyAllocator 的正确方法是什么?
ios - 金属:在 2D 渲染树中使用模板附件作为剪贴蒙版
我目前正在学习如何使用 Metal 并且在使用模板缓冲区时遇到了一些困难——可能是因为它对我遇到的问题的错误解决方案。
问题:我有一个二维渲染节点树,四边形,我用金属渲染。对于某些四边形,我想启用一个“剪贴蒙版”,它将所有子节点的渲染剪辑到其范围内。
我想这可能是模板附件的一个很好的用例(Metal 是我第一次涉足低级图形 API),但我不能 100% 确定。
然而,在设置了深度附件后,我不知道该怎么做。甚至可以用这种方法实现嵌套剪贴蒙版的想法吗?
我对它如何工作的粗略想法是:
- 像往常一样为每个四边形设置管道状态
设置几个深度模板状态,一个用于将剪辑的树元素,一个用于不会剪辑的节点。(分别写入 0xFF 和 0x00 的掩码。)
像往常一样开始渲染过程并开始遍历树。
- 如果一个节点应该剪裁,使用剪裁深度模板状态,否则使用非剪裁。
知道这是否是正确的方法吗?
关于解决这个问题的细节的任何想法。即配置MTLStencilDescriptor
和它的读/写掩码和各种比较操作和功能。如何在渲染命令编码器上设置 stencilReferenceValue?在树的每一级增加它?
编辑:一个类似的问题试图在 Open GL 中解决这个问题(尽管该解决方案有其自身的妥协),所以看来上述问题可以使用模板附件来解决。
链接问题中的解决方案指出“通过为场景图中的每个级别分配比上一个更高的数字,您可以为每个级别分配其自己的模板蒙版”,但附带警告:“当然,如果两个兄弟姐妹在同一深度重叠,或者只是太近了,那么你就有问题了。”
有没有更好的方法通过 Metal 提供的功能来实现这一点?在 Metal 的 API 的能力范围内推荐算法/方法的想法/指针将不胜感激!
ios - Metal 最佳实践:三重缓冲 – 纹理?
在Metal Best Practices Guide中,它指出为了获得最佳性能,应该“实现三重缓冲模型来更新动态缓冲区数据”,并且“动态缓冲区数据是指存储在缓冲区中的频繁更新的数据”。
MTLTexture
如果每帧都需要更新,是否符合“存储在缓冲区中的频繁更新数据”的条件?上面指南中的所有示例都集中在MTLBuffer
s 上。
我注意到 Apple 在 MetalKit 中的实现有一个 a 的概念nextDrawable
,所以也许这就是这里发生的事情?
metal - 传递一个 MTLTexture 导致崩溃
这是我的场景:
在一个MTKView
(以及其中的单个命令缓冲区)中,我有一个操作MTLTexture
的结果MTLComputeEncoder
。
我draw
在 上的方法MTKView
被称为 a 的高优先级实例dispatch_get_global_queue
。在结尾处drawRect
,MTKView
我“舀”那个纹理并将其设置为不同的属性MTKView
。然后我调度一个低优先级线程来调用该视图的draw
方法,将原始纹理的一个区域复制到第二个MTKView
,以及最终的presentDrawable
调用——所有这些都在不同的命令缓冲区上。同时,原来的方法以自己的调用MTKView
结束。draw
presentDrawable
我应该提一下,这两个MTKViews
都配置了isPaused=YES
和enableSetNeedsDisplay=NO
。
这一切都运行得相当好,但我偶尔会遇到“ [CAMetalLayerDrawable texture] should not be called after presenting the drawable
”警告或某些无法识别的线程中偶尔崩溃的崩溃:
如果我删除/注释掉辅助“独家新闻”并重新绘制原始纹理,则不会发生崩溃。
有没有更可接受的方法来实现这一点?可能使用 anMTLBlitCommandEncoder
显式复制所提供纹理的内容?
更新#1
使代码更加清晰是一个明智的想法,可能是:
这是drawRect
primary 的方法,MTKView
由 a 驱动dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)
:
在辅助视图中:
macos - OS X Metal 应用程序中的屏幕故障?错误(IOAF 代码 1)?
我正在使用 Metal 在 OS X Sierra 上制作应用程序。我正在做的事情是导致屏幕开始出现严重故障,在各个地方闪烁黑色,这很快升级为整个屏幕变黑。
在 XCode 中,如果我使用 GPU 帧捕获,则暂停的帧看起来是正确的——它突然从黑色深渊返回。我在 GPU 帧信息中看不到任何错误或警告。但是,我对 Metal 比较陌生,对框架调试器没有经验,所以我可能不知道要寻找什么。
通常没有打印到控制台,但偶尔我会得到其中之一:
由于执行期间出现错误,命令缓冲区的执行被中止。内部错误(IOAF 代码 1)
相同的应用程序在 iOS 设备上运行没有这个问题——到目前为止它只发生在 OS X 上。这听起来很熟悉吗?关于我应该检查什么的任何建议?
如果有帮助,我可以发布一些代码,但现在我不确定程序的哪一部分是问题所在。
编辑:响应诺亚威瑟斯彭 - 似乎问题是由我的场景绘图和 UI 绘图之间的某种交互引起的。如果我只显示我的场景,它由粗大的模糊线条组成,那么问题就不会发生。如果我只显示 UI,即正交投影、一堆圆角矩形和某种类型,它也不会发生。仅当两者都显示时才会出现问题。这是很多代码,很多缓冲区和大量 commandBuffer 使用,太多了,无法放入帖子中。但这里有一点。
我的线条是用顶点缓冲区渲染的,顶点缓冲区是浮点数组,每个顶点四个:
这些呈现如下:
这是我使用 Buffer 命令绘制的主循环。
线条绘制发生在 strokeNode.subrender 中,然后我的 UI 绘制发生在 mainscreen.draw 中。UI 绘图有很多组件 - 很多要在此处列出 - 但我会尝试将它们一一取出,看看是否可以缩小范围。如果这些看起来都没有问题,我会编辑并发布其中的一些......
谢谢!
metal - 在 MTKViews 之间传递纹理的最佳方式?
我有一段时间一直在挣扎的情况。
在对 a 的draw:
调用中MTKView
,我生成了 a MTLTexture
,它是该视图的可绘制对象的渲染链的一部分。现在,我想使用该纹理作为在辅助中绘制的基础MTKView
。
为了防止在修改应用程序菜单时出现动画卡顿,我将两个视图都配置为显式绘制模式,并将CVDisplayLink
这些绘制调用分派到串行队列中(即不在主线程上)。我什至尝试将辅助视图配置为使用 setNeedsDisplay 在主队列上绘制。
我可以让它大部分工作,但由于我怀疑是一些线程问题,我偶尔会收到崩溃。我什至甚至将这两个的绘图调用MTKViews
连续放置在同一个串行线程(通过dispatch_queue_async
)上,但没有取得多大成功。我还尝试将生成MTLTexture
的数据放入一个受信号量保护的小 FIFO 队列中,辅助视图从该队列中消费——同样,没有太大成功。
以全动态视频帧为源,事情会顺利运行几分钟,然后draw
在第二个视图的方法中我收到崩溃。通常,当我去检索纹理时会发生这种情况:
有时,我最终会放弃绘制纹理,因为纹理是MTLTextureType1D
(而不是 2D)或者它的使用是错误的MTLTextureUsageShaderRead
。然而我MTLTextureDescriptor
的很好;就像我说的,在 99.99% 的情况下,一切都运行良好。
我想知道是否有人可以协助以适当的、线程安全的方式获取一个纹理MTKView
并将其传递给辅助节点MTKView
以进行后续处理。