diff --git a/src/Deferred.cpp b/src/Deferred.cpp index ac6d831dc0..8491cc981f 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -267,7 +267,7 @@ void Deferred::StartDeferred() ID3D11Buffer* vrBuffer = nullptr; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { static REL::Relocation VRValues{ REL::Offset(0x3180688) }; vrBuffer = *VRValues.get(); } @@ -302,7 +302,7 @@ void Deferred::DeferredPasses() ID3D11Buffer* buffers[1] = { *globals::game::perFrame }; ID3D11Buffer* vrBuffer = nullptr; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { static REL::Relocation VRValues{ REL::Offset(0x3180688) }; vrBuffer = *VRValues.get(); } @@ -357,7 +357,7 @@ void Deferred::DeferredPasses() albedo.SRV, // t1 AlbedoTexture normalRoughness.SRV, // t2 NormalRoughnessTexture masks.SRV, // t3 MasksTexture - dynamicCubemaps.loaded || REL::Module::IsVR() ? Util::GetCurrentSceneDepthSRV(false) : nullptr, // t4 DepthTexture (24/32-bit; HLSL type baked at compile via TERRAIN_BLENDING) + dynamicCubemaps.loaded || globals::game::isVR ? Util::GetCurrentSceneDepthSRV(false) : nullptr, // t4 DepthTexture (24/32-bit; HLSL type baked at compile via TERRAIN_BLENDING) dynamicCubemaps.loaded ? reflectance.SRV : nullptr, // t5 ReflectanceTexture dynamicCubemaps.loaded ? dynamicCubemaps.envTexture->srv.get() : nullptr, // t6 EnvTexture dynamicCubemaps.loaded ? dynamicCubemaps.envReflectionsTexture->srv.get() : nullptr, // t7 EnvReflectionsTexture @@ -663,10 +663,10 @@ ID3D11ComputeShader* Deferred::GetComputeMainComposite() if (globals::features::ibl.loaded) defines.push_back({ "IBL", nullptr }); - if (REL::Module::IsVR()) + if (globals::game::isVR) defines.push_back({ "FRAMEBUFFER", nullptr }); - if (REL::Module::IsVR()) + if (globals::game::isVR) defines.push_back({ "VR_STEREO_OPT", nullptr }); // TERRAIN_BLENDING flips DepthTexture's HLSL type from `Texture2D` @@ -696,10 +696,10 @@ ID3D11ComputeShader* Deferred::GetComputeMainCompositeInterior() if (globals::features::ibl.loaded) defines.push_back({ "IBL", nullptr }); - if (REL::Module::IsVR()) + if (globals::game::isVR) defines.push_back({ "FRAMEBUFFER", nullptr }); - if (REL::Module::IsVR()) + if (globals::game::isVR) defines.push_back({ "VR_STEREO_OPT", nullptr }); // TERRAIN_BLENDING flips DepthTexture's HLSL type from `Texture2D` diff --git a/src/Deferred.h b/src/Deferred.h index 841ce082e0..e032878f8b 100644 --- a/src/Deferred.h +++ b/src/Deferred.h @@ -155,7 +155,7 @@ class Deferred stl::write_thunk_call(REL::RelocationID(99938, 106583).address() + REL::Relocate(0x8E, 0x84)); stl::write_thunk_call(REL::RelocationID(99938, 106583).address() + REL::Relocate(0x319, 0x308, 0x321)); - if (!REL::Module::IsVR()) + if (!globals::game::isVR) stl::write_thunk_call(REL::RelocationID(35560, 36559).address() + REL::Relocate(0x944, 0x954)); stl::detour_thunk(REL::RelocationID(75570, 77371)); diff --git a/src/Feature.cpp b/src/Feature.cpp index 5264802f5a..6915922341 100644 --- a/src/Feature.cpp +++ b/src/Feature.cpp @@ -250,7 +250,7 @@ const std::vector& Feature::GetFeatureList() &globals::features::hdrDisplay }; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { // Helper function to build VR feature list static auto BuildVRList = []() -> std::vector { auto v = features; diff --git a/src/FeatureIssues.cpp b/src/FeatureIssues.cpp index 64362979d5..2f18b4d128 100644 --- a/src/FeatureIssues.cpp +++ b/src/FeatureIssues.cpp @@ -787,7 +787,7 @@ namespace FeatureIssues } // Skip VR feature when not in VR mode (it's a core feature) - if (featureName == "VR" && !REL::Module::IsVR()) { + if (featureName == "VR" && !globals::game::isVR) { logger::info("Ignoring VR.ini in non-VR mode"); continue; } diff --git a/src/Features/GrassCollision.cpp b/src/Features/GrassCollision.cpp index 3dacd62da4..45db9a0959 100644 --- a/src/Features/GrassCollision.cpp +++ b/src/Features/GrassCollision.cpp @@ -369,7 +369,7 @@ void GrassCollision::UpdateCollisionTexture() ID3D11Buffer* buffers[1] = { *globals::game::perFrame }; ID3D11Buffer* vrBuffer = nullptr; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { static REL::Relocation VRValues{ REL::Offset(0x3180688) }; vrBuffer = *VRValues.get(); } diff --git a/src/Features/LightLimitFix.cpp b/src/Features/LightLimitFix.cpp index bf4d7ef4cf..c86bc1a10f 100644 --- a/src/Features/LightLimitFix.cpp +++ b/src/Features/LightLimitFix.cpp @@ -404,7 +404,7 @@ LightLimitFix::PerFrame LightLimitFix::GetCommonBufferData() void LightLimitFix::SetupResources() { auto screenSize = globals::state->screenSize; - if (REL::Module::IsVR()) + if (globals::game::isVR) screenSize.x *= .5; clusterSize[0] = ((uint)screenSize.x + 63) / 64; clusterSize[1] = ((uint)screenSize.y + 63) / 64; @@ -413,7 +413,7 @@ void LightLimitFix::SetupResources() { std::vector> clusterDefines; - if (REL::Module::IsVR()) + if (globals::game::isVR) clusterDefines = { { "VR", "" } }; clusterBuildingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterBuildingCS.hlsl", clusterDefines, "cs_5_0"); clusterCullingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterCullingCS.hlsl", clusterDefines, "cs_5_0"); @@ -847,7 +847,7 @@ void LightLimitFix::ClearShaderCache() clusterCullingCS = nullptr; } std::vector> clusterDefines; - if (REL::Module::IsVR()) + if (globals::game::isVR) clusterDefines = { { "VR", "" } }; clusterBuildingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterBuildingCS.hlsl", clusterDefines, "cs_5_0"); clusterCullingCS = (ID3D11ComputeShader*)Util::CompileShader(L"Data\\Shaders\\LightLimitFix\\ClusterCullingCS.hlsl", clusterDefines, "cs_5_0"); @@ -1150,7 +1150,7 @@ void LightLimitFix::UpdateStructure() lightsFar = *globals::game::cameraFar; auto renderSize = Util::ConvertToDynamic(globals::state->screenSize); - if (REL::Module::IsVR()) + if (globals::game::isVR) renderSize.x *= .5; clusterSize[0] = ((uint)renderSize.x + 63) / 64; clusterSize[1] = ((uint)renderSize.y + 63) / 64; diff --git a/src/Features/LightLimitFix.h b/src/Features/LightLimitFix.h index 09ec48aac1..3ff4692b74 100644 --- a/src/Features/LightLimitFix.h +++ b/src/Features/LightLimitFix.h @@ -193,6 +193,7 @@ struct LightLimitFix : OverlayFeature ConstantBuffer* strictLightDataCB = nullptr; + // Keep raw runtime check for ctor-time default before globals::ReInit(). int eyeCount = !REL::Module::IsVR() ? 1 : 2; // Debug-only visualization state. Lives on the instance rather than in diff --git a/src/Features/LightLimitFix/ShadowCasterManager.cpp b/src/Features/LightLimitFix/ShadowCasterManager.cpp index f6f250b1bb..a34a7caafa 100644 --- a/src/Features/LightLimitFix/ShadowCasterManager.cpp +++ b/src/Features/LightLimitFix/ShadowCasterManager.cpp @@ -402,7 +402,7 @@ namespace ShadowCasterManager // Hook #2: VR: renderer in R14, result -> RBP; SE/AE: renderer in RBP, result -> R14. static void Hook_SelectDepthBuffer2(CONTEXT& ctx) { - bool isVR = REL::Module::IsVR(); + bool isVR = globals::game::isVR; bool readOnly = isVR ? reinterpret_cast(ctx.R14)->GetRuntimeData().readOnlyDepth : reinterpret_cast(ctx.Rbp)->GetRuntimeData().readOnlyDepth; int type = GetDepthTargetType(); @@ -479,7 +479,7 @@ namespace ShadowCasterManager // cover the same range as FindFreeIndex; a mismatch means a light // silently gets idx=0 and corrupts the slot at index 0. - if (REL::Module::IsVR()) + if (globals::game::isVR) ctx.Rdx = static_cast(idx); else ctx.Rsi = static_cast(idx); @@ -1229,7 +1229,7 @@ namespace ShadowCasterManager static void GameApplyLensFlare(RE::BSLight* light) { // SE/AE only -- no VR equivalent (ID 100440) - if (REL::Module::IsVR()) + if (globals::game::isVR) return; using F = void (*)(RE::BSLight*); static REL::Relocation func{ REL::RelocationID(100440, 107157) }; @@ -1257,7 +1257,7 @@ namespace ShadowCasterManager // VR: (cam, coord, r1, r2, eyeIndex, eps) -- pass 0xffffffff for combined frustum static REL::Relocation addr{ REL::RelocationID(69265, 70632) }; auto ptr = addr.address(); - if (REL::Module::IsVR()) { + if (globals::game::isVR) { using VR = void (*)(RE::NiCamera*, float*, float*, float*, uint32_t, float); reinterpret_cast(ptr)(cam, coord, r1, r2, 0xffffffffu, eps); } else { @@ -1269,12 +1269,12 @@ namespace ShadowCasterManager // Convenience: runtime-aware shadow-light field accessor (SE vs VR RuntimeData differ). // Usage: ShadowField(light, maskIndex) = 3; #define ShadowField(light, member) \ - (REL::Module::IsVR() ? (light)->GetVRRuntimeData().member : (light)->GetRuntimeData().member) + (globals::game::isVR ? (light)->GetVRRuntimeData().member : (light)->GetRuntimeData().member) // Returns the culling process for the first shadow descriptor of a light. static RE::BSCullingProcess* GetLightCullingProcess(RE::BSShadowLight* light) { - return REL::Module::IsVR() ? light->GetVRRuntimeData().shadowmapDescriptors.front().cullingProcess : light->GetRuntimeData().shadowmapDescriptors.front().cullingProcess; + return globals::game::isVR ? light->GetVRRuntimeData().shadowmapDescriptors.front().cullingProcess : light->GetRuntimeData().shadowmapDescriptors.front().cullingProcess; } // ========================================================================= @@ -1601,7 +1601,7 @@ namespace ShadowCasterManager if (drawFocus || (!*GetFocusShadowSelected() && light->GetIsFrustumOrDirectionalLight())) { GameSetupDirectionalLight(light, camera); GameAccumulate(light); - if (REL::Module::IsVR()) { + if (globals::game::isVR) { for (auto& desc : light->GetVRRuntimeData().focusShadowmapDescriptors) { desc.vrRenderTarget[0] = RE::RENDER_TARGET_DEPTHSTENCIL::kNONE; desc.vrRenderTarget[1] = RE::RENDER_TARGET_DEPTHSTENCIL::kNONE; @@ -1647,7 +1647,7 @@ namespace ShadowCasterManager float vw = (float)*globals::game::viewWidth; float vh = (float)*globals::game::viewHeight; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { vw *= GetVRDRSWidthRatio(); vh *= GetVRDRSHeightRatio(); } @@ -1683,7 +1683,7 @@ namespace ShadowCasterManager int32_t idx = s_lights.FindLight(light, s_settings.ShadowLightCount); if (idx < 0) idx = 0; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { for (auto& desc : light->GetVRRuntimeData().shadowmapDescriptors) { desc.renderTarget = RE::RENDER_TARGET_DEPTHSTENCIL::kNONE; desc.shadowmapIndex = static_cast(idx); @@ -1754,7 +1754,7 @@ namespace ShadowCasterManager } guard; // VR display guard: skip scheduling when the HMD display is not active. - if (REL::Module::IsVR() && !GetVRDrawShadows()) + if (globals::game::isVR && !GetVRDrawShadows()) return; auto* ssn = GetShadowSceneNode(); @@ -1792,13 +1792,13 @@ namespace ShadowCasterManager auto* sun = ssn->GetRuntimeData().sunShadowDirLight; if (sun) { static REL::Relocation vrUpdateFlag{ REL::Offset(0x1ed62f8) }; - uint8_t vrFlag = REL::Module::IsVR() ? static_cast(*vrUpdateFlag) + 1 : 0; + uint8_t vrFlag = globals::game::isVR ? static_cast(*vrUpdateFlag) + 1 : 0; sun->Accumulate(*GetAccumLightSlot(), 0, nullptr, vrFlag); - if (sun->lensFlareData && !REL::Module::IsVR()) + if (sun->lensFlareData && !globals::game::isVR) GameApplyLensFlare(sun); - if (REL::Module::IsVR() && !GetVRAccumFirst()) { + if (globals::game::isVR && !GetVRAccumFirst()) { GameVRPrepareShadowMaps(sun); GameVRAccumulateShadowMaps(sun); } @@ -2779,7 +2779,7 @@ namespace ShadowCasterManager // kSHADOWMAPS, so its descriptor.shadowmapIndex is unused. if (s_lights.Sun && i == 0) continue; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { for (auto& desc : e.Light->GetVRRuntimeData().shadowmapDescriptors) desc.shadowmapIndex = static_cast(i); } else { @@ -2866,7 +2866,7 @@ namespace ShadowCasterManager // iterating shadow casters, then restores it. Without this, each hemisphere // render is doubled for both eyes -> 4-quadrant shadow map texture. bool savedStereo = false; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { savedStereo = *globals::game::drawStereo; *globals::game::drawStereo = false; } @@ -2918,7 +2918,7 @@ namespace ShadowCasterManager state->EndPerfEvent(); - if (REL::Module::IsVR()) + if (globals::game::isVR) *globals::game::drawStereo = savedStereo; } @@ -2931,7 +2931,7 @@ namespace ShadowCasterManager // r8 gets a stale pointer whose [+0x50] slot is null -> crash at execute 0x0. static void Hook_RenderShadowLights(CONTEXT& ctx) { - if (!REL::Module::IsVR()) + if (!globals::game::isVR) ctx.Rax = 0; RenderScheduledShadowLights(); }; @@ -2999,7 +2999,7 @@ namespace ShadowCasterManager uint32_t fpMask = *reinterpret_cast(ctx.Rsp + 0x50); // a10 // VR passes an 11th arg: if non-zero, skip accumulation (vanilla early-out). - if (REL::Module::IsVR() && *reinterpret_cast(ctx.Rsp + 0x58) != 0) { + if (globals::game::isVR && *reinterpret_cast(ctx.Rsp + 0x58) != 0) { ctx.Rax = 1; // addedLightCount = sun only return; } diff --git a/src/Features/RemoteControl/DevBenchBridge.cpp b/src/Features/RemoteControl/DevBenchBridge.cpp index bbda35d0af..bf7a38362b 100644 --- a/src/Features/RemoteControl/DevBenchBridge.cpp +++ b/src/Features/RemoteControl/DevBenchBridge.cpp @@ -198,7 +198,7 @@ namespace // Don't let a remote caller enable a VR-incompatible feature on a VR runtime: // it bypasses the SupportsVR() gate and can destabilize the renderer. Reject + // report (covers both an explicit enable and an implicit flip resolving to true). - if (applied && REL::Module::IsVR() && !target->SupportsVR()) { + if (applied && globals::game::isVR && !target->SupportsVR()) { if (auto* dvb = DevBenchAPI::GetDevBenchInterface001()) { const std::string payload = json{ { "shortName", shortName }, { "error", "feature does not support VR; enable rejected" } }.dump(); dvb->EmitEvent("openshaders.feature.changed", payload.c_str()); @@ -292,7 +292,7 @@ namespace return json{ { "plugin", "CommunityShaders" }, { "frame_count", EnqueuedFrame() }, - { "vr", REL::Module::IsVR() }, + { "vr", globals::game::isVR }, }; } if (kind == "shadercache") { diff --git a/src/Features/ScreenSpaceGI.cpp b/src/Features/ScreenSpaceGI.cpp index 5a021c3cd8..99ce602a23 100644 --- a/src/Features/ScreenSpaceGI.cpp +++ b/src/Features/ScreenSpaceGI.cpp @@ -613,10 +613,10 @@ void ScreenSpaceGI::CompileComputeShaders() { &upsampleCompute, "upsample.cs.hlsl", {} }, }; - if (REL::Module::IsVR()) + if (globals::game::isVR) shaderInfos.push_back({ &stereoSyncCompute, "stereoSync.cs.hlsl", { { "FRAMEBUFFER", "" } } }); for (auto& info : shaderInfos) { - if (REL::Module::IsVR()) + if (globals::game::isVR) info.defines.push_back({ "VR", "" }); if (settings.ResolutionMode == 1) info.defines.push_back({ "HALF_RES", "" }); @@ -654,13 +654,13 @@ void ScreenSpaceGI::UpdateSB() SSGICB data; { - for (int eyeIndex = 0; eyeIndex < (1 + REL::Module::IsVR()); ++eyeIndex) { + for (int eyeIndex = 0; eyeIndex < (1 + globals::game::isVR); ++eyeIndex) { auto eye = Util::GetCameraData(eyeIndex); data.PrevInvViewMat[eyeIndex] = prevInvView[eyeIndex]; data.NDCToViewMul[eyeIndex] = { 2.0f / eye.projMat(0, 0), -2.0f / eye.projMat(1, 1) }; data.NDCToViewAdd[eyeIndex] = { -1.0f / eye.projMat(0, 0), 1.0f / eye.projMat(1, 1) }; - if (REL::Module::IsVR()) + if (globals::game::isVR) data.NDCToViewMul[eyeIndex].x *= 2; prevInvView[eyeIndex] = eye.viewMat.Invert(); @@ -913,7 +913,7 @@ void ScreenSpaceGI::DrawSSGI() // VR stereo sync: bilateral blend of SSGI buffers between eyes // Shi, Billeter, Eisemann 2022, "Stereo-consistent screen-space ambient occlusion" - if (REL::Module::IsVR() && stereoSyncCompute) { + if (globals::game::isVR && stereoSyncCompute) { TracyD3D11Zone(globals::state->tracyCtx, "SSGI - Stereo Sync"); if (globals::state->frameAnnotations) diff --git a/src/Features/ScreenSpaceGI.h b/src/Features/ScreenSpaceGI.h index 45c0c1a03e..acce28a0cd 100644 --- a/src/Features/ScreenSpaceGI.h +++ b/src/Features/ScreenSpaceGI.h @@ -21,7 +21,7 @@ struct ScreenSpaceGI : Feature "Screen Space Global Illumination adds realistic indirect lighting and " "ambient occlusion to the game. This technique simulates how light " "bounces off surfaces to illuminate other objects naturally."; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { desc += "\n\nWarning: In VR, this feature may have visual artifacts and " "can have a significant performance impact due to the nature of " @@ -60,6 +60,7 @@ struct ScreenSpaceGI : Feature struct Settings { bool Enabled = true; + // Keep raw runtime check for ctor-time defaults before globals::ReInit(). bool EnableGI = REL::Module::IsVR() ? false : true; // AO only for VR by default bool EnableExperimentalSpecularGI = false; bool EnableVanillaSSAO = false; diff --git a/src/Features/ScreenshotFeature.cpp b/src/Features/ScreenshotFeature.cpp index 68ea6502c3..4023101799 100644 --- a/src/Features/ScreenshotFeature.cpp +++ b/src/Features/ScreenshotFeature.cpp @@ -304,7 +304,7 @@ void ScreenshotFeature::PostPostLoad() // only dispatches to LoadSettings when the JSON already has a settings // block, so a fresh install would skip a seed placed there. Left first so // it's the initial selection (matches vanilla Skyrim VR's left-eye save). - if (REL::Module::IsVR()) { + if (globals::game::isVR) { subrect.SeedDefaultPresets({ { .name = "Left Eye", .uv = { 0.0f, 0.0f, 0.5f, 1.0f } }, { .name = "Right Eye", .uv = { 0.5f, 0.0f, 0.5f, 1.0f } }, diff --git a/src/Features/Skylighting.cpp b/src/Features/Skylighting.cpp index 771c5240a4..9f7f4ad608 100644 --- a/src/Features/Skylighting.cpp +++ b/src/Features/Skylighting.cpp @@ -256,7 +256,7 @@ void Skylighting::PostPostLoad() stl::write_vfunc<0x2D, BSLightingShaderProperty_GetPrecipitationOcclusionMapRenderPassesImpl>(RE::VTABLE_BSLightingShaderProperty[0]); stl::write_thunk_call(REL::RelocationID(35560, 36559).address() + REL::Relocate(0x3A1, 0x3A1, 0x2FA)); - if (REL::Module::IsVR()) + if (globals::game::isVR) stl::write_thunk_call(REL::RelocationID(25643, 26185).address() + REL::Relocate(0x5D9, 0x59D, 0x5DC)); else stl::write_thunk_call(REL::RelocationID(25643, 26185).address() + REL::Relocate(0x5D9, 0x59D, 0x5DC)); diff --git a/src/Features/Upscaling/DX12SwapChain.cpp b/src/Features/Upscaling/DX12SwapChain.cpp index 430cf3a194..5058a25832 100644 --- a/src/Features/Upscaling/DX12SwapChain.cpp +++ b/src/Features/Upscaling/DX12SwapChain.cpp @@ -37,7 +37,7 @@ void DX12SwapChain::CreateSwapChain(IDXGIAdapter* adapter, DXGI_SWAP_CHAIN_DESC // Runtime format negotiation for swap chain DXGI_FORMAT attemptedFormat = DXGI_FORMAT_R10G10B10A2_UNORM; DXGI_FORMAT negotiatedFormat = DXGI_FORMAT_R10G10B10A2_UNORM; - bool isVR = REL::Module::IsVR(); + bool isVR = globals::game::isVR; bool fallbackUsed = false; // Test R10G10B10A2 support (applies to both VR and non-VR for HDR capability) diff --git a/src/Features/Upscaling/PerfMode/MenuBridge.cpp b/src/Features/Upscaling/PerfMode/MenuBridge.cpp index 4d0603e474..bc9c6cb37f 100644 --- a/src/Features/Upscaling/PerfMode/MenuBridge.cpp +++ b/src/Features/Upscaling/PerfMode/MenuBridge.cpp @@ -166,7 +166,7 @@ void PerfMode::MaybeBlitMenuBG(uint32_t boundRTIdx) void PerfMode::InstallCreateRTThunks() { - if (!REL::Module::IsVR()) + if (!globals::game::isVR) return; auto vrBase = REL::RelocationID(100458, 107175).address(); stl::write_thunk_call(vrBase + 0x6cc); diff --git a/src/Features/VR.h b/src/Features/VR.h index a8a789190e..fbaf952545 100644 --- a/src/Features/VR.h +++ b/src/Features/VR.h @@ -129,7 +129,7 @@ struct VR : OverlayFeature void CompileStereoBlendShaders(); bool IsStereoOptimizationCullingReady() const { - return REL::Module::IsVR() && + return globals::game::isVR && stereoOpt.CanDispatchStencil() && stereoBlendOverwriteCS && stereoBlendCopyTex && diff --git a/src/Features/VR/StereoBlend.cpp b/src/Features/VR/StereoBlend.cpp index b296d80d1b..022952eb31 100644 --- a/src/Features/VR/StereoBlend.cpp +++ b/src/Features/VR/StereoBlend.cpp @@ -59,7 +59,7 @@ void VR::DrawStereoBlend() { bool vrStereoOptActive = IsStereoOptimizationCullingReady(); - if (!REL::Module::IsVR() || !stereoBlendCopyTex || !stereoBlendCB) + if (!globals::game::isVR || !stereoBlendCopyTex || !stereoBlendCB) return; // Modes 4/5 visualize the overwrite path (mode classification, POM depth) without requiring diff --git a/src/Features/VRStereoOptimizations.cpp b/src/Features/VRStereoOptimizations.cpp index 8f230c593b..6df2f4be52 100644 --- a/src/Features/VRStereoOptimizations.cpp +++ b/src/Features/VRStereoOptimizations.cpp @@ -85,7 +85,7 @@ void VRStereoOptimizations::RestoreDefaultSettings() void VRStereoOptimizations::SetupResources() { - if (!REL::Module::IsVR()) + if (!globals::game::isVR) return; auto device = globals::d3d::device; @@ -322,7 +322,7 @@ void VRStereoOptimizations::UpdateConstantBuffer() void VRStereoOptimizations::DispatchStencil() { - if (!REL::Module::IsVR()) + if (!globals::game::isVR) return; if (settings.stereoMode == StereoMode::Off) return; diff --git a/src/Globals.cpp b/src/Globals.cpp index 4b9aee14fd..222528d940 100644 --- a/src/Globals.cpp +++ b/src/Globals.cpp @@ -181,7 +181,7 @@ namespace globals graphicsState = RE::BSGraphics::State::GetSingleton(); renderer = RE::BSGraphics::Renderer::GetSingleton(); smState = &RE::BSShaderManager::State::GetSingleton(); - isVR = REL::Module::IsVR(); + isVR = REL::Module::IsVR(); // Init source of truth for globals::game::isVR iniSettingCollection = RE::INISettingCollection::GetSingleton(); iniPrefSettingCollection = RE::INIPrefSettingCollection::GetSingleton(); gameSettingCollection = RE::GameSettingCollection::GetSingleton(); @@ -203,7 +203,7 @@ namespace globals frameCounter = reinterpret_cast(REL::RelocationID(525008, 411489).address()); viewWidth = reinterpret_cast(REL::RelocationID(524978, 411459).address()); viewHeight = reinterpret_cast(REL::RelocationID(524979, 411460).address()); - if (REL::Module::IsVR()) + if (globals::game::isVR) drawStereo = reinterpret_cast(REL::RelocationID(524907, 411393).address() + sizeof(void*)); } @@ -253,7 +253,7 @@ namespace globals void CacheFramebuffer() { using namespace game; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { auto frameBufferVR = (FrameBufferVR*)mappedFrameBuffer->pData; frameBufferCached.vr = *frameBufferVR; } else { diff --git a/src/Globals.h b/src/Globals.h index ee79f93d1c..5b5cdf1c5c 100644 --- a/src/Globals.h +++ b/src/Globals.h @@ -150,7 +150,8 @@ namespace globals FrameBuffer nonVR; FrameBufferVR vr; - // Helper functions for VR-agnostic access to eye 0 (or single eye) + // Helper functions for VR-agnostic access to eye 0 (or single eye). + // Keep raw module VR checks in this header block to avoid relying on game::isVR declaration order. const Matrix& GetCameraView(uint32_t eyeIndex = 0) const { return REL::Module::IsVR() ? vr.CameraView[eyeIndex] : nonVR.CameraView; diff --git a/src/Hooks.cpp b/src/Hooks.cpp index fc55773f83..b2e487c742 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -954,7 +954,7 @@ namespace Hooks */ void Install() { - if (!REL::Module::IsVR()) { + if (!globals::game::isVR) { logger::info("Hooking BSImageSpace::Init::IBLF"); stl::detour_thunk(REL::RelocationID(100480, 107198)); } @@ -1034,7 +1034,7 @@ namespace Hooks if (REL::Module::IsAE()) { std::uint8_t patch[] = { 0x41, 0x83, 0xE7, 0x00 }; // and r15d, 0 REL::safe_write(setupGeometryUpdateRenderSpace + 0x71, patch, sizeof(patch)); - } else if (REL::Module::IsVR()) { + } else if (globals::game::isVR) { std::uint8_t patch[] = { 0x41, 0x83, 0xE4, 0x00 }; // and r12d, 0 REL::safe_write(setupGeometryUpdateRenderSpace + 0x65, patch, sizeof(patch)); } else { @@ -1068,6 +1068,6 @@ namespace Hooks } logger::info("Hooking CreateDXGIFactory"); - *(uintptr_t*)&ptrCreateDXGIFactory = SKSE::PatchIAT(hk_CreateDXGIFactory, "dxgi.dll", !REL::Module::IsVR() ? "CreateDXGIFactory" : "CreateDXGIFactory1"); + *(uintptr_t*)&ptrCreateDXGIFactory = SKSE::PatchIAT(hk_CreateDXGIFactory, "dxgi.dll", !globals::game::isVR ? "CreateDXGIFactory" : "CreateDXGIFactory1"); } } diff --git a/src/Menu.h b/src/Menu.h index 0f51be0110..a339955ed0 100644 --- a/src/Menu.h +++ b/src/Menu.h @@ -233,7 +233,8 @@ class Menu }; float FontSize = ThemeManager::Constants::DEFAULT_FONT_SIZE; - std::string FontName = "Jost/Jost-Regular.ttf"; // Default font file name (legacy) + std::string FontName = "Jost/Jost-Regular.ttf"; // Default font file name (legacy) + // Keep raw runtime check for ctor-time default before globals::ReInit(). float GlobalScale = REL::Module::IsVR() ? -0.5f : 0.f; // exponential std::array(FontRole::Count)> FontRoles = []() { std::array(FontRole::Count)> roles{}; diff --git a/src/Menu/HomePageRenderer.cpp b/src/Menu/HomePageRenderer.cpp index 2d59c59774..44ffe881e0 100644 --- a/src/Menu/HomePageRenderer.cpp +++ b/src/Menu/HomePageRenderer.cpp @@ -517,7 +517,7 @@ void HomePageRenderer::RenderFirstTimeSetupDialog() bool HomePageRenderer::ShouldShowFirstTimeSetup() { // Never show first-time setup in VR mode - if (REL::Module::IsVR()) { + if (globals::game::isVR) { return false; } diff --git a/src/ShaderCache.cpp b/src/ShaderCache.cpp index 6c3a50d9fa..feb711bf8c 100644 --- a/src/ShaderCache.cpp +++ b/src/ShaderCache.cpp @@ -906,7 +906,7 @@ namespace SIE { "ScaleMask", 13 }, }; - if (REL::Module::IsVR()) { + if (globals::game::isVR) { grassVS.insert({ "Padding", 14 }); } else { grassVS.insert({ "ShadowClampValue", 14 }); @@ -1012,7 +1012,7 @@ namespace SIE { "CellTexCoordOffset", 11 }, }; - if (!REL::Module::IsVR()) { + if (!globals::game::isVR) { waterVS.insert( { { "SubTexOffset", 12 }, @@ -1079,7 +1079,7 @@ namespace SIE { "ShadowLightParam", 8 }, }; - if (!REL::Module::IsVR()) { + if (!globals::game::isVR) { utilityPS.insert( { { "ShadowFadeParam", 9 }, @@ -1454,7 +1454,7 @@ namespace SIE defines[lastIndex++] = { "D3DCOMPILE_SKIP_OPTIMIZATION", nullptr }; defines[lastIndex++] = { "D3DCOMPILE_DEBUG", nullptr }; } - if (REL::Module::IsVR()) + if (globals::game::isVR) defines[lastIndex++] = { "VR", nullptr }; auto shaderDefines = globals::state->GetDefines(); if (!shaderDefines->empty()) { diff --git a/src/ShaderCache.h b/src/ShaderCache.h index a80c8603ef..0afa732404 100644 --- a/src/ShaderCache.h +++ b/src/ShaderCache.h @@ -14,6 +14,7 @@ namespace ShaderConstants { static const LightingPS& Get() { + // Keep raw runtime check: this static can initialize before globals::ReInit(). static LightingPS instance = REL::Module::IsVR() ? GetVR() : GetFlat(); return instance; } diff --git a/src/TruePBR.cpp b/src/TruePBR.cpp index 75be9fe75c..34a47882dc 100644 --- a/src/TruePBR.cpp +++ b/src/TruePBR.cpp @@ -1176,7 +1176,7 @@ bool TruePBR::TESObjectLAND_SetupMaterial(RE::TESObjectLAND* land) if (land->loadedData != nullptr && land->loadedData->mesh[0] != nullptr) { land->data.flags.set(static_cast(8)); for (uint32_t quadIndex = 0; quadIndex < 4; ++quadIndex) { - auto shaderProperty = static_cast(memoryManager->Allocate(REL::Module::IsVR() ? 0x178 : sizeof(RE::BSLightingShaderProperty), 0, false)); + auto shaderProperty = static_cast(memoryManager->Allocate(globals::game::isVR ? 0x178 : sizeof(RE::BSLightingShaderProperty), 0, false)); shaderProperty->Ctor(); { diff --git a/src/Utils/D3D.cpp b/src/Utils/D3D.cpp index 5f6c4b5737..897ccee8fb 100644 --- a/src/Utils/D3D.cpp +++ b/src/Utils/D3D.cpp @@ -159,7 +159,7 @@ namespace Util } } - if (REL::Module::IsVR()) + if (globals::game::isVR) macros.push_back({ "VR", "" }); if (globals::state->IsDeveloperMode()) { macros.push_back({ "D3DCOMPILE_SKIP_OPTIMIZATION", "" }); diff --git a/src/Utils/D3D.h b/src/Utils/D3D.h index eef88de3f0..896cb8fe90 100644 --- a/src/Utils/D3D.h +++ b/src/Utils/D3D.h @@ -20,12 +20,12 @@ namespace Util // VR-aware counts for render targets inline int GetRenderTargetCount() { - return REL::Module::IsVR() ? RE::RENDER_TARGETS::kVRTOTAL : RE::RENDER_TARGETS::kTOTAL; + return globals::game::isVR ? RE::RENDER_TARGETS::kVRTOTAL : RE::RENDER_TARGETS::kTOTAL; } inline int GetDepthStencilCount() { - return REL::Module::IsVR() ? RE::RENDER_TARGETS_DEPTHSTENCIL::kVRTOTAL : RE::RENDER_TARGETS_DEPTHSTENCIL::kTOTAL; + return globals::game::isVR ? RE::RENDER_TARGETS_DEPTHSTENCIL::kVRTOTAL : RE::RENDER_TARGETS_DEPTHSTENCIL::kTOTAL; } HRESULT SaveTextureToFile(ID3D11Device* device, ID3D11DeviceContext* context, const std::filesystem::path& path, ID3D11Texture2D* tex); diff --git a/src/Utils/Game.cpp b/src/Utils/Game.cpp index 31900f417c..f9f7872779 100644 --- a/src/Utils/Game.cpp +++ b/src/Utils/Game.cpp @@ -96,7 +96,7 @@ namespace Util RE::NiPoint3 GetAverageEyePosition() { auto shadowState = globals::game::shadowState; - if (!REL::Module::IsVR()) + if (!globals::game::isVR) return shadowState->GetRuntimeData().posAdjust.getEye(); return (shadowState->GetVRRuntimeData().posAdjust.getEye(0) + shadowState->GetVRRuntimeData().posAdjust.getEye(1)) * 0.5f; } @@ -104,7 +104,7 @@ namespace Util RE::NiPoint3 GetEyePosition(int eyeIndex) { auto shadowState = globals::game::shadowState; - if (!REL::Module::IsVR()) + if (!globals::game::isVR) return shadowState->GetRuntimeData().posAdjust.getEye(); return shadowState->GetVRRuntimeData().posAdjust.getEye(eyeIndex); } @@ -112,7 +112,7 @@ namespace Util RE::BSGraphics::ViewData GetCameraData(int eyeIndex) { auto shadowState = globals::game::shadowState; - if (!REL::Module::IsVR()) { + if (!globals::game::isVR) { return shadowState->GetRuntimeData().cameraData.getEye(); } return shadowState->GetVRRuntimeData().cameraData.getEye(eyeIndex); @@ -135,7 +135,7 @@ namespace Util bool GetTemporal() { auto imageSpaceManager = RE::ImageSpaceManager::GetSingleton(); - return (!REL::Module::IsVR() ? imageSpaceManager->GetRuntimeData().BSImagespaceShaderISTemporalAA->taaEnabled : imageSpaceManager->GetVRRuntimeData().BSImagespaceShaderISTemporalAA->taaEnabled); + return (!globals::game::isVR ? imageSpaceManager->GetRuntimeData().BSImagespaceShaderISTemporalAA->taaEnabled : imageSpaceManager->GetVRRuntimeData().BSImagespaceShaderISTemporalAA->taaEnabled); } float GetVerticalFOVRad() diff --git a/src/Utils/Game.h b/src/Utils/Game.h index 83f620cdc7..130d9d3b60 100644 --- a/src/Utils/Game.h +++ b/src/Utils/Game.h @@ -12,7 +12,8 @@ @param a_source The instance of the class (e.g., state). @result The a_value will be set as a variable in the current namespace. (e.g., auto& renderTargets = state->renderTargets;) */ -#define GET_INSTANCE_MEMBER(a_value, a_source) \ +#define GET_INSTANCE_MEMBER(a_value, a_source) \ + /* Keep raw runtime check: this macro can be used before globals::ReInit(). */ \ auto& a_value = !REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value; /** @@ -25,7 +26,8 @@ @param a_source The instance of the class (e.g., state). @result The a_value will be returned as a refptr. (e.g., &state->renderTargets;) */ -#define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ +#define GET_INSTANCE_MEMBER_PTR(a_value, a_source) \ + /* Keep raw runtime check: this macro can be used before globals::ReInit(). */ \ &(!REL::Module::IsVR() ? a_source->GetRuntimeData().a_value : a_source->GetVRRuntimeData().a_value) namespace Util diff --git a/src/Utils/UI.cpp b/src/Utils/UI.cpp index f105e48e1f..cbb50b1c58 100644 --- a/src/Utils/UI.cpp +++ b/src/Utils/UI.cpp @@ -1805,7 +1805,7 @@ namespace Util } } - if (hasVRInput && REL::Module::IsVR()) { + if (hasVRInput && globals::game::isVR) { return InputCombo::GetVRString(combo); } @@ -2346,7 +2346,7 @@ namespace Util } // Draw VR-specific color coding if applicable - if (REL::Module::IsVR() && !combo.empty()) { + if (globals::game::isVR && !combo.empty()) { ImGui::SameLine(); // Check if we have mixed devices diff --git a/src/XSEPlugin.cpp b/src/XSEPlugin.cpp index 44b94558c8..db89fb661d 100644 --- a/src/XSEPlugin.cpp +++ b/src/XSEPlugin.cpp @@ -145,7 +145,7 @@ bool Load() return true; } - if (REL::Module::IsVR()) { + if (REL::Module::IsVR()) { // Pre-ReInit check; globals::game::isVR not populated yet REL::IDDatabase::get().IsVRAddressLibraryAtLeastVersion("0.207.0", true); } @@ -199,7 +199,7 @@ bool Load() }; // Engine Fixes: VR accepts either EngineFixesVR.dll or the EngineFixes.dll NG - if (REL::Module::IsVR()) { + if (globals::game::isVR) { if (!LoadLibrary(L"Data/SKSE/Plugins/EngineFixesVR.dll") && !LoadLibrary(L"Data/SKSE/Plugins/EngineFixes.dll")) { pushMissingDllError("EngineFixesVR.dll or EngineFixes.dll"); }