#include "openxrswapchainimage.hpp" #include "openxrmanagerimpl.hpp" #include "vrenvironment.hpp" #include "vrframebuffer.hpp" // The OpenXR SDK's platform headers assume we've included platform headers #ifdef _WIN32 #include #include #ifdef XR_USE_GRAPHICS_API_D3D11 #include #include #endif #elif __linux__ #include #include #undef None #else #error Unsupported platform #endif #include #include #include #include #include #define GLERR if(auto err = glGetError() != GL_NO_ERROR) Log(Debug::Verbose) << __FILE__ << "." << __LINE__ << ": " << glGetError() namespace MWVR { template class OpenXRSwapchainImageTemplate; template<> class OpenXRSwapchainImageTemplate< XrSwapchainImageOpenGLKHR > : public OpenXRSwapchainImage { public: static constexpr XrStructureType XrType = XR_TYPE_SWAPCHAIN_IMAGE_OPENGL_KHR; public: OpenXRSwapchainImageTemplate(osg::GraphicsContext* gc, XrSwapchainCreateInfo swapchainCreateInfo, const XrSwapchainImageOpenGLKHR& xrImage) : OpenXRSwapchainImage() , mXrImage(xrImage) , mBufferBits(0) , mFramebuffer(nullptr) { mFramebuffer.reset(new VRFramebuffer(gc->getState(), swapchainCreateInfo.width, swapchainCreateInfo.height, swapchainCreateInfo.sampleCount)); if (swapchainCreateInfo.usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { mFramebuffer->setDepthBuffer(gc, mXrImage.image, false); mBufferBits = GL_DEPTH_BUFFER_BIT; } else { mFramebuffer->setColorBuffer(gc, mXrImage.image, false); mBufferBits = GL_COLOR_BUFFER_BIT; } } void blit(osg::GraphicsContext* gc, VRFramebuffer& readBuffer, int offset_x, int offset_y) override { mFramebuffer->bindFramebuffer(gc, GL_FRAMEBUFFER_EXT); readBuffer.blit(gc, offset_x, offset_y, offset_x + mFramebuffer->width(), offset_y + mFramebuffer->height(), 0, 0, mFramebuffer->width(), mFramebuffer->height(), mBufferBits, GL_NEAREST); } XrSwapchainImageOpenGLKHR mXrImage; uint32_t mBufferBits; std::unique_ptr mFramebuffer; }; #ifdef XR_USE_GRAPHICS_API_D3D11 template<> class OpenXRSwapchainImageTemplate< XrSwapchainImageD3D11KHR > : public OpenXRSwapchainImage { public: static constexpr XrStructureType XrType = XR_TYPE_SWAPCHAIN_IMAGE_D3D11_KHR; public: OpenXRSwapchainImageTemplate(osg::GraphicsContext* gc, XrSwapchainCreateInfo swapchainCreateInfo, const XrSwapchainImageD3D11KHR& xrImage) : OpenXRSwapchainImage() , mXrImage(xrImage) , mBufferBits(0) , mFramebuffer(nullptr) { mXrImage.texture->GetDevice(&mDevice); mDevice->GetImmediateContext(&mDeviceContext); mXrImage.texture->GetDesc(&mDesc); glGenTextures(1, &mGlTextureName); auto* xr = Environment::get().getManager(); //mDxResourceShareHandle = xr->impl().platform().DXRegisterObject(mXrImage.texture, mGlTextureName, GL_TEXTURE_2D, true, nullptr); if (!mDxResourceShareHandle) { // Some OpenXR runtimes return textures that cannot be directly shared. // So we need to make a redundant texture to use as an intermediary... mSharedTextureDesc.Width = mDesc.Width; mSharedTextureDesc.Height = mDesc.Height; mSharedTextureDesc.MipLevels = mDesc.MipLevels; mSharedTextureDesc.ArraySize = mDesc.ArraySize; mSharedTextureDesc.Format = static_cast(swapchainCreateInfo.format); mSharedTextureDesc.SampleDesc = mDesc.SampleDesc; mSharedTextureDesc.Usage = D3D11_USAGE_DEFAULT; mSharedTextureDesc.BindFlags = 0; mSharedTextureDesc.CPUAccessFlags = 0; mSharedTextureDesc.MiscFlags = 0;; mDevice->CreateTexture2D(&mSharedTextureDesc, nullptr, &mSharedTexture); mXrImage.texture->GetDesc(&mSharedTextureDesc); mDxResourceShareHandle = xr->impl().platform().DXRegisterObject(mSharedTexture, mGlTextureName, GL_TEXTURE_2D, true, nullptr); } // Set up shared texture as blit target mFramebuffer.reset(new VRFramebuffer(gc->getState(), swapchainCreateInfo.width, swapchainCreateInfo.height, swapchainCreateInfo.sampleCount)); if (swapchainCreateInfo.usageFlags & XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT) { mFramebuffer->setDepthBuffer(gc, mGlTextureName, false); mBufferBits = GL_DEPTH_BUFFER_BIT; } else { mFramebuffer->setColorBuffer(gc, mGlTextureName, false); mBufferBits = GL_COLOR_BUFFER_BIT; } } ~OpenXRSwapchainImageTemplate() { auto* xr = Environment::get().getManager(); if (mDxResourceShareHandle) xr->impl().platform().DXUnregisterObject(mDxResourceShareHandle); glDeleteTextures(1, &mGlTextureName); } void blit(osg::GraphicsContext* gc, VRFramebuffer& readBuffer, int offset_x, int offset_y) override { // Blit readBuffer into directx texture, while flipping the Y axis. auto* xr = Environment::get().getManager(); xr->impl().platform().DXLockObject(mDxResourceShareHandle); mFramebuffer->bindFramebuffer(gc, GL_FRAMEBUFFER_EXT); readBuffer.blit(gc, offset_x, offset_y, offset_x + mFramebuffer->width(), offset_y + mFramebuffer->height(), 0, mFramebuffer->height(), mFramebuffer->width(), 0, mBufferBits, GL_NEAREST); xr->impl().platform().DXUnlockObject(mDxResourceShareHandle); // If the d3d11 texture couldn't be shared directly, blit it again. if (mSharedTexture) { mDeviceContext->CopyResource(mXrImage.texture, mSharedTexture); } } ID3D11Device* mDevice = nullptr; ID3D11DeviceContext* mDeviceContext = nullptr; D3D11_TEXTURE2D_DESC mDesc; D3D11_TEXTURE2D_DESC mSharedTextureDesc; ID3D11Texture2D* mSharedTexture = nullptr; uint32_t mGlTextureName = 0; void* mDxResourceShareHandle = nullptr; XrSwapchainImageD3D11KHR mXrImage; uint32_t mBufferBits; std::unique_ptr mFramebuffer; }; #endif template< typename Image > static inline std::vector > enumerateSwapchainImagesImpl(osg::GraphicsContext* gc, XrSwapchain swapchain, XrSwapchainCreateInfo swapchainCreateInfo) { using SwapchainImage = OpenXRSwapchainImageTemplate; uint32_t imageCount = 0; std::vector< Image > images; CHECK_XRCMD(xrEnumerateSwapchainImages(swapchain, 0, &imageCount, nullptr)); images.resize(imageCount, { SwapchainImage::XrType }); CHECK_XRCMD(xrEnumerateSwapchainImages(swapchain, imageCount, &imageCount, reinterpret_cast(images.data()))); std::vector > swapchainImages; for(auto& image: images) { swapchainImages.emplace_back(new OpenXRSwapchainImageTemplate(gc, swapchainCreateInfo, image)); } return swapchainImages; } std::vector > OpenXRSwapchainImage::enumerateSwapchainImages(osg::GraphicsContext* gc, XrSwapchain swapchain, XrSwapchainCreateInfo swapchainCreateInfo) { auto* xr = Environment::get().getManager(); if (xr->xrExtensionIsEnabled(XR_KHR_OPENGL_ENABLE_EXTENSION_NAME)) { return enumerateSwapchainImagesImpl(gc, swapchain, swapchainCreateInfo); } #ifdef XR_USE_GRAPHICS_API_D3D11 else if (xr->xrExtensionIsEnabled(XR_KHR_D3D11_ENABLE_EXTENSION_NAME)) { return enumerateSwapchainImagesImpl(gc, swapchain, swapchainCreateInfo); } #endif else { throw std::logic_error("Implementation missing for selected graphics API"); } return std::vector>(); } OpenXRSwapchainImage::OpenXRSwapchainImage() { } }