如何将Metal Performance Shader与MTLBlitCommandEncoder同步?

时间:2018-08-24 15:29:48

标签: objective-c macos metal metalkit metal-performance-shaders

在尝试使用Metal Performance ShadersMTLBlitCommandEncoder时,我试图更好地理解同步要求。

我有一个MTLCommandBuffer,其设置如下:

  • 使用MTLBlitCommandEncoder将纹理A的一个区域复制到纹理B。纹理A大于纹理B。我从纹理A中提取“平铺”并将其复制到纹理中B。

  • 使用MPSImageBilinearScale金属性能着色器,将纹理B作为源纹理,将第三纹理纹理C作为目标。这种金属性能着色器将缩放并可能将纹理B的内容转换为纹理C。

在金属性能着色器开始尝试缩放纹理B之前,如何确保blit编码器完全完成了从纹理A到纹理B的数据复制?我什至不必担心这个问题,还是命令缓冲区的串行特性已经为我解决了这个问题?

金属具有使用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中的原因是因为MPSImageBilinearScale似乎可以缩放其整个源纹理。 clipOffset对于输出很有用,但不适用于实际缩放或变换。因此需要将图块从纹理A提取到与图块本身大小相同的纹理B中。然后缩放和变换将是“有意义的”。忽略此脚注,因为我忘记了一些基本的数学原理,并且此后就想出了如何使clip ect的缩放变换的转换属性起作用。

2 个答案:

答案 0 :(得分:4)

金属为您解决这个问题。驱动程序和GPU以串行方式在命令缓冲区中执行命令。 (“虽然”允许并行运行或无序运行以提高效率,但前提是结果与串行完成时相同。)

当CPU和GPU都使用相同的对象时,会出现同步问题。还可以在屏幕上呈现纹理。 (您不应该渲染到屏幕上呈现的纹理。)

有一个section of the Metal Programming Guide处理着色器对资源的读写访问,这并不完全相同,但是应该向您保证:

  

内存障碍

     

在命令编码器之间

     

在给定命令编码器中执行的所有资源写入均可见   在下一个命令编码器中。渲染和计算均是如此   命令编码器。

     

在渲染命令编码器内

     

对于缓冲区,原子写入对于后续的原子读取可见   跨多个线程。

     

对于纹理,for /L %a in () do ( cls & echo 1- Create password & echo 2- Check password & echo/ & choice /N /C 12 /M "What do you want to do? " & cls & (if not errorlevel 2 ( set /p "pass=What do you want your password to be?: " & (call echo %%pass%%)>test.txt ) else ( set /p "pass=What is your password? " & (call echo %%pass%%)>text.txt & fc test.txt text.txt >nul & if not errorlevel 1 ( echo You are right !!! ) else ( echo You are wrong !!! ) )) & echo/ & pause ) 方法可确保写入   在给定的绘图调用中执行的操作对于后续读取操作可见   下一次抽奖。

     

在Compute Command Encoder中

     

在给定的内核函数中执行的所有资源写入都是可见的   在下一个内核函数中。

答案 1 :(得分:0)

MPS位于Metal(大部分)上。它并不能取代它(大部分情况下)。您可能会假设它使用的是常用的命令编码器。

在某些区域需要MTLFence,特别是在与渲染编码器和MTLHeaps互操作时。如果可用,请在MPSImages和缓冲区类型上使用syncize方法,而不要自己滚动。