Unity3d 统一计算着色器同步

Unity3d 统一计算着色器同步,unity3d,parallel-processing,gpgpu,hlsl,Unity3d,Parallel Processing,Gpgpu,Hlsl,我今天需要你的帮助!我开始在一个非常简单的用例中使用计算着色器: 我有一个深度摄影机,我想计算摄影机附近对象的边界框 但我有太多的像素需要处理,我想使用GPGPU、计算着色器和并行化来计算 我目前有一个问题,当我运行我的程序时,我有相同的最小和最大坐标。所以我认为我的所有组和线程都同时写入我的StructuredBuffers 你知道怎么做吗 以下是我的计算着色器的代码: #pragma kernel ComputeBoundingBox //We define the size of a g

我今天需要你的帮助!我开始在一个非常简单的用例中使用计算着色器: 我有一个深度摄影机,我想计算摄影机附近对象的边界框

但我有太多的像素需要处理,我想使用GPGPU、计算着色器和并行化来计算

我目前有一个问题,当我运行我的程序时,我有相同的最小和最大坐标。所以我认为我的所有组和线程都同时写入我的StructuredBuffers

你知道怎么做吗

以下是我的计算着色器的代码:

#pragma kernel ComputeBoundingBox

//We define the size of a group in the x, y and z directions, y and z direction will just be one (because 1D array is used for depthData)
#define thread_group_size_x 1024
#define thread_group_size_y 1
#define thread_group_size_z 1
//Size of the depthData picture
#define width 512;
#define height 424;

//DataBuffer = depthData of the camera
//minBuffer, maxBuffer, array of size 3 with min/max x, y and z
//mask = image area to process
RWStructuredBuffer<float> dataBuffer;
globallycoherent RWStructuredBuffer<float>minBuffer;
globallycoherent RWStructuredBuffer<float> maxBuffer;
RWStructuredBuffer<float> mask;


float xValue = 0, yValue = 0, zValue = 0;

[numthreads(thread_group_size_x, thread_group_size_y, thread_group_size_z)]
void ComputeBoundingBox(uint3 id : SV_DispatchThreadID)
{
    //xValue and yValue = [X,Y] index in 2D
    //zValue = depthValue of [X,Y] index
    xValue = (id.x + 1) % width;
    yValue = (id.x + 1) / width;
    zValue = dataBuffer[id.x];

    if (mask[id.x] > 0.49)
    {
        if (zValue > 500 && zValue < 1500)
        {
            if (xValue < minBuffer[0])
                minBuffer[0] = xValue;
            else if (xValue > maxBuffer[0])
                maxBuffer[0] = xValue;
            if (yValue < minBuffer[1])
                minBuffer[1] = yValue;
            else if (yValue > maxBuffer[1])
                maxBuffer[1] = yValue;
            if (zValue < minBuffer[2])
                minBuffer[2] = zValue;
            else if (zValue > maxBuffer[2])
                maxBuffer[2] = zValue;
        }
    }
}
void RunShader()
    {
        dataBuffer.SetData(depthDataFloat);
        minDataBuffer.SetData(reinitialiseMinBuffer);
        maxDataBuffer.SetData(reinitialiseMaxBuffer);
        maskBuffer.SetData(mask);

        computeShader.SetBuffer(_kernel, "dataBuffer", dataBuffer);
        computeShader.SetBuffer(_kernel, "minBuffer", minDataBuffer);
        computeShader.SetBuffer(_kernel, "maxBuffer", maxDataBuffer);
        computeShader.SetBuffer(_kernel, "mask", maskBuffer);

        computeShader.Dispatch(_kernel, 212, 1, 1);
    }

在您的情况下,您不处理数据争用,因此多个线程可以在同一位置写入

为了确保写入是原子的,需要使用互锁函数。 这些仅适用于uint,但在您的情况下(假设深度数据始终大于0), 浮点数的二进制比较将匹配其值的比较

以下是修改后的着色器:

#pragma kernel ComputeBoundingBox

#define thread_group_size_x 1024
#define thread_group_size_y 1
#define thread_group_size_z 1
//Size of the depthData picture
#define width 512;
#define height 424;

