Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion features/Upscaling/Shaders/Features/Upscaling.ini
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
[Info]
Version = 1-0-0
Version = 1-1-0
Binary file not shown.
27 changes: 0 additions & 27 deletions features/Upscaling/Shaders/Upscaling/XeSS/LICENSE.txt

This file was deleted.

Binary file not shown.
97 changes: 75 additions & 22 deletions src/Features/Upscaling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(
Upscaling::Settings,
upscaleMethod,
upscaleMethodNoDLSS,
qualityMode,
frameLimitMode,
frameGenerationMode,
Expand Down Expand Up @@ -166,6 +167,8 @@ void Upscaling::DrawSettings()
availableModes = 2; // Add FSR
if (featureDLSS)
availableModes = 3; // Add DLSS if available
else
currentUpscaleMode = &settings.upscaleMethodNoDLSS;

// Slider for method selection
// Clamp the index used to read from the built label vector to avoid OOB if the stored value is stale
Expand Down Expand Up @@ -203,6 +206,12 @@ void Upscaling::DrawSettings()
if (baseLabel) {
ImGui::SliderInt("Upscale Preset", (int*)&settings.qualityMode, 0, 4, baseLabel);
}

if (upscaleMethod == UpscaleMethod::kFSR) {
ImGui::SliderFloat("Sharpness", &settings.sharpnessFSR, 0.0f, 1.0f, "%.1f");
} else if (upscaleMethod == UpscaleMethod::kDLSS) {
ImGui::SliderFloat("Sharpness", &settings.sharpnessDLSS, 0.0f, 1.0f, "%.1f");
}
}
} else {
ImGui::Text("Upscaling from lower resolutions is not currently available for VR");
Expand Down Expand Up @@ -415,28 +424,28 @@ void Upscaling::PostPostLoad()

Upscaling::UpscaleMethod Upscaling::GetUpscaleMethod()
{
settings.upscaleMethod = std::clamp(settings.upscaleMethod, (uint)UpscaleMethod::kNONE, (uint)UpscaleMethod::kDLSS);
settings.qualityMode = std::clamp(settings.qualityMode, 0u, 4u);
return (UpscaleMethod)settings.upscaleMethod;
if (streamline.featureDLSS)
return (UpscaleMethod)settings.upscaleMethod;
return (UpscaleMethod)settings.upscaleMethodNoDLSS;
}

void Upscaling::CreateUpscalingTextureResources(UpscaleMethod a_upscalemethod)
{
logger::debug("[Upscaling] Creating texture resources for method {}", (int)a_upscalemethod);

if (a_upscalemethod == UpscaleMethod::kDLSS || a_upscalemethod == UpscaleMethod::kFSR) {
auto renderer = globals::game::renderer;
auto& main = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kMAIN];
auto renderer = globals::game::renderer;
auto& main = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kMAIN];

D3D11_TEXTURE2D_DESC texDesc{};
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
D3D11_TEXTURE2D_DESC texDesc{};
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};
main.texture->GetDesc(&texDesc);
main.SRV->GetDesc(&srvDesc);
main.UAV->GetDesc(&uavDesc);

main.texture->GetDesc(&texDesc);
main.SRV->GetDesc(&srvDesc);
main.UAV->GetDesc(&uavDesc);
texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;

texDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
if (a_upscalemethod == UpscaleMethod::kDLSS || a_upscalemethod == UpscaleMethod::kFSR) {
texDesc.Format = DXGI_FORMAT_R8_UNORM;
srvDesc.Format = texDesc.Format;
uavDesc.Format = texDesc.Format;
Expand All @@ -457,24 +466,29 @@ void Upscaling::CreateUpscalingTextureResources(UpscaleMethod a_upscalemethod)
// Motion vector copy texture is only needed for DLSS
if (a_upscalemethod == UpscaleMethod::kDLSS) {
if (!motionVectorCopyTexture) {
auto renderer = globals::game::renderer;
auto& motionVector = renderer->GetRuntimeData().renderTargets[RE::RENDER_TARGETS::kMOTION_VECTOR];

D3D11_TEXTURE2D_DESC motionTexDesc{};
D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
D3D11_UNORDERED_ACCESS_VIEW_DESC uavDesc = {};

motionVector.texture->GetDesc(&motionTexDesc);
motionVector.SRV->GetDesc(&srvDesc);
motionVector.UAV->GetDesc(&uavDesc);

srvDesc.Format = motionTexDesc.Format;
uavDesc.Format = motionTexDesc.Format;
texDesc.Format = motionTexDesc.Format;
srvDesc.Format = texDesc.Format;
uavDesc.Format = texDesc.Format;

motionVectorCopyTexture = new Texture2D(motionTexDesc);
motionVectorCopyTexture->CreateSRV(srvDesc);
motionVectorCopyTexture->CreateUAV(uavDesc);
}

if (!nisSharpenerTexture) {
texDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
srvDesc.Format = texDesc.Format;
uavDesc.Format = texDesc.Format;

nisSharpenerTexture = new Texture2D(texDesc);
nisSharpenerTexture->CreateSRV(srvDesc);
nisSharpenerTexture->CreateUAV(uavDesc);
}
}
}

Expand Down Expand Up @@ -514,6 +528,14 @@ void Upscaling::DestroyUpscalingTextureResources(UpscaleMethod a_upscalemethod)
delete motionVectorCopyTexture;
motionVectorCopyTexture = nullptr;
}
if (nisSharpenerTexture) {
nisSharpenerTexture->srv = nullptr;
nisSharpenerTexture->uav = nullptr;
nisSharpenerTexture->resource = nullptr;

delete nisSharpenerTexture;
nisSharpenerTexture = nullptr;
}
}
}

Expand Down Expand Up @@ -1196,7 +1218,7 @@ void Upscaling::Upscale()
if (upscaleMethod == UpscaleMethod::kDLSS) {
streamline.Upscale(main.texture, reactiveMaskTexture->resource.get(), transparencyCompositionMaskTexture->resource.get(), motionVectorCopyTexture->resource.get());
} else if (upscaleMethod == UpscaleMethod::kFSR) {
fidelityFX.Upscale(main.texture, reactiveMaskTexture->resource.get(), transparencyCompositionMaskTexture->resource.get(), motionVector.texture);
fidelityFX.Upscale(main.texture, reactiveMaskTexture->resource.get(), transparencyCompositionMaskTexture->resource.get(), motionVector.texture, settings.sharpnessFSR);
}

state->EndPerfEvent();
Expand Down Expand Up @@ -1328,6 +1350,34 @@ void Upscaling::UpscaleDepth()
}
}

void Upscaling::ApplyNISSharpening()
{
if (!streamline.featureNIS || settings.sharpnessDLSS <= 0.0f) {
return;
}

auto context = globals::d3d::context;

ID3D11RenderTargetView* renderTarget = nullptr;
context->OMGetRenderTargets(1, &renderTarget, nullptr);

winrt::com_ptr<ID3D11Resource> mainResource;
renderTarget->GetResource(mainResource.put());

context->OMSetRenderTargets(0, nullptr, nullptr); // Unbind all bound render targets

context->CopyResource(nisSharpenerTexture->resource.get(), mainResource.get());

streamline.ApplyNISSharpening(nisSharpenerTexture->resource.get(), settings.sharpnessDLSS);

context->CopyResource(mainResource.get(), nisSharpenerTexture->resource.get());

globals::game::stateUpdateFlags->set(RE::BSGraphics::ShaderFlags::DIRTY_RENDERTARGET); // Run OMSetRenderTargets again

if (renderTarget)
renderTarget->Release();
}

