gpt4 book ai didi

ios - 有没有一种方法可以一次绑定(bind) Assets 而不是每个命令编码器?

转载 作者:行者123 更新时间:2023-12-05 03:27:01 29 4
gpt4 key购买 nike

我正在使用计算内核渲染顶点/片段着色器。

每一帧我都以通常的方式绑定(bind)大型资源(例如 450MB 纹理):

computeEncoder.setTexture(highResTexture, index: 0)
computeEncoder.setBuffer(largeBuffer, offset: 0, index: 0)
...
renderEncoder.setVertexTexture(highResTexture, index: 0)
renderEncoder.setVertexBuffer(largeBuffer, offset: 0, index: 0)

单个纹理的带宽接近 1GB,而且我有更多 Assets ,总计几百兆,所以我为每一帧绑定(bind)了大约 1.5GB。

有没有办法将纹理/缓冲区绑定(bind)到 GPU 一次,这样它们就可以在内核和顶点函数中使用,而无需绑定(bind)每一帧?

我可能是错的,但我认为在最近的几个 WWDC 之一中引入了一些东西,所以我想我会要求确保我没有遗漏任何东西。

编辑:

通过在顶点函数中简单地绑定(bind)一个纹理,我已经在计算编码器中绑定(bind)了它,它确实显示了更多的纹理带宽使用,即使我没有将它用于捕获。

GPU 读取带宽:

  • 6.3920 GiB/s,无绑定(bind)
  • 7.1919 GiB/s,具有绑定(bind)

不绑定(bind)纹理: enter image description here

绑定(bind)纹理但不以任何方式使用它: enter image description here

此外,如果它像您描述的那样工作,为什么使用多个命令编码器会警告浪费带宽?如果我使用多个发射器,每个发射器都有一个单独的编码器,即使它们绑定(bind)相同的资源,我也会收到性能警告:

enter image description here

最佳答案

我觉得你很困惑。将纹理设置为命令编码器不会消耗带宽。在着色器中读取它或对其进行采样。

当您为编码器设置纹理或任何其他缓冲区时,发生的情况是驱动程序使用某种机制将少量元数据传递给着色器,可能是您作为 API 用户看不到的一些内部缓冲区。它不会在任何地方“加载”纹理。在着色器中标记为 constant 地址缓冲区的缓冲区是一个异常(exception),因为这些缓冲区可能被 GPU 预取以获得更好的性能。

发生的另一件事是资源成为驻留,这意味着 GPU 驱动程序将映射 GPU 地址虚拟内存表中的地址范围以指向存储纹理内容的物理内存.这也不会消耗内存,但会消耗可用的虚拟地址空间。在某些情况下,您可能会用完虚拟地址空间,但这不是带宽问题。

不过,如果您确实有很多 纹理,您实际上可能会花费大量 CPU 时间来编码那些 setTexture 命令。相反,您可以使用参数缓冲区。如果您的目标硬件支持第 2 层参数缓冲区,您可以将每个纹理放在参数缓冲区中。这将需要对所有这些纹理调用 useResource,因为驱动程序需要知道您将使用这些纹理来使它们驻留,因此您仍将花费 CPU 时间对这些命令进行编码。为避免这种情况,您可以从一个或多个堆中分配所有纹理并在这些堆上调用 useHeaps。这将使整个堆驻留,并且您不需要对单个资源调用 useResource。关于这个话题有很多 WWDC 演讲,最新的是 Explore bindless rendering in Metal .

但再次重申:我在这里提到的任何内容都不会“浪费”带宽。

更新:

使用参数缓冲区的一个非常基本的例子是像这样使用它。

let argumentDescriptor = MTLArgumentDescriptor()
argumentDescriptor.index = 0
argumentDescriptor.dataType = .texture
argumentDescriptor.textureType = .type2D

let argumentEncoder = MTLArgumentEncoder(arguments: [argumentDescriptor])

let argumentBuffer = device.makeBuffer(length: argumentEncoder.encodedLength, options: [.storageModeShared])

argumentEncoder.setArgumentBuffer(argumentBuffer, offset: 0)
argumentEncoder.setTexture(someTexture, index: 0)

commandEncoder.setBuffer(argumentBuffer, offset: 0, index: 0)
commandEncoder.useResource(someTexture, usage: .read)

然后在着色器中,您将编写如下结构:

struct MyTexture 
{
texture2d<float> texture [[ id(0) ]];
};

然后像这样绑定(bind)

device MyTexture& myTexture [[ buffer(0) ]]

并像使用任何其他结构一样使用它。这是一个非常基本的示例,您实际上可以使用反射从函数和绑定(bind)索引中为您创建那些 MTLArgumentEncoders

关于ios - 有没有一种方法可以一次绑定(bind) Assets 而不是每个命令编码器?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/71563690/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com