Cleanup: OpenXR: Move Direct3D to its own compile unit
_No response_ Pull Request: https://projects.blender.org/blender/blender/pulls/137255
This commit is contained in:
@@ -579,6 +579,14 @@ if(WITH_XR_OPENXR)
|
||||
# Header only library.
|
||||
../../extern/tinygltf/tiny_gltf.h
|
||||
)
|
||||
if(WIN32)
|
||||
list(APPEND SRC
|
||||
intern/GHOST_XrGraphicsBindingD3D.cc
|
||||
|
||||
intern/GHOST_XrGraphicsBindingD3D.hh
|
||||
)
|
||||
endif()
|
||||
|
||||
list(APPEND INC_SYS
|
||||
../../extern/json/include
|
||||
../../extern/tinygltf
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
# include "GHOST_ContextD3D.hh"
|
||||
# include "GHOST_ContextWGL.hh"
|
||||
# include "GHOST_SystemWin32.hh"
|
||||
# include "GHOST_XrGraphicsBindingD3D.hh"
|
||||
#endif
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
# include "GHOST_XrGraphicsBindingVulkan.hh"
|
||||
@@ -303,237 +304,6 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding {
|
||||
GLuint m_fbo = 0;
|
||||
};
|
||||
|
||||
#ifdef WIN32
|
||||
static void ghost_format_to_dx_format(GHOST_TXrSwapchainFormat ghost_format,
|
||||
bool expects_srgb_buffer,
|
||||
DXGI_FORMAT &r_dx_format)
|
||||
{
|
||||
r_dx_format = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
switch (ghost_format) {
|
||||
case GHOST_kXrSwapchainFormatRGBA8:
|
||||
r_dx_format = expects_srgb_buffer ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB :
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case GHOST_kXrSwapchainFormatRGBA16:
|
||||
r_dx_format = DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
break;
|
||||
case GHOST_kXrSwapchainFormatRGBA16F:
|
||||
r_dx_format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
case GHOST_kXrSwapchainFormatRGB10_A2:
|
||||
r_dx_format = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r_dx_format == DXGI_FORMAT_UNKNOWN) {
|
||||
throw GHOST_XrException("No supported DirectX swapchain format found.");
|
||||
}
|
||||
}
|
||||
|
||||
class GHOST_XrGraphicsBindingD3D : public GHOST_IXrGraphicsBinding {
|
||||
public:
|
||||
GHOST_XrGraphicsBindingD3D() : GHOST_IXrGraphicsBinding()
|
||||
{
|
||||
m_ghost_d3d_ctx = GHOST_SystemWin32::createOffscreenContextD3D();
|
||||
}
|
||||
virtual ~GHOST_XrGraphicsBindingD3D()
|
||||
{
|
||||
if (m_ghost_d3d_ctx) {
|
||||
GHOST_SystemWin32::disposeContextD3D(m_ghost_d3d_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
bool checkVersionRequirements(
|
||||
GHOST_Context & /*ghost_ctx*/, /* Remember: This is the OpenGL context! */
|
||||
XrInstance instance,
|
||||
XrSystemId system_id,
|
||||
std::string *r_requirement_info) const override
|
||||
{
|
||||
static PFN_xrGetD3D11GraphicsRequirementsKHR s_xrGetD3D11GraphicsRequirementsKHR_fn = nullptr;
|
||||
// static XrInstance s_instance = XR_NULL_HANDLE;
|
||||
XrGraphicsRequirementsD3D11KHR gpu_requirements = {XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
|
||||
|
||||
/* Although it would seem reasonable that the PROC address would not change if the instance was
|
||||
* the same, in testing, repeated calls to #xrGetInstanceProcAddress() with the same instance
|
||||
* can still result in changes so the workaround is to simply set the function pointer every
|
||||
* time (trivializing its 'static' designation). */
|
||||
// if (instance != s_instance) {
|
||||
// s_instance = instance;
|
||||
s_xrGetD3D11GraphicsRequirementsKHR_fn = nullptr;
|
||||
//}
|
||||
if (!s_xrGetD3D11GraphicsRequirementsKHR_fn &&
|
||||
XR_FAILED(
|
||||
xrGetInstanceProcAddr(instance,
|
||||
"xrGetD3D11GraphicsRequirementsKHR",
|
||||
(PFN_xrVoidFunction *)&s_xrGetD3D11GraphicsRequirementsKHR_fn)))
|
||||
{
|
||||
s_xrGetD3D11GraphicsRequirementsKHR_fn = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
s_xrGetD3D11GraphicsRequirementsKHR_fn(instance, system_id, &gpu_requirements);
|
||||
|
||||
if (r_requirement_info) {
|
||||
std::ostringstream strstream;
|
||||
strstream << "Minimum DirectX 11 Feature Level " << gpu_requirements.minFeatureLevel
|
||||
<< std::endl;
|
||||
|
||||
*r_requirement_info = strstream.str();
|
||||
}
|
||||
|
||||
return m_ghost_d3d_ctx->m_device->GetFeatureLevel() >= gpu_requirements.minFeatureLevel;
|
||||
}
|
||||
|
||||
void initFromGhostContext(
|
||||
GHOST_Context & /*ghost_ctx*/ /* Remember: This is the OpenGL context! */,
|
||||
XrInstance /*instance*/,
|
||||
XrSystemId /*system_id*/
|
||||
) override
|
||||
{
|
||||
oxr_binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
|
||||
oxr_binding.d3d11.device = m_ghost_d3d_ctx->m_device;
|
||||
}
|
||||
|
||||
std::optional<int64_t> chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
|
||||
GHOST_TXrSwapchainFormat &r_format,
|
||||
bool &r_is_srgb_format) const override
|
||||
{
|
||||
std::vector<int64_t> gpu_binding_formats = {
|
||||
# if 0 /* RGB10A2, RGBA16 don't seem to work with Oculus head-sets, \
|
||||
* so move them after RGBA16F for the time being. */
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
# endif
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
# if 1
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
# endif
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
};
|
||||
|
||||
std::optional result = choose_swapchain_format_from_candidates(gpu_binding_formats,
|
||||
runtime_formats);
|
||||
if (result) {
|
||||
switch (*result) {
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
r_format = GHOST_kXrSwapchainFormatRGB10_A2;
|
||||
break;
|
||||
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA16;
|
||||
break;
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA16F;
|
||||
break;
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA8;
|
||||
break;
|
||||
}
|
||||
r_is_srgb_format = (*result == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
|
||||
}
|
||||
else {
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA8;
|
||||
r_is_srgb_format = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
|
||||
{
|
||||
std::vector<XrSwapchainImageD3D11KHR> d3d_images(image_count);
|
||||
std::vector<XrSwapchainImageBaseHeader *> base_images;
|
||||
|
||||
/* Need to return vector of base header pointers, so of a different type. Need to build a new
|
||||
* list with this type, and keep the initial one alive. */
|
||||
for (XrSwapchainImageD3D11KHR &image : d3d_images) {
|
||||
image.type = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR;
|
||||
base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
|
||||
}
|
||||
|
||||
/* Keep alive. */
|
||||
m_image_cache.push_back(std::move(d3d_images));
|
||||
|
||||
return base_images;
|
||||
}
|
||||
|
||||
bool needsUpsideDownDrawing(GHOST_Context &) const
|
||||
{
|
||||
return m_ghost_d3d_ctx->isUpsideDown();
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Secondary DirectX 11 context used by OpenXR. */
|
||||
GHOST_ContextD3D *m_ghost_d3d_ctx = nullptr;
|
||||
|
||||
std::list<std::vector<XrSwapchainImageD3D11KHR>> m_image_cache;
|
||||
};
|
||||
|
||||
class GHOST_XrGraphicsBindingOpenGLD3D : public GHOST_XrGraphicsBindingD3D {
|
||||
public:
|
||||
GHOST_XrGraphicsBindingOpenGLD3D(GHOST_Context &ghost_ctx)
|
||||
: GHOST_XrGraphicsBindingD3D(), m_ghost_wgl_ctx(static_cast<GHOST_ContextWGL &>(ghost_ctx))
|
||||
{
|
||||
}
|
||||
~GHOST_XrGraphicsBindingOpenGLD3D()
|
||||
{
|
||||
if (m_shared_resource) {
|
||||
m_ghost_d3d_ctx->disposeSharedOpenGLResource(m_shared_resource);
|
||||
m_shared_resource = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void submitToSwapchainImage(XrSwapchainImageBaseHeader &swapchain_image,
|
||||
const GHOST_XrDrawViewInfo &draw_info) override
|
||||
{
|
||||
XrSwapchainImageD3D11KHR &d3d_swapchain_image = reinterpret_cast<XrSwapchainImageD3D11KHR &>(
|
||||
swapchain_image);
|
||||
|
||||
# if 0
|
||||
/* Ideally we'd just create a render target view for the OpenXR swap-chain image texture and
|
||||
* blit from the OpenGL context into it. The NV_DX_interop extension doesn't want to work with
|
||||
* this though. At least not with OPTIMUS hardware. See:
|
||||
* https://github.com/mpv-player/mpv/issues/2949#issuecomment-197262807.
|
||||
*/
|
||||
|
||||
ID3D11RenderTargetView *rtv;
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(D3D11_RTV_DIMENSION_TEXTURE2D,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
|
||||
m_ghost_ctx->m_device->CreateRenderTargetView(d3d_swapchain_image.texture, &rtv_desc, &rtv);
|
||||
if (!m_shared_resource) {
|
||||
DXGI_FORMAT format;
|
||||
ghost_format_to_dx_format(draw_info.swapchain_format, draw_info.expects_srgb_buffer, format);
|
||||
m_shared_resource = m_ghost_ctx->createSharedOpenGLResource(
|
||||
draw_info.width, draw_info.height, format, rtv);
|
||||
}
|
||||
m_ghost_ctx->blitFromOpenGLContext(m_shared_resource, draw_info.width, draw_info.height);
|
||||
# else
|
||||
if (!m_shared_resource) {
|
||||
DXGI_FORMAT format;
|
||||
ghost_format_to_dx_format(draw_info.swapchain_format, draw_info.expects_srgb_buffer, format);
|
||||
m_shared_resource = m_ghost_d3d_ctx->createSharedOpenGLResource(
|
||||
draw_info.width, draw_info.height, format);
|
||||
}
|
||||
m_ghost_d3d_ctx->blitFromOpenGLContext(m_shared_resource, draw_info.width, draw_info.height);
|
||||
|
||||
m_ghost_d3d_ctx->m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
m_ghost_d3d_ctx->m_device_ctx->CopyResource(
|
||||
d3d_swapchain_image.texture, m_ghost_d3d_ctx->getSharedTexture2D(m_shared_resource));
|
||||
# endif
|
||||
}
|
||||
|
||||
private:
|
||||
/** Primary OpenGL context for Blender to use for drawing. */
|
||||
GHOST_ContextWGL &m_ghost_wgl_ctx;
|
||||
/** Handle to shared resource object. */
|
||||
GHOST_SharedOpenGLResource *m_shared_resource = nullptr;
|
||||
};
|
||||
#endif // WIN32
|
||||
|
||||
std::unique_ptr<GHOST_IXrGraphicsBinding> GHOST_XrGraphicsBindingCreateFromType(
|
||||
GHOST_TXrGraphicsBinding type, GHOST_Context &context)
|
||||
{
|
||||
|
||||
263
intern/ghost/intern/GHOST_XrGraphicsBindingD3D.cc
Normal file
263
intern/ghost/intern/GHOST_XrGraphicsBindingD3D.cc
Normal file
@@ -0,0 +1,263 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
|
||||
#ifndef _WIN32
|
||||
# error "GHOST_XrGraphcisBindingD3D can only be compiled on Windows platforms."
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <sstream>
|
||||
|
||||
#include "GHOST_SystemWin32.hh"
|
||||
#include "GHOST_XrException.hh"
|
||||
#include "GHOST_XrGraphicsBindingD3D.hh"
|
||||
|
||||
static void ghost_format_to_dx_format(GHOST_TXrSwapchainFormat ghost_format,
|
||||
bool expects_srgb_buffer,
|
||||
DXGI_FORMAT &r_dx_format)
|
||||
{
|
||||
r_dx_format = DXGI_FORMAT_UNKNOWN;
|
||||
|
||||
switch (ghost_format) {
|
||||
case GHOST_kXrSwapchainFormatRGBA8:
|
||||
r_dx_format = expects_srgb_buffer ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB :
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM;
|
||||
break;
|
||||
case GHOST_kXrSwapchainFormatRGBA16:
|
||||
r_dx_format = DXGI_FORMAT_R16G16B16A16_UNORM;
|
||||
break;
|
||||
case GHOST_kXrSwapchainFormatRGBA16F:
|
||||
r_dx_format = DXGI_FORMAT_R16G16B16A16_FLOAT;
|
||||
break;
|
||||
case GHOST_kXrSwapchainFormatRGB10_A2:
|
||||
r_dx_format = DXGI_FORMAT_R10G10B10A2_UNORM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (r_dx_format == DXGI_FORMAT_UNKNOWN) {
|
||||
throw GHOST_XrException("No supported DirectX swapchain format found.");
|
||||
}
|
||||
}
|
||||
|
||||
static std::optional<int64_t> choose_swapchain_format_from_candidates(
|
||||
const std::vector<int64_t> &gpu_binding_formats, const std::vector<int64_t> &runtime_formats)
|
||||
{
|
||||
if (gpu_binding_formats.empty()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
auto res = std::find_first_of(gpu_binding_formats.begin(),
|
||||
gpu_binding_formats.end(),
|
||||
runtime_formats.begin(),
|
||||
runtime_formats.end());
|
||||
if (res == gpu_binding_formats.end()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
return *res;
|
||||
}
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Direct3D binding
|
||||
* \{ */
|
||||
|
||||
GHOST_XrGraphicsBindingD3D::GHOST_XrGraphicsBindingD3D() : GHOST_IXrGraphicsBinding()
|
||||
{
|
||||
m_ghost_d3d_ctx = GHOST_SystemWin32::createOffscreenContextD3D();
|
||||
}
|
||||
GHOST_XrGraphicsBindingD3D::~GHOST_XrGraphicsBindingD3D()
|
||||
{
|
||||
if (m_ghost_d3d_ctx) {
|
||||
GHOST_SystemWin32::disposeContextD3D(m_ghost_d3d_ctx);
|
||||
}
|
||||
}
|
||||
|
||||
bool GHOST_XrGraphicsBindingD3D::checkVersionRequirements(
|
||||
GHOST_Context & /*ghost_ctx*/, /* Remember: This is the OpenGL context! */
|
||||
XrInstance instance,
|
||||
XrSystemId system_id,
|
||||
std::string *r_requirement_info) const
|
||||
{
|
||||
static PFN_xrGetD3D11GraphicsRequirementsKHR s_xrGetD3D11GraphicsRequirementsKHR_fn = nullptr;
|
||||
// static XrInstance s_instance = XR_NULL_HANDLE;
|
||||
XrGraphicsRequirementsD3D11KHR gpu_requirements = {XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR};
|
||||
|
||||
/* Although it would seem reasonable that the PROC address would not change if the instance was
|
||||
* the same, in testing, repeated calls to #xrGetInstanceProcAddress() with the same instance
|
||||
* can still result in changes so the workaround is to simply set the function pointer every
|
||||
* time (trivializing its 'static' designation). */
|
||||
// if (instance != s_instance) {
|
||||
// s_instance = instance;
|
||||
s_xrGetD3D11GraphicsRequirementsKHR_fn = nullptr;
|
||||
//}
|
||||
if (!s_xrGetD3D11GraphicsRequirementsKHR_fn &&
|
||||
XR_FAILED(
|
||||
xrGetInstanceProcAddr(instance,
|
||||
"xrGetD3D11GraphicsRequirementsKHR",
|
||||
(PFN_xrVoidFunction *)&s_xrGetD3D11GraphicsRequirementsKHR_fn)))
|
||||
{
|
||||
s_xrGetD3D11GraphicsRequirementsKHR_fn = nullptr;
|
||||
return false;
|
||||
}
|
||||
|
||||
s_xrGetD3D11GraphicsRequirementsKHR_fn(instance, system_id, &gpu_requirements);
|
||||
|
||||
if (r_requirement_info) {
|
||||
std::ostringstream strstream;
|
||||
strstream << "Minimum DirectX 11 Feature Level " << gpu_requirements.minFeatureLevel
|
||||
<< std::endl;
|
||||
|
||||
*r_requirement_info = strstream.str();
|
||||
}
|
||||
|
||||
return m_ghost_d3d_ctx->m_device->GetFeatureLevel() >= gpu_requirements.minFeatureLevel;
|
||||
}
|
||||
|
||||
void GHOST_XrGraphicsBindingD3D::initFromGhostContext(
|
||||
GHOST_Context & /*ghost_ctx*/ /* Remember: This is the OpenGL context! */,
|
||||
XrInstance /*instance*/,
|
||||
XrSystemId /*system_id*/
|
||||
)
|
||||
{
|
||||
oxr_binding.d3d11.type = XR_TYPE_GRAPHICS_BINDING_D3D11_KHR;
|
||||
oxr_binding.d3d11.device = m_ghost_d3d_ctx->m_device;
|
||||
}
|
||||
|
||||
std::optional<int64_t> GHOST_XrGraphicsBindingD3D::chooseSwapchainFormat(
|
||||
const std::vector<int64_t> &runtime_formats,
|
||||
GHOST_TXrSwapchainFormat &r_format,
|
||||
bool &r_is_srgb_format) const
|
||||
{
|
||||
std::vector<int64_t> gpu_binding_formats = {
|
||||
#if 0 /* RGB10A2, RGBA16 don't seem to work with Oculus head-sets, \
|
||||
* so move them after RGBA16F for the time being. */
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
#endif
|
||||
DXGI_FORMAT_R16G16B16A16_FLOAT,
|
||||
#if 1
|
||||
DXGI_FORMAT_R10G10B10A2_UNORM,
|
||||
DXGI_FORMAT_R16G16B16A16_UNORM,
|
||||
#endif
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
};
|
||||
|
||||
std::optional result = choose_swapchain_format_from_candidates(gpu_binding_formats,
|
||||
runtime_formats);
|
||||
if (result) {
|
||||
switch (*result) {
|
||||
case DXGI_FORMAT_R10G10B10A2_UNORM:
|
||||
r_format = GHOST_kXrSwapchainFormatRGB10_A2;
|
||||
break;
|
||||
case DXGI_FORMAT_R16G16B16A16_UNORM:
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA16;
|
||||
break;
|
||||
case DXGI_FORMAT_R16G16B16A16_FLOAT:
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA16F;
|
||||
break;
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM:
|
||||
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA8;
|
||||
break;
|
||||
}
|
||||
r_is_srgb_format = (*result == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB);
|
||||
}
|
||||
else {
|
||||
r_format = GHOST_kXrSwapchainFormatRGBA8;
|
||||
r_is_srgb_format = false;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<XrSwapchainImageBaseHeader *> GHOST_XrGraphicsBindingD3D::createSwapchainImages(
|
||||
uint32_t image_count)
|
||||
{
|
||||
std::vector<XrSwapchainImageD3D11KHR> d3d_images(image_count);
|
||||
std::vector<XrSwapchainImageBaseHeader *> base_images;
|
||||
|
||||
/* Need to return vector of base header pointers, so of a different type. Need to build a new
|
||||
* list with this type, and keep the initial one alive. */
|
||||
for (XrSwapchainImageD3D11KHR &image : d3d_images) {
|
||||
image.type = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR;
|
||||
base_images.push_back(reinterpret_cast<XrSwapchainImageBaseHeader *>(&image));
|
||||
}
|
||||
|
||||
/* Keep alive. */
|
||||
m_image_cache.push_back(std::move(d3d_images));
|
||||
|
||||
return base_images;
|
||||
}
|
||||
|
||||
bool GHOST_XrGraphicsBindingD3D::needsUpsideDownDrawing(GHOST_Context &) const
|
||||
{
|
||||
return m_ghost_d3d_ctx->isUpsideDown();
|
||||
}
|
||||
|
||||
/* \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name OpenGL-Direct3D bridge
|
||||
* \{ */
|
||||
|
||||
GHOST_XrGraphicsBindingOpenGLD3D::GHOST_XrGraphicsBindingOpenGLD3D(GHOST_Context &ghost_ctx)
|
||||
|
||||
: GHOST_XrGraphicsBindingD3D(), m_ghost_wgl_ctx(static_cast<GHOST_ContextWGL &>(ghost_ctx))
|
||||
{
|
||||
}
|
||||
|
||||
GHOST_XrGraphicsBindingOpenGLD3D::~GHOST_XrGraphicsBindingOpenGLD3D()
|
||||
{
|
||||
if (m_shared_resource) {
|
||||
m_ghost_d3d_ctx->disposeSharedOpenGLResource(m_shared_resource);
|
||||
m_shared_resource = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GHOST_XrGraphicsBindingOpenGLD3D::submitToSwapchainImage(
|
||||
XrSwapchainImageBaseHeader &swapchain_image, const GHOST_XrDrawViewInfo &draw_info)
|
||||
{
|
||||
XrSwapchainImageD3D11KHR &d3d_swapchain_image = reinterpret_cast<XrSwapchainImageD3D11KHR &>(
|
||||
swapchain_image);
|
||||
|
||||
#if 0
|
||||
/* Ideally we'd just create a render target view for the OpenXR swap-chain image texture and
|
||||
* blit from the OpenGL context into it. The NV_DX_interop extension doesn't want to work with
|
||||
* this though. At least not with OPTIMUS hardware. See:
|
||||
* https://github.com/mpv-player/mpv/issues/2949#issuecomment-197262807.
|
||||
*/
|
||||
|
||||
ID3D11RenderTargetView *rtv;
|
||||
CD3D11_RENDER_TARGET_VIEW_DESC rtv_desc(D3D11_RTV_DIMENSION_TEXTURE2D,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM);
|
||||
|
||||
m_ghost_ctx->m_device->CreateRenderTargetView(d3d_swapchain_image.texture, &rtv_desc, &rtv);
|
||||
if (!m_shared_resource) {
|
||||
DXGI_FORMAT format;
|
||||
ghost_format_to_dx_format(draw_info.swapchain_format, draw_info.expects_srgb_buffer, format);
|
||||
m_shared_resource = m_ghost_ctx->createSharedOpenGLResource(
|
||||
draw_info.width, draw_info.height, format, rtv);
|
||||
}
|
||||
m_ghost_ctx->blitFromOpenGLContext(m_shared_resource, draw_info.width, draw_info.height);
|
||||
#else
|
||||
if (!m_shared_resource) {
|
||||
DXGI_FORMAT format;
|
||||
ghost_format_to_dx_format(draw_info.swapchain_format, draw_info.expects_srgb_buffer, format);
|
||||
m_shared_resource = m_ghost_d3d_ctx->createSharedOpenGLResource(
|
||||
draw_info.width, draw_info.height, format);
|
||||
}
|
||||
m_ghost_d3d_ctx->blitFromOpenGLContext(m_shared_resource, draw_info.width, draw_info.height);
|
||||
|
||||
m_ghost_d3d_ctx->m_device_ctx->OMSetRenderTargets(0, nullptr, nullptr);
|
||||
m_ghost_d3d_ctx->m_device_ctx->CopyResource(
|
||||
d3d_swapchain_image.texture, m_ghost_d3d_ctx->getSharedTexture2D(m_shared_resource));
|
||||
#endif
|
||||
}
|
||||
|
||||
/* \} */
|
||||
71
intern/ghost/intern/GHOST_XrGraphicsBindingD3D.hh
Normal file
71
intern/ghost/intern/GHOST_XrGraphicsBindingD3D.hh
Normal file
@@ -0,0 +1,71 @@
|
||||
/* SPDX-FileCopyrightText: 2025 Blender Authors
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
/** \file
|
||||
* \ingroup GHOST
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#ifndef _WIN32
|
||||
# error "GHOST_XrGraphcisBindingD3D can only be compiled on Windows platforms."
|
||||
#endif
|
||||
|
||||
#include "GHOST_ContextD3D.hh"
|
||||
#include "GHOST_ContextWGL.hh"
|
||||
#include "GHOST_IXrGraphicsBinding.hh"
|
||||
|
||||
/**
|
||||
* Base class for bridging to an OpenXR platform that only supports Direct3D.
|
||||
*
|
||||
* OpenGL/Vulkan have their own specific implementations.
|
||||
*/
|
||||
class GHOST_XrGraphicsBindingD3D : public GHOST_IXrGraphicsBinding {
|
||||
public:
|
||||
GHOST_XrGraphicsBindingD3D();
|
||||
~GHOST_XrGraphicsBindingD3D() override;
|
||||
|
||||
/**
|
||||
* Check the version requirements to use OpenXR with the Vulkan backend.
|
||||
*/
|
||||
bool checkVersionRequirements(GHOST_Context &ghost_ctx,
|
||||
XrInstance instance,
|
||||
XrSystemId system_id,
|
||||
std::string *r_requirement_info) const override;
|
||||
|
||||
void initFromGhostContext(GHOST_Context &ghost_ctx,
|
||||
XrInstance instance,
|
||||
XrSystemId system_id) override;
|
||||
std::optional<int64_t> chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
|
||||
GHOST_TXrSwapchainFormat &r_format,
|
||||
bool &r_is_srgb_format) const override;
|
||||
std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override;
|
||||
|
||||
bool needsUpsideDownDrawing(GHOST_Context &ghost_ctx) const override;
|
||||
|
||||
protected:
|
||||
/** Secondary DirectX 11 context used by OpenXR. */
|
||||
GHOST_ContextD3D *m_ghost_d3d_ctx = nullptr;
|
||||
|
||||
std::list<std::vector<XrSwapchainImageD3D11KHR>> m_image_cache;
|
||||
};
|
||||
|
||||
/**
|
||||
* OpenXR bridge between OpenGL and D3D.
|
||||
*
|
||||
* The D3D swapchain image is imported into OpenGL.
|
||||
*/
|
||||
class GHOST_XrGraphicsBindingOpenGLD3D : public GHOST_XrGraphicsBindingD3D {
|
||||
public:
|
||||
GHOST_XrGraphicsBindingOpenGLD3D(GHOST_Context &ghost_ctx);
|
||||
~GHOST_XrGraphicsBindingOpenGLD3D();
|
||||
|
||||
void submitToSwapchainImage(XrSwapchainImageBaseHeader &swapchain_image,
|
||||
const GHOST_XrDrawViewInfo &draw_info) override;
|
||||
|
||||
private:
|
||||
/** Primary OpenGL context for Blender to use for drawing. */
|
||||
GHOST_ContextWGL &m_ghost_wgl_ctx;
|
||||
/** Handle to shared resource object. */
|
||||
GHOST_SharedOpenGLResource *m_shared_resource = nullptr;
|
||||
};
|
||||
Reference in New Issue
Block a user