为啥尽管源代码没有变化,但从一个系统到另一个系统的片段数量却有很大差异?

Posted

技术标签:

【中文标题】为啥尽管源代码没有变化,但从一个系统到另一个系统的片段数量却有很大差异?【英文标题】:Why does the number of fragments vary significantly from one system to the other despite no changes in source code?为什么尽管源代码没有变化,但从一个系统到另一个系统的片段数量却有很大差异? 【发布时间】:2018-05-26 03:38:14 【问题描述】:

我已经实现了一个着色器,它可以计算它生成的片段数。

我注意到,在不改变代码的情况下,不同机器所统计的生成片段的数量是不同的。

在一台机器上是一致的(总是相同的值),但在不同的电脑上却明显不同。

显示器的分辨率相同,但显卡不同。我的期望是,如果几何、着色器、C++ 代码、视口尺寸和监视器都相同,那么片段的数量也应该相同,但似乎我错了,为什么会这样?

编辑: 有人要求我添加 MVC 示例。老实说,我认为这实际上与问题无关,因为这不是我的代码特有的行为,而是 GPU 的属性:

顶点着色器:

#version 430

layout(location = 0) in vec3 position;  // (x,y,z) coordinates of a vertex
layout(location = 1) in vec3 normal;      // normal to the vertex
layout(location = 2) in vec2 uv;        // texture coordinates

out vec3 v_pos;
out vec3 v_norm;
out vec2 v_uv;

uniform mat4 model_m = mat4(1); // model matrix
uniform mat4 view_m = mat4(1);  // view matrix
uniform mat4 proj_m = mat4(1);  // perspective projection matrix

void main()

    v_pos = vec3(model_m*vec4(position,1));
    v_norm = vec3(model_m*vec4(normal,1.0));
    v_uv = uv;

    gl_Position = proj_m*view_m*vec4(v_pos, 1.0);

片段着色器:

#version 430

layout(location = 0) in vec3 position; // (x,y,z) coordinates of a vertex

out vec3 v_pos;

uniform mat4 model_m = mat4(1); // model matrix

void main()

    v_pos = vec3(model_m*vec4(position,1));

C++:

    //Binding the buffer
    glGenBuffers(1, &ssbo);
    glBindBuffer(GL_SHADER_STORAGE_BUFFER, ssbo);
    glObjectLabel(GL_BUFFER, ssbo, -1, "\"SSBO\"");
    GLint zero = 0;
    glBufferStorage(GL_SHADER_STORAGE_BUFFER, sizeof(GLint), &zero,
        GL_MAP_READ_BIT | GL_MAP_WRITE_BIT | GL_DYNAMIC_STORAGE_BIT);
    glBindBufferBase(GL_SHADER_STORAGE_BUFFER, 0, ssbo);
GLuint *counter;
void render()

    glClearColor(0,0.5,0.5,0);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    glUseProgram(counter);
    mesh->draw();
    glMemoryBarrier(GL_SHADER_STORAGE_BARRIER_BIT);
    GLint z2;
    glGetBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLint), &z2);
    cout << "Fragments: " << z2 << endl;
    GLint zero=0;
    glBufferSubData(GL_SHADER_STORAGE_BUFFER, 0, sizeof(GLint), &zero);endl;


【问题讨论】:

编辑您的问题以包含minimal reproducible example。 @SidS 我不认为有必要,但我已经添加了它 【参考方案1】:

OpenGL 不是像素精确的 API。因此,实现可以以稍微不同的方式实现光栅化,或者提供不同的数值精度,从而生成不同数量的片段。

此外,如果您要渲染实际场景而不仅仅是全屏四边形,则可能会有其他效果。例如,假设您在渲染命令中有两个三角形,其中一个比另一个更接近。在某些硬件上,较近的三角形会在较远的三角形完全被光栅化之前在深度缓冲区上进行完整的读取/修改/写入传递。如果early depth tests are on,则不会生成来自更远三角形的片段的片段着色器。

但是如果同时处理来自两个三角形的片段呢?这可能会发生,而导致这种情况的原因取决于硬件(以及渲染命令中三角形之间的距离)。对于某些像素,较远的三角形会与较近的三角形一样计算其一些片段。

如果您将图像加载/存储操作与深度测试结合使用,这也是 turn on early fragment tests 很重要的原因。

【讨论】:

对于我当前的用例,打开该功能实际上是有害的,因为深度与应该优先考虑哪个片段无关(对于体素化算法)。此外,在所有情况下,几何形状和相机位置都是相同的。由于我正在测试片段的数量是否一致,因此我确保没有修改任何内容。 @Makogan:“几何和相机位置在所有情况下都是相同的。”就数值精度和光栅化差异而言,这并不意味着什么。同样,OpenGL 不是像素精确的 API。无法保证每个实现都会产生二进制相同的结果。 @Makogan:“对于我当前的用例,打开该功能实际上是有害的,因为深度与应该优先考虑哪个片段无关(对于体素化算法)。 i>" 那么……你把它关闭了吗?因为如果你不这样做,那是经销商的选择。而且由于“经销商”认为通过早期深度测试,您的程序会更快,他们可能是。 我只是澄清一下,生成片段的差异不是由跨系统或跨时间的几何变化引起的(生成的片段数量随时间变化) 是的,深度测试、背面剔除和混合都​​已禁用

以上是关于为啥尽管源代码没有变化,但从一个系统到另一个系统的片段数量却有很大差异?的主要内容,如果未能解决你的问题,请参考以下文章

角度应用程序正在获得访问权限,但从另一个系统调用时未访问 webapi,但在服务器内尝试工作。为啥?

回形针:为啥尽管质量降低了,图像的大小却没有太大变化?

为啥 HttpServletRequest 对象在从一个 servlet 转发到另一个 servlet 时会发生变化?

为啥尽管观察者的状态发生变化,但应用程序重启后 Flutter BloC UI 没有更新?

ubuntu为啥克隆不到mininet

为啥智能手机在网络变化期间一直连接到服务器