【发布时间】:2019-01-31 02:51:47
【问题描述】:
我试图更好地理解使用Metal Performance Shaders 和MTLBlitCommandEncoder 时的同步要求。
我有一个MTLCommandBuffer,设置如下:
使用
MTLBlitCommandEncoder将纹理 A 的区域复制到纹理 B。纹理 A 大于纹理 B。我正在从纹理 A 中提取“平铺”并将其复制到纹理 B。使用
MPSImageBilinearScale金属性能着色器,纹理 B 作为源纹理,第三个纹理纹理 C 作为目标。此金属性能着色器将缩放并可能将纹理 B 的内容转换为纹理 C。
在金属性能着色器开始尝试缩放纹理 B 之前,如何确保 blit 编码器完全完成将数据从纹理 A 复制到纹理 B?我是否甚至需要担心这一点,或者命令缓冲区的串行特性是否已经为我解决了这个问题?
Metal 有栅栏的概念,使用MTLFence 来同步对资源的访问,但我不认为有金属性能着色器在栅栏上等待。 (而 waitForFence: 出现在编码器上。)
如果我不能使用栅栏并且我确实需要同步,推荐的做法是将 blit 编码器排入队列,然后在将着色器排入队列并再次调用 waitUntilCompleted 之前在命令缓冲区上调用 waitUntilCompleted?例如:
id<MTLCommandBuffer> commandBuffer;
// Enqueue blit encoder to copy Texture A -> Texture B
id<MTLBlitCommandEncoder> blitEncoder = [commandBuffer blitCommandEncoder];
[blitEncoder copyFromTexture:...];
[blitEncoder endEncoding];
// Wait for blit encoder to complete.
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
// Scale Texture B -> Texture C
MPSImageBilinearScale *imageScaleShader = [[MPSImageBilinearScale alloc] initWithDevice:...];
[imageScaleShader encodeToCommandBuffer:commandBuffer...];
// Wait for scaling shader to complete.
[commandBuffer commit];
[commandBuffer waitUntilCompleted];
我认为我需要将中间副本复制到纹理 B 的原因是因为 忽略这个脚注,因为我忘记了一些基本的数学原理,并且已经弄清楚如何使缩放变换的平移属性与 clipRect 一起使用。 p>
MPSImageBilinearScale 似乎会缩放其整个源纹理。 clipOffset 对输出很有用,但不适用于实际的缩放或变换。所以需要将贴图从纹理 A 中提取到与贴图本身大小相同的纹理 B 中。然后缩放和变换将“有意义”。
【问题讨论】:
标签: objective-c macos metal metalkit metal-performance-shaders