Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add HDR support #2030

Merged
merged 24 commits into from
Mar 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
bfb68db
WIP: HDR support
shinyquagsire23 Mar 14, 2024
bb73383
Proper BT.2020 conversion
shinyquagsire23 Mar 15, 2024
b337dbd
The correct matrices, finally
shinyquagsire23 Mar 15, 2024
97198ca
Use BT2020 for 10-bit encoding
shinyquagsire23 Mar 15, 2024
0f4e2c2
Add the settings option, add 8-bit HDR support
shinyquagsire23 Mar 15, 2024
b17efd0
Support all of the cursed permutations
shinyquagsire23 Mar 15, 2024
320226e
Cleanup
shinyquagsire23 Mar 15, 2024
b270f19
Cleanup
shinyquagsire23 Mar 15, 2024
27a7247
cargo fmt
shinyquagsire23 Mar 15, 2024
e04b369
Eyeball the necessary HDR changes for AMD
shinyquagsire23 Mar 15, 2024
a8a1104
Eyeball software encoder changes (doesn't actually seem to work idk)
shinyquagsire23 Mar 15, 2024
7534343
sRGB correction should only happen for sRGB textures, not HDR ones
shinyquagsire23 Mar 16, 2024
651307f
Allow forcing HDR sRGB correction on all layers
shinyquagsire23 Mar 16, 2024
37d08b4
Fix HDR on Android (or at least on Quest 3???)
shinyquagsire23 Mar 17, 2024
07b6c65
Fix linear RGB/HDR games for non-HDR encoding
shinyquagsire23 Mar 17, 2024
0381b48
Clarify this now that it's multipurpose
shinyquagsire23 Mar 17, 2024
3929f2a
Allow clamping HDR extended range
shinyquagsire23 Mar 17, 2024
a09c5f7
Merge branch 'master' into feat-hdr
shinyquagsire23 Mar 17, 2024
fc5c340
cargo fmt
shinyquagsire23 Mar 17, 2024
e73c9cf
Pico headsets don't composite linear RGB correctly, like Lynx R1
shinyquagsire23 Mar 18, 2024
1b08fda
Add encoding gamma, for prioritizing dark pixels in 10-bit encodings …
shinyquagsire23 Mar 20, 2024
a67c45b
This doesn't seem to work with cbindgen :/
shinyquagsire23 Mar 20, 2024
4c9c0cd
cargo fmt
shinyquagsire23 Mar 20, 2024
eab1609
Merge branch 'master' of https://github.com/alvr-org/ALVR into feat-hdr
shinyquagsire23 Mar 22, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion alvr/client_core/cpp/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ struct FfiStreamConfig {
float foveationEdgeRatioX;
float foveationEdgeRatioY;
unsigned int enableSrgbCorrection;
unsigned int fixLimitedRange;
float encodingGamma;
};

// gltf_model.h
Expand All @@ -37,7 +39,8 @@ extern "C" void destroyGraphicsNative();
extern "C" void prepareLobbyRoom(int viewWidth,
int viewHeight,
const unsigned int *swapchainTextures[2],
int swapchainLength);
int swapchainLength,
bool enable_srgb_correction);
extern "C" void destroyRenderers();
extern "C" void streamStartNative(FfiStreamConfig config);
extern "C" void updateLobbyHudTexture(const unsigned char *data);
Expand Down
21 changes: 14 additions & 7 deletions alvr/client_core/cpp/graphics.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@ void ovrFramebuffer_Create(ovrFramebuffer *frameBuffer,
for (int i = 0; i < textures.size(); i++) {
auto glRenderTarget = textures[i];
frameBuffer->renderTargets.push_back(std::make_unique<gl_render_utils::Texture>(
true, glRenderTarget, false, width, height, GL_SRGB8_ALPHA8, GL_RGBA));
true, glRenderTarget, false, width, height, GL_RGBA16F, GL_RGBA));
frameBuffer->renderStates.push_back(
std::make_unique<gl_render_utils::RenderState>(frameBuffer->renderTargets[i].get()));
}
Expand Down Expand Up @@ -580,19 +580,21 @@ void ovrRenderer_Create(ovrRenderer *renderer,
std::vector<GLuint> textures[2],
FFRData ffrData,
bool isLobby,
bool enableSrgbCorrection) {
bool enableSrgbCorrection,
bool fixLimitedRange,
float encodingGamma) {
if (!isLobby) {
renderer->srgbCorrectionPass = std::make_unique<SrgbCorrectionPass>(streamTexture);
renderer->enableFFE = ffrData.enabled;
if (renderer->enableFFE) {
FoveationVars fv = CalculateFoveationVars(ffrData);
renderer->srgbCorrectionPass->Initialize(
fv.optimizedEyeWidth, fv.optimizedEyeHeight, !enableSrgbCorrection);
fv.optimizedEyeWidth, fv.optimizedEyeHeight, !enableSrgbCorrection, fixLimitedRange, encodingGamma);
renderer->ffr = std::make_unique<FFR>(renderer->srgbCorrectionPass->GetOutputTexture());
renderer->ffr->Initialize(fv);
renderer->streamRenderTexture = renderer->ffr->GetOutputTexture()->GetGLTexture();
} else {
renderer->srgbCorrectionPass->Initialize(width, height, !enableSrgbCorrection);
renderer->srgbCorrectionPass->Initialize(width, height, !enableSrgbCorrection, fixLimitedRange, encodingGamma);
renderer->streamRenderTexture =
renderer->srgbCorrectionPass->GetOutputTexture()->GetGLTexture();
}
Expand Down Expand Up @@ -793,7 +795,8 @@ void destroyGraphicsNative() {
void prepareLobbyRoom(int viewWidth,
int viewHeight,
const unsigned int *swapchainTextures[2],
int swapchainLength) {
int swapchainLength,
bool enable_srgb_correction) {
for (int eye = 0; eye < 2; eye++) {
g_ctx.lobbySwapchainTextures[eye].clear();

Expand All @@ -811,7 +814,9 @@ void prepareLobbyRoom(int viewWidth,
g_ctx.lobbySwapchainTextures,
{false},
true,
false);
enable_srgb_correction,
false,
1.0);
}

// on pause
Expand Down Expand Up @@ -857,7 +862,9 @@ void streamStartNative(FfiStreamConfig config) {
config.foveationEdgeRatioX,
config.foveationEdgeRatioY},
false,
config.enableSrgbCorrection);
config.enableSrgbCorrection,
config.fixLimitedRange,
config.encodingGamma);
}

