【发布时间】:2020-09-19 21:02:32
【问题描述】:
我的片段着色器的输入之一是一个由 5 个结构组成的数组。着色器根据 5 个结构中的每一个计算颜色。最后,将这 5 种颜色相加得到最终输出。数组的总大小为 1440 字节。为了适应统一缓冲区的对齐,统一缓冲区的大小变为 1920 字节。
1- 如果我将 5 个结构的数组定义为统一缓冲区数组,则渲染需要 5ms(由 Nsight Graphics 测量)。统一缓冲区的内存属性是 'VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT'。 glsl中的uniform缓冲区定义如下
layout(set=0,binding=0) uniform UniformStruct { A a; } us[];
layout(location=0) out vec4 c;
void main()
{
vec4 col = vec4(0);
for (int i = 0; i < 5; i++)
col += func(us[nonuniformEXT(i)]);
c = col;
}
此外,我正在使用“GL_EXT_nonuniform_qualifier”扩展来访问统一缓冲区数组。这对我来说似乎是最直接的方式,但还有其他实现方式。
2- 我可以将渲染从一个 vkCmdDraw 拆分为五个 vkCmdDraw,将帧缓冲区的混合模式从覆盖更改为添加,并在片段着色器中定义一个统一缓冲区而不是统一缓冲区数组。在 CPU 方面,我将描述符类型从 UNIFORM_BUFFER 更改为 UNIFORM_BUFFER_DYNAMICS。在每个 vkCmdDraw 之前,我绑定了动态统一缓冲区和相应的偏移量。在片段着色器中,移除了 for 循环。虽然看起来它应该比第一种方法慢,但它比第一种方法快得多。 5 次绘制总共只需要 2 毫秒的渲染时间。
3- 如果我将 5 个结构的数组定义为存储缓冲区并执行一个 vkCmdDraw,则渲染只需 1.4ms。换句话说,如果我将数组从统一缓冲区数组更改为存储缓冲区,但其他任何内容都保持为 1,它会变得更快。
4- 如果我在 glsl 中将 5 个结构的数组定义为一个全局常量并执行一个 vkCmdDraw,则渲染只需要 0.5ms。
在我看来,4应该是最快的方式,在测试中也是如此。那么 1 应该是下一个。 2 和 3 都应该比 1 慢。但是,2 或 3 都不比 1 慢。相比之下,它们比 1 快得多。有什么想法为什么使用统一缓冲区数组会减慢渲染速度?是不是因为它是主机可见缓冲区?
【问题讨论】:
-
您是否考虑过一种明显的可能性,即您只有一个统一的缓冲区来存储 5 个
As 的数组?像这样:layout(set=0,binding=0) uniform UniformStruct { A a[5]; } us;