使用Vulkan时片段着色器中的纹理获取速度较慢

4
我将翻译为:

我正在使用核大小为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;
    }

采样器位置纹理的格式为VK_FORMAT_R16G16B16A16_SFLOAT,并使用标志VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT上传。
我使用的是一台带有NVIDIA K1100M图形卡的笔记本电脑。如果我在renderdoc中运行代码,则此着色器需要114毫秒。而如果我将kernelSize更改为1,则需要1毫秒
这个纹理获取时间正常吗?还是我在某个地方设置了错误?例如,布局转换未经过,因此纹理处于VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL而不是VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL

你为什么认为这是Vulkan特定的?你只是做了很多工作!我认为在运行循环64x与1x时,64x的成本比1x更高,是因为在1x上编译器会消除循环。尝试更改分辨率。时间是否随像素数量线性变化?如果是,那么你只是使GPU饱和了。优化循环! - starmole
2个回答

4

GPU内存依赖于大量的缓存使用,如果相邻的片段没有采样相邻的纹理像素(也称缺乏空间相关性),则缓存非常有限。随机访问纹理与线性、相关性访问相比,我预计会减速约10倍或更多。当使用大半径时,SSAO非常容易受到这种情况的影响。

我建议使用较小的半径并优化纹理访问。您正在采样4个16位浮点数,但只使用了一个。将深度复制到单独的16位深度图像中应该会让您轻松获得4倍的加速。


2
最好不要写出位置,只需根据深度和片段坐标进行重构即可;这是大多数延迟渲染器的工作方式。 - Nicol Bolas
1
@NicolBolas 很有趣,我刚刚在搜索它,不知道为什么以前从未听说过。但这对 SSAO 没有帮助。 - Samantha
1
@Samantha:当然可以。你只需要获取32字节(深度缓冲区值),而不是64字节。 - Nicol Bolas
@NicolBolas 是的,确实如此,但这是人们通常的做法,对于 ssao,在像素着色器中迭代32-64次,仍然需要很长时间,因为你仍然会遇到缓存未命中问题。 - Samantha
1
@Samantha:我的意思是每次获取只访问32字节的数据。减少检索的数据大小可以提高缓存一致性,总体上有助于纹理访问性能。 - Nicol Bolas

1
你正在片段着色器中计算纹理坐标,这意味着你不允许GPU预取纹理。最好在顶点着色器上计算所有纹理坐标并将其作为varying传递。
更新: 我建议在SSAO上添加一些高级技巧,而不是仅尝试计算AO贴图。 1.您可以渲染一个更小的AO贴图,并通过添加一些模糊滤镜来放大它。这将得到更好的结果。 2.如果您正在尝试进行实时渲染,则不需要每帧计算AO贴图。您可以根据自己的设置进行伪造。
免责声明:我做了很多基于OpenGL ES的着色器,我的知识大多限于移动平台。

如果它没有被着色器预取,那么114毫秒听起来像是正常的时间吗? - Samantha
你说的114毫秒是指每个片段还是整个帧? - codetiger
对于SSAO着色器来说,整个绘制调用需要114毫秒/64 = 17毫秒来获取每个1024x1024窗口上的纹素。 - Samantha
@codetiger 当我在顶点着色器中预先计算坐标时,速度会更快,但在这种情况下我无法这样做,因为我将无法获得相同的插值值。 - Samantha
@Samantha 你能解释一下为什么你不能在顶点着色器中预先计算坐标吗? - codetiger
显示剩余2条评论

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