Glsl 使用Vulkan在片段着色器中缓慢获取纹理
我正在做一个内核大小为64的SSAO着色器 SSAO片段着色器: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);
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饱和。优化循环!