void updateLobbyHudTexture(const unsigned char *data) {
Expand Down
16 changes: 15 additions & 1 deletion alvr/client_core/cpp/srgb_correction_pass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,39 @@ const string CORRECTION_FRAGMENT_SHADER = R"glsl(
{
color = texture(tex0, uv);

#ifdef LIMITED_RANGE_BUG
// For some reason, the encoder shifts full-range color into the negatives and over one.
color.rgb = LIMITED_MIN + ((LIMITED_MAX - LIMITED_MIN) * color.rgb);
#endif
#ifdef SRGB_CORRECTION
vec3 condition = vec3(color.r < THRESHOLD, color.g < THRESHOLD, color.b < THRESHOLD);
vec3 lowValues = color.rgb * DIV12;
vec3 highValues = pow((color.rgb + 0.055) * DIV1, GAMMA);
color.rgb = condition * lowValues + (1.0 - condition) * highValues;
#endif
#ifdef ENCODING_GAMMA
vec3 enc_condition = vec3(color.r < 0.0, color.g < 0.0, color.b < 0.0);
vec3 enc_lowValues = color.rgb;
vec3 enc_highValues = pow(color.rgb, vec3(ENCODING_GAMMA));
color.rgb = enc_condition * enc_lowValues + (1.0 - enc_condition) * enc_highValues;
#endif
}
)glsl";
} // namespace

SrgbCorrectionPass::SrgbCorrectionPass(Texture *inputSurface) : mInputSurface(inputSurface) {}

