为什么尽管源代码没有变化,但每个系统的片段数量却有很大差异?

Why does the number of fragments vary significantly from one system to the other despite no changes in source code?

本文关键字:片段 系统 源代码 有变化 为什么      更新时间:2023-10-16

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

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

它在一台计算机上是一致的(始终相同的值(,但在不同的计算机上明显不同。

显示器具有相同的分辨率,但图形卡不同。我的期望是,如果几何体、着色器、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;
}

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

此外,如果要渲染实际场景而不仅仅是全屏四边形,则可能会有其他效果。例如,假设渲染命令中有两个三角形,其中一个比另一个更近。在某些硬件上,较近的三角形在深度缓冲区上进行完全读/修改/写入传递,然后再对较远的三角形进行光栅化。如果启用了早期深度测试,则不会生成来自更远三角形的片段的任何片段着色器。

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

这也是为什么如果您将图像加载/存储操作与深度测试结合使用,则打开早期片段测试很重要的原因。