ios*_*v55 3 graphics ios swift metal metalkit
MTLTexture在 CPU 上,我正在收集要发送到片段着色器的对象数组。在任何给定时刻可以有任意数量的这些纹理。如何将MTLTextures 的可变长度数组发送到片段着色器?
示例。)CPU:
var txrs: [MTLTexture] = []
for ... {
txrs.append(...)
}
// Send array of textures to fragment shader.
Run Code Online (Sandbox Code Playgroud)
图形处理器:
fragment half4 my_fragment(Vertex v [[stage_in]], <array of textures>, ...) {
...
for(int i = 0; i < num_textures; i++) {
texture2d<half> txr = array_of_textures[i];
}
...
}
Run Code Online (Sandbox Code Playgroud)
这array人建议的方法不起作用,因为纹理将占用最多 31 个绑定点,此时它将耗尽。
相反,您需要使用参数缓冲区。
因此,要使其发挥作用,您需要第 2 层参数缓冲区支持。argumentBuffersSupport您可以使用 上的属性进行检查MTLDevice。
您可以在此处阅读有关参数缓冲区的更多信息,或观看有关无绑定渲染的讨论。
基本思想是用于MTLArgumentEncoder对参数缓冲区中所需的纹理进行编码。不幸的是,我认为没有直接的方法来编码一堆MTLTextures,所以相反,您可以在着色器中创建一个结构体,如下所示
struct SingleTexture
{
texture2d<half> texture;
};
Run Code Online (Sandbox Code Playgroud)
该texture结构中的 的隐式值为id0。要了解有关 的更多信息,请阅读规范id中的参数缓冲区部分,但它基本上是 ab 中每个条目的唯一索引。
然后,将函数签名更改为
fragment half4 my_fragment(Vertex v [[stage_in]], device ushort& textureCount [[ buffer(0), device SingleTexture* textures [[ buffer(1) ]])
Run Code Online (Sandbox Code Playgroud)
然后,您将需要绑定计数(在大多数情况下使用uint16_t而不是uint32_t)。就像 2(或 4)字节缓冲区一样。set<...>Bytes(您可以为此使用编码器上的函数)。
然后,您需要编译该函数MTLFunction并从中编译该函数,您可以创建一个MTLArgumentEncoderusingnewArgumentEncoderForBufferAtIndex方法。在这种情况下,您将使用缓冲区索引 1,因为这是您的 AB 在函数中绑定的位置。
从中MTLArgumentEncoder您可以得到encodedLength,它基本上是 AB 中一个结构的大小SingleTexture。获得该值后,将其乘以纹理数量,以获得适当大小的缓冲区来对参数缓冲区进行编码。
之后,在您的设置代码中,您可以这样做
for(size_t i = 0; i < textureCount; i++)
{
// We basically just offset into an array of SignlaTexture
[argumentEncoder setArgumentBuffer:<your buffer you just created> offset:argumentEncoder.encodedLength * i];
[argumentEncoder setTexture:textures[i] atIndex:0];
}
Run Code Online (Sandbox Code Playgroud)
然后,当您完成对缓冲区的编码后,您可以保留它,直到纹理数组发生变化(您不需要每帧都重新编码)。
然后,您需要将参数缓冲区绑定到缓冲区绑定点 1,就像绑定任何其他缓冲区一样。
您需要做的最后一件事是确保间接引用的所有资源都驻留在 GPU 上。由于您将纹理编码为 AB,驱动程序无法知道您是否使用它们,因为您没有直接绑定它们。
为此,请使用useResource或useResources改变您正在使用的编码器,有点像这样:
[encoder useResources:&textures[0] count:textureCount usage:MTLResourceUsageRead];
Run Code Online (Sandbox Code Playgroud)
这有点拗口,但这是将任何你想要的东西绑定到着色器的正确方法。
| 归档时间: |
|
| 查看次数: |
1046 次 |
| 最近记录: |