0
\$\begingroup\$

I am creating a game using OpenGl in c++. Whenever I create a new model while the game is running, such as fire a bullet, there is a huge lag spike. The function that creates the model is below.

    std::string jsonString;
    jsonString = file->load(type);
    json jf = json::parse(jsonString); //Might be causing the lag
    
    indicesSizeTexture = jf["textureIndices"].size();
    verticesSizeTexture = jf["textureVertices"].size();
    indicesSizeCollision = jf["collisionIndices"].size();
    verticesSizeCollision = jf["collisionVertices"].size();
    verticesTexture = new float[verticesSizeTexture * 8];
    verticesCollision = new float[verticesSizeCollision * 8];
    verticesCollisionUpdated = new float[verticesSizeCollision * 8];

    indicesTexture = new int[indicesSizeTexture];
    indicesCollision = new int[indicesSizeCollision];

    for (int i = 0; i < verticesSizeTexture; i++) {  //responsible for just the texture vertices
        verticesTexture[i] = jf["textureVertices"][i];
    }
    for (int i = 0; i < indicesSizeTexture; i++) { // responsible for just the texture indices
        indicesTexture[i] = jf["textureIndices"][i];
    }
    for (int i = 0; i < verticesSizeCollision; i++) {  //responsible for just the collision vertices
        verticesCollision[i] = jf["collisionVertices"][i];
        verticesCollisionUpdated[i] = verticesCollision[i];
    }
    for (int i = 0; i < indicesSizeCollision; i++) { // responsible for just the collision indices
        indicesCollision[i] = jf["collisionIndices"][i];
    }

    //binds id
    glGenBuffers(1, &VBO);
    glGenVertexArrays(1, &VAO);
    glGenBuffers(1, &EBO);
    glGenTextures(1, &texture);

    glBindVertexArray(VAO);
    glBindBuffer(GL_ARRAY_BUFFER, VBO);
    glBufferData(GL_ARRAY_BUFFER, verticesSizeTexture * 8 * sizeof(float), verticesTexture, GL_STATIC_DRAW);
    // position attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
    //texture
    glBindTexture(GL_TEXTURE_2D, texture);
    glVertexAttribPointer(2, 2, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void*)(6 * sizeof(float)));
    glEnableVertexAttribArray(2);

    stbi_set_flip_vertically_on_load(true);
    unsigned char* data = stbi_load(texturePathString.c_str(), &width, &height, &nrChannels, 0);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data);

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

I stripped out a lot of parts that I am almost certain aren't causing the lag. There is a lot of stuff going on, but it is mostly simple mathematical operations. The only parts that I think could be causing the lag is the json section used for loading the model data. The model data is stored in a variable from file as a string. I need the json section for the data storage though. What could be causing the lag? should I find a different data storage type? What if I created a bullet offscreen on startup, then copied it whenever I needed it? The specific json library I am using is https://github.com/nlohmann/json

\$\endgroup\$
4
  • 1
    \$\begingroup\$ //Might be causing the lag - what does your profiler say? Is this the cause of the lag or is it not? I presume you're not re-parsing your JSON, generating new vertex buffers, and loading new textures for every single bullet you spawn, only for the first unique instance of each kind of model? \$\endgroup\$
    – DMGregory
    Apr 27, 2021 at 21:31
  • \$\begingroup\$ @DMGregory How would I be able to test if it actually is causing the lag? I can't measure the difference in time when that line is removed versus when it is not, because it is a crucial part of the code. To your second statement, I am redoing everything (JSON, Vertex buffers. etc) on the creation of each bullet. I am going to fix that, but there would still be a lag spike for the first bullet. \$\endgroup\$ Apr 27, 2021 at 21:44
  • 1
    \$\begingroup\$ Get a high-resolution timestamp before and after that line runs, to measure how many processor cycles occurred in between. Your lag spike needn't be when you instantiate the bullet — you can pre-load all the assets used in the scene/level up front before play starts. Much of it you can even do on a background thread while displaying an intro animation. \$\endgroup\$
    – DMGregory
    Apr 27, 2021 at 21:51
  • 1
    \$\begingroup\$ It sounds like you might be loading all the JSON data every time you spawn the bullet. At least that's what you're describing. As DMGregory said, you can pre-load all the data and store it in memory. In that case, it almost doesn't matter how slow your plain text parsing is, because it doesn't affect runtime performance. \$\endgroup\$ Apr 28, 2021 at 13:20

1 Answer 1

1
\$\begingroup\$

This is normal expected behaviour when you create resources at runtime.

In your case, you are:

  • Loading a file from disk.
  • Parsing that file (and parsing plain text is a slow runtime operation).
  • Allocating a bunch of memory and copying data into it.
  • Creating a bunch of GL objects.
  • Transferring data to those objects.
  • Tearing down all the temp stuff that was set up to do all of this work.

You shouldn't be surprised that you get lag spikes.

To resolve, you can try:

  • Use a binary file format instead (parsing plain text is an exercise that only appeals to the type of person who likes writing plain text parsers). You can efficiently load models without needing to parse them this way, by e.g. memory-mapping a file and passing the resulting pointer directly to glBufferData. It should reduce or remove the overhead from parsing text and copying data around, but will not help with overhead from hitting the disk or from creating GL objects at runtime.
  • Don't create resources at runtime; create them during program startup instead.
  • Try spinning off an extra thread to do the loading - although if you need to use the object in the same frame as you load it, this may be of minimal benefit, and in any case will introduce possibly unwanted complexities to your code.
  • If you really must load at runtime from plain text files, then just accept that you're going to get this behaviour.
\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .