为访问体素的多个线程获取唯一的缓冲区索引

我试图实现“基于八叉树的实时全局照明稀疏体素化”的一部分。

基本上只是体素化,我已经完成了。

“体素片段列表”结构,基本上是几个预先分配的体素位置和属性的缓冲区。

使用原子计数器创建位置缓冲区非常简单,并且可以使用atomic-comp-swap或atomic-add来确保它仅由一个线程写入

layout(r32ui, binding = 0) uniform coherent volatile uimage3D     Voxels;
layout(r32ui, binding = 1) uniform coherent volatile uimageBuffer positionBuffer;

void writeVoxels(ivec3 coord)
{
    uint voxelVal = imageAtomicCompSwap(Voxels, coord, 0, 1);

    if(voxelVal == 0)
    {
        int index = 3*int(atomicCounterIncrement(voxelCounter));
        imageStore(positionBuffer, index+0, uvec4(coord.x));
        imageStore(positionBuffer, index+1, uvec4(coord.y));
        imageStore(positionBuffer, index+2, uvec4(coord.z));
    }
}

但是,在多个线程正在写入相同的体素位置的情况下,我如何确保所有线程都能获得适当的索引? 如上所示,正确的索引仅对1个线程有效。

像下面的东西

#extension GL_NV_shader_atomic_float : require

layout(r32ui, binding = 0) uniform coherent volatile uimage3D     Voxels;
layout(r32ui, binding = 1) uniform coherent volatile uimageBuffer positionBuffer;
layout(r32f,  binding = 2) uniform coherent volatile  imageBuffer colorBuffer;

void writeVoxels(ivec3 coord, vec3 color)
{
    uint voxelVal = imageAtomicAdd(Voxels, coord, 1);

    int index;
    if(voxelVal == 0)   //This ensure that only 1 thread performs the
    {                   //atomicCounterIncrement
        index = 3*int(atomicCounterIncrement(voxelCounter));
        imageStore(positionBuffer, index+0, uvec4(coord.x));
        imageStore(positionBuffer, index+1, uvec4(coord.y));
        imageStore(positionBuffer, index+2, uvec4(coord.z));
    }

    //Need index to be valid here

    imageAtomicAdd(colorBuffer, index+0, color.x);
    imageAtomicAdd(colorBuffer, index+1, color.y);
    imageAtomicAdd(colorBuffer, index+2, color.z);
}

我尝试了一堆不同的方法。 这篇论文中唯一的提示是

为了管理(体素片段)列表,我们将下一个可用条目的索引(也是列表中体素片段的数量的计数器)存储为另一个缓冲对象内的单个32位值。

这听起来像它只是描述原子计数器的缓冲区对象。 为了保持简单(目前),我没有计算运行平均值(如本文所述),只需将颜色相加并在渲染时除以访问计数即可。


我不确定,但我认为你不必使用imageAtomicAdd将具有相同坐标的体素存储到相同的体素片段中。 这意味着一些不同的体素片段可能具有相同的3d坐标。

这是我的代码。

const uint VOXEL_FRAGMENT_SIZE = 3;
layout(r32ui, binding = 0) uniform coherent volatile writeonly uimageBuffer voxelFragmentBuffer;
layout(binding=0, offset=0) uniform atomic_uint voxelIndexCounter;
// ...
int voxelIndex = int(atomicCounterIncrement( voxelIndexCounter ))* VOXEL_FRAGMENT_SIZE;
imageStore( voxelFragmentBuffer, voxelIndex+0, uvec4( convIVec3ToR32UI( voxelPosition ) ) );
imageStore( voxelFragmentBuffer, voxelIndex+1, uvec4( convVec4ToRGBA8( vec4( normal*127, 2.0 ) ) ) );
imageStore( voxelFragmentBuffer, voxelIndex+2, uvec4( convVec4ToRGBA8( color*255 ) ) );

我还没有完成实现,我可能是错的,但我认为具有相同坐标的体素将在22.5.4节点细分中的下一个过程中合并。

我想知道您提交此主题后是否有任何进展。

链接地址: http://www.djcxy.com/p/37173.html

上一篇: Obtaining a unique buffer index for multiple threads accessing a voxel

下一篇: Multiple textures in one shader with ZBuffer and alpha blending in 2D