void SrgbCorrectionPass::Initialize(uint32_t width, uint32_t height, bool passthrough) {
void SrgbCorrectionPass::Initialize(uint32_t width, uint32_t height, bool passthrough, bool fixLimitedRange, float encodingGamma) {
mOutputTexture.reset(new Texture(false, 0, false, width * 2, height));
mOutputTextureState = make_unique<RenderState>(mOutputTexture.get());

string defines = passthrough ? "" : "#define SRGB_CORRECTION";
if (fixLimitedRange) {
defines += "\n#define LIMITED_RANGE_BUG";
}
if (encodingGamma != 1.0) {
defines += "\n#define ENCODING_GAMMA (" + std::to_string(encodingGamma) + ")";
}

auto fragmentShader = CORRECTION_FRAGMENT_SHADER_HEADER + "\n" + defines + "\n" + CORRECTION_FRAGMENT_SHADER;
mStagingPipeline = unique_ptr<RenderPipeline>(
Expand Down
2 changes: 1 addition & 1 deletion alvr/client_core/cpp/srgb_correction_pass.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SrgbCorrectionPass {
public:
SrgbCorrectionPass(gl_render_utils::Texture *inputSurface);

void Initialize(uint32_t width, uint32_t height, bool passthrough);
void Initialize(uint32_t width, uint32_t height, bool passthrough, bool fixLimitedRange, float encodingGamma);

void Render() const;

Expand Down
11 changes: 10 additions & 1 deletion alvr/client_core/src/c_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -658,10 +658,12 @@ pub unsafe extern "C" fn alvr_resume_opengl(
preferred_view_height: u32,
swapchain_textures: *mut *const u32,
swapchain_length: u32,
enable_srgb_correction: bool,
) {
opengl::initialize_lobby(
UVec2::new(preferred_view_width, preferred_view_height),
convert_swapchain_array(swapchain_textures, swapchain_length),
enable_srgb_correction,
);
}

Expand Down Expand Up @@ -690,7 +692,14 @@ pub unsafe extern "C" fn alvr_start_stream_opengl(config: AlvrStreamConfig) {
edge_ratio_y: config.foveation_edge_ratio_y,
});

opengl::start_stream(view_resolution, swapchain_textures, foveated_encoding, true);
opengl::start_stream(
view_resolution,
swapchain_textures,
foveated_encoding,
true,
false, // TODO: limited range fix config
1.0, // TODO: encoding gamma config
);
}

#[no_mangle]
Expand Down
11 changes: 10 additions & 1 deletion alvr/client_core/src/opengl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,11 @@ pub fn destroy() {
}
}

pub fn initialize_lobby(preferred_view_resolution: UVec2, swapchain_textures: [Vec<u32>; 2]) {
pub fn initialize_lobby(
preferred_view_resolution: UVec2,
swapchain_textures: [Vec<u32>; 2],
enable_srgb_correction: bool,
) {
#[cfg(target_os = "android")]
unsafe {
let swapchain_length = swapchain_textures[0].len();
Expand All @@ -56,6 +60,7 @@ pub fn initialize_lobby(preferred_view_resolution: UVec2, swapchain_textures: [V
preferred_view_resolution.y as _,
swapchain_textures.as_mut_ptr(),
swapchain_length as _,
enable_srgb_correction,
);
}
}
Expand All @@ -72,6 +77,8 @@ pub fn start_stream(
swapchain_textures: [Vec<u32>; 2],
foveated_encoding: Option<FoveatedEncodingConfig>,
enable_srgb_correction: bool,
fix_limited_range: bool,
encoding_gamma: f32,
) {
#[cfg(target_os = "android")]
unsafe {
Expand Down Expand Up @@ -109,6 +116,8 @@ pub fn start_stream(
.map(|f| f.edge_ratio_y)
.unwrap_or_default(),
enableSrgbCorrection: enable_srgb_correction as u32,
fixLimitedRange: fix_limited_range as u32,
encodingGamma: encoding_gamma,
};

streamStartNative(config);
Expand Down
2 changes: 1 addition & 1 deletion alvr/client_openxr/src/graphics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ pub fn create_swapchain(
let swapchain_info = xr::SwapchainCreateInfo {
create_flags: xr::SwapchainCreateFlags::EMPTY,
usage_flags: xr::SwapchainUsageFlags::COLOR_ATTACHMENT | xr::SwapchainUsageFlags::SAMPLED,
format: glow::SRGB8_ALPHA8,
format: glow::RGBA16F,
sample_count: 1,
width: resolution.x,
height: resolution.y,
Expand Down
5 changes: 5 additions & 0 deletions alvr/client_openxr/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ use std::{
time::{Duration, Instant},
};
use stream::StreamContext;
use xr::ColorSpaceFB;

const DECODER_MAX_TIMEOUT_MULTIPLIER: f32 = 0.8;

Expand Down Expand Up @@ -188,6 +189,10 @@ pub fn entry_point() {
vec![90.0]
};

if exts.fb_color_space {
xr_session.set_color_space(ColorSpaceFB::P3).unwrap();
}

let capabilities = ClientCapabilities {
default_view_resolution,
external_decoder: false,
Expand Down
1 change: 1 addition & 0 deletions alvr/client_openxr/src/lobby.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ impl Lobby {
.map(|i| *i as _)
.collect(),
],
false, // TODO: correct lobby sRGB for some headsets
);

Self {
Expand Down
10 changes: 8 additions & 2 deletions alvr/client_openxr/src/stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ use alvr_common::{
};
use alvr_packets::{FaceData, NegotiatedStreamingConfig, Tracking};
use alvr_session::{
BodyTrackingSourcesConfig, ClientsideFoveationConfig, ClientsideFoveationMode,
BodyTrackingSourcesConfig, ClientsideFoveationConfig, ClientsideFoveationMode, EncoderConfig,
FaceTrackingSourcesConfig, FoveatedEncodingConfig, Settings,
};
use openxr as xr;
Expand All @@ -33,6 +33,7 @@ pub struct StreamConfig {
pub refresh_rate_hint: f32,
pub foveated_encoding_config: Option<FoveatedEncodingConfig>,
pub clientside_foveation_config: Option<ClientsideFoveationConfig>,
pub encoder_config: EncoderConfig,
pub face_sources_config: Option<FaceTrackingSourcesConfig>,
pub body_sources_config: Option<BodyTrackingSourcesConfig>,
}
Expand All @@ -47,6 +48,7 @@ impl StreamConfig {
.then(|| settings.video.foveated_encoding.as_option().cloned())
.flatten(),
clientside_foveation_config: settings.video.clientside_foveation.as_option().cloned(),
encoder_config: settings.video.encoder_config.clone(),
face_sources_config: settings
.headset
.face_tracking
Expand Down Expand Up @@ -187,7 +189,11 @@ impl StreamContext {
.collect(),
],
config.foveated_encoding_config.clone(),
platform != Platform::Lynx,
platform != Platform::Lynx
&& platform != Platform::Pico4
&& platform != Platform::PicoNeo3,
config.encoder_config.enable_hdr != true,
config.encoder_config.encoding_gamma,
);

core_ctx.send_playspace(
Expand Down
4 changes: 4 additions & 0 deletions alvr/server/cpp/alvr_server/Settings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ void Settings::Load() {
m_entropyCoding = (uint32_t)config.get("entropy_coding").get<int64_t>();
m_use10bitEncoder = config.get("use_10bit_encoder").get<bool>();
m_useFullRangeEncoding = config.get("use_full_range_encoding").get<bool>();
m_encodingGamma = config.get("encoding_gamma").get<double>();
m_enableHdr = config.get("enable_hdr").get<bool>();
m_forceHdrSrgbCorrection = config.get("force_hdr_srgb_correction").get<bool>();
m_clampHdrExtendedRange = config.get("clamp_hdr_extended_range").get<bool>();
m_enablePreAnalysis = config.get("enable_pre_analysis").get<bool>();
m_enableVbaq = config.get("enable_vbaq").get<bool>();
m_enableHmqb = config.get("enable_hmqb").get<bool>();
Expand Down
4 changes: 4 additions & 0 deletions alvr/server/cpp/alvr_server/Settings.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ class Settings {
int m_h264Profile;
bool m_use10bitEncoder;
bool m_useFullRangeEncoding;
double m_encodingGamma;
bool m_enableHdr;
bool m_forceHdrSrgbCorrection;
bool m_clampHdrExtendedRange;
bool m_enablePreAnalysis;
bool m_enableVbaq;
bool m_enableHmqb;
Expand Down
2 changes: 2 additions & 0 deletions alvr/server/cpp/alvr_server/alvr_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,8 @@ const unsigned char *COMPRESS_AXIS_ALIGNED_CSO_PTR;
unsigned int COMPRESS_AXIS_ALIGNED_CSO_LEN;
const unsigned char *COLOR_CORRECTION_CSO_PTR;
unsigned int COLOR_CORRECTION_CSO_LEN;
const unsigned char *RGBTOYUV420_CSO_PTR;
unsigned int RGBTOYUV420_CSO_LEN;

const unsigned char *QUAD_SHADER_COMP_SPV_PTR;
unsigned int QUAD_SHADER_COMP_SPV_LEN;
Expand Down
3 changes: 3 additions & 0 deletions alvr/server/cpp/alvr_server/bindings.h
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ extern "C" const unsigned char *COMPRESS_AXIS_ALIGNED_CSO_PTR;
extern "C" unsigned int COMPRESS_AXIS_ALIGNED_CSO_LEN;
extern "C" const unsigned char *COLOR_CORRECTION_CSO_PTR;
extern "C" unsigned int COLOR_CORRECTION_CSO_LEN;
extern "C" const unsigned char *RGBTOYUV420_CSO_PTR;
extern "C" unsigned int RGBTOYUV420_CSO_LEN;


extern "C" const unsigned char *QUAD_SHADER_COMP_SPV_PTR;
extern "C" unsigned int QUAD_SHADER_COMP_SPV_LEN;
Expand Down
Loading
Loading