几何着色器的不相关更改后,SwapBuffers块

时间:2018-08-18 15:49:47

标签: c++ winapi opengl amd

我正在实现在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();

0 个答案:

没有答案