[Bf-blender-cvs] [aff49f607a3] soc-2019-openxr: Use draw manager offscreen context for the VR session

Julian Eisel noreply at git.blender.org
Wed Jul 24 01:41:42 CEST 2019


Commit: aff49f607a391ac9d08c5f2e3e0b3d9fc632f383
Author: Julian Eisel
Date:   Wed Jul 24 01:39:04 2019 +0200
Branches: soc-2019-openxr
https://developer.blender.org/rBaff49f607a391ac9d08c5f2e3e0b3d9fc632f383

Use draw manager offscreen context for the VR session

This way we avoid the big overhead of context switches. Makes frames
render about twice as fast here. For heavy Spring scenes I'm getting
around 20 FPS here, classroom scene is at 50 FPS.
This is great given that drawing itself still isn't optimized for dual
eye rendering.

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

M	intern/ghost/intern/GHOST_SystemWin32.cpp
M	source/blender/draw/DRW_engine.h
M	source/blender/draw/intern/draw_manager.c
M	source/blender/windowmanager/intern/wm_xr.c

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

diff --git a/intern/ghost/intern/GHOST_SystemWin32.cpp b/intern/ghost/intern/GHOST_SystemWin32.cpp
index cc6a0d8f3f1..ada34dc26f2 100644
--- a/intern/ghost/intern/GHOST_SystemWin32.cpp
+++ b/intern/ghost/intern/GHOST_SystemWin32.cpp
@@ -459,8 +459,6 @@ GHOST_TSuccess GHOST_SystemWin32::disposeContext(GHOST_IContext *context)
 GHOST_IContext *GHOST_SystemWin32::createOffscreenContextD3D()
 {
   GHOST_Context *context;
-  HDC prev_hdc = wglGetCurrentDC();
-  HGLRC prev_context = wglGetCurrentContext();
 
   /* TODO Doesn't use STATIC class to allow offscreen context framebuffer bigger than screen size.
    * For that, WM_GETMINMAXINFO event has to be listented to in custom WndProc callback. Need to
@@ -500,7 +498,6 @@ GHOST_IContext *GHOST_SystemWin32::createOffscreenContextD3D()
   if (context->initializeDrawingContext() == GHOST_kFailure) {
     delete context;
   }
-  wglMakeCurrent(prev_hdc, prev_context);
 
   return context;
 }
diff --git a/source/blender/draw/DRW_engine.h b/source/blender/draw/DRW_engine.h
index ba76ae449ec..b4a7d3b84fc 100644
--- a/source/blender/draw/DRW_engine.h
+++ b/source/blender/draw/DRW_engine.h
@@ -164,7 +164,10 @@ void DRW_opengl_context_destroy(void);
 void DRW_opengl_context_enable(void);
 void DRW_opengl_context_disable(void);
 
+/* Not nice to expose these. Code to render offscreen viewports can save expensive context switches
+ * by using this directly however. */
 void *DRW_opengl_context_get(void);
+void *DRW_gpu_context_get(void);
 
 /* For garbage collection */
 void DRW_cache_free_old_batches(struct Main *bmain);
diff --git a/source/blender/draw/intern/draw_manager.c b/source/blender/draw/intern/draw_manager.c
index c17aaa9c58d..1abe68b622d 100644
--- a/source/blender/draw/intern/draw_manager.c
+++ b/source/blender/draw/intern/draw_manager.c
@@ -3254,6 +3254,11 @@ void *DRW_opengl_context_get(void)
   return DST.gl_context;
 }
 
+void *DRW_gpu_context_get(void)
+{
+  return DST.gpu_context;
+}
+
 void DRW_opengl_render_context_enable(void *re_gl_context)
 {
   /* If thread is main you should use DRW_opengl_context_enable(). */
diff --git a/source/blender/windowmanager/intern/wm_xr.c b/source/blender/windowmanager/intern/wm_xr.c
index db4d306217e..200606211e5 100644
--- a/source/blender/windowmanager/intern/wm_xr.c
+++ b/source/blender/windowmanager/intern/wm_xr.c
@@ -141,7 +141,6 @@ static void wm_xr_session_free_data(wmSurface *surface)
 {
   wmXrSurfaceData *data = surface->customdata;
 
-  WM_opengl_context_dispose(surface->ghost_ctx);
   if (surface->secondary_ghost_ctx) {
 #ifdef WIN32
     if (data->gpu_binding_type == GHOST_kXrGraphicsD3D11) {
@@ -150,6 +149,7 @@ static void wm_xr_session_free_data(wmSurface *surface)
 #endif
   }
   GPU_context_active_set(surface->gpu_ctx);
+  DRW_opengl_context_enable_ex(false);
   if (data->viewport) {
     GPU_viewport_clear_from_offscreen(data->viewport);
     GPU_viewport_free(data->viewport);
@@ -157,7 +157,7 @@ static void wm_xr_session_free_data(wmSurface *surface)
   if (data->offscreen) {
     GPU_offscreen_free(data->offscreen);
   }
-  GPU_context_discard(surface->gpu_ctx);
+  DRW_opengl_context_disable_ex(false);
 
   MEM_freeN(surface->customdata);
 
@@ -173,7 +173,6 @@ static wmSurface *wm_xr_session_surface_create(wmWindowManager *wm, unsigned int
 
   wmSurface *surface = MEM_callocN(sizeof(*surface), __func__);
   wmXrSurfaceData *data = MEM_callocN(sizeof(*data), "XrSurfaceData");
-  unsigned int default_fb;
 
 #ifndef WIN32
   BLI_assert(gpu_binding_type == GHOST_kXrGraphicsOpenGL);
@@ -185,10 +184,8 @@ static wmSurface *wm_xr_session_surface_create(wmWindowManager *wm, unsigned int
   data->gpu_binding_type = gpu_binding_type;
   surface->customdata = data;
 
-  wm_window_clear_drawable(wm);
-  wm_surface_clear_drawable();
-  surface->ghost_ctx = WM_opengl_context_create();
-  WM_opengl_context_activate(surface->ghost_ctx);
+  surface->ghost_ctx = DRW_opengl_context_get();
+  DRW_opengl_context_enable();
 
   switch (gpu_binding_type) {
     case GHOST_kXrGraphicsOpenGL:
@@ -200,14 +197,9 @@ static wmSurface *wm_xr_session_surface_create(wmWindowManager *wm, unsigned int
 #endif
   }
 
-  default_fb = GHOST_GetContextDefaultOpenGLFramebuffer(surface->ghost_ctx);
-  surface->gpu_ctx = GPU_context_create(default_fb);
-
-  wm_surface_set_drawable(surface, false);
-  GHOST_SwapContextBuffers(surface->ghost_ctx);
-  GPU_state_init();
+  surface->gpu_ctx = DRW_gpu_context_get();
 
-  wm_surface_clear_drawable();
+  DRW_opengl_context_disable();
 
   g_xr_surface = surface;
 
@@ -254,6 +246,7 @@ static bool wm_xr_session_surface_offscreen_ensure(const GHOST_XrDrawViewInfo *d
     return true;
   }
 
+  DRW_opengl_context_enable();
   if (surface_data->offscreen) {
     GPU_viewport_clear_from_offscreen(surface_data->viewport);
     GPU_viewport_free(surface_data->viewport);
@@ -269,6 +262,7 @@ static bool wm_xr_session_surface_offscreen_ensure(const GHOST_XrDrawViewInfo *d
     GPU_offscreen_free(surface_data->offscreen);
     failure = true;
   }
+  DRW_opengl_context_disable();
 
   if (failure) {
     fprintf(stderr, "%s: failed to get buffer, %s\n", __func__, err_out);
@@ -294,15 +288,14 @@ static GHOST_ContextHandle wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view
 
   wm_xr_draw_matrices_create(CTX_data_scene(C), draw_view, clip_start, clip_end, viewmat, winmat);
 
-  DRW_opengl_context_enable();
   if (!wm_xr_session_surface_offscreen_ensure(draw_view)) {
     return NULL;
   }
-  DRW_opengl_context_disable();
 
   offscreen = surface_data->offscreen;
   viewport = surface_data->viewport;
   GPU_viewport_bind(viewport, &rect);
+  glClear(GL_DEPTH_BUFFER_BIT);
 
   BKE_screen_view3d_shading_init(&shading);
   ED_view3d_draw_offscreen_simple(CTX_data_depsgraph(C),
@@ -325,18 +318,12 @@ static GHOST_ContextHandle wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view
                                   offscreen,
                                   viewport);
 
-  /* Blit from the DRW context into the offscreen surface context. Would be good to avoid this.
-   * Idea: Allow passing custom offscreen context to DRW? */
-  //  GHOST_ContextBlitOpenGLOffscreenContext(
-  //      g_xr_surface->ghost_ctx, DRW_opengl_context_get(), draw_view->width, draw_view->height);
-
-  GPU_viewport_unbind(viewport);
   GPU_framebuffer_restore();
 
   GPUTexture *texture = GPU_offscreen_color_texture(offscreen);
 
-  WM_opengl_context_activate(g_xr_surface->ghost_ctx);
   wm_draw_offscreen_texture_parameters(offscreen);
+  GPU_depth_test(false);
 
   wmViewport(&rect);
   GPU_viewport_draw_to_screen(viewport, &rect);
@@ -346,6 +333,7 @@ static GHOST_ContextHandle wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view
     wm_draw_upside_down(draw_view->width, draw_view->height);
     GPU_texture_unbind(texture);
   }
+  GPU_viewport_unbind(viewport);
 
   return g_xr_surface->ghost_ctx;
 }



More information about the Bf-blender-cvs mailing list