在尝试使用Metal Performance Shaders
和MTLBlitCommandEncoder
时,我试图更好地理解同步要求。
我有一个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中的原因是因为忽略此脚注,因为我忘记了一些基本的数学原理,并且此后就想出了如何使clip ect的缩放变换的转换属性起作用。 >
MPSImageBilinearScale
似乎可以缩放其整个源纹理。 clipOffset
对于输出很有用,但不适用于实际缩放或变换。因此需要将图块从纹理A提取到与图块本身大小相同的纹理B中。然后缩放和变换将是“有意义的”。
答案 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方法,而不要自己滚动。