diff --git a/apps/openmw/mwvr/openxrmanager.cpp b/apps/openmw/mwvr/openxrmanager.cpp index 03693c34d..6bc262969 100644 --- a/apps/openmw/mwvr/openxrmanager.cpp +++ b/apps/openmw/mwvr/openxrmanager.cpp @@ -148,6 +148,11 @@ namespace MWVR return impl().selectDepthFormat(); } + void OpenXRManager::eraseFormat(int64_t format) + { + return impl().eraseFormat(format); + } + void OpenXRManager::CleanupOperation::operator()( osg::GraphicsContext* gc) diff --git a/apps/openmw/mwvr/openxrmanager.hpp b/apps/openmw/mwvr/openxrmanager.hpp index b3e1e2ae3..b090dcb5c 100644 --- a/apps/openmw/mwvr/openxrmanager.hpp +++ b/apps/openmw/mwvr/openxrmanager.hpp @@ -106,6 +106,9 @@ namespace MWVR //! Returns 0 if no format is supported. int64_t selectDepthFormat(); + //! Erase format from list of format candidates + void eraseFormat(int64_t format); + OpenXRManagerImpl& impl() { return *mPrivate; } const OpenXRManagerImpl& impl() const { return *mPrivate; } diff --git a/apps/openmw/mwvr/openxrmanagerimpl.cpp b/apps/openmw/mwvr/openxrmanagerimpl.cpp index 1c25b3f9c..24ee7715e 100644 --- a/apps/openmw/mwvr/openxrmanagerimpl.cpp +++ b/apps/openmw/mwvr/openxrmanagerimpl.cpp @@ -646,6 +646,11 @@ namespace MWVR return mPlatform.selectDepthFormat(); } + void OpenXRManagerImpl::eraseFormat(int64_t format) + { + mPlatform.eraseFormat(format); + } + void OpenXRManagerImpl::enablePredictions() { mPredictionsEnabled = true; diff --git a/apps/openmw/mwvr/openxrmanagerimpl.hpp b/apps/openmw/mwvr/openxrmanagerimpl.hpp index d80032374..1bf660b3a 100644 --- a/apps/openmw/mwvr/openxrmanagerimpl.hpp +++ b/apps/openmw/mwvr/openxrmanagerimpl.hpp @@ -66,6 +66,7 @@ namespace MWVR PFN_xrVoidFunction xrGetFunction(const std::string& name); int64_t selectColorFormat(); int64_t selectDepthFormat(); + void eraseFormat(int64_t format); OpenXRPlatform& platform() { return mPlatform; }; protected: diff --git a/apps/openmw/mwvr/openxrplatform.cpp b/apps/openmw/mwvr/openxrplatform.cpp index 1caec08b5..494b48086 100644 --- a/apps/openmw/mwvr/openxrplatform.cpp +++ b/apps/openmw/mwvr/openxrplatform.cpp @@ -625,6 +625,18 @@ namespace MWVR } } + void OpenXRPlatform::eraseFormat(int64_t format) + { + for (auto it = mSwapchainFormats.begin(); it != mSwapchainFormats.end(); it++) + { + if (*it == format) + { + mSwapchainFormats.erase(it); + return; + } + } + } + int64_t OpenXRPlatform::selectFormat(const std::vector& requestedFormats) { auto it = diff --git a/apps/openmw/mwvr/openxrplatform.hpp b/apps/openmw/mwvr/openxrplatform.hpp index b7b5c6a75..adf13dc58 100644 --- a/apps/openmw/mwvr/openxrplatform.hpp +++ b/apps/openmw/mwvr/openxrplatform.hpp @@ -49,6 +49,7 @@ namespace MWVR int64_t selectColorFormat(); int64_t selectDepthFormat(); int64_t selectFormat(const std::vector& requestedFormats); + void eraseFormat(int64_t format); std::vector mSwapchainFormats{}; /// Registers an object for sharing as if calling wglDXRegisterObjectNV requesting write access. diff --git a/apps/openmw/mwvr/openxrswapchainimpl.cpp b/apps/openmw/mwvr/openxrswapchainimpl.cpp index 742f41df6..30d6856d4 100644 --- a/apps/openmw/mwvr/openxrswapchainimpl.cpp +++ b/apps/openmw/mwvr/openxrswapchainimpl.cpp @@ -113,23 +113,6 @@ namespace MWVR { { auto* xr = Environment::get().getManager(); - // Select a swapchain format. - if (use == Use::COLOR) - mFormat = xr->selectColorFormat(); - else - mFormat = xr->selectDepthFormat(); - std::string typeString = use == Use::COLOR ? "color" : "depth"; - - if (mFormat == 0) { - throw std::runtime_error(std::string("Swapchain ") + typeString + " format not supported"); - } - Log(Debug::Verbose) << "Selected " << typeString << " format: " << std::dec << mFormat << " (" << std::hex << mFormat << ")" << std::dec; - - if (xr->xrExtensionIsEnabled(XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME)) - { - // TODO - } - XrSwapchainCreateInfo swapchainCreateInfo{ XR_TYPE_SWAPCHAIN_CREATE_INFO }; swapchainCreateInfo.arraySize = 1; swapchainCreateInfo.width = mWidth; @@ -137,18 +120,40 @@ namespace MWVR { swapchainCreateInfo.mipCount = 1; swapchainCreateInfo.faceCount = 1; - while (mSamples > 0 && mSwapchain == XR_NULL_HANDLE) + while (mSamples > 0 && mSwapchain == XR_NULL_HANDLE && mFormat == 0) { + // Select a swapchain format. + if (use == Use::COLOR) + mFormat = xr->selectColorFormat(); + else + mFormat = xr->selectDepthFormat(); + std::string typeString = use == Use::COLOR ? "color" : "depth"; + if (mFormat == 0) { + throw std::runtime_error(std::string("Swapchain ") + typeString + " format not supported"); + } + Log(Debug::Verbose) << "Selected " << typeString << " format: " << std::dec << mFormat << " (" << std::hex << mFormat << ")" << std::dec; + + // Now create the swapchain Log(Debug::Verbose) << "Creating swapchain with dimensions Width=" << mWidth << " Heigh=" << mHeight << " SampleCount=" << mSamples; - // First create the swapchain of color buffers. swapchainCreateInfo.format = mFormat; swapchainCreateInfo.sampleCount = mSamples; - if(use == Use::COLOR) - swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; + if(mUsage == Use::COLOR) + swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_COLOR_ATTACHMENT_BIT; else - swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_SAMPLED_BIT | XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; + swapchainCreateInfo.usageFlags = XR_SWAPCHAIN_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT; auto res = xrCreateSwapchain(xr->impl().xrSession(), &swapchainCreateInfo, &mSwapchain); - if (!XR_SUCCEEDED(res)) + + // Check errors and try again if possible + if (res == XR_ERROR_SWAPCHAIN_FORMAT_UNSUPPORTED) + { + // We only try swapchain formats enumerated by the runtime itself. + // This does not guarantee that that swapchain format is going to be supported for this specific usage. + Log(Debug::Verbose) << "Failed to create swapchain with Format=" << mFormat<< ": " << XrResultString(res); + xr->eraseFormat(mFormat); + mFormat = 0; + continue; + } + else if (!XR_SUCCEEDED(res)) { Log(Debug::Verbose) << "Failed to create swapchain with SampleCount=" << mSamples << ": " << XrResultString(res); mSamples /= 2; @@ -216,9 +221,38 @@ namespace MWVR { } } } + void OpenXRSwapchainImpl::SwapchainPrivate::checkAcquired() const { if (!isAcquired()) throw std::logic_error("Swapchain must be acquired before use. Call between OpenXRSwapchain::beginFrame() and OpenXRSwapchain::endFrame()"); } + + XrSwapchain OpenXRSwapchainImpl::xrSwapchain(void) const + { + if(mSwapchain) + return mSwapchain->xrSwapchain(); + return XR_NULL_HANDLE; + } + + XrSwapchain OpenXRSwapchainImpl::xrSwapchainDepth(void) const + { + if (mSwapchainDepth) + return mSwapchainDepth->xrSwapchain(); + return XR_NULL_HANDLE; + } + + XrSwapchainSubImage OpenXRSwapchainImpl::xrSubImage(void) const + { + if (mSwapchain) + return mSwapchain->xrSubImage(); + return XrSwapchainSubImage{ XR_NULL_HANDLE }; + } + + XrSwapchainSubImage OpenXRSwapchainImpl::xrSubImageDepth(void) const + { + if (mSwapchainDepth) + return mSwapchainDepth->xrSubImage(); + return XrSwapchainSubImage{ XR_NULL_HANDLE }; + } } diff --git a/apps/openmw/mwvr/openxrswapchainimpl.hpp b/apps/openmw/mwvr/openxrswapchainimpl.hpp index 8b1c86816..b850e95c8 100644 --- a/apps/openmw/mwvr/openxrswapchainimpl.hpp +++ b/apps/openmw/mwvr/openxrswapchainimpl.hpp @@ -47,7 +47,7 @@ namespace MWVR int32_t mWidth = -1; int32_t mHeight = -1; int32_t mSamples = -1; - int64_t mFormat = -1; + int64_t mFormat = 0; uint32_t mAcquiredIndex{ 0 }; Use mUsage; bool mIsIndexAcquired{ false }; @@ -62,10 +62,10 @@ namespace MWVR void endFrame(osg::GraphicsContext* gc, VRFramebuffer& readBuffer); bool isAcquired() const; - XrSwapchain xrSwapchain(void) const { return mSwapchain->xrSwapchain(); }; - XrSwapchain xrSwapchainDepth(void) const { return mSwapchainDepth->xrSwapchain(); }; - XrSwapchainSubImage xrSubImage(void) const { return mSwapchain->xrSubImage(); }; - XrSwapchainSubImage xrSubImageDepth(void) const { return mSwapchainDepth->xrSubImage(); }; + XrSwapchain xrSwapchain(void) const; + XrSwapchain xrSwapchainDepth(void) const; + XrSwapchainSubImage xrSubImage(void) const; + XrSwapchainSubImage xrSubImageDepth(void) const; int width() const { return mConfig.selectedWidth; }; int height() const { return mConfig.selectedHeight; }; int samples() const { return mConfig.selectedSamples; };