diff --git a/package/SKSE/Plugins/Streamline/sl.nis.dll b/package/SKSE/Plugins/Streamline/sl.nis.dll new file mode 100644 index 0000000000..4b47ea0f92 Binary files /dev/null and b/package/SKSE/Plugins/Streamline/sl.nis.dll differ diff --git a/package/Shaders/Upscaling/EncodeTexturesCS.hlsl b/package/Shaders/Upscaling/EncodeTexturesCS.hlsl index c301089fc6..10344c2fbd 100644 --- a/package/Shaders/Upscaling/EncodeTexturesCS.hlsl +++ b/package/Shaders/Upscaling/EncodeTexturesCS.hlsl @@ -6,7 +6,7 @@ RWTexture2D AlphaMask : register(u0); : SV_DispatchThreadID) { float2 taaMask = TAAMask[dispatchID.xy]; - float alphaMask = taaMask.x * 0.5; + float alphaMask = taaMask.x * 0.25; #if defined(DLSS) alphaMask = lerp(alphaMask, 1.0, taaMask.y > 0.0); diff --git a/src/State.cpp b/src/State.cpp index 22c2fac289..24e250ac0e 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -707,12 +707,12 @@ void State::UpdateSharedData(bool a_inWorld, bool a_prepass) else data.InMapMenu = true; - auto renderSize = Util::ConvertToDynamic(screenSize); - - if (a_inWorld || a_prepass) - data.MipBias = bTAA ? std::log2f(renderSize.x / screenSize.x) - 1.0f : 0.0f; - else + if (!globals::game::isVR && bTAA && (a_inWorld || a_prepass)) { + auto renderSize = Util::ConvertToDynamic(screenSize); + data.MipBias = std::log2f(renderSize.x / screenSize.x) - 1.0f; + } else { data.MipBias = 0; + } sharedDataCB->Update(data); } diff --git a/src/Streamline.cpp b/src/Streamline.cpp index b7e8c96c10..8428707406 100644 --- a/src/Streamline.cpp +++ b/src/Streamline.cpp @@ -72,7 +72,7 @@ void Streamline::Initialize() sl::Preferences pref; - sl::Feature featuresToLoad[] = { sl::kFeatureDLSS, sl::kFeatureDLSS_G, sl::kFeatureReflex }; + sl::Feature featuresToLoad[] = { sl::kFeatureDLSS, sl::kFeatureDLSS_G, sl::kFeatureReflex, sl::kFeatureNIS }; pref.featuresToLoad = featuresToLoad; pref.numFeaturesToLoad = _countof(featuresToLoad); @@ -136,6 +136,11 @@ void Streamline::PostDevice(DXGI_SWAP_CHAIN_DESC* a_swapChainDesc) slGetFeatureFunction(sl::kFeatureReflex, "slReflexSetOptions", (void*&)slReflexSetOptions); } + if (featureNIS) { + slGetFeatureFunction(sl::kFeatureNIS, "slNISSetOptions", (void*&)slNISSetOptions); + slGetFeatureFunction(sl::kFeatureNIS, "slNISGetState", (void*&)slNISGetState); + } + MONITORINFOEX monitorInfo = {}; monitorInfo.cbSize = sizeof(MONITORINFOEX); @@ -219,9 +224,23 @@ HRESULT Streamline::CreateDeviceAndSwapChain(IDXGIAdapter* pAdapter, } } + slIsFeatureLoaded(sl::kFeatureNIS, featureNIS); + if (featureReflex) { + logger::info("[Streamline] NIS feature is loaded"); + featureReflex = slIsFeatureSupported(sl::kFeatureNIS, adapterInfo) == sl::Result::eOk; + } else { + logger::info("[Streamline] NIS feature is not loaded"); + sl::FeatureRequirements featureRequirements; + sl::Result result = slGetFeatureRequirements(sl::kFeatureNIS, featureRequirements); + if (result != sl::Result::eOk) { + logger::info("[Streamline] NIS feature failed to load due to: {}", magic_enum::enum_name(result)); + } + } + logger::info("[Streamline] DLSS {} available", featureDLSS ? "is" : "is not"); logger::info("[Streamline] DLSSG {} available", featureDLSSG && !REL::Module::IsVR() ? "is" : "is not"); logger::info("[Streamline] Reflex {} available", featureReflex ? "is" : "is not"); + logger::info("[Streamline] NIS {} available", featureNIS ? "is" : "is not"); HRESULT hr = S_OK; @@ -454,7 +473,7 @@ void Streamline::Present() slSetTag(viewport, inputs, _countof(inputs), globals::d3d::context); } -void Streamline::Upscale(Texture2D* a_upscaleTexture, Texture2D* a_alphaMask, sl::DLSSPreset a_preset) +void Streamline::Upscale(Texture2D* a_upscaleTexture, Texture2D* a_alphaMask, sl::DLSSPreset a_preset, float a_sharpness) { UpdateConstants(); @@ -515,6 +534,68 @@ void Streamline::Upscale(Texture2D* a_upscaleTexture, Texture2D* a_alphaMask, sl sl::ViewportHandle view(viewport); const sl::BaseStructure* inputs[] = { &view }; slEvaluateFeature(sl::kFeatureDLSS, *frameToken, inputs, _countof(inputs), globals::d3d::context); + + { + sl::Extent fullExtent{ 0, 0, (uint)state->screenSize.x, (uint)state->screenSize.y }; + + sl::Resource colorIn = { sl::ResourceType::eTex2d, a_upscaleTexture->resource.get(), 0 }; + sl::Resource colorOut = { sl::ResourceType::eTex2d, a_upscaleTexture->resource.get(), 0 }; + + sl::ResourceTag colorInTag = sl::ResourceTag{ &colorIn, sl::kBufferTypeScalingInputColor, sl::ResourceLifecycle::eOnlyValidNow, &fullExtent }; + sl::ResourceTag colorOutTag = sl::ResourceTag{ &colorOut, sl::kBufferTypeScalingOutputColor, sl::ResourceLifecycle::eOnlyValidNow, &fullExtent }; + + sl::ResourceTag resourceTags[] = { colorInTag, colorOutTag }; + slSetTag(viewport, resourceTags, _countof(resourceTags), globals::d3d::context); + } + + { + sl::NISOptions nisOptions{}; + nisOptions.mode = sl::NISMode::eSharpen; + nisOptions.hdrMode = sl::NISHDR::eNone; + nisOptions.sharpness = a_sharpness / 3.0f; + + if (SL_FAILED(result, slNISSetOptions(viewport, nisOptions))) { + logger::critical("[Streamline] Could not set NIS options"); + } + } + + slEvaluateFeature(sl::kFeatureNIS, *frameToken, inputs, _countof(inputs), globals::d3d::context); +} + +void Streamline::Sharpen(Texture2D* a_sharpenTexture, float a_sharpness) +{ + UpdateConstants(); + + auto state = globals::state; + + { + sl::Extent fullExtent{ 0, 0, (uint)state->screenSize.x, (uint)state->screenSize.y }; + + sl::Resource colorIn = { sl::ResourceType::eTex2d, a_sharpenTexture->resource.get(), 0 }; + sl::Resource colorOut = { sl::ResourceType::eTex2d, a_sharpenTexture->resource.get(), 0 }; + + sl::ResourceTag colorInTag = sl::ResourceTag{ &colorIn, sl::kBufferTypeScalingInputColor, sl::ResourceLifecycle::eOnlyValidNow, &fullExtent }; + sl::ResourceTag colorOutTag = sl::ResourceTag{ &colorOut, sl::kBufferTypeScalingOutputColor, sl::ResourceLifecycle::eOnlyValidNow, &fullExtent }; + + sl::ResourceTag resourceTags[] = { colorInTag, colorOutTag }; + slSetTag(viewport, resourceTags, _countof(resourceTags), globals::d3d::context); + } + + { + sl::NISOptions nisOptions{}; + nisOptions.mode = sl::NISMode::eSharpen; + nisOptions.hdrMode = sl::NISHDR::eNone; + nisOptions.sharpness = a_sharpness * 0.5f; + + if (SL_FAILED(result, slNISSetOptions(viewport, nisOptions))) { + logger::critical("[Streamline] Could not set NIS options"); + } + } + + sl::ViewportHandle view(viewport); + const sl::BaseStructure* inputs[] = { &view }; + + slEvaluateFeature(sl::kFeatureNIS, *frameToken, inputs, _countof(inputs), globals::d3d::context); } void Streamline::UpdateConstants() diff --git a/src/Streamline.h b/src/Streamline.h index 3b7a7ad68c..01404999e7 100644 --- a/src/Streamline.h +++ b/src/Streamline.h @@ -6,6 +6,7 @@ #include #include #include +#include #include class Streamline @@ -25,6 +26,7 @@ class Streamline bool featureDLSS = false; bool featureDLSSG = false; bool featureReflex = false; + bool featureNIS = false; double refreshRate = 60.0; @@ -75,6 +77,10 @@ class Streamline PFun_slReflexSleep* slReflexSleep{}; PFun_slReflexSetOptions* slReflexSetOptions{}; + // NIS specific functions + PFun_slNISSetOptions* slNISSetOptions{}; + PFun_slNISGetState* slNISGetState{}; + Texture2D* colorBufferShared; Texture2D* depthBufferShared; @@ -106,7 +112,8 @@ class Streamline void CopyResourcesToSharedBuffers(); void Present(); - void Upscale(Texture2D* a_color, Texture2D* a_alphaMask, sl::DLSSPreset a_preset); + void Upscale(Texture2D* a_color, Texture2D* a_alphaMask, sl::DLSSPreset a_preset, float a_sharpness); + void Sharpen(Texture2D* a_sharpenTexture, float a_sharpness); void UpdateConstants(); void SaveSettings(json& o_json); diff --git a/src/Upscaling.cpp b/src/Upscaling.cpp index 6a90665151..a4f0602fa4 100644 --- a/src/Upscaling.cpp +++ b/src/Upscaling.cpp @@ -295,7 +295,7 @@ void Upscaling::Upscale() context->CopyResource(upscalingTexture->resource.get(), inputTextureResource); if (upscaleMethod == UpscaleMethod::kDLSS) - globals::streamline->Upscale(upscalingTexture, alphaMaskTexture, (sl::DLSSPreset)settings.dlssPreset); + globals::streamline->Upscale(upscalingTexture, alphaMaskTexture, (sl::DLSSPreset)settings.dlssPreset, settings.sharpness); else if (upscaleMethod == UpscaleMethod::kFSR) FidelityFX::GetSingleton()->Upscale(upscalingTexture, alphaMaskTexture, jitter, reset, settings.sharpness); @@ -304,37 +304,6 @@ void Upscaling::Upscale() state->EndPerfEvent(); } - if (upscaleMethod != UpscaleMethod::kFSR && settings.sharpness > 0.0f) { - state->BeginPerfEvent("Sharpening"); - - context->CopyResource(inputTextureResource, upscalingTexture->resource.get()); - - { - { - ID3D11ShaderResourceView* views[1] = { inputTextureSRV }; - context->CSSetShaderResources(0, ARRAYSIZE(views), views); - - ID3D11UnorderedAccessView* uavs[1] = { upscalingTexture->uav.get() }; - context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr); - - context->CSSetShader(GetRCASCS(), nullptr, 0); - - context->Dispatch(dispatchCount.x, dispatchCount.y, 1); - } - - ID3D11ShaderResourceView* views[1] = { nullptr }; - context->CSSetShaderResources(0, ARRAYSIZE(views), views); - - ID3D11UnorderedAccessView* uavs[1] = { nullptr }; - context->CSSetUnorderedAccessViews(0, ARRAYSIZE(uavs), uavs, nullptr); - - ID3D11ComputeShader* shader = nullptr; - context->CSSetShader(shader, nullptr, 0); - } - - state->EndPerfEvent(); - } - context->CopyResource(outputTextureResource, upscalingTexture->resource.get()); } @@ -347,11 +316,6 @@ void Upscaling::SharpenTAA() auto state = globals::state; auto context = globals::d3d::context; - ID3D11ShaderResourceView* inputTextureSRV; - context->PSGetShaderResources(0, 1, &inputTextureSRV); - - inputTextureSRV->Release(); - ID3D11RenderTargetView* outputTextureRTV; ID3D11DepthStencilView* dsv; context->OMGetRenderTargets(1, &outputTextureRTV, &dsv); @@ -362,9 +326,6 @@ void Upscaling::SharpenTAA() if (dsv) dsv->Release(); - ID3D11Resource* inputTextureResource; - inputTextureSRV->GetResource(&inputTextureResource); - ID3D11Resource* outputTextureResource; outputTextureRTV->GetResource(&outputTextureResource); @@ -372,9 +333,19 @@ void Upscaling::SharpenTAA() state->BeginPerfEvent("Sharpening"); - context->CopyResource(inputTextureResource, outputTextureResource); + if (globals::streamline->featureNIS) { + context->CopyResource(upscalingTexture->resource.get(), outputTextureResource); + globals::streamline->Sharpen(upscalingTexture, settings.sharpness); + } else { + ID3D11ShaderResourceView* inputTextureSRV; + context->PSGetShaderResources(0, 1, &inputTextureSRV); + inputTextureSRV->Release(); + + ID3D11Resource* inputTextureResource; + inputTextureSRV->GetResource(&inputTextureResource); + + context->CopyResource(inputTextureResource, outputTextureResource); - { { ID3D11ShaderResourceView* views[1] = { inputTextureSRV }; context->CSSetShaderResources(0, ARRAYSIZE(views), views); diff --git a/src/Upscaling.h b/src/Upscaling.h index f79897aad5..478d832f00 100644 --- a/src/Upscaling.h +++ b/src/Upscaling.h @@ -42,7 +42,7 @@ class Upscaling : public RE::BSTEventSink uint upscaleMethodNoDLSS = (uint)UpscaleMethod::kTAA; uint upscaleMethodNoFSR = (uint)UpscaleMethod::kTAA; float sharpness = 0.5f; - uint dlssPreset = (uint)sl::DLSSPreset::ePresetC; + uint dlssPreset = (uint)sl::DLSSPreset::ePresetE; }; Settings settings;