使用glMapBuffer会导致大量性能损失吗?

问题描述

我发现,无论使用glMapBuffer,glMapBufferARB还是glMapBufferRange映射具有写访问权的缓冲区,我都会得到巨大的FPS下降。

一切正常,直到我映射了缓冲区并随后将其取消映射为止。无论是在绘制图形时映射缓冲区还是长时间重新映射缓冲区都没有关系,我总是会遭受巨大的性能损失。当我仅映射一个浮点数(4字节)而不是整个缓冲区时,FPS下降也存在。

我在不同的GPU上运行了代码,结果是1024 * 1024个四边形:

  • NVIDIA GeForce GTX 1080 Ti:
    • 不映射缓冲区:〜1100 FPS
    • 映射缓冲区:约200 FPS
  • NVIDIA GeForce RTX 2070:
    • 不映射缓冲区:〜800 FPS
    • 映射缓冲区:约40 FPS
  • NVIDIA GeForce RTX 2060:
    • 不映射缓冲区:〜800 FPS
    • 映射缓冲区:约200 FPS
  • NVIDIA GeForce MX150:
    • 不映射缓冲区:〜160 FPS
    • 映射缓冲区:〜30 FPS
  • 英特尔UHD图形620:
    • 不映射缓冲区:〜140 FPS
    • 映射缓冲区:〜140 FPS

正如您在运行程序的每个NVIDIA GPU上看到的那样,glMapBuffer使我的性能大幅下降(在RTX 2070上,帧率仅为常规帧率的1/20),但是在Intel UHD Graphics 620上,我没有根本没有性能问题。

我使用:

  • OpenGL 4.6
  • glew 2.1.0
  • glfw 2.7

现在我有几个问题:

  • 为什么会有这样的FPS下降?
  • 为什么只在NVIDIA GPU上而不是在Intel图形上?
  • NVIDIA无法处理已映射或已映射的缓冲区吗?
  • 这可能是库中的错误吗?
  • 我有什么问题吗,想念我什么吗?
  • 是否有解决方法或解决方法?

这是我的测试程序的代码:

#include <GL/glew.h>
#include <GL/glfw.h>

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtc/type_ptr.hpp>

#include <iostream>
#include <ctime>
#include <cmath>
#include <vector>

#define WIN_WIDTH 1500
#define WIN_HEIGHT 900
#define WIN_POS_X 300
#define WIN_POS_Y 10

#define M_PI 3.14159265359

#define SPEED                   100     // moving speed
#define ROTATION_SENSETIVITY    0.002f  // mouse sensetivity

#define SQRT_QUAD_COUNT         1024    // num quads: 1024 * 1024
#define QUAD_SPACE              0.2f    // Space between quads

uint32_t atXY(uint32_t x,uint32_t y,uint32_t xSize)
{
    return y*xSize + x;
}

void gen_shaders(uint32_t& shader_program)
{
    std::string vertex_shader_code      =   "#version 460 core\n"
                                            "layout (location = 0) in vec3 aPos;\n"
                                            "uniform mat4 MVP;\n"
                                            "void main()\n"
                                            "{\n"
                                            "   gl_Position = MVP * vec4(aPos,1.0f);\n"
                                            "}\0";

    std::string fragment_shader_code    =   "#version 460 core\n"
                                            "out vec4 outColor;\n"
                                            "void main()\n"
                                            "{\n"
                                            "   outColor = vec4(0.0f,1.0f,1.0f);\n"
                                            "}\0";

    const char* hilfe1 = vertex_shader_code.c_str();
    const char* hilfe2 = fragment_shader_code.c_str();

    uint32_t vertex_shader = glCreateShader(GL_VERTEX_SHADER);
    glShaderSource(vertex_shader,1,&hilfe1,NULL);
    glCompileShader(vertex_shader);

    uint32_t fragment_shader = glCreateShader(GL_FRAGMENT_SHADER);
    glShaderSource(fragment_shader,&hilfe2,NULL);
    glCompileShader(fragment_shader);

    shader_program = glCreateProgram();
    glAttachShader(shader_program,vertex_shader);
    glAttachShader(shader_program,fragment_shader);
    glLinkProgram(shader_program);

    glDeleteShader(vertex_shader);
    glDeleteShader(fragment_shader);
}

void initWindow(int xsize,int ysize,int xpos,int ypos)
{
    if(!glfwOpenWindow(xsize,ysize,24,GLFW_WINDOW))
    {
        glfwTerminate();
        exit(-1);
    }
    glfwSetWindowPos(xpos,ypos);
}

void gen_vertices(std::vector<float>& vertices)
{
    for(int y=0; y<SQRT_QUAD_COUNT; y++)
    {
        for(int x=0; x<SQRT_QUAD_COUNT; x++)
        {
            const float posx = (1.0f + QUAD_SPACE) * x;
            const float posy = (1.0f + QUAD_SPACE) * y;

            const float curr_vertices[12] = {
                        posx,posy,10.0f,1.0f +  posx,1.0f +  posy,posx,10.0f

            };

            for(int i=0; i<12; i++)
                vertices.push_back(curr_vertices[i]);
        }
    }
}
void mouse_action(int sx,int sy,double& rotx,double& roty,float sensetivity)
{
    constexpr double roty_max = 89.9/180.0*M_PI;
    const int sx_half = sx / 2;
    const int sy_half = sy / 2;

    int mx,my;
    glfwGetMousePos(&mx,&my);

    const int deltax = sx_half - mx;
    const int deltay = sy_half - my;

    rotx += deltax * sensetivity;
    roty += deltay * sensetivity;

    if(rotx >= 2*M_PI)
        rotx -= 2*M_PI;
    else if(rotx <= -2*M_PI)
        rotx += 2*M_PI;

    if(roty > roty_max)
        roty = roty_max;
    else if(roty < -roty_max)
        roty = -roty_max;

    glfwSetMousePos(sx_half,sy_half);
}

