使用计算着色器的Mipmapping

6
我有一个体素化场景的颜色、法线和其他数据的3D纹理,由于其中一些数据不能仅以平均值计算出来,所以我需要自己计算mip等级。 3D纹理的大小为(128+64)x 128 x 128,额外的64 x 128 x 128用于mip级别。
因此,当我取第一个mip级别时,它位于(0, 0, 0),大小为128 x 128 x 128,并将体素复制到第二个级别,即(128, 0, 0),数据会显示在那里,但是一旦我将第二级别从(128, 0, 0)复制到第三级别的(128, 0, 64),数据就不会显示在第三级别。
着色器代码:
#version 450 core

layout (local_size_x = 1,
        local_size_y = 1,
        local_size_z = 1) in;

layout (location = 0) uniform unsigned int resolution;
layout (binding = 0, rgba32f) uniform image3D voxel_texture;

void main()
{
    ivec3 index = ivec3(gl_WorkGroupID);
    ivec3 spread_index = index * 2;

    vec4 voxel = imageLoad(voxel_texture, spread_index);
    imageStore(voxel_texture, index + ivec3(resolution, 0, 0), voxel);

    // This isn't working
    voxel = imageLoad(voxel_texture, spread_index + 
                      ivec3(resolution, 0, 0));
    imageStore(voxel_texture, index + ivec3(resolution, 0, 64), voxel);
}

着色器程序被调用。
glUniform1ui(0, OCTREE_RES);

glBindImageTexture(0, voxel_textures[0], 0, GL_TRUE, 0, GL_READ_WRITE, 
                   GL_RGBA32F);

glDispatchCompute(64, 64, 64);

我不知道是否遗漏了一些基础知识,这是我的第一个计算着色器。我还尝试使用内存屏障,但这没有改变任何东西。

1个回答

3

你不能指望第二次图像加载读取你在第一次存储中刚写入的纹素。

而且没有办法在“本地”工作组之外同步访问。

你需要:

  • 使用多个内核调用来执行每个层
  • 重写你的着色器逻辑,使你总是从“原始”区域获取。

对,我以为屏障可以全局生效。你知道使用一个128x128x128的"全局"工作组和你提供的两个选项相比会不会更低效? - FamZ
2
@FamZ:你假设一个128x128x128的工作组大小是可能的。 任何硬件支持的工作项最大数量为1536。这就像比128 ^ 3还要多。你想要的根本不可能。更好的方法是重新构造算法,并可能重塑数据,以适应合理的工作组大小。 - Nicol Bolas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接