Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[opengl] Fix GLFW global context issue #7230

Merged
merged 8 commits into from
Jan 24, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions cmake/TaichiCore.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,7 @@ if (TI_WITH_OPENGL OR TI_WITH_VULKAN AND NOT ANDROID)
endif()

message("Building with GLFW")
add_compile_definitions(TI_WITH_GLFW)
add_subdirectory(external/glfw)
target_link_libraries(${CORE_LIBRARY_NAME} PRIVATE glfw)
target_include_directories(${CORE_LIBRARY_NAME} PUBLIC external/glfw/include)
Expand Down
16 changes: 4 additions & 12 deletions taichi/rhi/opengl/opengl_api.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@

#include "glad/gl.h"
#include "glad/egl.h"
#ifndef ANDROID
#include "GLFW/glfw3.h"
#endif // ANDROID
#include "taichi/rhi/opengl/opengl_device.h"

#include "taichi/rhi/window_system.h"

namespace taichi::lang {
namespace opengl {

Expand All @@ -28,12 +27,6 @@ static bool kUseGles = false;
static std::optional<bool> supported; // std::nullopt
void *kGetOpenglProcAddr;

#ifndef ANDROID
static void glfw_error_callback(int code, const char *description) {
TI_WARN("GLFW Error {}: {}", code, description);
}
#endif // ANDROID

bool initialize_opengl(bool use_gles, bool error_tolerance) {
TI_TRACE("initialize_opengl({}, {}) called", use_gles, error_tolerance);

Expand All @@ -52,8 +45,7 @@ bool initialize_opengl(bool use_gles, bool error_tolerance) {
void *get_proc_addr = nullptr;

#ifndef ANDROID
if (glfwInit()) {
glfwSetErrorCallback(glfw_error_callback);
if (window_system::glfw_context_acquire()) {
// Compute Shader requires OpenGL 4.3+ (or OpenGL ES 3.1+)
if (use_gles) {
glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API);
Expand Down Expand Up @@ -220,7 +212,7 @@ void reset_opengl() {
supported = std::nullopt;
kUseGles = false;
#ifndef ANDROID
glfwTerminate();
window_system::glfw_context_release();
#endif
}

Expand Down
60 changes: 60 additions & 0 deletions taichi/rhi/window_system.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#include "window_system.h"
#include "taichi/rhi/impl_support.h"

#include <mutex>
#include <array>
#include <iostream>

namespace taichi::lang::window_system {

#ifdef TI_WITH_GLFW
struct GLFWState {
std::mutex mutex;
int glfw_ref_count = 0;
};

static GLFWState glfw_state;

static void glfw_error_callback(int code, const char *description) {
std::array<char, 1024> buf;
snprintf(buf.data(), buf.size(), "GLFW Error %d: %s", code, description);
RHI_LOG_ERROR(buf.data());
}

bool glfw_context_acquire() {
std::lock_guard lg(glfw_state.mutex);
if (glfw_state.glfw_ref_count == 0) {
auto res = glfwInit();
k-ye marked this conversation as resolved.
Show resolved Hide resolved
if (res != GLFW_TRUE) {
return false;
}

glfwSetErrorCallback(glfw_error_callback);
}
glfw_state.glfw_ref_count++;
return true;
}

void glfw_context_release() {
std::lock_guard lg(glfw_state.mutex);
glfw_state.glfw_ref_count--;
if (glfw_state.glfw_ref_count == 0) {
glfwTerminate();
} else if (glfw_state.glfw_ref_count < 0) {
assert(false && "GLFW context double release?");
}
}

#else

bool glfw_context_acquire() {
return false;
}

void glfw_context_release() {
return;
}

#endif // TI_WITH_GLFW

} // namespace taichi::lang::window_system
12 changes: 12 additions & 0 deletions taichi/rhi/window_system.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#pragma once

#ifdef TI_WITH_GLFW
#include "GLFW/glfw3.h"
#endif // TI_WITH_GLFW

namespace taichi::lang::window_system {

bool glfw_context_acquire();
void glfw_context_release();

} // namespace taichi::lang::window_system
12 changes: 2 additions & 10 deletions taichi/runtime/program_impls/vulkan/vulkan_program.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
#include "taichi/runtime/gfx/aot_module_loader_impl.h"
#include "taichi/util/offline_cache.h"

#if !defined(ANDROID)
#include "GLFW/glfw3.h"
#endif
#include "taichi/rhi/window_system.h"

using namespace taichi::lang::vulkan;

Expand Down Expand Up @@ -85,10 +83,6 @@ FunctionType VulkanProgramImpl::compile(const CompileConfig &compile_config,
vulkan_runtime_.get());
}

static void glfw_error_callback(int code, const char *description) {
TI_WARN("GLFW Error {}: {}", code, description);
}

void VulkanProgramImpl::materialize_runtime(MemoryPool *memory_pool,
KernelProfilerBase *profiler,
uint64 **result_buffer_ptr) {
Expand All @@ -101,9 +95,7 @@ void VulkanProgramImpl::materialize_runtime(MemoryPool *memory_pool,
#ifndef ANDROID
GLFWwindow *glfw_window = nullptr;

if (glfwInit()) {
glfwSetErrorCallback(glfw_error_callback);

if (window_system::glfw_context_acquire()) {
// glfw init success
glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);
Expand Down
3 changes: 2 additions & 1 deletion taichi/ui/backends/vulkan/window.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

#include "taichi/program/program.h"
#include "taichi/ui/utils/utils.h"
#include "taichi/rhi/window_system.h"

using taichi::lang::Program;

Expand Down Expand Up @@ -91,7 +92,7 @@ Window::~Window() {
gui_.reset();
renderer_.reset();
if (config_.show_window) {
glfwTerminate();
taichi::lang::window_system::glfw_context_release();
}
}

Expand Down
26 changes: 7 additions & 19 deletions taichi/ui/utils/utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,7 @@
#endif

#include "taichi/rhi/vulkan/vulkan_common.h"
#if !defined(ANDROID)
#include <GLFW/glfw3.h>
#endif
#include "taichi/rhi/window_system.h"

#include <stdarg.h>

Expand All @@ -46,37 +44,27 @@

namespace taichi::ui {

#if !defined(ANDROID)
inline void initGLFW() {
if (!glfwInit()) {
printf("cannot initialize GLFW\n");
exit(EXIT_FAILURE);
}
}

static void glfw_error_callback(int code, const char *description) {
printf("GLFW Error %d: %s\n", code, description);
}

#ifdef TI_WITH_GLFW
inline GLFWwindow *create_glfw_window_(const std::string &name,
int screenWidth,
int screenHeight,
int window_pos_x,
int window_pos_y,
bool vsync) {
initGLFW();
if (!taichi::lang::window_system::glfw_context_acquire()) {
printf("cannot initialize GLFW\n");
exit(EXIT_FAILURE);
}
GLFWwindow *window;

glfwSetErrorCallback(glfw_error_callback);

glfwWindowHint(GLFW_VISIBLE, GLFW_FALSE);
glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API);

window = glfwCreateWindow(screenWidth, screenHeight, name.c_str(), nullptr,
nullptr);

if (!window) {
glfwTerminate();
taichi::lang::window_system::glfw_context_release();
exit(EXIT_FAILURE);
}

Expand Down