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.
This commit is contained in:
Julian Eisel 2020-06-24 18:26:51 +02:00 committed by Jeroen Bakker
parent 8a129041c5
commit 70637b303d
Notes: blender-bot 2023-02-14 08:45:12 +01:00
Referenced by issue #77348, Blender LTS: Maintenance Task 2.83
5 changed files with 39 additions and 19 deletions

View File

@ -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<int64_t> &runtime_formats,
int64_t *r_result) const = 0;
int64_t &r_result,
bool &r_is_rgb_format) const = 0;
virtual std::vector<XrSwapchainImageBaseHeader *> createSwapchainImages(
uint32_t image_count) = 0;
virtual void submitToSwapchainImage(XrSwapchainImageBaseHeader *swapchain_image,

View File

@ -36,7 +36,7 @@
static bool choose_swapchain_format_from_candidates(std::vector<int64_t> gpu_binding_formats,
std::vector<int64_t> 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<int64_t> 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<int64_t> &runtime_formats,
int64_t *r_result) const override
int64_t &r_result,
bool &r_is_srgb_format) const override
{
std::vector<int64_t> gpu_binding_formats = {GL_RGBA8};
return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
std::vector<int64_t> 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<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override
@ -248,10 +258,19 @@ class GHOST_XrGraphicsBindingD3D : public GHOST_IXrGraphicsBinding {
}
bool chooseSwapchainFormat(const std::vector<int64_t> &runtime_formats,
int64_t *r_result) const override
int64_t &r_result,
bool &r_is_srgb_format) const override
{
std::vector<int64_t> gpu_binding_formats = {DXGI_FORMAT_R8G8B8A8_UNORM};
return choose_swapchain_format_from_candidates(gpu_binding_formats, runtime_formats, r_result);
std::vector<int64_t> 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<XrSwapchainImageBaseHeader *> createSwapchainImages(uint32_t image_count) override

View File

@ -375,14 +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). */
return (context->getOpenXRRuntimeID() == OPENXR_RUNTIME_MONADO);
}
void GHOST_XrSession::drawView(GHOST_XrSwapchain &swapchain,
XrCompositionLayerProjectionView &r_proj_layer_view,
XrSpaceLocation &view_location,
@ -397,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;

View File

@ -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};

View File

@ -38,9 +38,12 @@ class GHOST_XrSwapchain {
void updateCompositionLayerProjectViewSubImage(XrSwapchainSubImage &r_sub_image);
bool isBufferSRGB();
private:
std::unique_ptr<OpenXRSwapchainData> 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