Obtaining a unique buffer index for multiple threads accessing a voxel
I'm trying to implement a portion of "Octree-Based Sparse Voxelization for Real-Time Global Illumination".
Basically just the voxelization, which I am already done with.
And the "Voxel-fragment list" construction, which is basically several pre-allocated buffers of voxel positions and attributes.
Its pretty easy to create the position buffer using an atomic counter and either an atomic-comp-swap or atomic-add to ensure it is only written to by one thread
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));
}
}
But, in cases where multiple threads are writing to same voxel location how can I ensure all threads get the appropriate index? As its shown above the correct index is only valid for 1 thread.
Something like below
#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);
}
I've tried a bunch of different approaches to this. The only hint in the paper is
To mange the (voxel-fragment) list, we store the index of the next available entry (that is also a counter of the number of voxel fragments in the list) as a single 32-bit value inside another buffer object.
Which sounds like its just describing the buffer object for the atomic counter. In the interest of keeping things simple (for now), I'm not computing a running average (as described in the paper), simply summing the colors and dividing by the access count when rendering.
I'm not sure but I think you don't have to use imageAtomicAdd to store voxels having same coords into the same voxel fragment. That means some distinct voxel fragments may have same 3d coords.
Here's my codes.
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 ) ) );
I've not completed implementation yet and I could be wrong, but I think voxels having same coords will be merged in the next process which is in 22.5.4 Node Subdivision.
I'd like to know if you have any progress since you submitted this thread.
链接地址: http://www.djcxy.com/p/37174.html上一篇: 网格中缺少三角形
下一篇: 为访问体素的多个线程获取唯一的缓冲区索引