初始化组共享变量的最佳实践



我正在使用一个大的groupshared变量来进行计算,但最近我发现(困难的是(groupshared内存没有初始化。对于我的用例,我需要对其进行初始化,因为在所有计算之后,我将直接将其复制回纹理。

所以我想问,有什么更好的方法来解决这个问题?主要是性能方面,因为我认为初始化必须作为整个着色器程序的一部分进行。

这就是我目前处理它的方式,但它似乎没有按预期工作,因为一些数据在下一次调度中仍然存在。基本上,每个线程都被分配了一些值来初始化,然后等待其他线程。

#define GroupSize 64
#define FoWMap_Size 4096
groupshared uint _FoWMap[FoWMap_Size];
[numthreads(GroupSize, 1, 1)]
void FOWMapGenerator(uint3 id : SV_DispatchThreadID)
{
uint instPerThread = FoWMap_Size / GroupSize;
[unroll]
for (uint k = 0; k < instPerThread; k++)
{
uint realID = (id.x * instPerThread) + k;
if (realID > FoWMap_Size)
break;

_FoWMap[realID] = 0;
}
//wait for all units to finish
GroupMemoryBarrierWithGroupSync();
...
...
...
}

这是我之前快速而草率的方法:

void InitArray(uint size)
{
for (uint i = 0; i < size; i++)
{
_FoWMap[i] = 0;
}
}
[numthreads(GroupSize, 1, 1)]
void FOWMapGenerator(uint3 id : SV_DispatchThreadID)
{
InitArray(FoWMap_Size);
...
...
...
}

然而,我放弃了这个,因为理论上这意味着每个线程都在完全初始化组共享数组,这在性能方面并不理想。编译器可能正在为我优化这一点,但我不确定。

总而言之,如何初始化组共享数组?我急需建议。

在初始化组共享内存时,应该使用SV_GroupThreadID(组内的本地线程ID(,而不是SV_DispatchThreadID(跨组的全局线程ID(。

否则,您将超出第二组及以上数组索引的范围。