diff --git a/.gitmodules b/.gitmodules index ae8c7aef11bba6c98adc54f5f9899f3255125196..3fe8d1304b6b6087300a26607d3533b6a2be1a78 100644 --- a/.gitmodules +++ b/.gitmodules @@ -40,3 +40,6 @@ [submodule "modules/algorithm/lib/FidelityFX-SPD"] path = modules/algorithm/lib/FidelityFX-SPD 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 diff --git a/include/vkcv/FeatureManager.hpp b/include/vkcv/FeatureManager.hpp index f2138f6f3b7c5f639d42e98a83991704df0eb352..9ccc9880e807529bb6eb392515973d51f3aa6e37 100644 --- a/include/vkcv/FeatureManager.hpp +++ b/include/vkcv/FeatureManager.hpp @@ -325,6 +325,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 Checks support of the @p vk::PhysicalDeviceIndexTypeUint8FeaturesEXT. * diff --git a/modules/upscaling/CMakeLists.txt b/modules/upscaling/CMakeLists.txt index 47a963d43f0444216a7a972987a7d584333a1fc8..4578f97fd654a5cad0e66549fbc944ab16051b11 100644 --- a/modules/upscaling/CMakeLists.txt +++ b/modules/upscaling/CMakeLists.txt @@ -20,6 +20,9 @@ set(vkcv_upscaling_sources ${vkcv_upscaling_include}/vkcv/upscaling/NISUpscaling.hpp ${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 @@ -29,6 +32,9 @@ set(vkcv_upscaling_lib_path ${PROJECT_SOURCE_DIR}/${vkcv_upscaling_lib}) # Check and load FidelityFX_FSR include(config/FidelityFX_FSR.cmake) +# Check and load FidelityFX_FSR2 +include(config/FidelityFX_FSR2.cmake) + # Check and load NVIDIAImageScaling include(config/NVIDIAImageScaling.cmake) diff --git a/modules/upscaling/README.md b/modules/upscaling/README.md index 57f6dbdc8a9457982580170755a751fee74cefa6..9c4bed679f5a7a756e8b25edc85360672f8fabd0 100644 --- a/modules/upscaling/README.md +++ b/modules/upscaling/README.md @@ -6,10 +6,11 @@ A VkCV module to upscale images in realtime ### Dependencies (required): -| Name of dependency | Used as submodule | -|----------------------------------------------------|---| -| [FidelityFX-FSR](https://github.com/GPUOpen-Effects/FidelityFX-FSR/) | ✅ | -| [NVIDIAImageScaling](https://github.com/NVIDIAGameWorks/NVIDIAImageScaling/) | ✅ | +| Name of dependency | Used as submodule | +|------------------------------------------------------------------------------|---| +| [FidelityFX-FSR](https://github.com/GPUOpen-Effects/FidelityFX-FSR/) | ✅ | +| [NVIDIAImageScaling](https://github.com/NVIDIAGameWorks/NVIDIAImageScaling/) | ✅ | +| [FidelityFX-FSR2](https://github.com/GPUOpen-Effects/FidelityFX-FSR2/) | ✅ | ## Docs diff --git a/modules/upscaling/config/FidelityFX_FSR2.cmake b/modules/upscaling/config/FidelityFX_FSR2.cmake new file mode 100644 index 0000000000000000000000000000000000000000..3dbc43e6721ae139f9ceb76c9f05b6fbce010fba --- /dev/null +++ b/modules/upscaling/config/FidelityFX_FSR2.cmake @@ -0,0 +1,14 @@ + +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 () diff --git a/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp index 4f0bfea8499aaa04ce9d7503b47b08e4cd8cde26..a3f29276aa95e17e11ce2a044721d47d558dd869 100644 --- a/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/BilinearUpscaling.hpp @@ -23,7 +23,7 @@ namespace vkcv::upscaling { explicit BilinearUpscaling(Core& core); /** - * Record the comands of the bilinear upscaling instance to + * Record the commands of the bilinear upscaling instance to * scale the image of the input handle to the resolution of * the output image handle via bilinear interpolation. * diff --git a/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp new file mode 100644 index 0000000000000000000000000000000000000000..95dbd9a804ab6ec6a0232cafac7bc43dcf8b5d6d --- /dev/null +++ b/modules/upscaling/include/vkcv/upscaling/FSR2Upscaling.hpp @@ -0,0 +1,235 @@ +#pragma once + +#include "Upscaling.hpp" + +#include <vector> + +struct FfxFsr2ContextDescription; +struct FfxFsr2Context; + +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 + */ + class FSR2Upscaling : public Upscaling { + private: + std::vector<char> m_scratchBuffer; + + std::unique_ptr<FfxFsr2ContextDescription> m_description; + std::unique_ptr<FfxFsr2Context> m_context; + + ImageHandle m_depth; + ImageHandle m_velocity; + + uint32_t m_frameIndex; + + 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); + + /** + * 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) const; + + /** + * 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 commands 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 diff --git a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp index 64bc78aca4fe42ff813d05fc016a70c7108bd557..5a4c59ef02c2f17ed017535ca79b834e7391546a 100644 --- a/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/FSRUpscaling.hpp @@ -44,7 +44,7 @@ namespace vkcv::upscaling { * Low quality of FSR upscaling: * 2.0x per dimension */ - PERFORMANCE = 4 + PERFORMANCE = 4, }; /** @@ -188,7 +188,7 @@ namespace vkcv::upscaling { explicit FSRUpscaling(Core& core); /** - * Record the comands of the FSR upscaling instance to + * Record the commands of the FSR upscaling instance to * scale the image of the input handle to the resolution of * the output image handle via FidelityFX Super Resolution. * diff --git a/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp b/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp index 913983400808f3353adf3a1c653045345d36c6f1..62fadf8332afd78ad7cb9dbe1eadda75de35d1c3 100644 --- a/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/NISUpscaling.hpp @@ -84,7 +84,7 @@ namespace vkcv::upscaling { explicit NISUpscaling(Core &core); /** - * Record the comands of the NIS upscaling instance to + * Record the commands of the NIS upscaling instance to * scale the image of the input handle to the resolution of * the output image handle via NVIDIA Image Scaling. * diff --git a/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp b/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp index 4d04746f0849615a112d04827c7af41811031116..06e35208744734f903c8a48aa6abcd9478685c1e 100644 --- a/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp +++ b/modules/upscaling/include/vkcv/upscaling/Upscaling.hpp @@ -32,7 +32,7 @@ namespace vkcv::upscaling { ~Upscaling() = default; /** - * Record the comands of the given upscaling instance to + * Record the commands of the given upscaling instance to * scale the image of the input handle to the resolution of * the output image handle. * diff --git a/modules/upscaling/lib/FidelityFX-FSR2 b/modules/upscaling/lib/FidelityFX-FSR2 new file mode 160000 index 0000000000000000000000000000000000000000..0ce4ff5c5a0210273be7e3085bb4b15d0590431c --- /dev/null +++ b/modules/upscaling/lib/FidelityFX-FSR2 @@ -0,0 +1 @@ +Subproject commit 0ce4ff5c5a0210273be7e3085bb4b15d0590431c diff --git a/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp b/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp new file mode 100644 index 0000000000000000000000000000000000000000..0478596daef709ef8b5ae583221d402d36d76dba --- /dev/null +++ b/modules/upscaling/src/vkcv/upscaling/FSR2Upscaling.cpp @@ -0,0 +1,349 @@ + +#include "vkcv/upscaling/FSR2Upscaling.hpp" + +#include <cmath> + +#define FFX_GCC +#include <ffx_fsr2.h> +#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, + 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; + } + + 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(); + + if (m_context) { + assert(ffxFsr2ContextDestroy(m_context.get()) == FFX_OK); + m_context.reset(nullptr); + } + + m_frameIndex = 0; + } + + 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.get(), 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(1, 1, 1, 1); + } + + FSR2Upscaling::~FSR2Upscaling() { + destroyFSR2Context(); + + m_scratchBuffer.clear(); + m_description->callbacks.scratchBuffer = nullptr; + } + + 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 { + const int32_t phaseCount = ffxFsr2GetJitterPhaseCount( + static_cast<int32_t>(renderWidth), + static_cast<int32_t>(renderHeight) + ); + + const int32_t phaseIndex = (static_cast<int32_t>(m_frameIndex) % phaseCount); + + assert(ffxFsr2GetJitterOffset( + &jitterOffsetX, + &jitterOffsetY, + phaseIndex, + phaseCount + ) == FFX_OK); + + jitterOffsetX *= +2.0f / renderWidth; + jitterOffsetY *= -2.0f / renderHeight; + } + + 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) { + m_core.recordBeginDebugLabel(cmdStream, "vkcv::upscaling::FSR2Upscaling", { + 1.0f, 0.05f, 0.05f, 1.0f + }); + + 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 + ); + } + + 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)) + ); + + 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 + ); + + 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) { + 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 diff --git a/projects/indirect_dispatch/CMakeLists.txt b/projects/indirect_dispatch/CMakeLists.txt index 53b0d1b15dc2eeb32308e16ad81d476ed502d370..ad59d5b24efa1af1b387253b4c007fd25c50500f 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 f17a3df647359018411e5bebcc3175295359678b..f871338af2670087eaf851901790631a4711f680 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 0a334932defb8ea3632d4047a4ca8e66e91faa20..5dc6c81e0e9599a561c3de1e359563c1f25334ea 100644 --- a/projects/indirect_dispatch/src/AppSetup.cpp +++ b/projects/indirect_dispatch/src/AppSetup.cpp @@ -299,16 +299,29 @@ 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; - vkcv::ImageConfig depthBufferConfig (width, height); + uint32_t renderWidth, renderHeight; + + vkcv::upscaling::getFSR2Resolution( + mode, + width, + height, + renderWidth, + renderHeight + ); + + vkcv::ImageConfig depthBufferConfig (renderWidth, renderHeight); targets.depthBuffer = core.createImage( AppConfig::depthBufferFormat, depthBufferConfig ); - vkcv::ImageConfig bufferConfig (width, height); + vkcv::ImageConfig bufferConfig (renderWidth, renderHeight); bufferConfig.setSupportingColorAttachment(true); targets.colorBuffer = core.createImage( @@ -320,6 +333,20 @@ AppRenderTargets createRenderTargets(vkcv::Core& core, const uint32_t width, con AppConfig::motionBufferFormat, bufferConfig ); + + vkcv::ImageConfig finalConfig (width, height); + finalConfig.setSupportingColorAttachment(true); + finalConfig.setSupportingStorage(true); + + targets.finalBuffer = core.createImage( + AppConfig::colorBufferFormat, + finalConfig + ); + + 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 41e020c357a3d868775a581170596e1748e39700..d06910b5f02325d27ee7f2a0e0fbfe4cf7560dab 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 fecdaf98b8429dcb18c8aec811ce40c24eb5d0f4..6b6e2eea46dd6d0e87d2cb8e33ce4c69c4429ca1 100644 --- a/projects/voxelization/src/main.cpp +++ b/projects/voxelization/src/main.cpp @@ -658,7 +658,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 e642139fe71e988488cbd47041599a061b481d93..c9d48456550f786ce6f6ee25d755ad258bc11d1f 100644 --- a/src/vkcv/Context.cpp +++ b/src/vkcv/Context.cpp @@ -426,6 +426,24 @@ namespace vkcv { ); } + 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 + ); + } + if (featureManager.useExtension(VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, false)) { featureManager.useFeatures<vk::PhysicalDeviceIndexTypeUint8FeaturesEXT>( [](vk::PhysicalDeviceIndexTypeUint8FeaturesEXT &features) { @@ -467,13 +485,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/DescriptorSetUsage.cpp b/src/vkcv/DescriptorSetUsage.cpp index 70fc7811791e02d57cb3a4de3d1c2f75db6e9b3a..cfa2ba1998e124cec0f1fc851356d28009288e1b 100644 --- a/src/vkcv/DescriptorSetUsage.cpp +++ b/src/vkcv/DescriptorSetUsage.cpp @@ -5,7 +5,10 @@ namespace vkcv { DescriptorSetUsage useDescriptorSet(uint32_t location, const DescriptorSetHandle &descriptorSet, const std::vector<uint32_t> &dynamicOffsets) { - DescriptorSetUsage usage(location, descriptorSet, dynamicOffsets); + DescriptorSetUsage usage; + usage.location = location; + usage.descriptorSet = descriptorSet; + usage.dynamicOffsets = dynamicOffsets; return usage; } diff --git a/src/vkcv/FeatureManager.cpp b/src/vkcv/FeatureManager.cpp index bc9640c781c33abfb0ac7dee915696ce563bbc0a..afb2ff8c2d91f290718fb9e53edf2c075f7ebe2b 100644 --- a/src/vkcv/FeatureManager.cpp +++ b/src/vkcv/FeatureManager.cpp @@ -477,6 +477,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; + } + bool FeatureManager::checkSupport(const vk::PhysicalDeviceIndexTypeUint8FeaturesEXT &features, bool required) const { vkcv_check_init_features2(vk::PhysicalDeviceIndexTypeUint8FeaturesEXT); diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index fa227fc6c9838b214c027a80ae984f0ce7940704..65c645897520f9e92049824d163b27a1fb5e7124 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -404,20 +404,33 @@ namespace vkcv { const uint32_t mipLevelsMax = image.m_viewPerMip.size(); - if (mipLevelOffset > mipLevelsMax) + if (mipLevelOffset > mipLevelsMax) { mipLevelOffset = mipLevelsMax; + } - if ((!mipLevelCount) || (mipLevelOffset + mipLevelCount > mipLevelsMax)) + 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, diff --git a/src/vkcv/VertexData.cpp b/src/vkcv/VertexData.cpp index 9b9db90166a0be6f0e3a4a5666f837ceba293690..a1fcfb3692fcc6051e237e759ce29c38e4c688f4 100644 --- a/src/vkcv/VertexData.cpp +++ b/src/vkcv/VertexData.cpp @@ -4,7 +4,9 @@ namespace vkcv { VertexBufferBinding vertexBufferBinding(const BufferHandle &buffer, size_t offset) { - VertexBufferBinding binding(buffer, offset); + VertexBufferBinding binding; + binding.buffer = buffer; + binding.offset = offset; return binding; }