From b468023aa1b51b2cdef38cd651c7487b9f4d34c4 Mon Sep 17 00:00:00 2001 From: Julian Eisel Date: Wed, 24 Jun 2020 18:26:51 +0200 Subject: VR: Properly support outputting sRGB swapchain buffers Latest SteamVR OpenXR updates brought OpenGL support, but only with sRGB buffers. I think for DirectX it's the same now. It's not a big issue for us to use sRGB buffers, so that's what I will do for now. That way we shouldn't need hardcoded exceptions for specific runtimes that don't transform linear buffers correctly. --- intern/ghost/intern/GHOST_IXrGraphicsBinding.h | 3 ++- intern/ghost/intern/GHOST_XrGraphicsBinding.cpp | 35 +++++++++++++++++++------ intern/ghost/intern/GHOST_XrSession.cpp | 11 +------- intern/ghost/intern/GHOST_XrSwapchain.cpp | 7 ++++- intern/ghost/intern/GHOST_XrSwapchain.h | 3 +++ 5 files changed, 39 insertions(+), 20 deletions(-) (limited to 'intern') diff --git a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h index 5794a682023..b199c5f9b28 100644 --- a/intern/ghost/intern/GHOST_IXrGraphicsBinding.h +++ b/intern/ghost/intern/GHOST_IXrGraphicsBinding.h @@ -56,7 +56,8 @@ class GHOST_IXrGraphicsBinding { std::string *r_requirement_info) const = 0; virtual void initFromGhostContext(class GHOST_Context *ghost_ctx) = 0; virtual bool chooseSwapchainFormat(const std::vector &runtime_formats, - int64_t *r_result) const = 0; + int64_t &r_result, + bool &r_is_rgb_format) const = 0; virtual std::vector createSwapchainImages( uint32_t image_count) = 0; virtual void submitToSwapchainImage(XrSwapchainImageBaseHeader *swapchain_image, diff --git a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp index 71e6af3fa4f..7d7405a974d 100644 --- a/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp +++ b/intern/ghost/intern/GHOST_XrGraphicsBinding.cpp @@ -36,7 +36,7 @@ static bool choose_swapchain_format_from_candidates(std::vector gpu_binding_formats, std::vector runtime_formats, - int64_t *r_result) + int64_t &r_result) { if (gpu_binding_formats.empty()) { return false; @@ -50,7 +50,7 @@ static bool choose_swapchain_format_from_candidates(std::vector gpu_bin return false; } - *r_result = *res; + r_result = *res; return true; } @@ -132,10 +132,20 @@ class GHOST_XrGraphicsBindingOpenGL : public GHOST_IXrGraphicsBinding { } bool chooseSwapchainFormat(const std::vector &runtime_formats, - int64_t *r_result) const override + int64_t &r_result, + bool &r_is_srgb_format) const override { - std::vector gpu_binding_formats = {GL_RGBA8}; - return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result); + std::vector gpu_binding_formats = { + GL_RGBA8, + GL_SRGB8_ALPHA8, + }; + + if (choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result)) { + r_is_srgb_format = (r_result == GL_SRGB8_ALPHA8); + return true; + } + + return false; } std::vector createSwapchainImages(uint32_t image_count) override @@ -248,10 +258,19 @@ class GHOST_XrGraphicsBindingD3D : public GHOST_IXrGraphicsBinding { } bool chooseSwapchainFormat(const std::vector &runtime_formats, - int64_t *r_result) const override + int64_t &r_result, + bool &r_is_srgb_format) const override { - std::vector gpu_binding_formats = {DXGI_FORMAT_R8G8B8A8_UNORM}; - return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result); + std::vector gpu_binding_formats = { + DXGI_FORMAT_R8G8B8A8_UNORM, + DXGI_FORMAT_R8G8B8A8_UNORM_SRGB, + }; + + if (choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result)) { + r_is_srgb_format = (r_result == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB); + return true; + } + return false; } std::vector createSwapchainImages(uint32_t image_count) override diff --git a/intern/ghost/intern/GHOST_XrSession.cpp b/intern/ghost/intern/GHOST_XrSession.cpp index 7ae819dbfb2..5a747b1e787 100644 --- a/intern/ghost/intern/GHOST_XrSession.cpp +++ b/intern/ghost/intern/GHOST_XrSession.cpp @@ -375,15 +375,6 @@ static void ghost_xr_draw_view_info_from_view(const XrView &view, GHOST_XrDrawVi r_info.fov.angle_down = view.fov.angleDown; } -static bool ghost_xr_draw_view_expects_srgb_buffer(const GHOST_XrContext *context) -{ - /* Monado seems to be faulty and doesn't do OETF transform correctly. So expect a SRGB buffer to - * compensate. You get way too dark rendering without this, it's pretty obvious (even in the - * default startup scene). */ - GHOST_TXrOpenXRRuntimeID runtime_id = context->getOpenXRRuntimeID(); - return (runtime_id == OPENXR_RUNTIME_MONADO) || (runtime_id == OPENXR_RUNTIME_STEAMVR); -} - void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain, XrCompositionLayerProjectionView &r_proj_layer_view, XrSpaceLocation &view_location, @@ -398,7 +389,7 @@ void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain, r_proj_layer_view.fov = view.fov; swapchain.updateCompositionLayerProjectViewSubImage(r_proj_layer_view.subImage); - draw_view_info.expects_srgb_buffer = ghost_xr_draw_view_expects_srgb_buffer(m_context); + draw_view_info.expects_srgb_buffer = swapchain.isBufferSRGB(); draw_view_info.ofsx = r_proj_layer_view.subImage.imageRect.offset.x; draw_view_info.ofsy = r_proj_layer_view.subImage.imageRect.offset.y; draw_view_info.width = r_proj_layer_view.subImage.imageRect.extent.width; diff --git a/intern/ghost/intern/GHOST_XrSwapchain.cpp b/intern/ghost/intern/GHOST_XrSwapchain.cpp index f50cfde0687..f7808c20112 100644 --- a/intern/ghost/intern/GHOST_XrSwapchain.cpp +++ b/intern/ghost/intern/GHOST_XrSwapchain.cpp @@ -68,7 +68,7 @@ GHOST_XrSwapchain::GHOST_XrSwapchain(GHOST_IXrGraphicsBinding &gpu_binding, "Failed to get swapchain image formats."); assert(swapchain_formats.size() == format_count); - if (!gpu_binding.chooseSwapchainFormat(swapchain_formats, &chosen_format)) { + if (!gpu_binding.chooseSwapchainFormat(swapchain_formats, chosen_format, m_is_srgb_buffer)) { throw GHOST_XrException( "Error: No format matching OpenXR runtime supported swapchain formats found."); } @@ -132,6 +132,11 @@ void GHOST_XrSwapchain::updateCompositionLayerProjectViewSubImage(XrSwapchainSub r_sub_image.imageRect.extent = {m_image_width, m_image_height}; } +bool GHOST_XrSwapchain::isBufferSRGB() +{ + return m_is_srgb_buffer; +} + void GHOST_XrSwapchain::releaseImage() { XrSwapchainImageReleaseInfo release_info = {XR_TYPE_SWAPCHAIN_IMAGE_RELEASE_INFO}; diff --git a/intern/ghost/intern/GHOST_XrSwapchain.h b/intern/ghost/intern/GHOST_XrSwapchain.h index ab0a6736c9c..7a3e7fcea68 100644 --- a/intern/ghost/intern/GHOST_XrSwapchain.h +++ b/intern/ghost/intern/GHOST_XrSwapchain.h @@ -38,9 +38,12 @@ class GHOST_XrSwapchain { void updateCompositionLayerProjectViewSubImage(XrSwapchainSubImage &r_sub_image); + bool isBufferSRGB(); + private: std::unique_ptr m_oxr; /* Could use stack, but PImpl is preferable. */ int32_t m_image_width, m_image_height; + bool m_is_srgb_buffer = false; }; #endif // GHOST_XRSWAPCHAIN_H -- cgit v1.2.3