//DataBuffer = depthData of the camera
//minBuffer, maxBuffer, array of size 3 with min/max x, y and z
//mask = image area to process
StructuredBuffer<float> dataBuffer;
RWStructuredBuffer<float>minBuffer;
RWStructuredBuffer<float> maxBuffer;
StructuredBuffer<float> mask;

[numthreads(thread_group_size_x, thread_group_size_y, thread_group_size_z)]
void ComputeBoundingBox(uint3 id : SV_DispatchThreadID)
{
    //xValue and yValue = [X,Y] index in 2D
    //zValue = depthValue of [X,Y] index
    uint xValue = (id.x + 1) % width;
    uint yValue = (id.x + 1) / width;
    uint zValue = asuint(dataBuffer[id.x]);

    if (mask[id.x] > 0.49)
    {
        if (zValue > 500 && zValue < 1500)
        {
             uint oldValue;
             InterlockedMin(minBuffer[0],xValue,oldValue); 
             InterlockedMax(maxBuffer[0],xValue,oldValue); 

             InterlockedMin(minBuffer[1],yValue,oldValue); 
             InterlockedMax(maxBuffer[1],yValue,oldValue);

             InterlockedMin(minBuffer[2],zValue,oldValue); 
             InterlockedMax(maxBuffer[2],zValue,oldValue);
        }
    }
}
#pragma内核计算边界框
#定义线程组大小1024
#定义线程组大小1
#定义线程组大小1
//深度数据图片的大小
#定义宽度512;
#定义高度424;
//DataBuffer=相机的深度数据
//minBuffer、maxBuffer、大小为3且具有最小/最大x、y和z的数组
//掩码=要处理的图像区域
StructuredBuffer-dataBuffer;
RWStructuredBufferminBuffer;
rwStructuredBufferMaxBuffer;
结构缓冲掩模;
[numthreads(线程组大小x、线程组大小y、线程组大小z)]
无效计算边界框(uint3 id:SV_DispatchThreadID)
{
//xValue和yValue=[X,Y]二维索引
//zValue=[X,Y]索引的深度值
uint xValue=(id.x+1)%width;
uint yValue=(id.x+1)/宽度;
uint zValue=asuint(数据缓冲[id.x]);
如果(掩码[id.x]>0.49)
{
如果(zValue>500&&zValue<1500)
{
单位价值;
InterlocatedMin(最小缓冲区[0],xValue,oldValue);
InterlocatedMax(maxBuffer[0],xValue,oldValue);
InterlocatedMin(最小缓冲区[1],yValue,oldValue);
InterlocatedMax(maxBuffer[1],yValue,oldValue);
InterlockedMin(最小缓冲区[2],zValue,oldValue);
InterlocatedMax(maxBuffer[2],zValue,oldValue);
}
}
}
我确实也将dataBuffer和mask指定为StructuredBuffers(因为您只读取它们,所以将它们绑定为StructuredBuffers通常会更快)

此外,您还需要确保首先使用合适的值清除最小/最大缓冲区(即,在调用该着色器之前)

这可以通过一个简单的计算着色器(分派一个线程)完成:

RWStructuredBuffer-minBuffer;
rwStructuredBufferMaxBuffer;
[numthreads(1,1,1)]
无效ClearBuffers(uint3 id:SV_DispatchThreadID)
{
uint最大uint=0xFFFFFF;
uint minUint=0;
minBuffer[0]=asfloat(maxiint);
minBuffer[1]=asfloat(maxiint);
minBuffer[2]=asfloat(maxiint);
maxBuffer[0]=asfloat(minUint);
maxBuffer[1]=asfloat(minUint);
maxBuffer[2]=asfloat(minUint);
}
请注意,在这种情况下,uint/float别名将起作用,因此不需要执行任何转换

RWStructuredBuffer<float> minBuffer;
RWStructuredBuffer<float> maxBuffer;

[numthreads(1, 1, 1)]
void ClearBuffers(uint3 id : SV_DispatchThreadID)
{
     uint maxUint = 0xffffffff;
     uint minUint = 0;
     minBuffer[0]= asfloat(maxUint);
     minBuffer[1]= asfloat(maxUint);
     minBuffer[2]= asfloat(maxUint);

     maxBuffer[0]= asfloat(minUint);
     maxBuffer[1]= asfloat(minUint);
     maxBuffer[2]= asfloat(minUint);
}