当AppendStructuredBuffer在计算着色器中溢出时会发生什么?

时间:2019-07-10 12:05:18

标签: unity3d glsl buffer-overflow compute-shader hsl

我有一个Unity项目,其中我正在通过计算着色器中的AppendStructuredBuffer<Triangle>写入Append(triangle)

在这种情况下,我知道可能存在的三角形数量的理论限制,因此显而易见的正确方法是相应地调整缓冲区的大小。不过,作为黑客,我正在尝试分配大得多的缓冲区,以便可以由系统的其他部分更有效地处理它们(尤其是读回CPU)。人们可能会想到其他情况,在这些情况下可能不知道或可能会错误地假定特定限制。

显然,这有潜在危险。我敢肯定,在不牺牲性能的前提下,有一些更健壮的方法可以用于我当前的系统(或更广泛地说),但是我并没有(尤其是)寻求建议。

我想知道的是,程序调用{​​{1}}超出了此类缓冲区的容量时,预期的行为是什么。我认为它是未定义的,并且可能会损坏VRAM的其他区域,在某种程度上取决于GPU驱动程序/ DirectX版本等。可能是它是更正式地指定的,但是我无法发现这一点。

当然,即使指定了行为 ,蓄意冒险似乎也有些鲁ck。不过,我想知道:

  • 在内核函数的上下文中是否有可能检测到这样的缓冲区已满(鉴于高度线程化的特性,这可能是不切实际的)。
  • 如果可能的话,对性能的影响是什么。
  • 溢出的后果是什么(在这种情况下,我特别预计会发生错误,但是会发生错误)。
  • 对于不同的硬件供应商,API等,上述所有期望可能会有所不同。

如果多余的数据将被简单地丢失而没有成本,那么这也许是“安全的”。在任何情况下,该系统都可以(例如)定期检查缓冲区是否已满,并做任何可能需要做的额外的工作……剩下的问题是这种系统的调整有多严重。

1 个答案:

答案 0 :(得分:0)

在很多情况下,至少在DirectX中,越界访问被定义为返回0。我仍然不确定写入,但认为有理由相信它们在当前实现中通常是安全的。

根据this specification

  

5.3.10.2使用无序计数和追加缓冲区

     

...   imm_atomic_alloc和imm_atomic_consume后面的计数器没有   上溢或下溢钳位,并且没有反馈给   有关是否发生上溢/下溢的着色器(   计数器)。计数器真正完成的唯一工作就是   生成独特的地址,并方便地与无人机捆绑在一起。

进一步,https://microsoft.github.io/DirectX-Specs/d3d/archive/D3D11_3_FunctionalSpec.htm#inst_IMM_ATOMIC_ALLOC

  

没有计数的限制,因此溢出时会自动结束。

在这些情况下,我认为将“包装”解释为缓冲区的长度并没有错。

因此,据我所知,答案是内部计数器将在Append()上包装,随后的调用最终将覆盖较早的数据。碰巧的是,我当前正在渲染缓冲区而未引用此类计数器(因为我再次对“三角形”进行了传递,以将其变为用于渲染的顶点,而我目前在非AppendBuffer上进行了渲染)。我应该尝试将带有计数的缓冲区传递给该绘制调用,这应该允许我验证我的大多数模型在溢出时是否突然消失。

无论如何,从不破坏系统其他部分的角度来看,该操作应该是安全的,但是引用计数器可能是检测问题的错误方法。