[Bf-blender-cvs] [fec7ac7c518] soc-2019-openxr: Refactor OpenGL/DirectX resource sharing for multiple shared resources

Julian Eisel noreply at git.blender.org
Wed Aug 21 19:46:19 CEST 2019


Commit: fec7ac7c51896a165ab0a5b19a984f9c2fdba1ce
Author: Julian Eisel
Date:   Wed Aug 21 19:44:08 2019 +0200
Branches: soc-2019-openxr
https://developer.blender.org/rBfec7ac7c51896a165ab0a5b19a984f9c2fdba1ce

Refactor OpenGL/DirectX resource sharing for multiple shared resources

Rather than max. one shared resource per DirectX context, code can now
request a handle for a shared resource and ask the DirectX context to do
operations on that.

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

M	intern/ghost/intern/GHOST_ContextD3D.cpp
M	intern/ghost/intern/GHOST_ContextD3D.h
M	intern/ghost/intern/GHOST_XrGraphicsBinding.cpp

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

diff --git a/intern/ghost/intern/GHOST_ContextD3D.cpp b/intern/ghost/intern/GHOST_ContextD3D.cpp
index 8e357a80702..f5fc36a4831 100644
--- a/intern/ghost/intern/GHOST_ContextD3D.cpp
+++ b/intern/ghost/intern/GHOST_ContextD3D.cpp
@@ -27,7 +27,7 @@
 #include "GHOST_ContextWGL.h" /* For shared drawing */
 #include "GHOST_ContextD3D.h"
 
-// #define USE_DRAW_D3D_TEST_TRIANGLE
+//#define USE_DRAW_D3D_TEST_TRIANGLE
 
 HMODULE GHOST_ContextD3D::s_d3d_lib = NULL;
 PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN GHOST_ContextD3D::s_D3D11CreateDeviceAndSwapChainFn = NULL;
@@ -35,107 +35,10 @@ PFN_D3D11_CREATE_DEVICE_AND_SWAP_CHAIN GHOST_ContextD3D::s_D3D11CreateDeviceAndS
 #ifdef USE_DRAW_D3D_TEST_TRIANGLE
 static void drawTestTriangle(ID3D11Device *m_device,
                              ID3D11DeviceContext *m_device_ctx,
-                             HWND hwnd,
                              GHOST_TInt32 width,
                              GHOST_TInt32 height);
 #endif
 
