Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Kim <pk15950@gmail.com>2021-07-23 18:11:22 +0300
committerPeter Kim <pk15950@gmail.com>2021-07-23 18:12:17 +0300
commitc41b93bda5328ce13faf7048dfd38708e6486b6a (patch)
treef544026d65acfaf3e4923ae2182ea374c5ae67af /source/blender/windowmanager
parenteb434778511070238ec189c8929c9b267842606a (diff)
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
Diffstat (limited to 'source/blender/windowmanager')
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_draw.c16
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_intern.h8
-rw-r--r--source/blender/windowmanager/xr/intern/wm_xr_session.c66
3 files changed, 59 insertions, 31 deletions
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);