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

Glsl 使用Vulkan在片段着色器中缓慢获取纹理,glsl,vulkan,ssao,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);

我正在做一个内核大小为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;
    }
const int kernelSize=64;
for(int i=0;i=s.z?1.0:0.0)*范围检查;
}
samplerposition纹理的格式为
VK\u format\u R16G16B16A16\u SFLOAT
,并与标志
VK\u MEMORY\u PROPERTY\u DEVICE\u LOCAL\u位一起上载

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

这个纹理提取时间正常吗?或者是我在什么地方设置了错误


就像没有经过布局转换一样,因此纹理位于
VK\u IMAGE\u layout\u COLOR\u ATTACHMENT\u OPTIMAL
中,而不是
VK\u IMAGE\u layout\u SHADER\u READ\u OPTIMAL

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

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


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

GPU内存依赖于大量缓存使用,如果彼此靠近的片段不采样彼此相邻的纹理,这是非常有限的,也称为缺乏空间一致性。我预计随机访问纹理的速度比线性一致访问慢10倍或更多。当使用大半径时,SSAO很容易发生这种情况


我建议使用较小的半径并优化纹理访问。您正在采样4个16位浮点,但只使用一个。将深度设置为单独的16位仅深度图像应该可以轻松地将速度提高4倍。

因此,如果着色器未预取,114毫秒听起来像是正常时间?说114毫秒是指每个片段吗?或者对于整个帧?对于SSAO着色器,整个绘制调用,在1024x1024窗口上,其114ms/64=17 ms/texel获取。据我所知,依赖纹理读取确实只是移动平台上的一个问题。在所有平台上,尽可能将计算从片段着色器移动到顶点着色器仍然是一个好主意。@codetiger当我在顶点着色器中预计算坐标时,速度要快得多,但在这种情况下,我真的不能这样做,我不会得到相同的插值。最好根本不写位置。只需根据需要从深度和碎片坐标进行重建;这就是大多数延迟渲染器的工作原理。@Nicolabolas有趣的是,我只是在搜索它,不知道为什么我以前从未读过这方面的文章。这对SSAO没有帮助though@Samantha:当然会的。与获取64个字节不同,您只获取32个字节(深度缓冲区值)。@Nicolas确实如此,但这是人们通常的做法,在pixel shaderf或ssao中迭代32-64次,这仍然需要大量时间,因为您仍然可以获取缓存misses@Samantha:我的意思是每次提取只访问32字节的数据。减少您检索的数据的大小可以提高缓存的一致性和整体性能,这有助于提高纹理访问性能。为什么您认为这是vulkan特有的?你只是做了很多工作!我认为,运行64x和1x循环的成本比运行64x要高,因为在1x上,编译器将摆脱循环。尝试更改分辨率。时间是否与像素数成线性变化?如果是,您只是使GPU饱和。优化循环!