void move_action(double& posx,double& posy,double& posz,double rotx,float speed)
{
    static double old_time = glfwGetTime();
    double deltatime = glfwGetTime() - old_time;
    old_time = glfwGetTime();

    if(glfwGetKey('W') == GLFW_PRESS)
    {
        posx += speed * deltatime * sin(rotx);
        posz += speed * deltatime * cos(rotx);
    }
    if(glfwGetKey('A') == GLFW_PRESS)
    {
        posx += speed * deltatime * sin(rotx + M_PI / 2);
        posz += speed * deltatime * cos(rotx + M_PI / 2);
    }
    if(glfwGetKey('S') == GLFW_PRESS)
    {
        posx += speed * deltatime * sin(rotx + M_PI);
        posz += speed * deltatime * cos(rotx + M_PI);
    }
    if(glfwGetKey('D') == GLFW_PRESS)
    {
        posx += speed * deltatime * sin(rotx + M_PI * 1.5);
        posz += speed * deltatime * cos(rotx + M_PI * 1.5);
    }
    if(glfwGetKey(GLFW_KEY_SPACE) == GLFW_PRESS)
        posy += speed * deltatime;
    if(glfwGetKey(GLFW_KEY_LSHIFT) == GLFW_PRESS)
        posy -= speed * deltatime;
}

int main()
{
    int width,height;
    bool running = true;

    glfwInit();
    initWindow(WIN_WIDTH,WIN_HEIGHT,WIN_POS_X,WIN_POS_Y);
    glfwSetMousePos(WIN_WIDTH/2,WIN_HEIGHT/2);
    glfwDisable(GLFW_MOUSE_CURSOR);
    glewInit();
    glfwSwapInterval(0);

    uint32_t shader_program;
    uint32_t vao,vbo;

    std::vector<float> vertices;

    double posx = 0.0;
    double posy = 0.0;
    double posz = 0.0;
    double rotx = 0.0;
    double roty = 0.0;

    gen_shaders(shader_program);    // generate the shaders
    gen_vertices(vertices);         // generate the vertex data

    glGenVertexArrays(1,&vao); // generate vao
    glGenBuffers(1,&vbo);      // generate vbo

    // bind both
    glBindVertexArray(vao);
    glBindBuffer(GL_ARRAY_BUFFER,vbo);

    glBufferData(GL_ARRAY_BUFFER,vertices.size() * sizeof(float),vertices.data(),GL_DYNAMIC_DRAW);   // fill buffer with vertex data
    glEnableVertexAttribArray(0);
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,3 * sizeof(float),NULL);   // set attribute pointer ( 0 )

    // in this #if - #endif - block are the 2 lines of code that cause the problem / FPS drop:
    #if 1
    void* ptr = glMapBuffer(GL_ARRAY_BUFFER,GL_WRITE_ONLY); // <----- map the buffer

    if(ptr == NULL) // does not return with -1
        return -1;

    glUnmapBuffer(GL_ARRAY_BUFFER); // <------ unmap the buffer

    if(glGetError() != 0)   // does not return with -2
        return -2;
    #endif

    glBindBuffer(GL_ARRAY_BUFFER,0);
    glBindVertexArray(0);

    int frames = 0;
    clock_t time = clock();
    while(running)
    {
        // get fps
        if(clock() - time >= 1000)
        {
            std::cout << frames << std::endl;
            time = clock();
            frames = 0;
        }

        glfwGetWindowSize(&width,&height);
        height = height > 0 ? height : 1;

        glViewport(0,width,height);
        glClearColor(0.0f,0.0f,1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

        mouse_action(width,height,rotx,roty,ROTATION_SENSETIVITY);
        move_action(posx,posz,SPEED);

        glUseProgram(shader_program);
        glm::mat4 model(1.0f);
        glm::mat4 projection              = glm::perspective(glm::radians(100.0f),(float)width/(float)height,0.1f,1000.0f);
        glm::mat4 view                    = glm::lookAt(glm::dvec3(posx,posz),glm::dvec3(posx+cos(roty)*sin(rotx),posy+sin(roty),posz+cos(rotx)*cos(roty)),glm::dvec3(0.0,1.0,0.0));

        uint32_t mvp_loc = glGetUniformLocation(shader_program,"MVP");
        glUniformMatrix4fv(mvp_loc,glm::value_ptr(projection * view * model));

        glEnable(GL_DEPTH_TEST);

        glBindVertexArray(vao);
        glDrawArrays(GL_QUADS,vertices.size() / 3); // draw everything
        glBindVertexArray(0);

        glDisable(GL_DEPTH_TEST);
        glUseProgram(0);

        glfwSwapBuffers();
        frames++;

        // exit if ESC was pressed or window was closed
        running = !glfwGetKey(GLFW_KEY_ESC) && glfwGetWindowParam( GLFW_OPENED);
    }

    glDeleteProgram(shader_program);
    glDeleteBuffers(1,&vbo);
    glDeleteVertexArrays(1,&vao);
    glfwTerminate();

    return 0;
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...