如何向 glDispatchComputeIndirect 提供工作组的计算数量?

How to provide computed number of workgroups to glDispatchComputeIndirect?

如果你想在第一个分派中计算第二个分派的线程数,glDispatchComputeIndirect 应该如何工作?

我有一个在缓冲区上运行的计算着色器,检查元素的值是否有效,然后在原子计数器的帮助下有条件地将元素的索引写入另一个缓冲区。我现在如何最有效地为每个写入索引分派第二个计算着色器和一个线程?

可能最慢的解决方案是读回原子计数器的值 n 和 glDispatchCompute(n / workgroupSize, 1, 1 ).

我考虑过使用 glDispatchComputeIndirect 并在第一个计算着色器中准备调度间接缓冲区。但是调度间接缓冲区中的值应该是工作组的整数,而不是线程的数量,所以我不能简单地为每个写入的元素增加一个原子计数器。我可以用一个线程分派另一个计算着色器,该线程仅将写入元素的数量除以工作组大小,但这不是一个合适的解决方案。

我还可以使用原子 "element counter" 来计算写入的元素,检查每个线程中的 return 值并在 return 时递增另一个原子 "workgroup counter" atomicAdd 的值可以被工作组大小整除。这为我节省了 return 到 CPU 的行程和第三次调度,但代价是另一个原子计数器。但我现在想不出更好的解决方案。

您不需要 "threads" 的数量。您需要工作组的数量。所以计算你需要计算的东西。

第二次调度调用中的工作组数与您计算的 "threads" 数之间的关系很简单:(threadCount / threadPerGroup),其中 threadPerGroup 是工作组中的调用数第二个计算着色器。

现在您不需要计算所有 threadCount 来计算这个。您真正需要做的就是每次递增 threadCount 超过 threadPerGroup 倍数时触发一个原子计数器。这很容易,因为 atomicCounterIncrement returns 原子计数器的先前值。

因此您的代码将如下所示:

if(<I should add a thread>)
{
  uint oldThreadCount = atomicCounterIncrement(threadCount); //Returns old value
  if(oldThreadCount % threadPerGroup == 0) //That means `threadCount` is now in the next group.
    atomicCounterIncrement(groupCount);
}