void Upscaling::Main_UpdateJitter::thunk(RE::BSGraphics::State* a_state)
{
globals::features::upscaling.ConfigureTAA();
Expand Down Expand Up @@ -1359,6 +1409,9 @@ void Upscaling::Main_PostProcessing::thunk(RE::ImageSpaceManager* a1, uint32_t a

func(a1, a3, er8_);

if (upscaleMethod == UpscaleMethod::kDLSS)
upscaling.ApplyNISSharpening();

// Disable TAA in some menus
BSImagespaceShaderISTemporalAA->taaEnabled = false;
}
Expand Down
8 changes: 7 additions & 1 deletion src/Features/Upscaling.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ struct Upscaling : Feature

struct Settings
{
uint upscaleMethod = (uint)UpscaleMethod::kTAA;
uint upscaleMethod = (uint)UpscaleMethod::kDLSS;
uint upscaleMethodNoDLSS = (uint)UpscaleMethod::kFSR;
uint qualityMode = 1; // Default to Quality (1=Quality, 2=Balanced, 3=Performance, 4=Ultra Performance, 0=Native AA)
uint frameLimitMode = 1;
uint frameGenerationMode = 1;
uint frameGenerationForceEnable = 0;
uint streamlineLogLevel = 0; // 0=Off, 1=Default, 2=Verbose
float sharpnessFSR = 1.0f;
float sharpnessDLSS = 0.1f;
};

Settings settings;
Expand Down Expand Up @@ -134,6 +137,7 @@ struct Upscaling : Feature
Texture2D* reactiveMaskTexture = nullptr;
Texture2D* transparencyCompositionMaskTexture = nullptr;
Texture2D* motionVectorCopyTexture = nullptr;
Texture2D* nisSharpenerTexture = nullptr;

virtual void ClearShaderCache() override;

Expand All @@ -155,6 +159,8 @@ struct Upscaling : Feature
void PerformUpscaling();
void UpscaleDepth();

void ApplyNISSharpening();

static void TimerSleepQPC(int64_t targetQPC);

void FrameLimiter();
Expand Down
4 changes: 2 additions & 2 deletions src/Features/Upscaling/FidelityFX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -263,7 +263,7 @@ FfxResource ffxGetResource(ID3D11Resource* dx11Resource,
return resource;
}

void FidelityFX::Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_reactiveMask, ID3D11Resource* a_transparencyCompositionMask, ID3D11Resource* a_motionVectors)
void FidelityFX::Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_reactiveMask, ID3D11Resource* a_transparencyCompositionMask, ID3D11Resource* a_motionVectors, float a_sharpness)
{
auto renderer = globals::game::renderer;
auto context = globals::d3d::context;
Expand Down Expand Up @@ -302,7 +302,7 @@ void FidelityFX::Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_r
dispatchParameters.cameraNear = *globals::game::cameraNear;

dispatchParameters.enableSharpening = true;
dispatchParameters.sharpness = 0.0f;
dispatchParameters.sharpness = a_sharpness;

dispatchParameters.cameraFovAngleVertical = Util::GetVerticalFOVRad();
dispatchParameters.viewSpaceToMetersFactor = 0.01428222656f;
Expand Down
2 changes: 1 addition & 1 deletion src/Features/Upscaling/FidelityFX.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ class FidelityFX

float GetInputResolutionScale(uint32_t outputWidth, uint32_t outputHeight, uint32_t qualityMode);

void Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_reactiveMask, ID3D11Resource* a_transparencyCompositionMask, ID3D11Resource* a_motionVectors);
void Upscale(ID3D11Resource* a_upscalingTexture, ID3D11Resource* a_reactiveMask, ID3D11Resource* a_transparencyCompositionMask, ID3D11Resource* a_motionVectors, float a_sharpness);

private:
// FSR scratch buffer - needs to be freed in DestroyFSRResources
Expand Down
61 changes: 59 additions & 2 deletions src/Features/Upscaling/Streamline.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,8 +102,8 @@ void Streamline::LoadInterposer()

sl::Preferences pref;

sl::Feature featuresToLoad[] = { sl::kFeatureDLSS };
sl::Feature featuresToLoadVR[] = { sl::kFeatureDLSS };
sl::Feature featuresToLoad[] = { sl::kFeatureDLSS, sl::kFeatureNIS };
sl::Feature featuresToLoadVR[] = { sl::kFeatureDLSS, sl::kFeatureNIS };

