我可以让落沙游戏在GPU上并行运行吗?

时间:2018-11-10 16:54:10

标签: gpu simulation metal

我一直在尝试用Metal组合一个落砂游戏,该游戏使用计算机着色器完成工作。最初的工作看起来还不错,直到遇到以下问题:

Sand particles

在一次更新中,粒子1A和1B都可以流入空间T。

顺序

在顺序循环中,我了解了如何简单地将1A移至T,然后在评估1B时,我看到该空间已被填充。

并行

我的问题是,使用GPU,检查1A和1B的代码都在不同的线程上运行,因此在一个更新循环中,它们都可以移动到位置T,实际上杀死了其中一个。

那么我的问题是,我可以对此做出并行解决方案,还是只能依次解决?

这是我的计算代码,为640 x 480网格中的每个像素运行一个GPU线程:

struct Particle {
    float4 color;
    int live;
    int particleType;
};


kernel void calculateFrame(
                           device Particle *src [[buffer(1)]],
                           device Particle *dst [[buffer(2)]],
                           uint2 threadgroup_position_in_grid   [[ threadgroup_position_in_grid ]],
                           uint2 thread_position_in_threadgroup [[ thread_position_in_threadgroup ]],
                           uint2 threads_per_threadgroup        [[ threads_per_threadgroup ]]) {

    uint2 gid = threadgroup_position_in_grid;
    int index = (gid * 640) + gid;
    Particle particle = src[index];

    Particle bottom = src[toLinear( gid + uint2( 0, 1))]; //bottom
    Particle bottomLeft = src[toLinear( gid + uint2(-1, 1))]; //bottom left
    Particle bottomRight = src[toLinear( gid + uint2( 1, 1))]; //bottom right

    if (particle.live == 1 && particle.particleType == SAND) { // move down

        if (bottom.live == 0) {

            dst[index].live = 0;

            dst[toLinear( gid + uint2( 0, 1))].particleType = particle.particleType;
            dst[toLinear( gid + uint2( 0, 1))].color = particle.color;
            dst[toLinear( gid + uint2( 0, 1))].live = 1;

        }
        else if (bottomLeft.live == 0) { // move down to the left if clear
            dst[index].live = 0;

            dst[toLinear( gid + uint2( -1, 1))].particleType = particle.particleType;
            dst[toLinear( gid + uint2( -1, 1))].color = red;
            dst[toLinear( gid + uint2( -1, 1))].live = 1;


        }
        else if (bottomRight.live == 0) { // move down to the right if clear

            dst[index].live = 0;

            dst[toLinear( gid + uint2( 1, 1))].particleType = particle.particleType;
            dst[toLinear( gid + uint2( 1, 1))].color = red;
            dst[toLinear( gid + uint2( 1, 1))].live = 1;
        }
        else { // cant move
            dst[index] = src[index];
        }

    }

    if (particle.particleType == WALL) {
        dst[index] = particle;
        dst[index].live = 1;
    }

    if (particle.particleType == ERASER) {
        dst[index].color = blue;
        dst[index].live = 0;
    }
}

0 个答案:

没有答案