[Bf-blender-cvs] [f7d42065ebf] xr-controller-support: XR: Fix render artifacts with viewport denoising

Peter Kim noreply at git.blender.org
Sat Jul 3 06:08:18 CEST 2021


Commit: f7d42065ebf705232bfb1bc28ecc0740595c911f
Author: Peter Kim
Date:   Sat Jul 3 13:05:32 2021 +0900
Branches: xr-controller-support
https://developer.blender.org/rBf7d42065ebf705232bfb1bc28ecc0740595c911f

XR: Fix render artifacts with viewport denoising

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

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

M	intern/ghost/GHOST_Types.h
M	intern/ghost/intern/GHOST_XrSession.cpp
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 1380a17d9ff..9924d0b0600 100644
--- a/intern/ghost/GHOST_Types.h
+++ b/intern/ghost/GHOST_Types.h
@@ -697,8 +697,9 @@ typedef struct GHOST_XrDrawViewInfo {
   /** Set if the buffer should be submitted with a SRGB transfer applied. */
   char expects_srgb_buffer;
 
-  /** The eye (left or right) that this view represents. */
-  char view;
+  /** 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 b94a7a4048d..43c8bd428b4 100644
--- a/intern/ghost/intern/GHOST_XrSession.cpp
+++ b/intern/ghost/intern/GHOST_XrSession.cpp
@@ -420,7 +420,7 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
   r_proj_layer_view.fov = view.fov;
   swapchain.updateCompositionLayerProjectViewSubImage(r_proj_layer_view.subImage);
 
-  draw_view_info.view = (char)view_idx;
+  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;
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_draw.c b/source/blender/windowmanager/xr/intern/wm_xr_draw.c
index 2d77080c59b..bd0ff8c7db1 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_draw.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_draw.c
@@ -132,7 +132,7 @@ static void wm_xr_draw_viewport_buffers_to_active_framebuffer(
     SWAP(int, rect.ymin, rect.ymax);
   }
   GPU_viewport_draw_to_screen_ex(
-      surface_data->viewport, 0, &rect, draw_view->expects_srgb_buffer, true);
+      surface_data->viewport[draw_view->view_idx], 0, &rect, draw_view->expects_srgb_buffer, true);
 }
 
 /**
@@ -185,8 +185,8 @@ void wm_xr_draw_view(const GHOST_XrDrawViewInfo *draw_view, void *customdata)
                                   true,
                                   NULL,
                                   false,
-                                  surface_data->offscreen,
-                                  surface_data->viewport);
+                                  surface_data->offscreen[draw_view->view_idx],
+                                  surface_data->viewport[draw_view->view_idx]);
 
   /* 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
@@ -196,7 +196,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(surface_data->offscreen[draw_view->view_idx], 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 0c14dddf744..a8ceb8337d6 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_intern.h
+++ b/source/blender/windowmanager/xr/intern/wm_xr_intern.h
@@ -116,8 +116,9 @@ typedef struct wmXrRuntimeData {
 } wmXrRuntimeData;
 
 typedef struct {
-  struct GPUOffScreen *offscreen;
-  struct GPUViewport *viewport;
+  /* Offscreen buffers/viewports for each view. */
+  struct GPUOffScreen *offscreen[2];
+  struct GPUViewport *viewport[2];
 
   /** XR events. */
   ListBase events;
diff --git a/source/blender/windowmanager/xr/intern/wm_xr_session.c b/source/blender/windowmanager/xr/intern/wm_xr_session.c
index 52e781500e7..112eef9e8ef 100644
--- a/source/blender/windowmanager/xr/intern/wm_xr_session.c
+++ b/source/blender/windowmanager/xr/intern/wm_xr_session.c
@@ -390,7 +390,9 @@ void wm_xr_session_state_update(const XrSessionSettings *settings,
                                 const float viewmat[4][4],
                                 wmXrSessionState *state)
 {
-  wmXrEyeData *eye = &state->eyes[draw_view->view];
+  const unsigned int view_idx = (unsigned int)min_ii((int)ARRAY_SIZE(state->eyes),
+                                                     (int)draw_view->view_idx);
+  wmXrEyeData *eye = &state->eyes[view_idx];
   GHOST_XrPose viewer_pose;
   float viewer_mat[4][4], base_mat[4][4], nav_mat[4][4];
 
@@ -1380,32 +1382,36 @@ static void wm_xr_session_surface_draw(bContext *C)
 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);
+  const unsigned int view_idx = (unsigned int)min_ii((int)ARRAY_SIZE(surface_data->offscreen),
+                                                     (int)draw_view->view_idx);
+  GPUOffScreen *offscreen = surface_data->offscreen[view_idx];
+  GPUViewport *viewport = surface_data->viewport[view_idx];
+  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 = surface_data->offscreen[view_idx] = GPU_offscreen_create(
+      draw_view->width, draw_view->height, true, false, err_out);
+  if (offscreen) {
+    viewport = surface_data->viewport[view_idx] = GPU_viewport_create();
+    if (!viewport) {
+      GPU_offscreen_free(offscreen);
+      offscreen = surface_data->offscreen[view_idx] = NULL;
+      failure = true;
+    }
   }
-  else if (!(surface_data->viewport = GPU_viewport_create())) {
-    GPU_offscreen_free(surface_data->offscreen);
+  else {
     failure = true;
   }
 
@@ -1421,12 +1427,15 @@ static void wm_xr_session_surface_free_data(wmSurface *surface)
 {
   wmXrSurfaceData *data = surface->customdata;
 
-  if (data->viewport) {
-    GPU_viewport_free(data->viewport);
-  }
-  if (data->offscreen) {
-    GPU_offscreen_free(data->offscreen);
+  for (unsigned int i = 0; i < (unsigned int)ARRAY_SIZE(data->offscreen); ++i) {
+    if (data->viewport[i]) {
+      GPU_viewport_free(data->viewport[i]);
+    }
+    if (data->offscreen[i]) {
+      GPU_offscreen_free(data->offscreen[i]);
+    }
   }
+
   if (data->controller_art) {
     BLI_freelistN(&data->controller_art->drawcalls);
     MEM_freeN(data->controller_art);



More information about the Bf-blender-cvs mailing list