-class SharedOpenGLContext {
-  ID3D11Device *m_d3d_device;
-  GHOST_ContextWGL *m_wgl_ctx;
-  /* NV_DX_interop2 requires ID3D11Texture2D as backbuffer when sharing with GL_RENDERBUFFER */
-  ID3D11Texture2D *m_d3d_render_target;
-  GLuint m_gl_render_buf;
-
- public:
-  struct SharedData {
-    HANDLE device;
-    GLuint fbo;
-    HANDLE render_buf{nullptr};
-  } m_shared;
-
-  /* XXX Should have a map of render_target items to shared resource data (SharedData) to
-   * allow multiple shared surfaces in a context. Current code assumes a single one. That would be
-   * an issue if we wanted to use the OpenXR provided textures (changes for each eye and each
-   * redraw) and not the constant D3D swapchain texture like now. */
-  SharedOpenGLContext(ID3D11Device *d3d_device,
-                      GHOST_ContextWGL *wgl_ctx,
-                      ID3D11Texture2D *render_target)
-      : m_d3d_device(d3d_device), m_wgl_ctx(wgl_ctx), m_d3d_render_target(render_target)
-  {
-  }
-  ~SharedOpenGLContext()
-  {
-    if (m_shared.render_buf) {
-      wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
-    }
-    if (m_shared.device) {
-      wglDXCloseDeviceNV(m_shared.device);
-    }
-    glDeleteFramebuffers(1, &m_shared.fbo);
-    glDeleteRenderbuffers(1, &m_gl_render_buf);
-  }
-
-  void reregisterSharedObject()
-  {
-    if (m_shared.render_buf) {
-      wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
-      m_shared.render_buf = nullptr;
-    }
-
-    m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device,
-                                                m_d3d_render_target,
-                                                m_gl_render_buf,
-                                                GL_RENDERBUFFER,
-                                                WGL_ACCESS_READ_WRITE_NV);
-    if (!m_shared.render_buf) {
-      fprintf(stderr, "Error registering shared object using wglDXRegisterObjectNV()\n");
-      return;
-    }
-  }
-
-  GHOST_TSuccess initialize()
-  {
-    m_wgl_ctx->activateDrawingContext();
-
-    m_shared.device = wglDXOpenDeviceNV(m_d3d_device);
-    if (m_shared.device == NULL) {
-      fprintf(stderr, "Error opening shared device using wglDXOpenDeviceNV()\n");
-      return GHOST_kFailure;
-    }
-
-    /* Build the renderbuffer. */
-    glGenRenderbuffers(1, &m_gl_render_buf);
-    glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_buf);
-
-    reregisterSharedObject();
-
-    /* Build the framebuffer */
-    glGenFramebuffers(1, &m_shared.fbo);
-    glBindFramebuffer(GL_FRAMEBUFFER, m_shared.fbo);
-    glFramebufferRenderbuffer(
-        GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_gl_render_buf);
-
-    return GHOST_kSuccess;
-  }
-  void update(int width, int height)
-  {
-    m_wgl_ctx->setDefaultFramebufferSize(width, height);
-    m_wgl_ctx->activateDrawingContext();
-    /* TODO avoid re-registering if resource to share has not changed. */
-    reregisterSharedObject();
-  }
-
-  void beginGLOnly()
-  {
-    wglDXLockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
-  }
-  void endGLOnly()
-  {
-    wglDXUnlockObjectsNV(m_shared.device, 1, &m_shared.render_buf);
-  }
-};
-
 GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
     : GHOST_Context(GHOST_kDrawingContextTypeD3D, stereoVisual), m_hWnd(hWnd)
 {
@@ -143,7 +46,6 @@ GHOST_ContextD3D::GHOST_ContextD3D(bool stereoVisual, HWND hWnd)
 
 GHOST_ContextD3D::~GHOST_ContextD3D()
 {
-  delete glshared;
   m_swapchain->Release();
   m_backbuffer_view->Release();
   m_device->Release();
@@ -214,8 +116,6 @@ GHOST_TSuccess GHOST_ContextD3D::updateSwapchain(GHOST_TUns32 width, GHOST_TUns3
   } \
   (void)0
 
-  setDefaultFramebufferSize(width, height);
-
   m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
 
   m_backbuffer_view->Release();
@@ -315,75 +215,245 @@ GHOST_TSuccess GHOST_ContextD3D::blitOpenGLOffscreenContext(GHOST_Context *offsc
                                                             GHOST_TInt32 width,
                                                             GHOST_TInt32 height)
 {
-  if (!(WGL_NV_DX_interop && WGL_NV_DX_interop2)) {
-    fprintf(stderr,
-            "Error: Can't render OpenGL framebuffer using Direct3D. NV_DX_interop extension not "
-            "available.");
-    return GHOST_kFailure;
+  GHOST_SharedOpenGLResource *shared_res = createSharedOpenGLResource(
+      width, height, render_target);
+
+  if (shared_res) {
+    GHOST_TSuccess ret = blitFromOpenGLContext(shared_res, width, height);
+    disposeSharedOpenGLResource(shared_res);
+    return ret;
   }
-  m_device_ctx->OMSetRenderTargets(1, &render_target, nullptr);
 
-  offscreen_ctx->activateDrawingContext();
+  return GHOST_kFailure;
+}
 
-  GLint fbo;
-  glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &fbo);
+GHOST_TSuccess GHOST_ContextD3D::blitOpenGLOffscreenContext(GHOST_Context *offscreen_ctx,
+                                                            GHOST_TInt32 width,
+                                                            GHOST_TInt32 height)
+{
+  if (updateSwapchain(width, height) == GHOST_kSuccess) {
+    return blitOpenGLOffscreenContext(offscreen_ctx, m_backbuffer_view, width, height);
+  }
+
+  return GHOST_kFailure;
+}
+
+class GHOST_SharedOpenGLResource {
+  struct SharedData {
+    HANDLE device;
+    GLuint fbo;
+    HANDLE render_buf{nullptr};
+  } m_shared;
 
-  if (glshared == NULL) {
+ public:
+  GHOST_SharedOpenGLResource(ID3D11Device *device,
+                             ID3D11DeviceContext *device_ctx,
+                             unsigned int width,
+                             unsigned int height,
+                             ID3D11RenderTargetView *render_target = nullptr)
+      : m_device(device), m_device_ctx(device_ctx), m_cur_width(width), m_cur_height(height)
+  {
     ID3D11Resource *backbuffer_res;
-    ID3D11Texture2D *backbuffer_tex;
-    render_target->GetResource(&backbuffer_res);
-    backbuffer_res->QueryInterface<ID3D11Texture2D>(&backbuffer_tex);
 
-    glshared = new SharedOpenGLContext(
-        m_device, (GHOST_ContextWGL *)offscreen_ctx, backbuffer_tex);
+    if (!render_target) {
+      D3D11_TEXTURE2D_DESC texDesc{};
+      D3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc{};
+      ID3D11Texture2D *tex;
+
+      texDesc.Width = width;
+      texDesc.Height = height;
+      texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
+      texDesc.SampleDesc.Count = 1;
+      texDesc.ArraySize = 1;
+      texDesc.MipLevels = 1;
+      texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_RENDER_TARGET;
+
+      device->CreateTexture2D(&texDesc, NULL, &tex);
+
+      renderTargetViewDesc.Format = texDesc.Format;
+      renderTargetViewDesc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;
+      renderTargetViewDesc.Texture2D.MipSlice = 0;
+
+      device->CreateRenderTargetView(tex, &renderTargetViewDesc, &m_render_target);
+
+      tex->Release();
+    }
+
+    m_render_target->GetResource(&backbuffer_res);
+    backbuffer_res->QueryInterface<ID3D11Texture2D>(&m_render_target_tex);
     backbuffer_res->Release();
-    backbuffer_tex->Release();
+  }
 
-    if (glshared->initialize() == GHOST_kFailure) {
-      return GHOST_kFailure;
+  ~GHOST_SharedOpenGLResource()
+  {
+    m_render_target_tex->Release();
+    m_render_target->Release();
+
+    if (m_is_initialized) {
+      if (m_shared.render_buf) {
+        wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
+      }
+      if (m_shared.device) {
+        wglDXCloseDeviceNV(m_shared.device);
+      }
+      glDeleteFramebuffers(1, &m_shared.fbo);
+      glDeleteRenderbuffers(1, &m_gl_render_buf);
     }
   }
-  SharedOpenGLContext::SharedData *shared = &glshared->m_shared;
 
-  glshared->update(width, height);
+  void reregisterSharedObject()
+  {
+    if (m_shared.render_buf) {
+      wglDXUnregisterObjectNV(m_shared.device, m_shared.render_buf);
+    }
 
-  const float clear_col[] = {0.8f, 0.5f, 1.0f, 1.0f};
-  m_device_ctx->ClearRenderTargetView(render_target, clear_col);
+    m_shared.render_buf = wglDXRegisterObjectNV(m_shared.device,
+                                                m_render_target_tex,
+                                                m_gl_render_buf,
+                                                GL_RENDERBUFFER,
+                                                WGL_ACCESS_READ_WRITE_NV);
+    if (!m_shared.render_buf) {
+      fprintf(stderr, "Error registering shared object using wglDXRegisterObjectNV()\n");
+      return;
+    }
+  }
 
-  glshared->beginGLOnly();
+  GHOST_TSuccess initialize()
+  {
+    m_shared.device = wglDXOpenDeviceNV(m_device);
+    if (m_shared.device == NULL) {
+      fprintf(stderr, "Error opening shared device using wglDXOpenDeviceNV()\n");
+      return GHOST_kFailure;
+    }
 
-  glBindFramebuffer(GL_DRAW_FRAMEBUFFER, shared->fbo);
-  GLenum err = glCheckFramebufferStatus(GL_FRAMEBUFFER);
-  if (err != GL_FRAMEBUFFER_COMPLETE) {
-    fprintf(stderr, "Error: Framebuffer incomplete %u\n", err);
-    return GHOST_kFailure;
+    /* Build the renderbuffer. */
+    glGenRenderbuffers(1, &m_gl_render_buf);
+    glBindRenderbuffer(GL_RENDERBUFFER, m_gl_render_buf);
+
+    reregisterSharedObject();
+
+    /

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-blender-cvs mailing list