From c3ec8ee355a279edcfd57843fb3c552110357703 Mon Sep 17 00:00:00 2001 From: ocornut Date: Mon, 23 May 2022 12:44:34 +0200 Subject: [PATCH] Backends: OpenGL: Partially revert 1.86 change of using glBufferSubData(): now only done on Intel GPUs. (#4468, #3381, #2981, #4825, #4832, #5127) Essentially reverts 389982eb for non-Intel GPUs + update imgui_impl_opengl3_loader.h --- backends/imgui_impl_opengl3.cpp | 39 +++++++++++++++++++++------- backends/imgui_impl_opengl3_loader.h | 2 ++ docs/CHANGELOG.txt | 7 +++++ 3 files changed, 38 insertions(+), 10 deletions(-) diff --git a/backends/imgui_impl_opengl3.cpp b/backends/imgui_impl_opengl3.cpp index 0347e1d0400b..ac48d0e9d7f8 100644 --- a/backends/imgui_impl_opengl3.cpp +++ b/backends/imgui_impl_opengl3.cpp @@ -14,6 +14,7 @@ // CHANGELOG // (minor and older changes stripped away, please see git history for details) +// 2022-05-23: OpenGL: Reworking 2021-12-15 "Using buffer orphaning" so it only happens on Intel GPU, seems to cause problems otherwise. (#4468, #4825, #4832, #5127). // 2022-05-13: OpenGL: Fix state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states. // 2021-12-15: OpenGL: Using buffer orphaning + glBufferSubData(), seems to fix leaks with multi-viewports with some Intel HD drivers. // 2021-08-23: OpenGL: Fixed ES 3.0 shader ("#version 300 es") use normal precision floats to avoid wobbly rendering at HD resolutions. @@ -193,6 +194,7 @@ struct ImGui_ImplOpenGL3_Data GLsizeiptr VertexBufferSize; GLsizeiptr IndexBufferSize; bool HasClipOrigin; + bool UseBufferSubData; ImGui_ImplOpenGL3_Data() { memset((void*)this, 0, sizeof(*this)); } }; @@ -261,6 +263,12 @@ bool ImGui_ImplOpenGL3_Init(const char* glsl_version) sscanf(gl_version, "%d.%d", &major, &minor); } bd->GlVersion = (GLuint)(major * 100 + minor * 10); + + // Query vendor to enable glBufferSubData kludge + if (const char* vendor = (const char*)glGetString(GL_VENDOR)) + if (strncmp(vendor, "Intel", 5) == 0) + bd->UseBufferSubData = true; + //printf("GL_MAJOR_VERSION = %d\nGL_MINOR_VERSION = %d\nGL_VENDOR = '%s'\nGL_RENDERER = '%s'\n", major, minor, (const char*)glGetString(GL_VENDOR), (const char*)glGetString(GL_RENDERER)); // [DEBUG] #else bd->GlVersion = 200; // GLES 2 #endif @@ -474,20 +482,31 @@ void ImGui_ImplOpenGL3_RenderDrawData(ImDrawData* draw_data) const ImDrawList* cmd_list = draw_data->CmdLists[n]; // Upload vertex/index buffers - GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); - GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); - if (bd->VertexBufferSize < vtx_buffer_size) + // - On Intel windows drivers we got reports that regular glBufferData() led to accumulating leaks when using multi-viewports, so we started using orphaning + glBufferSubData(). (See https://github.com/ocornut/imgui/issues/4468) + // - On NVIDIA drivers we got reports that using orphaning + glBufferSubData() led to glitches when using multi-viewports. + // - OpenGL drivers are in a very sorry state in 2022, for now we are switching code path based on vendors. + const GLsizeiptr vtx_buffer_size = (GLsizeiptr)cmd_list->VtxBuffer.Size * (int)sizeof(ImDrawVert); + const GLsizeiptr idx_buffer_size = (GLsizeiptr)cmd_list->IdxBuffer.Size * (int)sizeof(ImDrawIdx); + if (bd->UseBufferSubData) { - bd->VertexBufferSize = vtx_buffer_size; - glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW); + if (bd->VertexBufferSize < vtx_buffer_size) + { + bd->VertexBufferSize = vtx_buffer_size; + glBufferData(GL_ARRAY_BUFFER, bd->VertexBufferSize, NULL, GL_STREAM_DRAW); + } + if (bd->IndexBufferSize < idx_buffer_size) + { + bd->IndexBufferSize = idx_buffer_size; + glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW); + } + glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data); + glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data); } - if (bd->IndexBufferSize < idx_buffer_size) + else { - bd->IndexBufferSize = idx_buffer_size; - glBufferData(GL_ELEMENT_ARRAY_BUFFER, bd->IndexBufferSize, NULL, GL_STREAM_DRAW); + glBufferData(GL_ARRAY_BUFFER, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data, GL_STREAM_DRAW); + glBufferData(GL_ELEMENT_ARRAY_BUFFER, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data, GL_STREAM_DRAW); } - glBufferSubData(GL_ARRAY_BUFFER, 0, vtx_buffer_size, (const GLvoid*)cmd_list->VtxBuffer.Data); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, idx_buffer_size, (const GLvoid*)cmd_list->IdxBuffer.Data); for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) { diff --git a/backends/imgui_impl_opengl3_loader.h b/backends/imgui_impl_opengl3_loader.h index 67ac389d96bb..d576235993db 100644 --- a/backends/imgui_impl_opengl3_loader.h +++ b/backends/imgui_impl_opengl3_loader.h @@ -164,6 +164,8 @@ typedef khronos_uint8_t GLubyte; #define GL_FLOAT 0x1406 #define GL_RGBA 0x1908 #define GL_FILL 0x1B02 +#define GL_VENDOR 0x1F00 +#define GL_RENDERER 0x1F01 #define GL_VERSION 0x1F02 #define GL_EXTENSIONS 0x1F03 #define GL_LINEAR 0x2601 diff --git a/docs/CHANGELOG.txt b/docs/CHANGELOG.txt index 6dc978ef7d5d..85234ab7a228 100644 --- a/docs/CHANGELOG.txt +++ b/docs/CHANGELOG.txt @@ -121,6 +121,13 @@ Other Changes: - Backends: OSX: Monitor NSKeyUp events to catch missing keyUp for key when user press Cmd + key (#5128) [@thedmd] - Backends: OSX, Metal: Store backend data in a per-context struct, allowing to use these backends with multiple contexts. (#5203, #5221, #4141) [@noisewuwei] +- Backends: OpenGL3: Partially revert 1.86 change of using glBufferSubData(): now only done on Intel GPU + based on querying glGetString(GL_VENDOR). Essentially we got report of accumulating leaks on Intel with + multi-viewports when using simple glBufferData() without orphaning, and report of corruptions on other GPUs + with multi-viewports when using orphaning and glBufferSubData(), so currently switching technique based on + GPU vendor, which unfortunately reinforce the cargo-cult nature of dealing with OpenGL drivers. + Navigating the space of mysterious OpenGL drivers is particularly difficult as they are known to rely on + application specific whitelisting. (#4468, #3381, #2981, #4825, #4832, #5127). - Backends: OpenGL3: Fix state corruption on OpenGL ES 2.0 due to not preserving GL_ELEMENT_ARRAY_BUFFER_BINDING and vertex attribute states. [@rokups] - Examples: Emscripten+WebGPU: Fix building for latest WebGPU specs. (#3632)