[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