经常写入片段时奇怪的内核工件

问题描述 投票:0回答:1

我正在开发一个游戏引擎并处理延迟渲染管道。完成(第二遍)(着色)着色器后,我开始在我拥有的其他各种计算机上测试管道。有趣的是,在我的旧笔记本电脑上,我在每个4x8像素组上得到了这种奇怪的伪像(下面的示例)。它看起来像着色器正在执行并最终返回正确的颜色,但是以非常随机的方式。

此问题不是错误报告或解决方案请求。我用下面的代码修补程序解决了这个问题。这个主题是为了更好地理解为什么会发生这种情况,并为可能受同一问题影响的任何其他人提供见解。

Resulting image with artifacts更详细地描述效果: 大约50%的屏幕具有4x8像素组,这些像素高度调整实际产生的颜色。 这些4x8组在屏幕上的每个帧上随机放置,产生“静态”效果。 某些型号着色不同。如下所示,反光兔子呈蓝色,但折射球呈黄色。这似乎不是Gbuffer问题,因为它们都是从我确定正确的相同纹理中采样(因为我可以在屏幕上同时看到它)。 不同对象的4x8块具有更高的显示正确颜色的速率。你可以看到折射兔子大多是正确的,但反光地板和折射球只是白色和黄色。 根据GPU上运行的其他程序,4x8块的色调会发生巨大变化。

图像应如下所示:Correct render

破碎着色器的伪代码就像

out vec3 FragColor; // Out pixel of fragment shader

void main() {
    for (int i=0; i<NumberOfPointLights; i++) {
        ... Lighting calculation code...
        FragColor += lighting;
    }

    for (int i=0; i<NumberOfSpotLights; i++) {
        ... Lighting calculation code...
        FragColor += lighting;
    }

    for (int i=0; i<NumberOfDirectionalLights; i++) {
        ... Lighting calculation code...
        FragColor += lighting;
    }
}

为了解决这个问题,我简单地初始化了一个临时变量来保存输出颜色,在光照计算过程中写入,然后将其写入最后的片段输出。如下:

out vec3 FragColor; // Out pixel of fragment shader

void main() {
    vec3 outcolor = vec3(0);
    for (int i=0; i<NumberOfPointLights; i++) {
        ... Lighting calculation code...
        outcolor += lighting;
    }

    for (int i=0; i<NumberOfSpotLights; i++) {
        ... Lighting calculation code...
        outcolor += lighting;
    }

    for (int i=0; i<NumberOfDirectionalLights; i++) {
        ... Lighting calculation code...
        outcolor += lighting;
    }

    FragColor = outcolor;
}

我很惊讶这是有效的,因为我认为默认情况下会假设此行为。对片段输出的写入实际上并不是每次都写入VRAM,而是在最后。我的印象是在着色器执行后读取片段输出变量,因此它的全局性。

Suspicions and Questions

  1. 根据我的研究,我读到4x8像素组是nVidia GPU(我正在使用)上的一个“工作组”或“核心”的大小,而AMD使用8x8像素工作组。因此,某些东西会导致随机工作组的输出颜色永久受到影响,直到它被重新分配到屏幕上的其他位置。
  2. 颜色根据使用GPU的其他内容而变化的事实告诉我,GPU有一个非常复杂的内存分配方案,它从其他程序的内存中读取(我怀疑)或着色器每帧都获得未初始化的内存。但是每次都会写出相同的纹理内存吗?
  3. 写入片段输出变量每次写入VRAM,每个工作组写入它太多次导致工作组保释,留下混合结果。这可以解释为什么临时/局部变量有效。
  4. 因为我总是使用+ =(读然后写)临时变量初始化充当一个明确的指令,以黑色开始并添加到它,而直接写入片段直接添加到该像素的最后一种颜色。如果这种情况虽然如此,为什么它在高端PC上正常工作?
Other details

我的旧笔记本电脑使用带有Optimus技术的GT540m和集成的Intel 3000显卡(这里没有使用) 我的新台式电脑使用的是GTX1070。在运行应用程序期间,两个GPU都使用非常少的VRAM,小于100MB。 Shader正在使用#version 400 core编译

opengl glsl shader artifacts
1个回答
1
投票

这是一个驱动程序错误。这里没什么可看的了。

可以读取和写入输出变量。这是GLSL的一部分。因此,似乎司机只是搞砸了它的实施。

© www.soinside.com 2019 - 2024. All rights reserved.