Search code examples
c++openglruntime-errorglfwimgui

ImGui ERROR related with ImGui_ImplOpenGL3_CreateDeviceObjects


When I run my code I'm getting this Error. Consider that I'm getting this Error (Runtime Error) from ImGui only when threading is Enabled.

ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile vertex shader! With GLSL: #version 130

ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to compile fragment shader! With GLSL: #version 130

ERROR: ImGui_ImplOpenGL3_CreateDeviceObjects: failed to link shader program! With GLSL #version 130

And this is my Code.

gui.h

#include "imgui.h"
#include "imgui_impl_glfw.h"
#include "imgui_impl_opengl3.h"

#define GLEW_STATIC
#include <GL/glew.h>
#define GLFW_STATIC
#include <GLFW/glfw3.h>
#include "nfd.h"

#include <string>
#include <vector>
#include <thread>

#include "fileHandler.h"
#include "errors.h"

class MyGUI{
private:
  GLFWwindow *window;
  ImFont *tabFont, *ctntFonr, *logFont;
  ImGuiIO* io;

  bool isOpen = true;

  bool shouldRunFileOp = false;

  std::string m_OriginalFilePath, m_PartSizeMB, m_OutputFolderPath;

  void writeToFile(std::string _inputFile, unsigned long long _partByteSize, std::string _outputFolder){
    while(isOpen){
      if(shouldRunFileOp){

        // Do Some Large Files Related Stuff
        shouldRunFileOp = false;
      }
    }
  }

  void setCustomTheme(ImGuiStyle& _style){

    ImVec4 *colors = _style.Colors;

    colors[ImGuiCol_Tab] = ImVec4(0.4, 0.4, 0.4, 1.0);
    colors[ImGuiCol_TabHovered] = ImVec4(0.7, 0.3, 0.2, 1.0);
    colors[ImGuiCol_TabActive] = ImVec4(0.8, 0.3, 0.2, 1.0);
    colors[ImGuiCol_WindowBg] = ImVec4(0.1, 0.1, 0.1, 0.85);
    colors[ImGuiCol_TitleBgActive] = ImVec4(0.3, 0.3, 0.3, 1.0);
    colors[ImGuiCol_Text] = ImVec4(1.0, 1.0, 1.0, 1.0);

    _style.FrameRounding = 6;
    _style.WindowPadding = ImVec2(10, 10);
    _style.FramePadding = ImVec2(7.0, 4.0);
    _style.ItemSpacing = ImVec2(10.0, 20.0);
    _style.ItemInnerSpacing = ImVec2(2.0, 0.0);

  }

public:

  int init(){

    if (!glfwInit())
      return 1;

    // GL 3.0 + GLSL 130
    const char* glsl_version = "#version 130";
    glfwWindowHint(GLFW_TRANSPARENT_FRAMEBUFFER, GL_TRUE);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
    glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0);

    this->window = glfwCreateWindow(winSize.x, winSize.y, windowTitle.c_str(), NULL, NULL);
    if (window == NULL)
        return 1;

    glfwMakeContextCurrent(window);
    glfwSwapInterval(1); // Enable vsync

    IMGUI_CHECKVERSION();
    ImGui::CreateContext();
    this->io = &ImGui::GetIO(); (void)*(this->io);
    ImGui::StyleColorsDark();

    ImGuiStyle& style = ImGui::GetStyle();
    style.TabRounding = 4.0;
    style.WindowRounding = 5.0;
    style.WindowTitleAlign = ImVec2(0.5, 0.5);

    this->setCustomTheme(style);

    if(!ImGui_ImplGlfw_InitForOpenGL(window, true)) return 1;
    if(!ImGui_ImplOpenGL3_Init(glsl_version)) return 1;

    tabFont = io->Fonts->AddFontFromFileTTF("./assets/fonts/comic.ttf", 22.0f);
    ctntFont = io->Fonts->AddFontFromFileTTF("./assets/fonts/comic.ttf", 20.0f);
    logFont = io->Fonts->AddFontFromFileTTF("./assets/fonts/comic.ttf", 18.0f);
  }

  int run(){
    std::thread t1(&MyGUI::render, this);
    std::thread t2(&MyGUI::writeToFile, this, m_OriginalFilePath, m_PartSizeMB, m_OutputFolderPath);

    t1.join();
    t2.join();
  }

  int render(){
      while(!glfwWindowShouldClose(window)){

        glfwPollEvents();

        ImGui_ImplOpenGL3_NewFrame(); // Error is Getting from this Line.
        ImGui_ImplGlfw_NewFrame();
        ImGui::NewFrame();

        {
          ImGui::Begin("File Window");
            // Another GUI Elements
            if(ImGui::Button("Proceed")){
              shouldRunFileOp = true;
            }
          ImGui::End();
        }

        ImGui::Render();
        int display_w, display_h;
        glfwGetFramebufferSize(this->window, &display_w, &display_h);
        glViewport(0, 0, display_w, display_h);
        glClearColor(0.2, 0.2, 0.2, 1.0);
        glClear(GL_COLOR_BUFFER_BIT);
        ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
    
        glfwSwapBuffers(this->window);

      }

      isOpen = false;

      ImGui_ImplOpenGL3_Shutdown();
      ImGui_ImplGlfw_Shutdown();
      ImGui::DestroyContext();

      glfwDestroyWindow(this->window);
      glfwTerminate();

      return 0;
  }
};

main.cpp

#include "gui.h"

int main(){

  MyGUI gui;
  gui.init();
  gui.run();

  return 0;
}

I have checked and the error is getting from this line in gui.h ,

ImGui_ImplOpenGL3_NewFrame();

What is wrong with my Code? BTW This code working fine when not defining threads

I have to use threads because my program is handling Large Sized Files.

If anyone who also knows how to handle Large Sized files without interrupting to the Rendering Loop, please drop your solutions also!

Thank You!


Solution

  • The OpenGL Context is local to a thread and needs to be made "current" in a thread (glfwMakeContextCurrent(window). A Context cannot be "current" in multiple threads at the same time. You have to make the OpenGL Context current in the render thread:

    int render(){
    
        glfwMakeContextCurrent(window);   // <---
    
        while(!glfwWindowShouldClose(window)){
            // [...]  
        }
        // [...]
    }