From b7dbb8cf4bd4282a29033af4a6e05d65e00126af Mon Sep 17 00:00:00 2001 From: Tobias Frisch <tfrisch@uni-koblenz.de> Date: Fri, 30 Sep 2022 23:07:40 +0200 Subject: [PATCH] Adjust indirect_dispatch project to test out FSR 2.1.1 Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de> --- include/vkcv/FeatureManager.hpp | 20 ++ .../include/vkcv/upscaling/FSR2Upscaling.hpp | 11 +- .../src/vkcv/upscaling/FSR2Upscaling.cpp | 295 ++++++++++-------- projects/indirect_dispatch/CMakeLists.txt | 22 +- projects/indirect_dispatch/src/App.cpp | 230 ++++++++++++-- projects/indirect_dispatch/src/AppSetup.cpp | 67 ++-- projects/indirect_dispatch/src/AppSetup.hpp | 7 +- projects/voxelization/src/main.cpp | 3 +- src/vkcv/Context.cpp | 58 +++- src/vkcv/FeatureManager.cpp | 19 ++ src/vkcv/ImageManager.cpp | 25 +- 11 files changed, 556 insertions(+), 201 deletions(-) diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp index f465d674..8dcdf0e4 100644 --- a/include/vkcv/FeatureManager.hpp +++ b/include/vkcv/FeatureManager.hpp @@ -324,6 +324,26 @@ namespace vkcv { */ [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceVulkan13Features &features, bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceCoherentMemoryFeaturesAMD. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceCoherentMemoryFeaturesAMD &features, + bool required) const; + + /** + * @brief Checks support of the @p vk::PhysicalDeviceSubgroupSizeControlFeatures. + * + * @param[in] features The features + * @param[in] required True, if the @p features are required, else false + * @return @p True, if the @p features are supported, else @p false + */ + [[nodiscard]] bool checkSupport(const vk::PhysicalDeviceSubgroupSizeControlFeatures &features, + bool required) const; /** * @brief Searches for a base structure of a given structure type. diff --git a/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp index d61eef8d..95dbd9a8 100644 --- a/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp @@ -4,9 +4,8 @@ #include <vector> -#define FFX_GCC -#include <ffx_fsr2.h> -#undef FFX_GCC +struct FfxFsr2ContextDescription; +struct FfxFsr2Context; namespace vkcv::upscaling { @@ -81,8 +80,8 @@ namespace vkcv::upscaling { private: std::vector<char> m_scratchBuffer; - FfxFsr2ContextDescription m_description; - FfxFsr2Context m_context; + std::unique_ptr<FfxFsr2ContextDescription> m_description; + std::unique_ptr<FfxFsr2Context> m_context; ImageHandle m_depth; ImageHandle m_velocity; @@ -155,7 +154,7 @@ namespace vkcv::upscaling { void calcJitterOffset(uint32_t renderWidth, uint32_t renderHeight, float& jitterOffsetX, - float& jitterOffsetY); + float& jitterOffsetY) const; /** * Bind the depth buffer image to use with the FSR2 diff --git a/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp index 2737d5f7..0478596d 100644 --- a/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp +++ b/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp @@ -4,6 +4,7 @@ #include <cmath> #define FFX_GCC +#include <ffx_fsr2.h> #include <ffx_fsr2_vk.h> #undef FFX_GCC @@ -60,54 +61,87 @@ namespace vkcv::upscaling { uint32_t displayHeight, uint32_t renderWidth, uint32_t renderHeight) { - m_description.displaySize.width = displayWidth; - m_description.displaySize.height = displayHeight; + m_description->displaySize.width = displayWidth; + m_description->displaySize.height = displayHeight; - m_description.maxRenderSize.width = renderWidth; - m_description.maxRenderSize.height = renderHeight; + m_description->maxRenderSize.width = renderWidth; + m_description->maxRenderSize.height = renderHeight; - m_description.flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE; + m_description->flags = FFX_FSR2_ENABLE_AUTO_EXPOSURE; if (m_hdr) { - m_description.flags |= FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE; + m_description->flags |= FFX_FSR2_ENABLE_HIGH_DYNAMIC_RANGE; } - assert(ffxFsr2ContextCreate(&m_context, &m_description) == FFX_OK); + if ((m_description->displaySize.width * m_description->displaySize.height <= 1) || + (m_description->maxRenderSize.width * m_description->maxRenderSize.height <= 1)) { + return; + } + + if (!m_context) { + m_context.reset(new FfxFsr2Context()); + } + + memset(m_context.get(), 0, sizeof(*m_context)); + assert(ffxFsr2ContextCreate(m_context.get(), m_description.get()) == FFX_OK); } void FSR2Upscaling::destroyFSR2Context() { m_core.getContext().getDevice().waitIdle(); - assert(ffxFsr2ContextDestroy(&m_context) == FFX_OK); + if (m_context) { + assert(ffxFsr2ContextDestroy(m_context.get()) == FFX_OK); + m_context.reset(nullptr); + } m_frameIndex = 0; } - FSR2Upscaling::FSR2Upscaling(Core &core) : Upscaling(core) { + FSR2Upscaling::FSR2Upscaling(Core &core) : + Upscaling(core), + m_scratchBuffer(), + + m_description(new FfxFsr2ContextDescription()), + m_context(nullptr), + + m_depth(), + m_velocity(), + + m_frameIndex(0), + + m_frameDeltaTime(0.0f), + m_reset(false), + + m_near(0.0f), + m_far(0.0f), + m_fov(0.0f), + + m_hdr(false), + m_sharpness(0.875f) { const auto& physicalDevice = core.getContext().getPhysicalDevice(); - memset(&m_description, 0, sizeof(m_description)); + memset(m_description.get(), 0, sizeof(*m_description)); m_scratchBuffer.resize(ffxFsr2GetScratchMemorySizeVK(physicalDevice)); assert(ffxFsr2GetInterfaceVK( - &(m_description.callbacks), + &(m_description->callbacks), m_scratchBuffer.data(), m_scratchBuffer.size(), physicalDevice, vkGetDeviceProcAddr ) == FFX_OK); - m_description.device = ffxGetDeviceVK(core.getContext().getDevice()); + m_description->device = ffxGetDeviceVK(core.getContext().getDevice()); - createFSR2Context(0, 0, 0, 0); + createFSR2Context(1, 1, 1, 1); } FSR2Upscaling::~FSR2Upscaling() { destroyFSR2Context(); m_scratchBuffer.clear(); - m_description.callbacks.scratchBuffer = nullptr; + m_description->callbacks.scratchBuffer = nullptr; } void FSR2Upscaling::update(float deltaTime, bool reset) { @@ -122,10 +156,10 @@ namespace vkcv::upscaling { void FSR2Upscaling::calcJitterOffset(uint32_t renderWidth, uint32_t renderHeight, float &jitterOffsetX, - float &jitterOffsetY) { + float &jitterOffsetY) const { const int32_t phaseCount = ffxFsr2GetJitterPhaseCount( - renderWidth, - renderHeight + static_cast<int32_t>(renderWidth), + static_cast<int32_t>(renderHeight) ); const int32_t phaseIndex = (static_cast<int32_t>(m_frameIndex) % phaseCount); @@ -136,6 +170,9 @@ namespace vkcv::upscaling { phaseIndex, phaseCount ) == FFX_OK); + + jitterOffsetX *= +2.0f / renderWidth; + jitterOffsetY *= -2.0f / renderHeight; } void FSR2Upscaling::bindDepthBuffer(const ImageHandle &depthInput) { @@ -146,8 +183,13 @@ namespace vkcv::upscaling { m_velocity = velocityInput; } - void FSR2Upscaling::recordUpscaling(const CommandStreamHandle &cmdStream, const ImageHandle &colorInput, + void FSR2Upscaling::recordUpscaling(const CommandStreamHandle &cmdStream, + const ImageHandle &colorInput, const ImageHandle &output) { + m_core.recordBeginDebugLabel(cmdStream, "vkcv::upscaling::FSR2Upscaling", { + 1.0f, 0.05f, 0.05f, 1.0f + }); + FfxFsr2DispatchDescription dispatch; memset(&dispatch, 0, sizeof(dispatch)); @@ -157,11 +199,11 @@ namespace vkcv::upscaling { 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))) { + 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( @@ -172,109 +214,114 @@ namespace vkcv::upscaling { ); } - 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)) - ); - - calcJitterOffset( - inputWidth, - inputHeight, - dispatch.jitterOffset.x, - dispatch.jitterOffset.y - ); - - dispatch.motionVectorScale.x = static_cast<float>(inputWidth); - dispatch.motionVectorScale.y = static_cast<float>(inputHeight); - - 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, [&](const vk::CommandBuffer& cmdBuffer) { - dispatch.commandList = ffxGetCommandListVK(cmdBuffer); + if (m_context) { + const bool sharpeningEnabled = ( + (m_sharpness > +0.0f) && + ((inputWidth < outputWidth) || (inputHeight < outputHeight)) + ); + + dispatch.color = ffxGetTextureResourceVK( + m_context.get(), + m_core.getVulkanImage(colorInput), + m_core.getVulkanImageView(colorInput), + inputWidth, + inputHeight, + static_cast<VkFormat>(m_core.getImageFormat(colorInput)) + ); - assert(ffxFsr2ContextDispatch( - &m_context, - &dispatch - ) == FFX_OK); + dispatch.depth = ffxGetTextureResourceVK( + m_context.get(), + 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.get(), + 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.get(), + nullptr, + nullptr, + 1, + 1, + VK_FORMAT_UNDEFINED + ); + + dispatch.reactive = ffxGetTextureResourceVK( + m_context.get(), + nullptr, + nullptr, + 1, + 1, + VK_FORMAT_UNDEFINED + ); - m_frameIndex++; - m_reset = false; - }, nullptr); + dispatch.transparencyAndComposition = ffxGetTextureResourceVK( + m_context.get(), + nullptr, + nullptr, + 1, + 1, + VK_FORMAT_UNDEFINED + ); + + dispatch.output = ffxGetTextureResourceVK( + m_context.get(), + m_core.getVulkanImage(output), + m_core.getVulkanImageView(output), + outputWidth, + outputHeight, + static_cast<VkFormat>(m_core.getImageFormat(output)) + ); + + calcJitterOffset( + inputWidth, + inputHeight, + dispatch.jitterOffset.x, + dispatch.jitterOffset.y + ); + + dispatch.motionVectorScale.x = static_cast<float>(+2.0f); + dispatch.motionVectorScale.y = static_cast<float>(-2.0f); + + 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, [&](const vk::CommandBuffer& cmdBuffer) { + dispatch.commandList = ffxGetCommandListVK(cmdBuffer); + + assert(ffxFsr2ContextDispatch( + m_context.get(), + &dispatch + ) == FFX_OK); + + m_frameIndex++; + m_reset = false; + }, nullptr); + } + + m_core.updateImageLayoutManual(output, vk::ImageLayout::eGeneral); + m_core.recordEndDebugLabel(cmdStream); } void FSR2Upscaling::setCamera(float near, float far, float fov) { diff --git a/projects/indirect_dispatch/CMakeLists.txt b/projects/indirect_dispatch/CMakeLists.txt index 53b0d1b1..ad59d5b2 100644 --- a/projects/indirect_dispatch/CMakeLists.txt +++ b/projects/indirect_dispatch/CMakeLists.txt @@ -25,7 +25,25 @@ target_sources(indirect_dispatch PRIVATE src/MotionBlurSetup.cpp) # including headers of dependencies and the VkCV framework -target_include_directories(indirect_dispatch SYSTEM BEFORE PRIVATE ${vkcv_include} ${vkcv_includes} ${vkcv_testing_include} ${vkcv_camera_include} ${vkcv_shader_compiler_include} ${vkcv_gui_include}) +target_include_directories(indirect_dispatch SYSTEM BEFORE PRIVATE + ${vkcv_include} + ${vkcv_includes} + ${vkcv_testing_include} + ${vkcv_camera_include} + ${vkcv_shader_compiler_include} + ${vkcv_gui_include} + ${vkcv_upscaling_include} +) # linking with libraries from all dependencies and the VkCV framework -target_link_libraries(indirect_dispatch vkcv ${vkcv_libraries} vkcv_asset_loader ${vkcv_asset_loader_libraries} vkcv_testing vkcv_camera vkcv_shader_compiler vkcv_gui) \ No newline at end of file +target_link_libraries(indirect_dispatch + vkcv + ${vkcv_libraries} + vkcv_asset_loader + ${vkcv_asset_loader_libraries} + vkcv_testing + vkcv_camera + vkcv_shader_compiler + vkcv_gui + vkcv_upscaling +) \ No newline at end of file diff --git a/projects/indirect_dispatch/src/App.cpp b/projects/indirect_dispatch/src/App.cpp index f17a3df6..f871338a 100644 --- a/projects/indirect_dispatch/src/App.cpp +++ b/projects/indirect_dispatch/src/App.cpp @@ -4,6 +4,11 @@ #include <vkcv/Sampler.hpp> #include <vkcv/gui/GUI.hpp> +#include <vkcv/upscaling/FSR2Upscaling.hpp> +#include <vkcv/upscaling/FSRUpscaling.hpp> +#include <vkcv/upscaling/NISUpscaling.hpp> +#include <vkcv/upscaling/BilinearUpscaling.hpp> + #include <chrono> #include <functional> @@ -35,7 +40,6 @@ App::App() : m_cameraManager(m_core.getWindow(m_windowHandle)){} bool App::initialize() { - if (!loadMeshPass(m_core, &m_meshPass)) return false; @@ -64,7 +68,12 @@ bool App::initialize() { return false; m_linearSampler = vkcv::samplerLinear(m_core, true); - m_renderTargets = createRenderTargets(m_core, m_windowWidth, m_windowHeight); + m_renderTargets = createRenderTargets( + m_core, + m_windowWidth, + m_windowHeight, + vkcv::upscaling::FSR2QualityMode::NONE + ); auto cameraHandle = m_cameraManager.addCamera(vkcv::camera::ControllerType::PILOT); m_cameraManager.getCamera(cameraHandle).setPosition(glm::vec3(0, 1, -3)); @@ -143,11 +152,46 @@ void App::run() { } } }); - + + vkcv::upscaling::FSR2Upscaling fsr2 (m_core); + + fsr2.bindDepthBuffer(m_renderTargets.depthBuffer); + fsr2.bindVelocityBuffer(m_renderTargets.motionBuffer); + + vkcv::upscaling::FSR2QualityMode fsrMode = vkcv::upscaling::FSR2QualityMode::NONE; + vkcv::upscaling::FSR2QualityMode oldFsrMode = fsrMode; + + int fsrModeIndex = static_cast<int>(fsrMode); + + const std::vector<const char*> fsrModeNames = { + "None", + "Quality", + "Balanced", + "Performance", + "Ultra Performance" + }; + + bool fsrMipLoadBiasFlag = true; + bool fsrMipLoadBiasFlagBackup = fsrMipLoadBiasFlag; + + vkcv::upscaling::FSRUpscaling fsr1 (m_core); + vkcv::upscaling::BilinearUpscaling bilinear (m_core); + vkcv::upscaling::NISUpscaling nis (m_core); + + const std::vector<const char*> modeNames = { + "FSR Upscaling 1.0", + "FSR Upscaling 2.1.1", + "NIS Upscaling", + "Bilinear Upscaling" + }; + + int upscalingMode = 3; + + vkcv::SamplerHandle fsr2Sampler; + auto frameEndTime = std::chrono::system_clock::now(); while (vkcv::Window::hasOpenWindow()) { - vkcv::Window::pollEvents(); if (!freezeFrame) { @@ -167,13 +211,42 @@ void App::run() { if (!m_core.beginFrame(swapchainWidth, swapchainHeight,m_windowHandle)) continue; - const bool hasResolutionChanged = (swapchainWidth != m_windowWidth) || (swapchainHeight != m_windowHeight); + const bool hasResolutionChanged = ( + (swapchainWidth != m_windowWidth) || + (swapchainHeight != m_windowHeight) || + (oldFsrMode != fsrMode) || + (fsrMipLoadBiasFlagBackup != fsrMipLoadBiasFlag) + ); + if (hasResolutionChanged) { m_windowWidth = swapchainWidth; m_windowHeight = swapchainHeight; - - m_renderTargets = createRenderTargets(m_core, m_windowWidth, m_windowHeight); + oldFsrMode = fsrMode; + fsrMipLoadBiasFlagBackup = fsrMipLoadBiasFlag; + + fsr2Sampler = m_core.createSampler( + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerFilterType::LINEAR, + vkcv::SamplerMipmapMode::LINEAR, + vkcv::SamplerAddressMode::REPEAT, + fsrMipLoadBiasFlag? vkcv::upscaling::getFSR2LodBias(fsrMode) : 0.0f + ); + + vkcv::DescriptorWrites meshPassDescriptorWrites; + meshPassDescriptorWrites.writeSampler(1, fsr2Sampler); + m_core.writeDescriptorSet(m_meshPass.descriptorSet, meshPassDescriptorWrites); + + m_renderTargets = createRenderTargets( + m_core, + m_windowWidth, + m_windowHeight, + fsrMode + ); + m_motionBlur.setResolution(m_windowWidth, m_windowHeight); + + fsr2.bindDepthBuffer(m_renderTargets.depthBuffer); + fsr2.bindVelocityBuffer(m_renderTargets.motionBuffer); } if(!freezeFrame) @@ -183,20 +256,41 @@ void App::run() { const float fDeltaTimeSeconds = microsecondToSecond * std::chrono::duration_cast<std::chrono::microseconds>(frameEndTime - frameStartTime).count(); m_cameraManager.update(fDeltaTimeSeconds); - - const auto time = frameEndTime - appStartTime; - const float fCurrentTime = std::chrono::duration_cast<std::chrono::milliseconds>(time).count() * 0.001f; + fsr2.update(fDeltaTimeSeconds, false); + + const auto& camera = m_cameraManager.getActiveCamera(); + float near, far; + + camera.getNearFar(near, far); + fsr2.setCamera(near, far, camera.getFov()); + + const auto time = frameEndTime - appStartTime; + const float fCurrentTime = std::chrono::duration_cast<std::chrono::milliseconds>(time).count() * 0.001f; + + float jitterX, jitterY; + + fsr2.calcJitterOffset( + m_core.getImageWidth(m_renderTargets.colorBuffer), + m_core.getImageHeight(m_renderTargets.colorBuffer), + jitterX, + jitterY + ); + + const glm::mat4 jitterMatrix = glm::translate( + glm::identity<glm::mat4>(), + glm::vec3(jitterX, jitterY, 0.0f) + ); // update matrices if (!freezeFrame) { - - viewProjection = m_cameraManager.getActiveCamera().getMVP(); + viewProjection = camera.getMVP(); for (Object& obj : sceneObjects) { if (obj.modelMatrixUpdate) { obj.modelMatrixUpdate(fCurrentTime, obj); } - obj.mvp = viewProjection * obj.modelMatrix; + + obj.mvp = jitterMatrix * viewProjection * obj.modelMatrix; } } @@ -212,7 +306,8 @@ void App::run() { const std::vector<vkcv::ImageHandle> prepassRenderTargets = { m_renderTargets.motionBuffer, - m_renderTargets.depthBuffer }; + m_renderTargets.depthBuffer + }; std::vector<vkcv::InstanceDrawcall> prepassSceneDrawcalls; for (const Object& obj : sceneObjects) { @@ -225,12 +320,15 @@ void App::run() { prepassPushConstants, prepassSceneDrawcalls, prepassRenderTargets, - m_windowHandle); + m_windowHandle + ); // sky prepass glm::mat4 skyPrepassMatrices[2] = { viewProjection, - viewProjectionPrevious }; + viewProjectionPrevious + }; + vkcv::PushConstants skyPrepassPushConstants(sizeof(glm::mat4) * 2); skyPrepassPushConstants.appendDrawcall(skyPrepassMatrices); @@ -240,12 +338,14 @@ void App::run() { skyPrepassPushConstants, { skyDrawcall }, prepassRenderTargets, - m_windowHandle); + m_windowHandle + ); // main pass const std::vector<vkcv::ImageHandle> renderTargets = { m_renderTargets.colorBuffer, - m_renderTargets.depthBuffer }; + m_renderTargets.depthBuffer + }; vkcv::PushConstants meshPushConstants(2 * sizeof(glm::mat4)); for (const Object& obj : sceneObjects) { @@ -266,11 +366,12 @@ void App::run() { meshPushConstants, forwardSceneDrawcalls, renderTargets, - m_windowHandle); + m_windowHandle + ); // sky vkcv::PushConstants skyPushConstants = vkcv::pushConstants<glm::mat4>(); - skyPushConstants.appendDrawcall(viewProjection); + skyPushConstants.appendDrawcall(jitterMatrix * viewProjection); m_core.recordDrawcallsToCmdStream( cmdStream, @@ -278,35 +379,82 @@ void App::run() { skyPushConstants, { skyDrawcall }, renderTargets, - m_windowHandle); + m_windowHandle + ); + + // upscaling + m_core.prepareImageForSampling(cmdStream, m_renderTargets.colorBuffer); + + switch (upscalingMode) { + case 0: + m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer); + + fsr1.recordUpscaling( + cmdStream, + m_renderTargets.colorBuffer, + m_renderTargets.finalBuffer + ); + break; + case 1: + m_core.prepareImageForSampling(cmdStream, m_renderTargets.depthBuffer); + m_core.prepareImageForSampling(cmdStream, m_renderTargets.motionBuffer); + + m_core.prepareImageForSampling(cmdStream, m_renderTargets.finalBuffer); + + fsr2.recordUpscaling( + cmdStream, + m_renderTargets.colorBuffer, + m_renderTargets.finalBuffer + ); + break; + case 2: + m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer); + + nis.recordUpscaling( + cmdStream, + m_renderTargets.colorBuffer, + m_renderTargets.finalBuffer + ); + break; + case 3: + m_core.prepareImageForStorage(cmdStream, m_renderTargets.finalBuffer); + + bilinear.recordUpscaling( + cmdStream, + m_renderTargets.colorBuffer, + m_renderTargets.finalBuffer + ); + break; + default: + break; + } + + m_core.prepareImageForSampling(cmdStream, m_renderTargets.finalBuffer); // motion blur vkcv::ImageHandle motionBlurOutput; if (motionVectorVisualisationMode == eMotionVectorVisualisationMode::None) { - float cameraNear; - float cameraFar; - m_cameraManager.getActiveCamera().getNearFar(cameraNear, cameraFar); - motionBlurOutput = m_motionBlur.render( cmdStream, m_renderTargets.motionBuffer, - m_renderTargets.colorBuffer, + m_renderTargets.finalBuffer, m_renderTargets.depthBuffer, motionBlurMode, - cameraNear, - cameraFar, + near, + far, fDeltaTimeSeconds, static_cast<float>(cameraShutterSpeedInverse), motionBlurTileOffsetLength, - motionBlurFastPathThreshold); - } - else { + motionBlurFastPathThreshold + ); + } else { motionBlurOutput = m_motionBlur.renderMotionVectorVisualisation( cmdStream, m_renderTargets.motionBuffer, motionVectorVisualisationMode, - motionVectorVisualisationRange); + motionVectorVisualisationRange + ); } // gamma correction @@ -330,7 +478,8 @@ void App::run() { m_gammaCorrectionPass.pipeline, fullScreenImageDispatch, { vkcv::useDescriptorSet(0, m_gammaCorrectionPass.descriptorSet) }, - vkcv::PushConstants(0)); + vkcv::PushConstants(0) + ); m_core.prepareSwapchainImageForPresent(cmdStream); m_core.submitCommandStream(cmdStream); @@ -364,6 +513,21 @@ void App::run() { ImGui::InputFloat("Object mean height", &objectMeanHeight); ImGui::InputFloat("Object rotation speed X", &objectRotationSpeedX); ImGui::InputFloat("Object rotation speed Y", &objectRotationSpeedY); + + float sharpness = fsr2.getSharpness(); + + ImGui::Combo("FSR Quality Mode", &fsrModeIndex, fsrModeNames.data(), fsrModeNames.size()); + ImGui::DragFloat("FSR Sharpness", &sharpness, 0.001, 0.0f, 1.0f); + ImGui::Checkbox("FSR Mip Lod Bias", &fsrMipLoadBiasFlag); + ImGui::Combo("Upscaling Mode", &upscalingMode, modeNames.data(), modeNames.size()); + + if ((fsrModeIndex >= 0) && (fsrModeIndex <= 4)) { + fsrMode = static_cast<vkcv::upscaling::FSR2QualityMode>(fsrModeIndex); + } + + fsr1.setSharpness(sharpness); + fsr2.setSharpness(sharpness); + nis.setSharpness(sharpness); ImGui::End(); gui.endGUI(); diff --git a/projects/indirect_dispatch/src/AppSetup.cpp b/projects/indirect_dispatch/src/AppSetup.cpp index 26cfbbc3..bc6090a7 100644 --- a/projects/indirect_dispatch/src/AppSetup.cpp +++ b/projects/indirect_dispatch/src/AppSetup.cpp @@ -299,36 +299,63 @@ bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, Comput return true; } -AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height) { +AppRenderTargets createRenderTargets(vkcv::Core& core, + uint32_t width, + uint32_t height, + vkcv::upscaling::FSR2QualityMode mode) { AppRenderTargets targets; + uint32_t renderWidth, renderHeight; + + vkcv::upscaling::getFSR2Resolution( + mode, + width, + height, + renderWidth, + renderHeight + ); targets.depthBuffer = core.createImage( - AppConfig::depthBufferFormat, - width, - height, - 1, - false + AppConfig::depthBufferFormat, + renderWidth, + renderHeight, + 1, + false ); targets.colorBuffer = core.createImage( - AppConfig::colorBufferFormat, - width, - height, - 1, - false, - false, - true + AppConfig::colorBufferFormat, + renderWidth, + renderHeight, + 1, + false, + false, + true ); targets.motionBuffer = core.createImage( - AppConfig::motionBufferFormat, - width, - height, - 1, - false, - false, - true + AppConfig::motionBufferFormat, + renderWidth, + renderHeight, + 1, + false, + false, + true + ); + + targets.finalBuffer = core.createImage( + AppConfig::colorBufferFormat, + width, + height, + 1, + false, + true, + true ); + + core.setDebugLabel(targets.depthBuffer, "Depth buffer"); + core.setDebugLabel(targets.colorBuffer, "Color buffer"); + core.setDebugLabel(targets.motionBuffer, "Motion buffer"); + core.setDebugLabel(targets.finalBuffer, "Final buffer"); return targets; } \ No newline at end of file diff --git a/projects/indirect_dispatch/src/AppSetup.hpp b/projects/indirect_dispatch/src/AppSetup.hpp index 41e020c3..d06910b5 100644 --- a/projects/indirect_dispatch/src/AppSetup.hpp +++ b/projects/indirect_dispatch/src/AppSetup.hpp @@ -1,10 +1,12 @@ #pragma once #include <vkcv/Core.hpp> +#include <vkcv/upscaling/FSR2Upscaling.hpp> struct AppRenderTargets { vkcv::ImageHandle depthBuffer; vkcv::ImageHandle colorBuffer; vkcv::ImageHandle motionBuffer; + vkcv::ImageHandle finalBuffer; }; struct GraphicPassHandles { @@ -46,4 +48,7 @@ bool loadSkyPrePass(vkcv::Core& core, GraphicPassHandles* outHandles); bool loadComputePass(vkcv::Core& core, const std::filesystem::path& path, ComputePassHandles* outComputePass); -AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, const uint32_t height); \ No newline at end of file +AppRenderTargets createRenderTargets(vkcv::Core& core, + uint32_t width, + uint32_t height, + vkcv::upscaling::FSR2QualityMode mode); \ No newline at end of file diff --git a/projects/voxelization/src/main.cpp b/projects/voxelization/src/main.cpp index ac2b2b6a..381761a7 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -637,7 +637,8 @@ int main(int argc, const char** argv) { width, height ); - if ((width != fsrWidth) || ((height != fsrHeight)) || (fsrMipLoadBiasFlagBackup != fsrMipLoadBiasFlag)) { + if ((width != fsrWidth) || ((height != fsrHeight)) || + (fsrMipLoadBiasFlagBackup != fsrMipLoadBiasFlag)) { fsrWidth = width; fsrHeight = height; fsrMipLoadBiasFlagBackup = fsrMipLoadBiasFlag; diff --git a/src/vkcv/Context.cpp b/src/vkcv/Context.cpp index c0458f23..8b23bc55 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -413,7 +413,8 @@ namespace vkcv { [](vk::PhysicalDeviceShaderFloat16Int8Features &features) { features.setShaderFloat16(true); }, - false); + false + ); } if (featureManager.useExtension(VK_KHR_16BIT_STORAGE_EXTENSION_NAME, false)) { @@ -421,7 +422,26 @@ namespace vkcv { [](vk::PhysicalDevice16BitStorageFeatures &features) { features.setStorageBuffer16BitAccess(true); }, - false); + false + ); + } + + if (featureManager.useExtension(VK_AMD_DEVICE_COHERENT_MEMORY_EXTENSION_NAME, false)) { + featureManager.useFeatures<vk::PhysicalDeviceCoherentMemoryFeaturesAMD>( + [](vk::PhysicalDeviceCoherentMemoryFeaturesAMD &features) { + features.setDeviceCoherentMemory(true); + }, + false + ); + } + + if (featureManager.useExtension(VK_EXT_SUBGROUP_SIZE_CONTROL_EXTENSION_NAME, false)) { + featureManager.useFeatures<vk::PhysicalDeviceSubgroupSizeControlFeatures>( + [](vk::PhysicalDeviceSubgroupSizeControlFeatures &features) { + features.setSubgroupSizeControl(true); + }, + false + ); } featureManager.useFeatures([](vk::PhysicalDeviceFeatures &features) { @@ -456,13 +476,37 @@ namespace vkcv { vk::Device device = physicalDevice.createDevice(deviceCreateInfo); - QueueManager queueManager = - QueueManager::create(device, queuePairsGraphics, queuePairsCompute, queuePairsTransfer); + QueueManager queueManager = QueueManager::create( + device, + queuePairsGraphics, + queuePairsCompute, + queuePairsTransfer + ); + + const bool coherentDeviceMemory = featureManager.checkFeatures<vk::PhysicalDeviceCoherentMemoryFeaturesAMD>( + vk::StructureType::ePhysicalDeviceCoherentMemoryFeaturesAMD, + [](const vk::PhysicalDeviceCoherentMemoryFeaturesAMD &features) { + return features.deviceCoherentMemory; + } + ); vma::AllocatorCreateFlags vmaFlags; - const vma::AllocatorCreateInfo allocatorCreateInfo(vmaFlags, physicalDevice, device, 0, - nullptr, nullptr, nullptr, nullptr, - instance, VK_HEADER_VERSION_COMPLETE); + if (coherentDeviceMemory) { + vmaFlags |= vma::AllocatorCreateFlagBits::eAmdDeviceCoherentMemory; + } + + const vma::AllocatorCreateInfo allocatorCreateInfo( + vmaFlags, + physicalDevice, + device, + 0, + nullptr, + nullptr, + nullptr, + nullptr, + instance, + VK_HEADER_VERSION_COMPLETE + ); vma::Allocator allocator = vma::createAllocator(allocatorCreateInfo); diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp index 12503a32..c83597e9 100644 --- a/src/vkcv/FeatureManager.cpp +++ b/src/vkcv/FeatureManager.cpp @@ -476,6 +476,25 @@ namespace vkcv { return true; } + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceCoherentMemoryFeaturesAMD &features, + bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceCoherentMemoryFeaturesAMD); + + vkcv_check_feature(deviceCoherentMemory); + + return true; + } + + bool FeatureManager::checkSupport(const vk::PhysicalDeviceSubgroupSizeControlFeatures &features, + bool required) const { + vkcv_check_init_features2(vk::PhysicalDeviceSubgroupSizeControlFeatures); + + vkcv_check_feature(subgroupSizeControl); + vkcv_check_feature(computeFullSubgroups); + + return true; + } vk::BaseOutStructure* FeatureManager::findFeatureStructure(vk::StructureType type) const { for (auto &base : m_featuresExtensions) { diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index 993243cb..e4961f76 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -345,14 +345,25 @@ namespace vkcv { if ((!mipLevelCount) || (mipLevelOffset + mipLevelCount > mipLevelsMax)) mipLevelCount = mipLevelsMax - mipLevelOffset; - vk::ImageSubresourceRange imageSubresourceRange(aspectFlags, mipLevelOffset, mipLevelCount, - 0, image.m_layers); - + vk::ImageSubresourceRange imageSubresourceRange( + aspectFlags, + mipLevelOffset, + mipLevelCount, + 0, + image.m_layers + ); + // TODO: precise AccessFlagBits, will require a lot of context - return vk::ImageMemoryBarrier(vk::AccessFlagBits::eMemoryWrite, - vk::AccessFlagBits::eMemoryRead, image.m_layout, newLayout, - VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, - image.m_handle, imageSubresourceRange); + return vk::ImageMemoryBarrier( + vk::AccessFlagBits::eMemoryWrite, + vk::AccessFlagBits::eMemoryRead, + image.m_layout, + newLayout, + VK_QUEUE_FAMILY_IGNORED, + VK_QUEUE_FAMILY_IGNORED, + image.m_handle, + imageSubresourceRange + ); } void ImageManager::switchImageLayoutImmediate(const ImageHandle &handle, -- GitLab