pref.featuresToLoad = REL::Module::IsVR() ? featuresToLoadVR : featuresToLoad;
pref.numFeaturesToLoad = REL::Module::IsVR() ? _countof(featuresToLoadVR) : _countof(featuresToLoad);
Expand Down Expand Up @@ -181,7 +181,21 @@ void Streamline::CheckFeatures(IDXGIAdapter* a_adapter)
}
}

slIsFeatureLoaded(sl::kFeatureNIS, featureNIS);
if (featureNIS) {
logger::info("[Streamline] NIS feature is loaded");
featureNIS = 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] NIS {} available", featureNIS ? "is" : "is not");
}

void Streamline::PostDevice()
Expand All @@ -193,6 +207,11 @@ void Streamline::PostDevice()
slGetFeatureFunction(sl::kFeatureDLSS, "slDLSSGetState", (void*&)slDLSSGetState);
slGetFeatureFunction(sl::kFeatureDLSS, "slDLSSSetOptions", (void*&)slDLSSSetOptions);
}

if (featureNIS) {
slGetFeatureFunction(sl::kFeatureNIS, "slNISSetOptions", (void*&)slNISSetOptions);
slGetFeatureFunction(sl::kFeatureNIS, "slNISGetState", (void*&)slNISGetState);
}
}

/**
Expand Down Expand Up @@ -394,4 +413,42 @@ void Streamline::DestroyDLSSResources()
dlssOptions.mode = sl::DLSSMode::eOff;
slDLSSSetOptions(viewport, dlssOptions);
slFreeResources(sl::kFeatureDLSS, viewport);
}

void Streamline::ApplyNISSharpening(ID3D11Resource* a_texture, float sharpness)
{
if (!featureNIS) {
return;
}

CheckFrameConstants();

sl::NISOptions nisOptions{};
nisOptions.mode = sl::NISMode::eSharpen;
nisOptions.sharpness = std::clamp(sharpness, 0.0f, 1.0f);
nisOptions.hdrMode = sl::NISHDR::eNone;
Comment thread
doodlum marked this conversation as resolved.

if (SL_FAILED(result, slNISSetOptions(viewport, nisOptions))) {
logger::error("[Streamline] Could not set NIS options");
return;
}

auto state = globals::state;
sl::Extent fullExtent{ 0, 0, (uint)state->screenSize.x, (uint)state->screenSize.y };

sl::Resource colorIn = { sl::ResourceType::eTex2d, a_texture, 0 };
sl::Resource colorOut = { sl::ResourceType::eTex2d, a_texture, 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::ViewportHandle view(viewport);
const sl::BaseStructure* inputs[] = { &view };
if (SL_FAILED(result, slEvaluateFeature(sl::kFeatureNIS, *frameToken, inputs, _countof(inputs), globals::d3d::context))) {
logger::error("[Streamline] Failed to evaluate NIS feature");
}
}
8 changes: 8 additions & 0 deletions src/Features/Upscaling/Streamline.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
#include <sl_consts.h>
#include <sl_dlss.h>
#include <sl_matrix_helpers.h>
#include <sl_nis.h>
#include <sl_version.h>
#pragma warning(pop)

Expand All @@ -31,6 +32,7 @@ class Streamline
bool triedInitialization = false;

bool featureDLSS = false;
bool featureNIS = false;

sl::ViewportHandle viewport{ 0 };

Expand Down Expand Up @@ -60,6 +62,10 @@ class Streamline
PFun_slDLSSGetState* slDLSSGetState{};
PFun_slDLSSSetOptions* slDLSSSetOptions{};

// NIS specific functions
PFun_slNISSetOptions* slNISSetOptions{};
PFun_slNISGetState* slNISGetState{};

Util::FrameChecker frameChecker;
sl::FrameToken* frameToken = nullptr;

Expand All @@ -79,4 +85,6 @@ class Streamline
float GetInputResolutionScale(uint32_t outputWidth, uint32_t outputHeight, uint32_t qualityPreset);

void DestroyDLSSResources();

void ApplyNISSharpening(ID3D11Resource* a_texture, float sharpness);
};