计算着色器如何分割任务?
Base
在这个例子中,通过指定local_size_x = 64,这是否意味着每个工作组将自动拥有64个线程,并且由于输入是一个vec2数组,它知道在单独的线程上只通过main与每个vec2?
另外,如果着色器为每个vec2输入生成10 vec2然后我想对每个进行不同的操作,每个都在一个单独的线程上,我该怎么办?最初的64个线程将分支到640.这可以在同一个着色器中完成,还是必须再制作第二个?
答案 0 :(得分:1)
在这个例子中,通过指定local_size_x = 64,这是否意味着每个工作组将自动拥有64个线程,并且由于输入是一个vec2数组,它知道在单独的线程上只通过main与每个vec2?
是的,这就是invocations within a work group are defined。
的方式另外,如果着色器为每个vec2输入生成10 vec2,我会怎么做?然后我想对每个vec2做一些不同的事情,每个都在一个单独的线程上。
你如何做到完全取决于你。但是,是的,它必须是一个不同的着色器。计算着色器无法创建调用。不是直接的。
在工作组中拥有工作项的目的是允许这些本地调用相互通信并帮助他们计算某些东西。如果您没有任何shared
variables or barrier
calls,那么您的本地尺寸并不重要(嗯,不是从功能角度来看。本地尺寸会影响性能)。
因此,您应该根据您打算在特定调度操作中推送的工作量来选择您的本地大小。现在,您必须以64的整数倍处理vec2
。如果同一组的多次调用正在读取相同的值,那么您需要重新评估整个组将执行的工作量。
工作组中调用次数的限制取决于硬件,但不会低于1024.因此,您可以有一些空间可以玩。
在新系统中,如果您仍然希望工作组调用来处理64个输入,那么显然工作组必须具有总计640的本地大小。我可能会建议更小的粒度,如8,留下您的本地大小总共80岁。
无论您选择何种尺寸,实际指定此尺寸的最佳方式是使用本地尺寸具有多个尺寸的事实。 X维应该引用输入索引,Y维是X输入的输出索引。所以Y大小为10,X大小为8或64或者你想要的任何东西。
因此,当您去获取输入时,您需要的索引是:
const uvec3 size_mult = {1, gl_NumWorkGroups.x, gl_NumWorkGroups.x * gl_NumWorkGroups.y};
const uint input_index = gl_WorkGroupSize.x * dot(gl_WorkGroupID, size_mult) + gl_LocalInvocationID.x;
输出的索引是:
const uint output_index = gl_WorkGroupSize.y * input_index + gl_LocalInvocationID.y;