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;
    }

samplerposition 纹理具有格式VK_FORMAT_R16G16B16A16_SFLOAT并与 flag 一起上传VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT

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

这个纹理获取时间正常吗?还是我在某处设置了错误?

就像布局过渡没有经过,所以纹理是 inVK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL而不是VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL.

4

2 回答 2

4

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

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

于 2016-08-15T12:47:50.297 回答
1

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

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

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

于 2016-08-15T11:20:00.447 回答