Persist upscaling mode and refine FSR2 jitter behavior

This commit is contained in:
Kelsi 2026-03-08 20:22:11 -07:00
parent 6fd1c94d99
commit a12126cc7e
3 changed files with 21 additions and 20 deletions

View file

@ -117,6 +117,7 @@ private:
bool pendingPOM = true; // on by default
int pendingPOMQuality = 1; // 0=Low(16), 1=Medium(32), 2=High(64)
bool pendingFSR = false;
int pendingUpscalingMode = 0; // 0=Off, 1=FSR1, 2=FSR2
int pendingFSRQuality = 0; // 0=UltraQuality, 1=Quality, 2=Balanced, 3=Performance
float pendingFSRSharpness = 0.5f;
bool fsrSettingsApplied_ = false;

View file

@ -1205,9 +1205,7 @@ void Renderer::endFrame() {
renderFSR2Sharpen();
// Maintain frame bookkeeping
fsr2_.prevViewProjection = fsr2_.useAmdBackend
? camera->getUnjitteredViewProjectionMatrix()
: camera->getViewProjectionMatrix();
fsr2_.prevViewProjection = camera->getViewProjectionMatrix();
fsr2_.prevJitter = camera->getJitter();
camera->clearJitter();
if (fsr2_.useAmdBackend) {
@ -3826,9 +3824,7 @@ bool Renderer::initFSR2Resources() {
fsr2_.amdScratchBufferSize = 0;
} else {
FfxFsr2ContextDescription ctxDesc{};
// AMD path uses unjittered reprojection matrices for motion vectors.
// Keep jitter cancellation off to avoid double compensation jitter.
ctxDesc.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE;
ctxDesc.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE | FFX_FSR2_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION;
ctxDesc.maxRenderSize.width = fsr2_.internalWidth;
ctxDesc.maxRenderSize.height = fsr2_.internalHeight;
ctxDesc.displaySize.width = swapExtent.width;
@ -4187,17 +4183,14 @@ void Renderer::dispatchMotionVectors() {
vkCmdBindDescriptorSets(currentCmd, VK_PIPELINE_BIND_POINT_COMPUTE,
fsr2_.motionVecPipelineLayout, 0, 1, &fsr2_.motionVecDescSet, 0, nullptr);
// Reprojection matrices:
// AMD path uses unjittered matrices (FSR handles jitter via desc.jitterOffset).
// Internal fallback keeps existing jittered behavior.
// Reprojection with jittered matrices:
// reconstruct world position from current depth, then project into previous clip.
struct {
glm::mat4 prevViewProjection;
glm::mat4 invCurrentViewProj;
} pc;
glm::mat4 currentVP = fsr2_.useAmdBackend
? camera->getUnjitteredViewProjectionMatrix()
: camera->getViewProjectionMatrix();
glm::mat4 currentVP = camera->getViewProjectionMatrix();
pc.prevViewProjection = fsr2_.prevViewProjection;
pc.invCurrentViewProj = glm::inverse(currentVP);

View file

@ -317,18 +317,17 @@ void GameScreen::render(game::GameHandler& gameHandler) {
}
}
// Apply saved FSR setting once when renderer is available
if (!fsrSettingsApplied_ && pendingFSR) {
// Apply saved upscaling setting once when renderer is available
if (!fsrSettingsApplied_) {
auto* renderer = core::Application::getInstance().getRenderer();
if (renderer) {
static const float fsrScales[] = { 0.77f, 0.67f, 0.59f, 0.50f };
renderer->setFSRQuality(fsrScales[pendingFSRQuality]);
renderer->setFSRSharpness(pendingFSRSharpness);
renderer->setFSREnabled(true);
renderer->setFSREnabled(pendingUpscalingMode == 1);
renderer->setFSR2Enabled(pendingUpscalingMode == 2);
fsrSettingsApplied_ = true;
}
} else {
fsrSettingsApplied_ = true;
}
// Apply auto-loot setting to GameHandler every frame (cheap bool sync)
@ -6300,9 +6299,9 @@ void GameScreen::renderSettingsWindow() {
{
// FSR mode selection: Off, FSR 1.0 (Spatial), FSR 2.2 (Temporal)
const char* fsrModeLabels[] = { "Off", "FSR 1.0 (Spatial)", "FSR 2.2 (Temporal)" };
int fsrMode = pendingFSR ? 1 : 0;
if (renderer && renderer->isFSR2Enabled()) fsrMode = 2;
int fsrMode = pendingUpscalingMode;
if (ImGui::Combo("Upscaling", &fsrMode, fsrModeLabels, 3)) {
pendingUpscalingMode = fsrMode;
pendingFSR = (fsrMode == 1);
if (renderer) {
renderer->setFSREnabled(fsrMode == 1);
@ -7441,6 +7440,7 @@ void GameScreen::saveSettings() {
out << "normal_map_strength=" << pendingNormalMapStrength << "\n";
out << "pom=" << (pendingPOM ? 1 : 0) << "\n";
out << "pom_quality=" << pendingPOMQuality << "\n";
out << "upscaling_mode=" << pendingUpscalingMode << "\n";
out << "fsr=" << (pendingFSR ? 1 : 0) << "\n";
out << "fsr_quality=" << pendingFSRQuality << "\n";
out << "fsr_sharpness=" << pendingFSRSharpness << "\n";
@ -7530,7 +7530,14 @@ void GameScreen::loadSettings() {
else if (key == "normal_map_strength") pendingNormalMapStrength = std::clamp(std::stof(val), 0.0f, 2.0f);
else if (key == "pom") pendingPOM = (std::stoi(val) != 0);
else if (key == "pom_quality") pendingPOMQuality = std::clamp(std::stoi(val), 0, 2);
else if (key == "fsr") pendingFSR = (std::stoi(val) != 0);
else if (key == "upscaling_mode") {
pendingUpscalingMode = std::clamp(std::stoi(val), 0, 2);
pendingFSR = (pendingUpscalingMode == 1);
} else if (key == "fsr") {
pendingFSR = (std::stoi(val) != 0);
// Backward compatibility: old configs only had fsr=0/1.
if (pendingUpscalingMode == 0 && pendingFSR) pendingUpscalingMode = 1;
}
else if (key == "fsr_quality") pendingFSRQuality = std::clamp(std::stoi(val), 0, 3);
else if (key == "fsr_sharpness") pendingFSRSharpness = std::clamp(std::stof(val), 0.0f, 2.0f);
// Controls