@@ -61,9 +61,11 @@ float4 SpritePixelShader(float4 color : COLOR0, float2 texCoord : TEXCOORD0) : S
6161 float4 tex = Texture.Sample(TextureSampler, texCoord);
6262 float threshold = saturate(color.r);
6363 float softness = max(color.g, 0.001);
64+ float invertAmount = saturate(color.b);
6465 float opacity = saturate(color.a);
6566 float luma = max(max(tex.r, tex.g), tex.b);
6667 float alpha = smoothstep(threshold, threshold + softness, luma) * opacity;
68+ alpha = lerp(alpha, 1.0 - alpha, invertAmount);
6769 return float4(tex.rgb, alpha);
6870}
6971)" ;
@@ -740,9 +742,9 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
740742 native_stereo_packet.reset ();
741743 }
742744
743- // Update the UI overlay. Days Gone normally composites Slate through BendTemporalAA
744- // into the scene. When the game-specific overlay path is enabled, use the captured
745- // SlateIntermediateBuffer and key black out into a real OpenXR UI layer .
745+ // Days Gone bypasses the normal viewport UI target and feeds a private
746+ // SlateIntermediateBuffer into BendTemporalAA. AHUD consumes that exact
747+ // target while leaving every other game's UI path unchanged .
746748 const auto daysgone_menu_is_in_scene = is_daysgone_executable ();
747749 auto * daysgone_native_ui_target = static_cast <ID3D11Texture2D*>(nullptr );
748750 D3D11_TEXTURE2D_DESC daysgone_native_ui_desc{};
@@ -752,8 +754,19 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
752754 daysgone_menu_is_in_scene &&
753755 vr != nullptr &&
754756 vr->is_daysgone_bend_ui_placement_fix_enabled ();
755-
756- if (daysgone_bend_fix_active && ffsr != nullptr && ffsr->should_use_daysgone_slate_ui_overlay ()) {
757+ const bool daysgone_ahud_active =
758+ daysgone_menu_is_in_scene &&
759+ vr != nullptr &&
760+ runtime != nullptr &&
761+ runtime->is_openxr () &&
762+ vr->is_hmd_active () &&
763+ vr->is_ahud_compatibility_enabled ();
764+ const bool daysgone_slate_target_requested =
765+ ffsr != nullptr &&
766+ (daysgone_ahud_active ||
767+ (daysgone_bend_fix_active && ffsr->should_use_daysgone_slate_ui_overlay ()));
768+
769+ if (daysgone_slate_target_requested) {
757770 daysgone_native_ui_target = reinterpret_cast <ID3D11Texture2D*>(ffsr->get_daysgone_slate_native_ui_target ());
758771 if (daysgone_native_ui_target != nullptr &&
759772 is_d3d11_or_dxgi_com_object (reinterpret_cast <IUnknown*>(daysgone_native_ui_target)))
@@ -769,6 +782,23 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
769782 }
770783
771784 const auto using_daysgone_native_ui_target = daysgone_native_ui_target != nullptr ;
785+ const auto using_daysgone_ahud_ui_target =
786+ using_daysgone_native_ui_target && daysgone_ahud_active;
787+
788+ if (daysgone_ahud_active != m_daysgone_ahud_was_active) {
789+ if (ffsr != nullptr ) {
790+ ffsr->reset_daysgone_ahud_overlay_readiness ();
791+ }
792+ if (vr != nullptr ) {
793+ vr->get_overlay_component ().get_openxr ().reset_daysgone_ahud_pose ();
794+ }
795+
796+ if (daysgone_ahud_active) {
797+ SPDLOG_INFO (" [DaysGone][AHUD] Armed fixed-stage UI after OpenXR/HMD became ready" );
798+ }
799+ }
800+ m_daysgone_ahud_was_active = daysgone_ahud_active;
801+
772802 const auto ui_target = (!using_daysgone_native_ui_target && !daysgone_menu_is_in_scene)
773803 ? ffsr->get_render_target_manager ()->get_ui_target ()
774804 : nullptr ;
@@ -789,7 +819,8 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
789819
790820 SPDLOG_INFO_EVERY_N_SEC (
791821 5 ,
792- " [DaysGone][SlateOverlay] using captured SlateIntermediateBuffer native={:x} [{}x{} fmt={} bind=0x{:X}] key=({:.3f},{:.3f},{:.3f}) offset=({:.1f},{:.1f}) scale={:.3f}" ,
822+ " [DaysGone][SlateOverlay] using captured SlateIntermediateBuffer route={} native={:x} [{}x{} fmt={} bind=0x{:X}] key=({:.3f},{:.3f},{:.3f}) invert={:.3f} offset=({:.1f},{:.1f}) scale={:.3f}" ,
823+ using_daysgone_ahud_ui_target ? " AHUD fixed-stage" : " Bend placement" ,
793824 (uintptr_t )native_ui_target,
794825 daysgone_native_ui_desc.Width ,
795826 daysgone_native_ui_desc.Height ,
@@ -798,9 +829,10 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
798829 ffsr->get_daysgone_slate_ui_key_threshold (),
799830 ffsr->get_daysgone_slate_ui_key_softness (),
800831 ffsr->get_daysgone_slate_ui_key_opacity (),
801- ffsr->get_daysgone_slate_ui_offset_x (),
802- ffsr->get_daysgone_slate_ui_offset_y (),
803- ffsr->get_daysgone_slate_ui_scale ());
832+ vr->get_overlay_component ().get_ui_invert_alpha (),
833+ using_daysgone_ahud_ui_target ? 0 .0f : ffsr->get_daysgone_slate_ui_offset_x (),
834+ using_daysgone_ahud_ui_target ? 0 .0f : ffsr->get_daysgone_slate_ui_offset_y (),
835+ using_daysgone_ahud_ui_target ? 1 .0f : ffsr->get_daysgone_slate_ui_scale ());
804836 } else if (is_naruto_executable () && native_ui_target != nullptr ) {
805837 D3D11_TEXTURE2D_DESC desc{};
806838 native_ui_target->GetDesc (&desc);
@@ -833,15 +865,17 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
833865 native->GetDesc (&desc);
834866
835867 if (runtime->is_openxr ()) {
836- if (auto it = vr->m_openxr ->swapchains .find ((uint32_t )runtimes::OpenXR::SwapchainIndex::UI );
837- it != vr->m_openxr ->swapchains .end ())
838- {
839- const auto & uisc = it->second ;
840- if (desc.Width != uisc.width ||
841- desc.Height != uisc.height )
868+ if (!using_daysgone_ahud_ui_target) {
869+ if (auto it = vr->m_openxr ->swapchains .find ((uint32_t )runtimes::OpenXR::SwapchainIndex::UI );
870+ it != vr->m_openxr ->swapchains .end ())
842871 {
843- SPDLOG_INFO_EVERY_N_SEC (1 , " [OpenXR] UI size changed, recreating [{}x{}]->[{}x{}]" , desc.Width , desc.Height , uisc.width , uisc.height );
844- ffsr->set_should_recreate_textures (true );
872+ const auto & uisc = it->second ;
873+ if (desc.Width != uisc.width ||
874+ desc.Height != uisc.height )
875+ {
876+ SPDLOG_INFO_EVERY_N_SEC (1 , " [OpenXR] UI size changed, recreating [{}x{}]->[{}x{}]" , desc.Width , desc.Height , uisc.width , uisc.height );
877+ ffsr->set_should_recreate_textures (true );
878+ }
845879 }
846880 }
847881 } else if (m_ui_tex != nullptr ) {
@@ -960,7 +994,7 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
960994 } else {
961995 if (m_engine_ui_ref.has_texture () && m_engine_ui_ref.has_srv ()) {
962996 if (using_daysgone_native_ui_target && ensure_daysgone_ui_key_resources ()) {
963- m_openxr.copy (
997+ const auto copied = m_openxr.copy (
964998 (uint32_t )runtimes::OpenXR::SwapchainIndex::UI ,
965999 nullptr ,
9661000 nullptr ,
@@ -971,10 +1005,11 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
9711005 ffsr->get_daysgone_slate_ui_key_threshold (),
9721006 ffsr->get_daysgone_slate_ui_key_softness (),
9731007 ffsr->get_daysgone_slate_ui_key_opacity (),
974- ffsr->get_daysgone_slate_ui_offset_x (),
975- ffsr->get_daysgone_slate_ui_offset_y (),
976- ffsr->get_daysgone_slate_ui_scale (),
977- ffsr->should_split_daysgone_slate_ui_overlay (),
1008+ ui_invert_alpha,
1009+ using_daysgone_ahud_ui_target ? 0 .0f : ffsr->get_daysgone_slate_ui_offset_x (),
1010+ using_daysgone_ahud_ui_target ? 0 .0f : ffsr->get_daysgone_slate_ui_offset_y (),
1011+ using_daysgone_ahud_ui_target ? 1 .0f : ffsr->get_daysgone_slate_ui_scale (),
1012+ using_daysgone_ahud_ui_target ? false : ffsr->should_split_daysgone_slate_ui_overlay (),
9781013 ffsr->get_daysgone_slate_ui_menu_src_x (),
9791014 ffsr->get_daysgone_slate_ui_menu_src_y (),
9801015 ffsr->get_daysgone_slate_ui_menu_src_w (),
@@ -985,6 +1020,9 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
9851020 ffsr->get_daysgone_slate_ui_footer_src_y (),
9861021 ffsr->get_daysgone_slate_ui_footer_src_h ());
9871022 });
1023+ if (copied && using_daysgone_ahud_ui_target) {
1024+ ffsr->note_daysgone_ahud_overlay_submitted ();
1025+ }
9881026 } else if (ui_invert_alpha > 0 .0f && ensure_ui_invert_resources ()) {
9891027 m_openxr.copy (
9901028 (uint32_t )runtimes::OpenXR::SwapchainIndex::UI ,
@@ -1237,7 +1275,9 @@ vr::EVRCompositorError D3D11Component::on_frame(VR* vr) {
12371275 quad_layers.push_back ((XrCompositionLayerBaseHeader*)&right_layer->get ());
12381276 }
12391277 } else if (m_openxr.ever_acquired ((uint32_t )runtimes::OpenXR::SwapchainIndex::UI )) {
1240- const auto slate_layer = openxr_overlay.generate_slate_layer ();
1278+ const auto slate_layer = daysgone_ahud_active && using_daysgone_ahud_ui_target
1279+ ? openxr_overlay.generate_daysgone_ahud_slate_layer ()
1280+ : openxr_overlay.generate_slate_layer ();
12411281
12421282 if (slate_layer) {
12431283 quad_layers.push_back (&slate_layer->get ());
@@ -1572,6 +1612,14 @@ void D3D11Component::on_post_present(VR* vr) {
15721612
15731613void D3D11Component::on_reset (VR * vr) {
15741614 m_force_reset = true ;
1615+ m_daysgone_ahud_was_active = false ;
1616+
1617+ if (vr != nullptr ) {
1618+ if (vr->m_fake_stereo_hook != nullptr ) {
1619+ vr->m_fake_stereo_hook ->reset_daysgone_ahud_overlay_readiness ();
1620+ }
1621+ vr->get_overlay_component ().get_openxr ().reset_daysgone_ahud_pose ();
1622+ }
15751623
15761624 m_backbuffer_rtv.Reset ();
15771625 m_backbuffer.Reset ();
@@ -2008,6 +2056,7 @@ void D3D11Component::render_daysgone_ui_key_to_rt(
20082056 float threshold,
20092057 float softness,
20102058 float opacity,
2059+ float invert_amount,
20112060 float offset_x,
20122061 float offset_y,
20132062 float scale,
@@ -2087,7 +2136,7 @@ void D3D11Component::render_daysgone_ui_key_to_rt(
20872136 const auto tint = DirectX::XMVectorSet (
20882137 std::clamp (threshold, 0 .0f , 0 .5f ),
20892138 std::clamp (softness, 0 .001f , 0 .5f ),
2090- 1 .0f ,
2139+ std::clamp (invert_amount, 0 . 0f , 1 .0f ) ,
20912140 std::clamp (opacity, 0 .0f , 2 .0f ));
20922141
20932142 auto set_custom_shaders = [&]() {
@@ -3095,13 +3144,13 @@ void D3D11Component::OpenXR::destroy_swapchains() {
30953144 vr->m_openxr ->swapchains .clear ();
30963145}
30973146
3098- void D3D11Component::OpenXR::copy (uint32_t swapchain_idx, ID3D11Texture2D* resource, D3D11_BOX * src_box, std::function<void (ID3D11Texture2D*)> pre_commands) {
3147+ bool D3D11Component::OpenXR::copy (uint32_t swapchain_idx, ID3D11Texture2D* resource, D3D11_BOX * src_box, std::function<void (ID3D11Texture2D*)> pre_commands) {
30993148 std::scoped_lock _{this ->mtx };
31003149
31013150 auto vr = VR::get ();
31023151
31033152 if (vr->m_openxr ->frame_state .shouldRender != XR_TRUE ) {
3104- return ;
3153+ return false ;
31053154 }
31063155
31073156 if (!vr->m_openxr ->frame_began ) {
@@ -3111,12 +3160,12 @@ void D3D11Component::OpenXR::copy(uint32_t swapchain_idx, ID3D11Texture2D* resou
31113160
31123161 if (!this ->contexts .contains (swapchain_idx)) {
31133162 spdlog::error (" [VR] OpenXR: Trying to copy to swapchain {} but it doesn't exist." , swapchain_idx);
3114- return ;
3163+ return false ;
31153164 }
31163165
31173166 if (!vr->m_openxr ->swapchains .contains (swapchain_idx)) {
31183167 spdlog::error (" [VR] OpenXR: Trying to copy to swapchain {} but it doesn't exist." , swapchain_idx);
3119- return ;
3168+ return false ;
31203169 }
31213170
31223171 if (this ->contexts [swapchain_idx].num_textures_acquired > 0 ) {
@@ -3176,12 +3225,15 @@ void D3D11Component::OpenXR::copy(uint32_t swapchain_idx, ID3D11Texture2D* resou
31763225
31773226 if (result != XR_SUCCESS ) {
31783227 spdlog::error (" [VR] xrReleaseSwapchainImage failed: {}" , vr->m_openxr ->get_result_string (result));
3179- return ;
3228+ return false ;
31803229 }
31813230
31823231 ctx.num_textures_acquired --;
31833232 ctx.ever_acquired = true ;
3233+ return true ;
31843234 }
31853235 }
3236+
3237+ return false ;
31863238}
31873239} // namespace vrmod
0 commit comments