ken*_*nyc 5 macos objective-c metal metalkit metal-performance-shaders
我正在尝试更好地了解与Metal Performance Shaders
和一起使用时的同步要求MTLBlitCommandEncoder
。
我有一个MTLCommandBuffer
设置如下:
使用MTLBlitCommandEncoder
到纹理A的区域复制到纹理B. 纹理A比纹理B.大我提取纹理特征的一个“瓦”,并复制成质地B.
使用MPSImageBilinearScale
金属性能着色器,将纹理B作为源纹理,将第三纹理纹理C作为目标。此金属性能着色器将缩放并可能将纹理B的内容转换为纹理C。
在金属性能着色器开始尝试缩放纹理B之前,如何确保blit编码器完全完成了从纹理A到纹理B的数据复制?我什至不必担心这个问题,还是命令缓冲区的串行特性已经为我解决了这个问题?
Metal具有MTLFence
用于同步访问资源的围栅的概念,但是我仍然看不到要在围栅上等待Metal Performance Shader。(而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];
Run Code Online (Sandbox Code Playgroud)
我认为我需要将中间副本复制到纹理B中的原因是因为它忽略此脚注,是因为我忘记了一些基本的数学原理,并且从那时起就已经弄清楚了如何使scale transform的translation属性与clipRect一起工作。MPSImageBilinearScale
似乎可以缩放其整个源纹理。该clipOffset
是对输出非常有用,但它并不适用于实际的缩放或变换。因此需要将图块从纹理A提取到与图块本身大小相同的纹理B中。然后缩放和变换将“有意义”。
Metal 会为您解决这个问题。驱动程序和 GPU 在命令缓冲区中执行命令,就像以串行方式一样。(“好像”允许并行或乱序运行以提高效率,但前提是结果与串行执行时的结果相同。)
当 CPU 和 GPU 使用相同的对象时,就会出现同步问题。还可以在屏幕上呈现纹理。(您不应该渲染到屏幕上呈现的纹理。)
Metal Programming Guide 中有一个部分涉及着色器对资源的读写访问,这并不完全相同,但应该让您放心:
记忆障碍
命令编码器之间
在给定命令编码器中执行的所有资源写入在下一个命令编码器中可见。对于渲染和计算命令编码器都是如此。
在渲染命令编码器中
对于缓冲区,原子写入对跨多个线程的后续原子读取可见。
对于纹理,该
textureBarrier
方法确保在给定绘制调用中执行的写入对下一个绘制调用中的后续读取可见。在计算命令编码器中
在给定内核函数中执行的所有资源写入在下一个内核函数中可见。
归档时间: |
|
查看次数: |
735 次 |
最近记录: |