diff --git a/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp index 9b1b702147034a782d5c7f63674ff0304d090d04..f10b23ec029a88bd56e8e5fa78ebdbdd502e1e14 100644 --- a/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp @@ -10,11 +10,69 @@ namespace vkcv::upscaling { -/** + /** * @addtogroup vkcv_upscaling * @{ */ + /** + * Enum to set the mode of quality for + * FSR2 upscaling. + */ + enum class FSR2QualityMode : int { + /** + * Don't upscale anything. + */ + NONE = 0, + + /** + * High quality of FSR upscaling: + * 1.5x per dimension + */ + QUALITY = 2, + + /** + * Medium quality of FSR upscaling: + * 1.7x per dimension + */ + BALANCED = 3, + + /** + * Low quality of FSR upscaling: + * 2.0x per dimension + */ + PERFORMANCE = 4, + + /** + * Lowest quality of FSR upscaling: + * 3.0x per dimension + */ + ULTRA_PERFORMANCE = 5, + }; + + /** + * Calculates the internal resolution for actual rendering if + * a specific mode of quality is used for upscaling with FSR2. + * + * @param[in] mode Mode of quality + * @param[in] outputWidth Final resolution width + * @param[in] outputHeight Final resolution height + * @param[out] inputWidth Internal resolution width + * @param[out] inputHeight Internal resolution height + */ + void getFSR2Resolution(FSR2QualityMode mode, + uint32_t outputWidth, uint32_t outputHeight, + uint32_t &inputWidth, uint32_t &inputHeight); + + /** + * Returns the matching negative lod bias to reduce artifacts + * upscaling with FSR2 under a given mode of quality. + * + * @param mode Mode of quality + * @return Lod bias + */ + float getFSR2LodBias(FSR2QualityMode mode); + /** * A class to handle upscaling via FidelityFX Super Resolution. * https://github.com/GPUOpen-Effects/FidelityFX-FSR2 @@ -29,6 +87,8 @@ namespace vkcv::upscaling { ImageHandle m_depth; ImageHandle m_velocity; + uint32_t m_frameIndex; + float m_frameDeltaTime; bool m_reset; @@ -83,6 +143,20 @@ namespace vkcv::upscaling { */ void update(float deltaTime, bool reset = false); + /** + * Calculates the jitter offset for the projection + * matrix of the camera to use in the current frame. + * + * @param[in] renderWidth Render resolution width + * @param[in] renderHeight Render resolution height + * @param[out] jitterOffsetX Jitter offset x-coordinate + * @param[out] jitterOffsetY Jitter offset y-coordinate + */ + void calcJitterOffset(uint32_t renderWidth, + uint32_t renderHeight, + float& jitterOffsetX, + float& jitterOffsetY); + /** * Bind the depth buffer image to use with the FSR2 * upscaling instance for utilizing depth information. diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp index ee2572da2d01a8234f03ced018704b48686e1a9b..5330c063f29a647e9d1a48d0d5b8e21dc2213bc2 100644 --- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp @@ -45,12 +45,6 @@ namespace vkcv::upscaling { * 2.0x per dimension */ PERFORMANCE = 4, - - /** - * Lowest quality of FSR upscaling: - * 3.0x per dimension - */ - ULTRA_PERFORMANCE = 5, }; /** diff --git a/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp index 4ef213e3d89ba57f7be6958a8d74a49a8c4cf4bd..d3b7b6c5b484c5943884576eb7c21f88640a9c1a 100644 --- a/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp +++ b/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp @@ -1,12 +1,61 @@ #include "vkcv/upscaling/FSR2Upscaling.hpp" +#include <cmath> + #define FFX_GCC #include <ffx_fsr2_vk.h> #undef FFX_GCC namespace vkcv::upscaling { + void getFSR2Resolution(FSR2QualityMode mode, + uint32_t outputWidth, uint32_t outputHeight, + uint32_t &inputWidth, uint32_t &inputHeight) { + float scale; + + switch (mode) { + case FSR2QualityMode::QUALITY: + scale = 1.5f; + break; + case FSR2QualityMode::BALANCED: + scale = 1.7f; + break; + case FSR2QualityMode::PERFORMANCE: + scale = 2.0f; + break; + case FSR2QualityMode::ULTRA_PERFORMANCE: + scale = 3.0f; + break; + default: + scale = 1.0f; + break; + } + + inputWidth = static_cast<uint32_t>( + std::round(static_cast<float>(outputWidth) / scale) + ); + + inputHeight = static_cast<uint32_t>( + std::round(static_cast<float>(outputHeight) / scale) + ); + } + + float getFSR2LodBias(FSR2QualityMode mode) { + switch (mode) { + case FSR2QualityMode::QUALITY: + return -1.58f; + case FSR2QualityMode::BALANCED: + return -1.76f; + case FSR2QualityMode::PERFORMANCE: + return -2.0f; + case FSR2QualityMode::ULTRA_PERFORMANCE: + return -2.58f; + default: + return 0.0f; + } + } + void FSR2Upscaling::createFSR2Context(uint32_t displayWidth, uint32_t displayHeight, uint32_t renderWidth, @@ -30,6 +79,8 @@ namespace vkcv::upscaling { m_core.getContext().getDevice().waitIdle(); assert(ffxFsr2ContextDestroy(&m_context) == FFX_OK); + + m_frameIndex = 0; } FSR2Upscaling::FSR2Upscaling(Core &core) : Upscaling(core) { @@ -60,10 +111,33 @@ namespace vkcv::upscaling { } void FSR2Upscaling::update(float deltaTime, bool reset) { + if (reset) { + m_frameIndex = 0; + } + m_frameDeltaTime = deltaTime; m_reset = reset; } + void FSR2Upscaling::calcJitterOffset(uint32_t renderWidth, + uint32_t renderHeight, + float &jitterOffsetX, + float &jitterOffsetY) { + const int32_t phaseCount = ffxFsr2GetJitterPhaseCount( + renderWidth, + renderHeight + ); + + const int32_t phaseIndex = (static_cast<int32_t>(m_frameIndex) % phaseCount); + + assert(ffxFsr2GetJitterOffset( + &jitterOffsetX, + &jitterOffsetY, + phaseIndex, + phaseCount + ) == FFX_OK); + } + void FSR2Upscaling::bindDepthBuffer(const ImageHandle &depthInput) { m_depth = depthInput; } @@ -166,11 +240,15 @@ namespace vkcv::upscaling { static_cast<VkFormat>(m_core.getImageFormat(output)) ); - dispatch.jitterOffset.x = 0; - dispatch.jitterOffset.y = 0; + calcJitterOffset( + inputWidth, + inputHeight, + dispatch.jitterOffset.x, + dispatch.jitterOffset.y + ); - dispatch.motionVectorScale.x = 0; - dispatch.motionVectorScale.y = 0; + dispatch.motionVectorScale.x = static_cast<float>(inputWidth); + dispatch.motionVectorScale.y = static_cast<float>(inputHeight); dispatch.renderSize.width = inputWidth; dispatch.renderSize.height = inputHeight; @@ -194,6 +272,7 @@ namespace vkcv::upscaling { &dispatch ) == FFX_OK); + m_frameIndex++; m_reset = false; }); } diff --git a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp index 2f37765e270c342a7aea3d52d37f1c9d4828cd89..d9ca8d9f0429960f1d43c074fb58ac6d79f6e677 100644 --- a/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp +++ b/modules/upscaling/src/vkcv/upscaling/FSRUpscaling.cpp @@ -36,9 +36,6 @@ namespace vkcv::upscaling { case FSRQualityMode::PERFORMANCE: scale = 2.0f; break; - case FSRQualityMode::ULTRA_PERFORMANCE: - scale = 3.0f; - break; default: scale = 1.0f; break; @@ -63,8 +60,6 @@ namespace vkcv::upscaling { return -0.79f; case FSRQualityMode::PERFORMANCE: return -1.0f; - case FSRQualityMode::ULTRA_PERFORMANCE: - return -2.0f; default: return 0.0f; }