Skip to content
Snippets Groups Projects
Verified Commit 880b06c4 authored by Tobias Frisch's avatar Tobias Frisch
Browse files

Add FSR2 to the upscaling module

parent 866262dd
Branches
Tags
1 merge request!107Resolve "Include FSR 2.0 in the upscaling module"
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
.editorconfig .editorconfig
# build directories # build directories
bin/
build/ build/
cmake-build-debug/ cmake-build-debug/
cmake-build-release/ cmake-build-release/
......
...@@ -40,3 +40,6 @@ ...@@ -40,3 +40,6 @@
[submodule "modules/algorithm/lib/FidelityFX-SPD"] [submodule "modules/algorithm/lib/FidelityFX-SPD"]
path = modules/algorithm/lib/FidelityFX-SPD path = modules/algorithm/lib/FidelityFX-SPD
url = https://github.com/GPUOpen-Effects/FidelityFX-SPD.git url = https://github.com/GPUOpen-Effects/FidelityFX-SPD.git
[submodule "modules/upscaling/lib/FidelityFX-FSR2"]
path = modules/upscaling/lib/FidelityFX-FSR2
url = https://github.com/TheJackiMonster/FidelityFX-FSR2.git
...@@ -20,6 +20,9 @@ set(vkcv_upscaling_sources ...@@ -20,6 +20,9 @@ set(vkcv_upscaling_sources
${vkcv_upscaling_include}/vkcv/upscaling/NISUpscaling.hpp ${vkcv_upscaling_include}/vkcv/upscaling/NISUpscaling.hpp
${vkcv_upscaling_source}/vkcv/upscaling/NISUpscaling.cpp ${vkcv_upscaling_source}/vkcv/upscaling/NISUpscaling.cpp
${vkcv_upscaling_include}/vkcv/upscaling/FSR2Upscaling.hpp
${vkcv_upscaling_source}/vkcv/upscaling/FSR2Upscaling.cpp
) )
# Setup some path variables to load libraries # Setup some path variables to load libraries
...@@ -29,6 +32,9 @@ set(vkcv_upscaling_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_upscaling_lib}) ...@@ -29,6 +32,9 @@ set(vkcv_upscaling_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_upscaling_lib})
# Check and load FidelityFX_FSR # Check and load FidelityFX_FSR
include(config/FidelityFX_FSR.cmake) include(config/FidelityFX_FSR.cmake)
# Check and load FidelityFX_FSR2
include(config/FidelityFX_FSR2.cmake)
# Check and load NVIDIAImageScaling # Check and load NVIDIAImageScaling
include(config/NVIDIAImageScaling.cmake) include(config/NVIDIAImageScaling.cmake)
......
use_git_submodule("${vkcv_upscaling_lib_path}/FidelityFX-FSR2" ffx_fsr2_status)
if (${ffx_fsr2_status})
set(FFX_FSR2_API_DX12 OFF CACHE INTERNAL "")
set(FFX_FSR2_API_VK ON CACHE INTERNAL "")
add_subdirectory(${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api)
list(APPEND vkcv_upscaling_libraries ${FFX_FSR2_API} ${FFX_FSR2_API_VK})
list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api)
list(APPEND vkcv_upscaling_includes ${vkcv_upscaling_lib}/FidelityFX-FSR2/src/ffx-fsr2-api/vk)
endif ()
#pragma once
#include "Upscaling.hpp"
#include <vector>
#define FFX_GCC
#include <ffx_fsr2.h>
#undef FFX_GCC
namespace vkcv::upscaling {
/**
* @addtogroup vkcv_upscaling
* @{
*/
/**
* A class to handle upscaling via FidelityFX Super Resolution.
* https://github.com/GPUOpen-Effects/FidelityFX-FSR2
*/
class FSR2Upscaling : public Upscaling {
private:
std::vector<char> m_scratchBuffer;
FfxFsr2ContextDescription m_description;
FfxFsr2Context m_context;
ImageHandle m_depth;
ImageHandle m_velocity;
float m_frameDeltaTime;
bool m_reset;
float m_near;
float m_far;
float m_fov;
/**
* Current state of HDR support.
*/
bool m_hdr;
/**
* Sharpness will improve the upscaled image quality with
* a factor between 0.0f for no sharpening and 1.0f for
* maximum sharpening.
*
* The default value for sharpness should be 0.875f.
*
* Beware that 0.0f or any negative value of sharpness will
* disable the sharpening pass completely.
*/
float m_sharpness;
void createFSR2Context(uint32_t displayWidth,
uint32_t displayHeight,
uint32_t renderWidth,
uint32_t renderHeight);
void destroyFSR2Context();
public:
/**
* Constructor to create an instance for FSR upscaling.
*
* @param[in,out] core Reference to a Core instance
*/
explicit FSR2Upscaling(Core& core);
/**
* Destructor to free the instance for FSR upscaling.
*/
~FSR2Upscaling();
/**
* Update the upscaling instance with current frame
* delta time and whether the temporal data needs to
* be reset (for example because the camera switched).
*
* @param[in] deltaTime Current frame delta time
* @param[in] reset Reset temporal frame data
*/
void update(float deltaTime, bool reset = false);
/**
* Bind the depth buffer image to use with the FSR2
* upscaling instance for utilizing depth information.
*
* @param[in] depthInput Depth input image handle
*/
void bindDepthBuffer(const ImageHandle& depthInput);
/**
* Bind the velocity buffer image to use with the FSR2
* upscaling instance for utilizing 2D motion vectors.
*
* @param[in] velocityInput Velocity input image handle
*/
void bindVelocityBuffer(const ImageHandle& velocityInput);
/**
* Record the comands of the FSR2 upscaling instance to
* scale the image of the input handle to the resolution of
* the output image handle via FidelityFX Super Resolution.
*
* @param[in] cmdStream Command stream handle to record commands
* @param[in] colorInput Color input image handle
* @param[in] output Output image handle
*/
void recordUpscaling(const CommandStreamHandle& cmdStream,
const ImageHandle& colorInput,
const ImageHandle& output) override;
/**
* Set the required camera values for the FSR2 upscaling
* instance including near- and far-plane as well as
* the FOV angle vertical.
*
* @param[in] near Camera near plane
* @param[in] far Camera far plane
* @param[in] fov Camera field of view angle vertical
*/
void setCamera(float near, float far, float fov);
/**
* Checks if HDR support is enabled and returns the status as boolean.
*
* @return true if HDR is supported, otherwise false
*/
[[nodiscard]]
bool isHdrEnabled() const;
/**
* Changes the status of HDR support of the FSR upscaling instance.
*
* @param[in] enabled New status of HDR support
*/
void setHdrEnabled(bool enabled);
/**
* Returns the amount of sharpness the FSR upscaling instance is using.
*
* @return The amount of sharpness
*/
[[nodiscard]]
float getSharpness() const;
/**
* Changes the amount of sharpness of the FSR upscaling instance.
* The new sharpness value is restricted by 0.0f as lower and 1.0f
* as upper boundary.
*
* @param[in] sharpness New sharpness value
*/
void setSharpness(float sharpness);
};
/** @} */
}
\ No newline at end of file
...@@ -44,7 +44,13 @@ namespace vkcv::upscaling { ...@@ -44,7 +44,13 @@ namespace vkcv::upscaling {
* Low quality of FSR upscaling: * Low quality of FSR upscaling:
* 2.0x per dimension * 2.0x per dimension
*/ */
PERFORMANCE = 4 PERFORMANCE = 4,
/**
* Lowest quality of FSR upscaling:
* 3.0x per dimension
*/
ULTRA_PERFORMANCE = 5,
}; };
/** /**
......
Subproject commit 0ce4ff5c5a0210273be7e3085bb4b15d0590431c
#include "vkcv/upscaling/FSR2Upscaling.hpp"
#define FFX_GCC
#include <ffx_fsr2_vk.h>
#undef FFX_GCC
namespace vkcv::upscaling {
void FSR2Upscaling::createFSR2Context(uint32_t displayWidth,
uint32_t displayHeight,
uint32_t renderWidth,
uint32_t renderHeight) {
m_description.displaySize.width = displayWidth;
m_description.displaySize.height = displayHeight;
m_description.maxRenderSize.width = renderWidth;
m_description.maxRenderSize.height = renderHeight;
m_description.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE;
if (m_hdr) {
m_description.flags |= FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE;
}
assert(ffxFsr2ContextCreate(&m_context, &m_description) == FFX_OK);
}
void FSR2Upscaling::destroyFSR2Context() {
m_core.getContext().getDevice().waitIdle();
assert(ffxFsr2ContextDestroy(&m_context) == FFX_OK);
}
FSR2Upscaling::FSR2Upscaling(Core &core) : Upscaling(core) {
const auto& physicalDevice = core.getContext().getPhysicalDevice();
memset(&m_description, 0, sizeof(m_description));
m_scratchBuffer.resize(ffxFsr2GetScratchMemorySizeVK(physicalDevice));
assert(ffxFsr2GetInterfaceVK(
&(m_description.callbacks),
m_scratchBuffer.data(),
m_scratchBuffer.size(),
physicalDevice,
vkGetDeviceProcAddr
) == FFX_OK);
m_description.device = ffxGetDeviceVK(core.getContext().getDevice());
createFSR2Context(0, 0, 0, 0);
}
FSR2Upscaling::~FSR2Upscaling() {
destroyFSR2Context();
m_scratchBuffer.clear();
m_description.callbacks.scratchBuffer = nullptr;
}
void FSR2Upscaling::update(float deltaTime, bool reset) {
m_frameDeltaTime = deltaTime;
m_reset = reset;
}
void FSR2Upscaling::bindDepthBuffer(const ImageHandle &depthInput) {
m_depth = depthInput;
}
void FSR2Upscaling::bindVelocityBuffer(const ImageHandle &velocityInput) {
m_velocity = velocityInput;
}
void FSR2Upscaling::recordUpscaling(const CommandStreamHandle &cmdStream, const ImageHandle &colorInput,
const ImageHandle &output) {
FfxFsr2DispatchDescription dispatch;
memset(&dispatch, 0, sizeof(dispatch));
const uint32_t inputWidth = m_core.getImageWidth(colorInput);
const uint32_t inputHeight = m_core.getImageHeight(colorInput);
const uint32_t outputWidth = m_core.getImageWidth(output);
const uint32_t outputHeight = m_core.getImageHeight(output);
if ((m_description.displaySize.width != outputWidth) ||
(m_description.displaySize.height != outputHeight) ||
(m_description.maxRenderSize.width < inputWidth) ||
(m_description.maxRenderSize.height < inputHeight) ||
(m_hdr != ((m_description.flags & FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE) != 0))) {
destroyFSR2Context();
createFSR2Context(
outputWidth,
outputHeight,
inputWidth,
inputHeight
);
}
const bool sharpeningEnabled = (
(m_sharpness > +0.0f) &&
((inputWidth < outputWidth) || (inputHeight < outputHeight))
);
dispatch.color = ffxGetTextureResourceVK(
&m_context,
m_core.getVulkanImage(colorInput),
m_core.getVulkanImageView(colorInput),
inputWidth,
inputHeight,
static_cast<VkFormat>(m_core.getImageFormat(colorInput))
);
dispatch.depth = ffxGetTextureResourceVK(
&m_context,
m_core.getVulkanImage(m_depth),
m_core.getVulkanImageView(m_depth),
m_core.getImageWidth(m_depth),
m_core.getImageHeight(m_depth),
static_cast<VkFormat>(m_core.getImageFormat(m_depth))
);
dispatch.motionVectors = ffxGetTextureResourceVK(
&m_context,
m_core.getVulkanImage(m_velocity),
m_core.getVulkanImageView(m_velocity),
m_core.getImageWidth(m_velocity),
m_core.getImageHeight(m_velocity),
static_cast<VkFormat>(m_core.getImageFormat(m_velocity))
);
dispatch.exposure = ffxGetTextureResourceVK(
&m_context,
nullptr,
nullptr,
1,
1,
VK_FORMAT_UNDEFINED
);
dispatch.reactive = ffxGetTextureResourceVK(
&m_context,
nullptr,
nullptr,
1,
1,
VK_FORMAT_UNDEFINED
);
dispatch.transparencyAndComposition = ffxGetTextureResourceVK(
&m_context,
nullptr,
nullptr,
1,
1,
VK_FORMAT_UNDEFINED
);
dispatch.output = ffxGetTextureResourceVK(
&m_context,
m_core.getVulkanImage(output),
m_core.getVulkanImageView(output),
outputWidth,
outputHeight,
static_cast<VkFormat>(m_core.getImageFormat(output))
);
dispatch.jitterOffset.x = 0;
dispatch.jitterOffset.y = 0;
dispatch.motionVectorScale.x = 0;
dispatch.motionVectorScale.y = 0;
dispatch.renderSize.width = inputWidth;
dispatch.renderSize.height = inputHeight;
dispatch.enableSharpening = sharpeningEnabled;
dispatch.sharpness = m_sharpness;
dispatch.frameTimeDelta = m_frameDeltaTime * 1000.0f; // from seconds to milliseconds
dispatch.preExposure = 1.0f;
dispatch.reset = m_reset;
dispatch.cameraNear = m_near;
dispatch.cameraFar = m_far;
dispatch.cameraFovAngleVertical = m_fov;
m_core.recordCommandsToStream(cmdStream, [&dispatch](const vk::CommandBuffer& cmdBuffer) {
dispatch.commandList = ffxGetCommandListVK(cmdBuffer);
}, [&]() {
assert(ffxFsr2ContextDispatch(
&m_context,
&dispatch
) == FFX_OK);
m_reset = false;
});
}
void FSR2Upscaling::setCamera(float near, float far, float fov) {
m_near = near;
m_far = far;
m_fov = fov;
}
bool FSR2Upscaling::isHdrEnabled() const {
return m_hdr;
}
void FSR2Upscaling::setHdrEnabled(bool enabled) {
m_hdr = enabled;
}
float FSR2Upscaling::getSharpness() const {
return m_sharpness;
}
void FSR2Upscaling::setSharpness(float sharpness) {
m_sharpness = (sharpness < 0.0f ? 0.0f : (sharpness > 1.0f ? 1.0f : sharpness));
}
}
\ No newline at end of file
...@@ -36,6 +36,9 @@ namespace vkcv::upscaling { ...@@ -36,6 +36,9 @@ namespace vkcv::upscaling {
case FSRQualityMode::PERFORMANCE: case FSRQualityMode::PERFORMANCE:
scale = 2.0f; scale = 2.0f;
break; break;
case FSRQualityMode::ULTRA_PERFORMANCE:
scale = 3.0f;
break;
default: default:
scale = 1.0f; scale = 1.0f;
break; break;
...@@ -60,6 +63,8 @@ namespace vkcv::upscaling { ...@@ -60,6 +63,8 @@ namespace vkcv::upscaling {
return -0.79f; return -0.79f;
case FSRQualityMode::PERFORMANCE: case FSRQualityMode::PERFORMANCE:
return -1.0f; return -1.0f;
case FSRQualityMode::ULTRA_PERFORMANCE:
return -2.0f;
default: default:
return 0.0f; return 0.0f;
} }
...@@ -333,7 +338,7 @@ namespace vkcv::upscaling { ...@@ -333,7 +338,7 @@ namespace vkcv::upscaling {
cmdStream, cmdStream,
m_easuPipeline, m_easuPipeline,
dispatch, dispatch,
{DescriptorSetUsage(0, m_easuDescriptorSet, { 0 })}, {vkcv::useDescriptorSet(0, m_easuDescriptorSet, { 0 })},
PushConstants(0) PushConstants(0)
); );
...@@ -353,7 +358,7 @@ namespace vkcv::upscaling { ...@@ -353,7 +358,7 @@ namespace vkcv::upscaling {
cmdStream, cmdStream,
m_rcasPipeline, m_rcasPipeline,
dispatch, dispatch,
{DescriptorSetUsage(0,m_rcasDescriptorSet, { 0 })}, {vkcv::useDescriptorSet(0,m_rcasDescriptorSet, { 0 })},
PushConstants(0) PushConstants(0)
); );
...@@ -371,7 +376,7 @@ namespace vkcv::upscaling { ...@@ -371,7 +376,7 @@ namespace vkcv::upscaling {
cmdStream, cmdStream,
m_easuPipeline, m_easuPipeline,
dispatch, dispatch,
{DescriptorSetUsage(0, m_easuDescriptorSet, { 0 })}, {vkcv::useDescriptorSet(0, m_easuDescriptorSet, { 0 })},
PushConstants(0) PushConstants(0)
); );
} }
......
...@@ -5,7 +5,10 @@ namespace vkcv { ...@@ -5,7 +5,10 @@ namespace vkcv {
DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet, DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet,
const std::vector<uint32_t> &dynamicOffsets) { const std::vector<uint32_t> &dynamicOffsets) {
DescriptorSetUsage usage(location, descriptorSet, dynamicOffsets); DescriptorSetUsage usage;
usage.location = location;
usage.descriptorSet = descriptorSet;
usage.dynamicOffsets = dynamicOffsets;
return usage; return usage;
} }
......
...@@ -4,7 +4,9 @@ ...@@ -4,7 +4,9 @@
namespace vkcv { namespace vkcv {
VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, size_t offset) { VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, size_t offset) {
VertexBufferBinding binding(buffer, offset); VertexBufferBinding binding;
binding.buffer = buffer;
binding.offset = offset;
return binding; return binding;
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment