[Bf-blender-cvs] [c41b93bda53] master: XR: Fix for Viewport Denoising Artifacts

Peter Kim noreply at git.blender.org
Fri Jul 23 17:12:52 CEST 2021


Commit: c41b93bda5328ce13faf7048dfd38708e6486b6a
Author: Peter Kim
Date:   Sat Jul 24 00:11:22 2021 +0900
Branches: master
https://developer.blender.org/rBc41b93bda5328ce13faf7048dfd38708e6486b6a

XR: Fix for Viewport Denoising Artifacts

Addresses T76003. When using VR with Eevee and viewport denoising,
scene geometry could sometimes be occluded for one eye. Solution is
to use a separate GPUViewport/GPUOffscreen for each VR view instead
of reusing a single one for rendering.

Reviewed By: Julian Eisel, Clément Foucault

Differential Revision: http://developer.blender.org/D11858

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

M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_XrSession.cpp
M	intern/ghost/intern/GHOST_XrSession.h
M	source/blender/windowmanager/xr/intern/wm_xr_draw.c
M	source/blender/windowmanager/xr/intern/wm_xr_intern.h
M	source/blender/windowmanager/xr/intern/wm_xr_session.c

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

diff --git a/intern/ghost/GHOST_Types.h b/intern/ghost/GHOST_Types.h
index ff93de4f203..ddebfa7e816 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -683,6 +683,10 @@ typedef struct GHOST_XrDrawViewInfo {
 
   /** Set if the buffer should be submitted with a SRGB transfer applied. */
   char expects_srgb_buffer;
+
+  /** The view that this info represents. Not necessarily the "eye index" (e.g. for quad view
+   * systems, etc). */
+  char view_idx;
 } GHOST_XrDrawViewInfo;
 
 typedef struct GHOST_XrError {
diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp
index 263b2b6cfbd..6140b2aab46 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -409,6 +409,7 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
                                XrCompositionLayerProjectionView &r_proj_layer_view,
                                XrSpaceLocation &view_location,
                                XrView &view,
+                               uint32_t view_idx,
                                void *draw_customdata)
 {
   XrSwapchainImageBaseHeader *swapchain_image = swapchain.acquireDrawableSwapchainImage();
@@ -419,6 +420,8 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
   r_proj_layer_view.fov = view.fov;
   swapchain.updateCompositionLayerProjectViewSubImage(r_proj_layer_view.subImage);
 
+  assert(view_idx < 256);
+  draw_view_info.view_idx = (char)view_idx;
   draw_view_info.expects_srgb_buffer = swapchain.isBufferSRGB();
   draw_view_info.ofsx = r_proj_layer_view.subImage.imageRect.offset.x;
   draw_view_info.ofsy = r_proj_layer_view.subImage.imageRect.offset.y;
@@ -468,6 +471,7 @@ XrCompositionLayerProjection GHOST_XrSession::drawLayer(
              r_proj_layer_views[view_idx],
              view_location,
              m_oxr->views[view_idx],
+             view_idx,
              draw_customdata);
   }
 
diff --git a/intern/ghost/intern/GHOST_XrSession.h b/intern/ghost/intern/GHOST_XrSession.h
index c871b98da46..d448585d14c 100644
--- a/intern/ghost/intern/GHOST_XrSession.h
+++ b/intern/ghost/intern/GHOST_XrSession.h
@@ -117,6 +117,7 @@ class GHOST_XrSession {
                 XrCompositionLayerProjectionView &r_proj_layer_view,
                 XrSpaceLocation &view_location,
                 XrView &view,
+                uint32_t view_idx,
                 void *draw_customdata);
   void beginFrameDrawing();
   void endFrameDrawing(std::vector<XrCompositionLayerBaseHeader *> &layers);
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c
index bef88505488..4ac05e339b9 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c
@@ -24,6 +24,7 @@
 
 #include <string.h>
 
+#include "BLI_listbase.h"
 #include "BLI_math.h"
 
 #include "ED_view3d_offscreen.h"
@@ -91,6 +92,9 @@ static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
     const wmXrSurfaceData *surface_data,
     const GHOST_XrDrawViewInfo *draw_view)
 {
+  const wmXrViewportPair *vp = BLI_findlink(&surface_data->viewports, draw_view->view_idx);
+  BLI_assert(vp && vp->viewport);
+
   const bool is_upside_down = GHOST_XrSessionNeedsUpsideDownDrawing(runtime_data->context);
   rcti rect = {.xmin = 0, .ymin = 0, .xmax = draw_view->width - 1, .ymax = draw_view->height - 1};
 
@@ -100,8 +104,7 @@ static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
   if (is_upside_down) {
     SWAP(int, rect.ymin, rect.ymax);
   }
-  GPU_viewport_draw_to_screen_ex(
-      surface_data->viewport, 0, &rect, draw_view->expects_srgb_buffer, true);
+  GPU_viewport_draw_to_screen_ex(vp->viewport, 0, &rect, draw_view->expects_srgb_buffer, true);
 }
 
 /**
@@ -132,6 +135,9 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
     return;
   }
 
+  const wmXrViewportPair *vp = BLI_findlink(&surface_data->viewports, draw_view->view_idx);
+  BLI_assert(vp && vp->offscreen && vp->viewport);
+
   /* In case a framebuffer is still bound from drawing the last eye. */
   GPU_framebuffer_restore();
   /* Some systems have drawing glitches without this. */
@@ -153,8 +159,8 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
                                   true,
                                   NULL,
                                   false,
-                                  surface_data->offscreen,
-                                  surface_data->viewport);
+                                  vp->offscreen,
+                                  vp->viewport);
 
   /* The draw-manager uses both GPUOffscreen and GPUViewport to manage frame and texture buffers. A
    * call to GPU_viewport_draw_to_screen() is still needed to get the final result from the
@@ -164,7 +170,7 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
    * In a next step, Ghost-XR will use the currently bound frame-buffer to retrieve the image
    * to be submitted to the OpenXR swap-chain. So do not un-bind the off-screen yet! */
 
-  GPU_offscreen_bind(surface_data->offscreen, false);
+  GPU_offscreen_bind(vp->offscreen, false);
 
   wm_xr_draw_viewport_buffers_to_active_framebuffer(xr_data->runtime, surface_data, draw_view);
 }
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_intern.h b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
index 9bf63be61dd..24582388228 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -85,9 +85,15 @@ typedef struct wmXrRuntimeData {
   wmXrSessionExitFn exit_fn;
 } wmXrRuntimeData;
 
-typedef struct {
+typedef struct wmXrViewportPair {
+  struct wmXrViewportPair *next, *prev;
   struct GPUOffScreen *offscreen;
   struct GPUViewport *viewport;
+} wmXrViewportPair;
+
+typedef struct {
+  /* Offscreen buffers/viewports for each view. */
+  ListBase viewports; /* wmXrViewportPair */
 } wmXrSurfaceData;
 
 typedef struct wmXrDrawData {
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index b740cb27471..4439f2fe479 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -546,7 +546,6 @@ void wm_xr_session_controller_data_clear(wmXrSessionState *state)
  */
 static void wm_xr_session_surface_draw(bContext *C)
 {
-  wmXrSurfaceData *surface_data = g_xr_surface->customdata;
   wmWindowManager *wm = CTX_wm_manager(C);
   Main *bmain = CTX_data_main(C);
   wmXrDrawData draw_data;
@@ -562,38 +561,50 @@ static void wm_xr_session_surface_draw(bContext *C)
 
   GHOST_XrSessionDrawViews(wm->xr.runtime->context, &draw_data);
 
-  GPU_offscreen_unbind(surface_data->offscreen, false);
+  GPU_framebuffer_restore();
 }
 
 bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data,
                                             const GHOST_XrDrawViewInfo *draw_view)
 {
-  const bool size_changed = surface_data->offscreen &&
-                            (GPU_offscreen_width(surface_data->offscreen) != draw_view->width) &&
-                            (GPU_offscreen_height(surface_data->offscreen) != draw_view->height);
+  wmXrViewportPair *vp = NULL;
+  if (draw_view->view_idx >= BLI_listbase_count(&surface_data->viewports)) {
+    vp = MEM_callocN(sizeof(*vp), __func__);
+    BLI_addtail(&surface_data->viewports, vp);
+  }
+  else {
+    vp = BLI_findlink(&surface_data->viewports, draw_view->view_idx);
+  }
+  BLI_assert(vp);
+
+  GPUOffScreen *offscreen = vp->offscreen;
+  GPUViewport *viewport = vp->viewport;
+  const bool size_changed = offscreen && (GPU_offscreen_width(offscreen) != draw_view->width) &&
+                            (GPU_offscreen_height(offscreen) != draw_view->height);
   char err_out[256] = "unknown";
   bool failure = false;
 
-  if (surface_data->offscreen) {
-    BLI_assert(surface_data->viewport);
+  if (offscreen) {
+    BLI_assert(viewport);
 
     if (!size_changed) {
       return true;
     }
-    GPU_viewport_free(surface_data->viewport);
-    GPU_offscreen_free(surface_data->offscreen);
-  }
-
-  if (!(surface_data->offscreen = GPU_offscreen_create(
-            draw_view->width, draw_view->height, true, false, err_out))) {
-    failure = true;
-  }
-
-  if (failure) {
-    /* Pass. */
+    GPU_viewport_free(viewport);
+    GPU_offscreen_free(offscreen);
+  }
+
+  offscreen = vp->offscreen = GPU_offscreen_create(
+      draw_view->width, draw_view->height, true, false, err_out);
+  if (offscreen) {
+    viewport = vp->viewport = GPU_viewport_create();
+    if (!viewport) {
+      GPU_offscreen_free(offscreen);
+      offscreen = vp->offscreen = NULL;
+      failure = true;
+    }
   }
-  else if (!(surface_data->viewport = GPU_viewport_create())) {
-    GPU_offscreen_free(surface_data->offscreen);
+  else {
     failure = true;
   }
 
@@ -608,12 +619,17 @@ bool wm_xr_session_surface_offscreen_ensure(wmXrSurfaceData *surface_data,
 static void wm_xr_session_surface_free_data(wmSurface *surface)
 {
   wmXrSurfaceData *data = surface->customdata;
+  ListBase *lb = &data->viewports;
+  wmXrViewportPair *vp;
 
-  if (data->viewport) {
-    GPU_viewport_free(data->viewport);
-  }
-  if (data->offscreen) {
-    GPU_offscreen_free(data->offscreen);
+  while (vp = BLI_pophead(lb)) {
+    if (vp->viewport) {
+      GPU_viewport_free(vp->viewport);
+    }
+    if (vp->offscreen) {
+      GPU_offscreen_free(vp->offscreen);
+    }
+    BLI_freelinkN(lb, vp);
   }
 
   MEM_freeN(surface->customdata);



More information about the Bf-blender-cvs mailing list