From 0595f258d89863ab2272fa8ccb315fffbb4b78f2 Mon Sep 17 00:00:00 2001 From: doodlum <15017472+doodlum@users.noreply.github.com> Date: Mon, 15 Sep 2025 17:51:07 +0100 Subject: [PATCH 1/7] fix: use GeometrySetupConstantPointLights hook to fix perf --- src/Hooks.cpp | 66 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) diff --git a/src/Hooks.cpp b/src/Hooks.cpp index f7f527a079..641f4a4b15 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -793,14 +793,76 @@ namespace Hooks PatchMemory(Address, Data.begin(), Data.size()); } + void GeometrySetupConstantPointLights(RE::BSRenderPass* Pass, uint32_t LightCount, uint32_t ShadowLightCount) + { + auto shadowState = globals::game::shadowState; + + // Constant buffer indices based on HLSL PerGeometry definition + const uint32_t pointLightPositionIndex = globals::game::isVR ? 27 : 15; // c27 for VR, c15 for non-VR + const uint32_t pointLightColorIndex = globals::game::isVR ? 41 : 22; // c41 for VR, c22 for non-VR + const uint32_t shadowLightMaskSelectIndex = globals::game::isVR ? 14 : 2; // c14 for VR, c2 for non-VR + + for (uint32_t i = 0; i < LightCount && i < 7; i++) { + if (auto bsLight = Pass->sceneLights[i + 1]) { + if (auto niLight = bsLight->light.get()) { + auto& runtimeData = niLight->GetLightRuntimeData(); + + float intensity = runtimeData.fade * bsLight->lodDimmer; + float colorR = runtimeData.diffuse.red * intensity; + float colorG = runtimeData.diffuse.green * intensity; + float colorB = runtimeData.diffuse.blue * intensity; + + if (globals::game::isVR) { + auto posAdjustLeft = shadowState->GetRuntimeData().posAdjust.getEye(0); + auto posAdjustRight = shadowState->GetRuntimeData().posAdjust.getEye(1); + + RE::NiPoint3 worldPosLeft = niLight->world.translate - posAdjustLeft; + RE::NiPoint3 worldPosRight = niLight->world.translate - posAdjustRight; + + // Set point light position (xyz = position, w = radius) + std::array pointLightPosition = { worldPosLeft.x, worldPosLeft.y, worldPosLeft.z, runtimeData.radius.x }; + shadowState->SetPSConstant(pointLightPosition, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + i * 2); + pointLightPosition = { worldPosRight.x, worldPosRight.y, worldPosRight.z, runtimeData.radius.x }; + shadowState->SetPSConstant(pointLightPosition, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + 1 + i * 2); + + } else { + auto posAdjust = shadowState->GetRuntimeData().posAdjust.getEye(0); + RE::NiPoint3 worldPos = niLight->world.translate - posAdjust; + + // Set point light position (xyz = position, w = radius) + std::array pointLightPosition = { worldPos.x, worldPos.y, worldPos.z, runtimeData.radius.x }; + shadowState->SetPSConstant(pointLightPosition, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + i); + } + + // Set point light color + std::array pointLightColor = { colorR, colorG, colorB, 1.0f }; + shadowState->SetPSConstant(pointLightColor, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightColorIndex + i); + } + } + } + + // Set shadow light mask select for shadow-casting lights + if (ShadowLightCount > 0) { + std::array shadowLightMaskSelect = { 0.0f, 0.0f, 0.0f, 0.0f }; + for (uint32_t i = 0; i < ShadowLightCount && i < 4; i++) { + if (auto bsLight = Pass->sceneLights[i + 1]) { + auto* shadowLight = static_cast(bsLight); + GET_INSTANCE_MEMBER(shadowLightIndex, shadowLight); + shadowLightMaskSelect[i] = static_cast(shadowLightIndex); + } + } + shadowState->SetPSConstant(shadowLightMaskSelect, RE::BSGraphics::ConstantGroupLevel::PerGeometry, shadowLightMaskSelectIndex); + } + } + struct BSLightingShader_SetupGeometry_GeometrySetupConstantPointLights { - static void thunk(RE::BSGraphics::PixelShader* PixelShader, RE::BSRenderPass* Pass, DirectX::XMMATRIX& Transform, uint32_t LightCount, uint32_t ShadowLightCount, float WorldScale, uint32_t) + static void thunk(RE::BSGraphics::PixelShader*, RE::BSRenderPass* Pass, DirectX::XMMATRIX&, uint32_t LightCount, uint32_t ShadowLightCount, float, uint32_t) { if (globals::features::lightLimitFix.loaded) globals::features::lightLimitFix.BSLightingShader_SetupGeometry_GeometrySetupConstantPointLights(Pass); else - func(PixelShader, Pass, Transform, LightCount, ShadowLightCount, WorldScale, 0); + GeometrySetupConstantPointLights(Pass, LightCount, ShadowLightCount); } static inline REL::Relocation func; }; From b7df12ae8424b82cba810078edf10ba77659f582 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 16:59:08 +0000 Subject: [PATCH 2/7] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20pre-commit.?= =?UTF-8?q?ci=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automated formatting by clang-format, prettier, and other hooks. See https://pre-commit.ci for details. --- src/Hooks.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 641f4a4b15..34c78597d8 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -798,9 +798,9 @@ namespace Hooks auto shadowState = globals::game::shadowState; // Constant buffer indices based on HLSL PerGeometry definition - const uint32_t pointLightPositionIndex = globals::game::isVR ? 27 : 15; // c27 for VR, c15 for non-VR - const uint32_t pointLightColorIndex = globals::game::isVR ? 41 : 22; // c41 for VR, c22 for non-VR - const uint32_t shadowLightMaskSelectIndex = globals::game::isVR ? 14 : 2; // c14 for VR, c2 for non-VR + const uint32_t pointLightPositionIndex = globals::game::isVR ? 27 : 15; // c27 for VR, c15 for non-VR + const uint32_t pointLightColorIndex = globals::game::isVR ? 41 : 22; // c41 for VR, c22 for non-VR + const uint32_t shadowLightMaskSelectIndex = globals::game::isVR ? 14 : 2; // c14 for VR, c2 for non-VR for (uint32_t i = 0; i < LightCount && i < 7; i++) { if (auto bsLight = Pass->sceneLights[i + 1]) { @@ -815,7 +815,7 @@ namespace Hooks if (globals::game::isVR) { auto posAdjustLeft = shadowState->GetRuntimeData().posAdjust.getEye(0); auto posAdjustRight = shadowState->GetRuntimeData().posAdjust.getEye(1); - + RE::NiPoint3 worldPosLeft = niLight->world.translate - posAdjustLeft; RE::NiPoint3 worldPosRight = niLight->world.translate - posAdjustRight; From 1be0ffeae05a1f9668e8b3586a53b0c19b36e2b3 Mon Sep 17 00:00:00 2001 From: doodlum <15017472+doodlum@users.noreply.github.com> Date: Mon, 15 Sep 2025 18:29:02 +0100 Subject: [PATCH 3/7] fix: more fixes --- .../Shaders/Upscaling/EncodeTexturesCS.hlsl | 3 +- src/Features/Upscaling.cpp | 54 +------------------ src/Features/Upscaling/DX12SwapChain.cpp | 2 +- 3 files changed, 4 insertions(+), 55 deletions(-) diff --git a/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl b/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl index 1f6c93aac7..a10fc08681 100644 --- a/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl +++ b/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl @@ -48,10 +48,11 @@ RWTexture2D MotionVectorOutput : register(u2); float neighborDepth = DepthMask[samplePos]; -#if defined(DLSS) || defined(XESS) // Take neighbor if it's longer AND closer if (neighborDepth < depth){ taaMask.x = min(taaMask.x, TAAMask[samplePos].x); + +#if defined(DLSS) || defined(XESS) float2 neighborMotionVector = MotionVectorMask[samplePos]; diff --git a/src/Features/Upscaling.cpp b/src/Features/Upscaling.cpp index 17fd038a14..cfb6b2ee91 100644 --- a/src/Features/Upscaling.cpp +++ b/src/Features/Upscaling.cpp @@ -58,9 +58,6 @@ HRESULT WINAPI hk_D3D11CreateDeviceAndSwapChainUpscaling( if (!globals::game::isVR) { // Use better swap effect to prevent tearing and improve performance pSwapChainDesc->SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; - - // Set new more precise format - pSwapChainDesc->BufferDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; } bool shouldProxy = !globals::game::isVR; @@ -380,49 +377,6 @@ void Upscaling::Load() *(uintptr_t*)&ptrD3D11CreateDeviceAndSwapChainUpscaling = SKSE::PatchIAT(hk_D3D11CreateDeviceAndSwapChainUpscaling, "d3d11.dll", "D3D11CreateDeviceAndSwapChain"); } -struct CreateRenderTarget_LDR1 -{ - static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) - { - RE::BSGraphics::RenderTargetProperties properties = *a_properties; - properties.format.set(RE::BSGraphics::Format::kR10G10B10A2_UNORM); - func(This, a_target, &properties); - } - static inline REL::Relocation func; -}; - -struct CreateRenderTarget_LDR2 -{ - static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) - { - RE::BSGraphics::RenderTargetProperties properties = *a_properties; - properties.format.set(RE::BSGraphics::Format::kR10G10B10A2_UNORM); - func(This, a_target, &properties); - } - static inline REL::Relocation func; -}; - -struct CreateRenderTarget_LDR3 -{ - static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) - { - RE::BSGraphics::RenderTargetProperties properties = *a_properties; - properties.format.set(RE::BSGraphics::Format::kR10G10B10A2_UNORM); - func(This, a_target, &properties); - } - static inline REL::Relocation func; -}; - -struct CreateRenderTarget_LDR4 -{ - static void thunk(RE::BSGraphics::Renderer* This, RE::RENDER_TARGETS::RENDER_TARGET a_target, RE::BSGraphics::RenderTargetProperties* a_properties) - { - RE::BSGraphics::RenderTargetProperties properties = *a_properties; - properties.format.set(RE::BSGraphics::Format::kR10G10B10A2_UNORM); - func(This, a_target, &properties); - } - static inline REL::Relocation func; -}; void Upscaling::PostPostLoad() { bool isGOG = !GetModuleHandle(L"steam_api64.dll"); @@ -438,12 +392,6 @@ void Upscaling::PostPostLoad() stl::write_thunk_call(REL::RelocationID(100430, 107148).address() + REL::Relocate(0x1F0, 0x1E7, 0x206)); if (!REL::Module::IsVR()) { - // Patches render target creation to use higher precision format - stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x529, 0x528)); - stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0xB2E, 0xB2E)); - stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x62F, 0x62E)); - stl::write_thunk_call(REL::RelocationID(100458, 107175).address() + REL::Relocate(0x642, 0x641)); - // Patches RSSetScissorRect calls to use dynamic resolution // This is a PC-specific function hence it was missing stl::detour_thunk(REL::RelocationID(75564, 77365)); @@ -857,7 +805,7 @@ void Upscaling::SetupResources() // Create NIS sharpener texture with swapchain format and UAV access D3D11_TEXTURE2D_DESC nisTexDesc = texDesc; - nisTexDesc.Format = DXGI_FORMAT_R10G10B10A2_UNORM; + nisTexDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; nisTexDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS; D3D11_SHADER_RESOURCE_VIEW_DESC nisSrvDesc = srvDesc; diff --git a/src/Features/Upscaling/DX12SwapChain.cpp b/src/Features/Upscaling/DX12SwapChain.cpp index b816fc145a..608e9df3ce 100644 --- a/src/Features/Upscaling/DX12SwapChain.cpp +++ b/src/Features/Upscaling/DX12SwapChain.cpp @@ -86,7 +86,7 @@ void DX12SwapChain::CreateInterop() swapChainBufferWrapped = new WrappedResource(texDesc11, d3d11Device.get(), upscaling.sharedD3D12Device.get()); - texDesc11.Format = DXGI_FORMAT_R16G16B16A16_UNORM; + texDesc11.Format = DXGI_FORMAT_R8G8B8A8_UNORM; uiBufferWrapped = new WrappedResource(texDesc11, d3d11Device.get(), upscaling.sharedD3D12Device.get()); } From 4d25d987d672fbf59982206b79a7bb60919d0c6e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 17:36:48 +0000 Subject: [PATCH 4/7] =?UTF-8?q?style:=20=F0=9F=8E=A8=20apply=20pre-commit.?= =?UTF-8?q?ci=20formatting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Automated formatting by clang-format, prettier, and other hooks. See https://pre-commit.ci for details. --- features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl b/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl index a10fc08681..58c2318c51 100644 --- a/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl +++ b/features/Upscaling/Shaders/Upscaling/EncodeTexturesCS.hlsl @@ -51,7 +51,7 @@ RWTexture2D MotionVectorOutput : register(u2); // Take neighbor if it's longer AND closer if (neighborDepth < depth){ taaMask.x = min(taaMask.x, TAAMask[samplePos].x); - + #if defined(DLSS) || defined(XESS) float2 neighborMotionVector = MotionVectorMask[samplePos]; From 7bdedb1a48b35ecbcfb7c87c1cd94bf2704ded22 Mon Sep 17 00:00:00 2001 From: doodlum <15017472+doodlum@users.noreply.github.com> Date: Mon, 15 Sep 2025 19:56:29 +0100 Subject: [PATCH 5/7] fix: high ssgi --- src/Features/ScreenSpaceGI.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Features/ScreenSpaceGI.cpp b/src/Features/ScreenSpaceGI.cpp index 89d21452e2..8fb7057cdc 100644 --- a/src/Features/ScreenSpaceGI.cpp +++ b/src/Features/ScreenSpaceGI.cpp @@ -113,19 +113,19 @@ void ScreenSpaceGI::DrawSettings() recompileFlag = true; } if (auto _tt = Util::HoverTooltipWrapper()) - ImGui::Text("Quarter res and somewhat stable."); + ImGui::Text("Half res and somewhat stable."); ImGui::TableNextColumn(); - if (ImGui::Button("High", { -1, 0 })) { + if (ImGui::Button("Extreme", { -1, 0 })) { settings.NumSlices = 4; settings.NumSteps = 8; - settings.ResolutionMode = 1; + settings.ResolutionMode = 0; settings.EnableBlur = true; settings.EnableGI = true; recompileFlag = true; } if (auto _tt = Util::HoverTooltipWrapper()) - ImGui::Text("Half res and clean."); + ImGui::Text("Full res and clean."); ImGui::TableNextColumn(); if (ImGui::Button("Reference", { -1, 0 })) { From 09362c493e4ca8efc4f250e02898eb9ce42fad7f Mon Sep 17 00:00:00 2001 From: doodlum <15017472+doodlum@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:49:15 +0100 Subject: [PATCH 6/7] fix: deferred interior check --- src/Deferred.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Deferred.cpp b/src/Deferred.cpp index 5a1aecc18c..03c842529d 100644 --- a/src/Deferred.cpp +++ b/src/Deferred.cpp @@ -409,11 +409,8 @@ void Deferred::DeferredPasses() auto motionVectors = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kMOTION_VECTOR]; bool interior = true; - if (auto player = RE::PlayerCharacter::GetSingleton()) { - if (auto parentCell = player->GetParentCell()) { - interior = parentCell->IsInteriorCell(); - } - } + if (auto sky = globals::game::sky) + interior = sky->mode.get() != RE::Sky::Mode::kFull; auto& skylighting = globals::features::skylighting; From 09686b507d3206b95979cfde7e2db16aeee113d4 Mon Sep 17 00:00:00 2001 From: doodlum <15017472+doodlum@users.noreply.github.com> Date: Mon, 15 Sep 2025 21:49:57 +0100 Subject: [PATCH 7/7] chore: remove light change --- src/Hooks.cpp | 66 ++------------------------------------------------- 1 file changed, 2 insertions(+), 64 deletions(-) diff --git a/src/Hooks.cpp b/src/Hooks.cpp index 34c78597d8..f7f527a079 100644 --- a/src/Hooks.cpp +++ b/src/Hooks.cpp @@ -793,76 +793,14 @@ namespace Hooks PatchMemory(Address, Data.begin(), Data.size()); } - void GeometrySetupConstantPointLights(RE::BSRenderPass* Pass, uint32_t LightCount, uint32_t ShadowLightCount) - { - auto shadowState = globals::game::shadowState; - - // Constant buffer indices based on HLSL PerGeometry definition - const uint32_t pointLightPositionIndex = globals::game::isVR ? 27 : 15; // c27 for VR, c15 for non-VR - const uint32_t pointLightColorIndex = globals::game::isVR ? 41 : 22; // c41 for VR, c22 for non-VR - const uint32_t shadowLightMaskSelectIndex = globals::game::isVR ? 14 : 2; // c14 for VR, c2 for non-VR - - for (uint32_t i = 0; i < LightCount && i < 7; i++) { - if (auto bsLight = Pass->sceneLights[i + 1]) { - if (auto niLight = bsLight->light.get()) { - auto& runtimeData = niLight->GetLightRuntimeData(); - - float intensity = runtimeData.fade * bsLight->lodDimmer; - float colorR = runtimeData.diffuse.red * intensity; - float colorG = runtimeData.diffuse.green * intensity; - float colorB = runtimeData.diffuse.blue * intensity; - - if (globals::game::isVR) { - auto posAdjustLeft = shadowState->GetRuntimeData().posAdjust.getEye(0); - auto posAdjustRight = shadowState->GetRuntimeData().posAdjust.getEye(1); - - RE::NiPoint3 worldPosLeft = niLight->world.translate - posAdjustLeft; - RE::NiPoint3 worldPosRight = niLight->world.translate - posAdjustRight; - - // Set point light position (xyz = position, w = radius) - std::array pointLightPosition = { worldPosLeft.x, worldPosLeft.y, worldPosLeft.z, runtimeData.radius.x }; - shadowState->SetPSConstant(pointLightPosition, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + i * 2); - pointLightPosition = { worldPosRight.x, worldPosRight.y, worldPosRight.z, runtimeData.radius.x }; - shadowState->SetPSConstant(pointLightPosition, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + 1 + i * 2); - - } else { - auto posAdjust = shadowState->GetRuntimeData().posAdjust.getEye(0); - RE::NiPoint3 worldPos = niLight->world.translate - posAdjust; - - // Set point light position (xyz = position, w = radius) - std::array pointLightPosition = { worldPos.x, worldPos.y, worldPos.z, runtimeData.radius.x }; - shadowState->SetPSConstant(pointLightPosition, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightPositionIndex + i); - } - - // Set point light color - std::array pointLightColor = { colorR, colorG, colorB, 1.0f }; - shadowState->SetPSConstant(pointLightColor, RE::BSGraphics::ConstantGroupLevel::PerGeometry, pointLightColorIndex + i); - } - } - } - - // Set shadow light mask select for shadow-casting lights - if (ShadowLightCount > 0) { - std::array shadowLightMaskSelect = { 0.0f, 0.0f, 0.0f, 0.0f }; - for (uint32_t i = 0; i < ShadowLightCount && i < 4; i++) { - if (auto bsLight = Pass->sceneLights[i + 1]) { - auto* shadowLight = static_cast(bsLight); - GET_INSTANCE_MEMBER(shadowLightIndex, shadowLight); - shadowLightMaskSelect[i] = static_cast(shadowLightIndex); - } - } - shadowState->SetPSConstant(shadowLightMaskSelect, RE::BSGraphics::ConstantGroupLevel::PerGeometry, shadowLightMaskSelectIndex); - } - } - struct BSLightingShader_SetupGeometry_GeometrySetupConstantPointLights { - static void thunk(RE::BSGraphics::PixelShader*, RE::BSRenderPass* Pass, DirectX::XMMATRIX&, uint32_t LightCount, uint32_t ShadowLightCount, float, uint32_t) + static void thunk(RE::BSGraphics::PixelShader* PixelShader, RE::BSRenderPass* Pass, DirectX::XMMATRIX& Transform, uint32_t LightCount, uint32_t ShadowLightCount, float WorldScale, uint32_t) { if (globals::features::lightLimitFix.loaded) globals::features::lightLimitFix.BSLightingShader_SetupGeometry_GeometrySetupConstantPointLights(Pass); else - GeometrySetupConstantPointLights(Pass, LightCount, ShadowLightCount); + func(PixelShader, Pass, Transform, LightCount, ShadowLightCount, WorldScale, 0); } static inline REL::Relocation func; };