[Bf-blender-cvs] [b961b3f0c91] temp-vr-draw-thread: Initial, mostly broken VR viewport drawing on own thread

Julian Eisel noreply at git.blender.org
Tue Jul 30 15:31:57 CEST 2019


Commit: b961b3f0c91ac091f0d74b24f75f48f62b039f11
Author: Julian Eisel
Date:   Tue Jul 30 13:28:20 2019 +0200
Branches: temp-vr-draw-thread
https://developer.blender.org/rBb961b3f0c91ac091f0d74b24f75f48f62b039f11

Initial, mostly broken VR viewport drawing on own thread

Spawns a separate thread to do any VR session drawing on. There are
four reasons for this:
* VR session doesn't need the usual main loop procedure for drawing.
  With the drawing on a separate thread, the session doesn't have the
  overhead of the other parts of the main loop.
* OpenXR performs thread blocking operations to synchronize rendering
  with the device refresh rate. This would conflict with the rest of
  Blender, causing lags on event handling, drawing, etc.
* With an own thread, we can keep a single OpenGL context alive,
  avoiding expensive context switches. This should improve performance
  significantly.
* With a bit more work, viewports can draw entirely in parallel (at
  least the CPU side of it), pushing performance even further.

Drawing the viewport on a separate thread shouldn't be much of an
issue. The draw-manager is already thread safe (mutex guarded). Not much
seems needed to get it entirely concurrent, allowing viewport drawing
from separate threads without any synchronization (i.e. only one at a
time).
I had to create an own depsgraph for the VR draw thread so the viewport
gets its own buffers for its own OpenGL context.

Right now this is utterly broken, but at least an empty viewport is
drawn for the VR session in a separate thread. Issues are:
* VR viewport doesn't draw any objects, just background + overlays
  (apparently the VR session depsgraph isn't built correctly).
* OpenGL context of the main thread seems messed up when drawing the VR
  view. Result is drawing glitches and eventually Blender crashes.
* Exiting the VR session causes failed assertions and memory leaks.

===================================================================

M	intern/ghost/GHOST_C-api.h
M	intern/ghost/GHOST_IXrContext.h
M	intern/ghost/intern/GHOST_C-api.cpp
M	intern/ghost/intern/GHOST_XrContext.cpp
M	intern/ghost/intern/GHOST_XrContext.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/gpu/intern/gpu_viewport.c
M	source/blender/windowmanager/intern/wm_draw.c
M	source/blender/windowmanager/intern/wm_surface.c
M	source/blender/windowmanager/intern/wm_xr.c

===================================================================

diff --git a/intern/ghost/GHOST_C-api.h b/intern/ghost/GHOST_C-api.h
index 84bad87e654..e9fb3373a4b 100644
--- a/intern/ghost/GHOST_C-api.h
+++ b/intern/ghost/GHOST_C-api.h
@@ -998,10 +998,11 @@ void GHOST_XrGraphicsContextBindFuncs(GHOST_XrContextHandle xr_context,
 void GHOST_XrDrawViewFunc(GHOST_XrContextHandle xr_context, GHOST_XrDrawViewFn draw_view_fn);
 
 /* sessions */
-int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
 void GHOST_XrSessionStart(GHOST_XrContextHandle xr_context,
                           const GHOST_XrSessionBeginInfo *begin_info);
 void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_context);
+int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle);
+int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_context);
 void GHOST_XrSessionDrawViews(GHOST_XrContextHandle xr_context, void *customdata);
 
 /* events */
diff --git a/intern/ghost/GHOST_IXrContext.h b/intern/ghost/GHOST_IXrContext.h
index 362bc923ee8..3b8455e6e86 100644
--- a/intern/ghost/GHOST_IXrContext.h
+++ b/intern/ghost/GHOST_IXrContext.h
@@ -29,6 +29,7 @@ class GHOST_IXrContext {
 
   virtual void startSession(const GHOST_XrSessionBeginInfo *begin_info) = 0;
   virtual void endSession() = 0;
+  virtual bool hasSession() const = 0;
   virtual bool isSessionRunning() const = 0;
   virtual void drawSessionViews(void *draw_customdata) = 0;
 
diff --git a/intern/ghost/intern/GHOST_C-api.cpp b/intern/ghost/intern/GHOST_C-api.cpp
index caa88f46ff9..c188cc8e819 100644
--- a/intern/ghost/intern/GHOST_C-api.cpp
+++ b/intern/ghost/intern/GHOST_C-api.cpp
@@ -937,6 +937,13 @@ void GHOST_XrSessionEnd(GHOST_XrContextHandle xr_contexthandle)
   GHOST_XR_CAPI_CALL(xr_context->endSession(), xr_context);
 }
 
+int GHOST_XrHasSession(const GHOST_XrContextHandle xr_contexthandle)
+{
+  const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
+  GHOST_XR_CAPI_CALL_RET(xr_context->hasSession(), xr_context);
+  return 0;  // Only reached if exception is thrown.
+}
+
 int GHOST_XrSessionIsRunning(const GHOST_XrContextHandle xr_contexthandle)
 {
   const GHOST_IXrContext *xr_context = (GHOST_IXrContext *)xr_contexthandle;
diff --git a/intern/ghost/intern/GHOST_XrContext.cpp b/intern/ghost/intern/GHOST_XrContext.cpp
index 03c3fed3b9e..51b39bcc193 100644
--- a/intern/ghost/intern/GHOST_XrContext.cpp
+++ b/intern/ghost/intern/GHOST_XrContext.cpp
@@ -441,6 +441,11 @@ void GHOST_XrContext::endSession()
   m_session = nullptr;
 }
 
+bool GHOST_XrContext::hasSession() const
+{
+  return m_session != nullptr;
+}
+
 bool GHOST_XrContext::isSessionRunning() const
 {
   return m_session && m_session->isRunning();
diff --git a/intern/ghost/intern/GHOST_XrContext.h b/intern/ghost/intern/GHOST_XrContext.h
index ec3b5d23f21..bd189f39491 100644
--- a/intern/ghost/intern/GHOST_XrContext.h
+++ b/intern/ghost/intern/GHOST_XrContext.h
@@ -50,6 +50,7 @@ class GHOST_XrContext : public GHOST_IXrContext {
 
   void startSession(const GHOST_XrSessionBeginInfo *begin_info) override;
   void endSession() override;
+  bool hasSession() const override;
   bool isSessionRunning() const override;
   void drawSessionViews(void *draw_customdata) override;
 
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index 1abe68b622d..2e4fe3b0b48 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -523,7 +523,7 @@ const float *DRW_viewport_pixelsize_get(void)
   return &DST.pixsize;
 }
 
-static void drw_viewport_cache_resize(void)
+void drw_viewport_cache_resize(void)
 {
   /* Release the memiter before clearing the mempools that references them */
   GPU_viewport_cache_release(DST.viewport);
diff --git a/source/blender/gpu/intern/gpu_viewport.c b/source/blender/gpu/intern/gpu_viewport.c
index e3c13b0ec14..20e9b42ee05 100644
--- a/source/blender/gpu/intern/gpu_viewport.c
+++ b/source/blender/gpu/intern/gpu_viewport.c
@@ -467,8 +467,6 @@ void GPU_viewport_bind(GPUViewport *viewport, const rcti *rect)
   int rect_w = BLI_rcti_size_x(rect) + 1;
   int rect_h = BLI_rcti_size_y(rect) + 1;
 
-  DRW_opengl_context_enable();
-
   if (dfbl->default_fb) {
     if (rect_w != viewport->size[0] || rect_h != viewport->size[1] ||
         U.ogl_multisamples != viewport->samples) {
@@ -553,7 +551,6 @@ void GPU_viewport_draw_to_screen(GPUViewport *viewport, const rcti *rect)
 void GPU_viewport_unbind(GPUViewport *UNUSED(viewport))
 {
   GPU_framebuffer_restore();
-  DRW_opengl_context_disable();
 }
 
 GPUTexture *GPU_viewport_color_texture(GPUViewport *viewport)
diff --git a/source/blender/windowmanager/intern/wm_draw.c b/source/blender/windowmanager/intern/wm_draw.c
index 8e15eb71395..e8b87795eb4 100644
--- a/source/blender/windowmanager/intern/wm_draw.c
+++ b/source/blender/windowmanager/intern/wm_draw.c
@@ -48,6 +48,8 @@
 #include "BKE_scene.h"
 #include "BKE_workspace.h"
 
+#include "DRW_engine.h"
+
 #include "GHOST_C-api.h"
 
 #include "ED_node.h"
@@ -395,6 +397,7 @@ static void wm_draw_region_bind(ARegion *ar, int view)
   }
 
   if (ar->draw_buffer->viewport[view]) {
+    DRW_opengl_context_enable();
     GPU_viewport_bind(ar->draw_buffer->viewport[view], &ar->winrct);
   }
   else {
@@ -419,6 +422,7 @@ static void wm_draw_region_unbind(ARegion *ar, int view)
 
   if (ar->draw_buffer->viewport[view]) {
     GPU_viewport_unbind(ar->draw_buffer->viewport[view]);
+    DRW_opengl_context_disable();
   }
   else {
     glDisable(GL_SCISSOR_TEST);
@@ -745,35 +749,25 @@ static void wm_draw_window_onscreen(bContext *C, wmWindow *win, int view)
 
 void wm_draw_upside_down(int sizex, int sizey)
 {
-  GPUVertFormat *format = immVertexFormat();
-  uint texcoord = GPU_vertformat_attr_add(format, "texCoord", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-  uint pos = GPU_vertformat_attr_add(format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
-
-  immBindBuiltinProgram(GPU_SHADER_2D_IMAGE);
+  /* Don't use imm here, this is called from a separate thread with no imm available. */
 
   /* wmOrtho for the screen has this same offset */
   const float halfx = GLA_PIXEL_OFS / sizex;
-  const float halfy = GLA_PIXEL_OFS / sizex;
-
-  immUniform1i("image", 0); /* texture is already bound to GL_TEXTURE0 unit */
-
-  immBegin(GPU_PRIM_TRI_FAN, 4);
-
-  immAttr2f(texcoord, halfx, 1.0f + halfy);
-  immVertex2f(pos, 0.0f, 0.0f);
-
-  immAttr2f(texcoord, 1.0f + halfx, 1.0f + halfy);
-  immVertex2f(pos, sizex, 0.0f);
+  const float halfy = GLA_PIXEL_OFS / sizey;
 
-  immAttr2f(texcoord, 1.0f + halfx, halfy);
-  immVertex2f(pos, sizex, sizey);
-
-  immAttr2f(texcoord, halfx, halfy);
-  immVertex2f(pos, 0.0f, sizey);
+  GPUShader *shader = GPU_shader_get_builtin_shader(GPU_SHADER_2D_IMAGE_RECT_COLOR);
+  GPU_shader_bind(shader);
 
-  immEnd();
+  glUniform1i(GPU_shader_get_uniform_ensure(shader, "image"), 0);
+  glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_icon"),
+              halfx,
+              halfy,
+              1.0f + halfx,
+              1.0f + halfy);
+  glUniform4f(GPU_shader_get_uniform_ensure(shader, "rect_geom"), 0, sizey, sizex, 0);
+  glUniform4f(GPU_shader_get_builtin_uniform(shader, GPU_UNIFORM_COLOR), 1.0f, 1.0f, 1.0f, 1.0f);
 
-  immUnbindProgram();
+  GPU_draw_primitive(GPU_PRIM_TRI_STRIP, 4);
 }
 
 static void wm_draw_window_upside_down_onscreen(bContext *C, wmWindow *win)
@@ -887,15 +881,15 @@ static void wm_draw_window(bContext *C, wmWindow *win)
  */
 static void wm_draw_surface(bContext *C, wmSurface *surface)
 {
-  wm_window_clear_drawable(CTX_wm_manager(C));
-  wm_surface_make_drawable(surface);
+  // wm_window_clear_drawable(CTX_wm_manager(C));
+  // wm_surface_make_drawable(surface);
 
   surface->draw(C);
 
-  wm_surface_present(surface);
+  // wm_surface_present(surface);
 
   /* Avoid interference with window drawable */
-  wm_surface_clear_drawable();
+  // wm_surface_clear_drawable();
 }
 
 /****************** main update call **********************/
diff --git a/source/blender/windowmanager/intern/wm_surface.c b/source/blender/windowmanager/intern/wm_surface.c
index 8b3a5e55beb..38057370b92 100644
--- a/source/blender/windowmanager/intern/wm_surface.c
+++ b/source/blender/windowmanager/intern/wm_surface.c
@@ -52,6 +52,7 @@ void wm_surfaces_iter(bContext *C, void (*cb)(bContext *C, wmSurface *))
 
 void wm_surface_clear_drawable(void)
 {
+#if 0
   if (g_drawable) {
     BLF_batch_reset();
     gpu_batch_presets_reset();
@@ -59,6 +60,7 @@ void wm_surface_clear_drawable(void)
 
     g_drawable = NULL;
   }
+#endif
 }
 
 void wm_surface_set_drawable(wmSurface *surface, bool activate)
@@ -67,11 +69,11 @@ void wm_surface_set_drawable(wmSurface *surface, bool activate)
 
   g_drawable = surface;
   if (activate) {
-    GHOST_ActivateOpenGLContext(surface->ghost_ctx);
+    //    GHOST_ActivateOpenGLContext(surface->ghost_ctx);
   }
 
-  GPU_context_active_set(surface->gpu_ctx);
-  immActivate();
+  //  GPU_context_active_set(surface->gpu_ctx);
+  //  immActivate();
 }
 
 void wm_surface_make_drawable(wmSurface *surface)
@@ -97,9 +99,9 @@ void wm_surface_reset_drawable(void)
 
 void wm_surface_present(wmSurface *surface)
 {
-  GHOST_SwapContextBuffers(surface->ghost_ctx);
+  //  GHOST_SwapContextBuffers(surface->ghost_ctx);
   if (surface->secondary_ghost_ctx) {
-    GHOST_SwapContextBuffers(surface->secondary_ghost_ctx);
+    //    GHOST_SwapContextBuffers(surface->secondary_ghost_ctx);
   }
 }
 
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
index 4f7d2430ba9..ced56fca938 100644
--- a/source/blender/windowmanager/intern/wm_xr.c
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -26,6 +26,12 @@
 
 #include "BLI_math_geom.h"
 #include "BLI_math_matrix.h"
+#include "BLI_threads.h"
+
+#include "DEG_depsgraph.h"
+#include "DEG_depsgraph_build.h"
+#include "DEG_depsgraph_debug.h"
+#include "DEG_depsgraph_query.h"
 
 #include "DNA_object_types.h"
 #include "DNA_scene_types.h"
@@ -62,6 +68,8 @@ static void xr_session_window_create(bContext *C);
 #endif
 
 static wmSurface *g_xr_surface = NULL;
+static Depsgraph *g_depsgraph = NULL;
+ListBase g_threadpool;
 
 typedef struct {
   GHOST_TXrGraphicsBinding gpu_binding_type;
@@ -129,

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list