使用Vulkan在片段着色器中缓慢纹理获取

时间:2016-08-15 10:46:37

标签: glsl vulkan ssao

我正在做一个内核大小为64的SSAO着色器。

SSAO片段着色器:

const int kernelSize = 64;
for (int i = 0; i < kernelSize; i++) {
        //Get sample position
        vec3 s = tbn * ubo.kernel[i].xyz;
        s = s * radius + origin;
        vec4 offset = vec4(s, 1.0);
        offset = ubo.projection * offset;
        offset.xy /= offset.w;
        offset.xy = offset.xy * 0.5 + 0.5;
        float sampleDepth = texture(samplerposition, offset.xy).z;
        float rangeCheck = abs(origin.z - sampleDepth) < radius ? 1.0 : 0.0;
        occlusion += (sampleDepth >= s.z ? 1.0 : 0.0) * rangeCheck;
    }

samplerposition纹理的格式为VK_FORMAT_R16G16B16A16_SFLOAT,并使用标记VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT上传。

我正在使用带有nvidia K1100M显卡的笔记本电脑。如果我在renderdoc中运行代码,则此着色器需要 114 ms 。如果我将kernelSize更改为1,则需要 1 ms

这个纹理获取时间是否正常?或者可能是我在某处设置了错误的东西?

就像布局转换没有完成一样,纹理位于VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL而不是VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL

2 个答案:

答案 0 :(得分:4)

GPU内存依赖于大量的缓存使用,如果彼此靠近的片段不会对彼此相邻的纹素进行采样,这种情况非常有限 - 也称为缺乏空间相干性。对于纹理的随机访问与线性,连贯访问相比,我预计会减少10倍或更多。当使用大半径时,SSAO非常容易发生这种情况。

我建议使用更小的半径并优化纹理访问。你正在采样4个16位浮点数,但你只使用了一个。将深度模糊到单独的16位深度图像应该可以轻松实现4倍的加速。

答案 1 :(得分:1)

您正在计算片段着色器上的纹理坐标,这意味着您不允许GPU预取纹理。更好地计算Vertex着色器上的所有纹理坐标,并将其作为变化传递。

更新: 我建议在SSAO上添加一些高级技巧,而不是试图纯粹计算AO图。 1.您可以通过添加一些模糊滤镜来渲染更小的AO贴图并将其放大。这将带来更好的结果。 2.如果您尝试进行实时渲染,则无需每帧计算AO Map。你可以根据你的设置假冒它。

免责声明:我做了很多基于OpenGL ES的着色器,而且我的知识主要限于移动平台。