我正在实现在opengl中渲染网格,在该网格中,单元格应该在悬停它们时改变颜色。代码起作用了,我现在开始清理代码并减少着色器中的指令。
现在,仅通过删除几何着色器中的一个矩阵乘法,输出将在某些帧后冻结。
作为一种解决方法,我添加了this_thread :: sleep_for将帧速率限制为〜60fps,尽管这不是解决方案。使用renderdoc启动我的应用程序也可以阻止发生此错误。
我必须注意,我在另一个线程中生成了opengl上下文,而不是在执行PeekMessage循环的线程中生成的,所以这可能与线程之间的同步问题有关吗? (帧时间正在影响这种行为,这似乎是一个指标,我错过了一些同步)
一旦发生阻塞,窗口线程仍在接收消息,但是我的opengl线程在SwapBuffers中阻塞。
在下面的着色器中,我将matVP和matTransform合并为一个,这导致了这一行:
mat4 m = matVP;
开始出现实际问题。
layout(points) in;
layout(triangle_strip, max_vertices = 6) out;
uniform mat4 matVP;
uniform mat4 matTransform;
uniform int gridDimensions;
layout(binding=0, r8ui) uniform readonly uimage2D tileMap;
out vec2 uv;
out vec2 pos;
void main()
{
int x = gl_PrimitiveIDIn % gridDimensions;
int y = gl_PrimitiveIDIn / gridDimensions;
uvec4 tileData = imageLoad(tileMap, ivec2(x, y));
// if(tileData.r == 0) return;
mat4 m = matVP;
vec4 startPosition = vec4(float(x), float(y), 0.0, 1.0);
vec4 xp = vec4(1.0, 0.0, 0.0,0.0);
vec4 yp = vec4(0.0, 1.0, 0.0, 0.0);
gl_Position = m * startPosition;
uv = vec2(0.0, 0.0);
pos = vec2(x, y);
EmitVertex();
gl_Position = m * (startPosition + xp);
uv = vec2(1.0, 0.0);
pos = vec2(x + 1, y);
EmitVertex();
gl_Position = m * (startPosition + yp);
uv = vec2(0.0, 1.0);
pos = vec2(x, y + 1);
EmitVertex();
EndPrimitive();
gl_Position = m * (startPosition + xp);
uv = vec2(1.0, 0.0);
pos = vec2(x + 1, y);
EmitVertex();
gl_Position = m * (startPosition + xp + yp);
uv = vec2(1.0, 1.0);
pos = vec2(x + 1, y + 1);
EmitVertex();
gl_Position = m * (startPosition + yp);
uv = vec2(0.0, 1.0);
pos = vec2(x, y + 1);
EmitVertex();
EndPrimitive();
}
我使用的显卡是vega 8,我将尝试在另一台装有nvidia的计算机上重现该问题。
我的主线程和opengl线程不以任何方式共享opengl上下文,这使我认为这可能是与驱动程序相关的错误。
主线程正在遍历以下代码:
done = false;
while (!done)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
if (msg.message == WM_QUIT)
{
done = true;
m_isOpen = false;
}
else
{
if (m_inputSystem->isKeyPressed(VK_ESCAPE))
{
done = true;
m_isOpen = false;
}
}
}
}
渲染网格的代码调用以下代码:
void TileGrid::render(const Camera* cam)
{
const auto matMVP = cam->getVP();
glUseProgram(m_renderGridProgram);
glUniformMatrix4fv(m_matVPLoc, 1, GL_FALSE, &((matMVP)[0][0]));
glUniformMatrix4fv(m_matTransformLocation, 1, GL_FALSE, &(m_transform[0][0]));
glUniform1i(m_GridDimensionsLoc, m_gridDimensions);
glBindVertexArray(m_vao);
glBindImageTexture(0, m_gridTexture, 0, GL_FALSE, 0, GL_READ_ONLY, GL_R8UI);
[...] // calculating "intersect", no gl involved
glUniform2f(m_cursorPosLocation, intersect.x, intersect.y);
glDrawArrays(GL_POINTS, 0, m_gridDimensions * m_gridDimensions);
}
然后是
glFinish();
auto frameTime = std::chrono::high_resolution_clock::now() - frameStart;
// the following line "solves" the problem
std::this_thread::sleep_for(std::chrono::milliseconds(16) - frameTime);
m_window->swapBuffers();