diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 021504a8..65a56751 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -125,41 +125,6 @@ jobs: - name: Build run: cmake --build build --parallel $(nproc) - - name: Verify FSR3 wrapper bridge exports (Linux) - run: | - set -euo pipefail - if cmake --build build --target help | grep -q 'wowee_fsr3_vk_wrapper'; then - cmake --build build --target wowee_fsr3_vk_wrapper --parallel $(nproc) - WRAPPER_SO="build/bin/libffx_fsr3_vk_wrapper.so" - if [ -f "$WRAPPER_SO" ]; then - nm -D "$WRAPPER_SO" | grep -q 'wowee_fsr3_wrapper_get_backend' - nm -D "$WRAPPER_SO" | grep -q 'wowee_fsr3_wrapper_get_capabilities' - nm -D "$WRAPPER_SO" | grep -q 'wowee_fsr3_wrapper_dispatch_upscale' - else - echo "Wrapper shared library not found at $WRAPPER_SO" - exit 1 - fi - else - echo "FSR3 wrapper target not generated for this SDK layout; skipping wrapper export verification." - fi - - - name: Run FSR3 wrapper runtime smoke probe (Linux) - run: | - set -euo pipefail - if cmake --build build --target help | grep -q 'wowee_fsr3_wrapper_runtime_smoke'; then - cmake --build build --target wowee_fsr3_wrapper_runtime_smoke --parallel $(nproc) - SMOKE_BIN="build/bin/wowee_fsr3_wrapper_runtime_smoke" - WRAPPER_SO="./build/bin/libffx_fsr3_vk_wrapper.so" - if [ -x "$SMOKE_BIN" ] && [ -f "$WRAPPER_SO" ]; then - "$SMOKE_BIN" "$WRAPPER_SO" - else - echo "Smoke probe binary or wrapper library missing." - exit 1 - fi - else - echo "FSR3 wrapper runtime smoke target not generated for this SDK layout; skipping." - fi - - name: Package (DEB) run: cd build && cpack -G DEB diff --git a/CMakeLists.txt b/CMakeLists.txt index 76f82f10..f3346293 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -18,12 +18,18 @@ set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) +if(WIN32) + # Needed for Vulkan Win32 external memory/semaphore handle types used by FSR3 interop. + add_compile_definitions(VK_USE_PLATFORM_WIN32_KHR) +endif() + # Options option(BUILD_SHARED_LIBS "Build shared libraries" OFF) option(WOWEE_BUILD_TESTS "Build tests" OFF) option(WOWEE_ENABLE_ASAN "Enable AddressSanitizer (Debug builds)" OFF) option(WOWEE_ENABLE_AMD_FSR2 "Enable AMD FidelityFX FSR2 backend when SDK is present" ON) option(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN "Enable AMD FidelityFX SDK FSR3 frame generation interface probe when SDK is present" ON) +option(WOWEE_BUILD_AMD_FSR3_RUNTIME "Build native AMD FidelityFX VK runtime (Path A) from extern/FidelityFX-SDK/Kits" ON) # AMD FidelityFX FSR2 SDK detection (drop-in under extern/FidelityFX-FSR2) set(WOWEE_AMD_FSR2_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-FSR2) @@ -105,8 +111,22 @@ if(EXISTS ${WOWEE_AMD_FFX_SDK_FI_HEADER} set(WOWEE_AMD_FFX_SDK_LEGACY_READY TRUE) endif() -if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_LEGACY_READY) - message(STATUS "AMD FidelityFX-SDK framegen headers detected at ${WOWEE_AMD_FFX_SDK_DIR}") +set(WOWEE_AMD_FFX_SDK_KITS_READY FALSE) +if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/fsr3/include/ffx_fsr3upscaler.h + AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include/ffx_frameinterpolation.h + AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include/ffx_opticalflow.h + AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/backend/vk/ffx_vk.h) + set(WOWEE_AMD_FFX_SDK_KITS_READY TRUE) +endif() + +if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND (WOWEE_AMD_FFX_SDK_LEGACY_READY OR WOWEE_AMD_FFX_SDK_KITS_READY)) + if(WOWEE_AMD_FFX_SDK_LEGACY_READY) + message(STATUS "AMD FidelityFX-SDK framegen headers detected at ${WOWEE_AMD_FFX_SDK_DIR} (legacy layout)") + add_compile_definitions(WOWEE_AMD_FFX_SDK_KITS=0) + else() + message(STATUS "AMD FidelityFX-SDK framegen headers detected at ${WOWEE_AMD_FFX_SDK_KITS_DIR} (Kits layout)") + add_compile_definitions(WOWEE_AMD_FFX_SDK_KITS=1) + endif() add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=1) add_library(wowee_fsr3_framegen_amd_vk_probe STATIC src/rendering/amd_fsr3_framegen_probe.cpp @@ -115,44 +135,80 @@ if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_LEGACY_READY) CXX_STANDARD 17 CXX_STANDARD_REQUIRED ON ) - target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC - ${WOWEE_AMD_FFX_SDK_DIR}/include - ) + if(WOWEE_AMD_FFX_SDK_LEGACY_READY) + target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC + ${WOWEE_AMD_FFX_SDK_DIR}/include + ) + else() + target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC + ${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/fsr3/include + ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include + ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/include + ${WOWEE_AMD_FFX_SDK_KITS_DIR}/backend/vk + ${WOWEE_AMD_FFX_SDK_KITS_DIR}/api/internal + ${WOWEE_AMD_FFX_SDK_KITS_DIR}/api/include + ) + endif() target_link_libraries(wowee_fsr3_framegen_amd_vk_probe PUBLIC Vulkan::Vulkan) - add_library(wowee_fsr3_vk_wrapper SHARED - src/rendering/amd_fsr3_wrapper_impl.cpp - include/rendering/amd_fsr3_wrapper_abi.h - ) - set_target_properties(wowee_fsr3_vk_wrapper PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED ON - OUTPUT_NAME ffx_fsr3_vk_wrapper - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY} - ) - target_include_directories(wowee_fsr3_vk_wrapper PUBLIC - ${CMAKE_SOURCE_DIR}/include - ${WOWEE_AMD_FFX_SDK_DIR}/include - ) - target_link_libraries(wowee_fsr3_vk_wrapper PUBLIC Vulkan::Vulkan ${CMAKE_DL_LIBS}) + if(WOWEE_BUILD_AMD_FSR3_RUNTIME AND WOWEE_AMD_FFX_SDK_KITS_READY) + message(STATUS "AMD FSR3 Path A runtime target enabled: build with target 'wowee_fsr3_official_runtime_copy'") + set(WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR ${CMAKE_BINARY_DIR}/ffx_sdk_runtime_build) + if(WIN32) + set(WOWEE_AMD_FSR3_RUNTIME_NAME amd_fidelityfx_vk.dll) + if(CMAKE_CONFIGURATION_TYPES) + set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/$/amd_fidelityfx_vk.dll) + else() + set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/amd_fidelityfx_vk.dll) + endif() + elseif(APPLE) + set(WOWEE_AMD_FSR3_RUNTIME_NAME libamd_fidelityfx_vk.dylib) + if(CMAKE_CONFIGURATION_TYPES) + set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/$/libamd_fidelityfx_vk.dylib) + else() + set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/libamd_fidelityfx_vk.dylib) + endif() + else() + set(WOWEE_AMD_FSR3_RUNTIME_NAME libamd_fidelityfx_vk.so) + set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/libamd_fidelityfx_vk.so) + endif() + + if(CMAKE_BUILD_TYPE) + set(WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE ${CMAKE_BUILD_TYPE}) + else() + set(WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE Release) + endif() + + add_custom_target(wowee_fsr3_official_runtime_build + COMMAND ${CMAKE_COMMAND} + -S ${WOWEE_AMD_FFX_SDK_KITS_DIR} + -B ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR} + -DCMAKE_BUILD_TYPE=${WOWEE_AMD_FSR3_RUNTIME_BUILD_TYPE} + -DFFX_BUILD_VK=ON + -DFFX_BUILD_FRAMEGENERATION=ON + -DFFX_BUILD_UPSCALER=ON + COMMAND ${CMAKE_COMMAND} + --build ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR} + --config $ + --parallel + COMMENT "Building native AMD FSR3 runtime (Path A) from FidelityFX-SDK Kits" + VERBATIM + ) + + add_custom_target(wowee_fsr3_official_runtime_copy + COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${WOWEE_AMD_FSR3_RUNTIME_SRC} + ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/${WOWEE_AMD_FSR3_RUNTIME_NAME} + DEPENDS wowee_fsr3_official_runtime_build + COMMENT "Copying native AMD FSR3 runtime to ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}" + VERBATIM + ) + endif() - add_executable(wowee_fsr3_wrapper_runtime_smoke - src/rendering/amd_fsr3_wrapper_runtime_smoke.cpp - include/rendering/amd_fsr3_wrapper_abi.h - ) - set_target_properties(wowee_fsr3_wrapper_runtime_smoke PROPERTIES - CXX_STANDARD 17 - CXX_STANDARD_REQUIRED ON - RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY} - ) - target_include_directories(wowee_fsr3_wrapper_runtime_smoke PUBLIC - ${CMAKE_SOURCE_DIR}/include - ) - target_link_libraries(wowee_fsr3_wrapper_runtime_smoke PUBLIC ${CMAKE_DL_LIBS}) else() add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=0) + add_compile_definitions(WOWEE_AMD_FFX_SDK_KITS=0) if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN) if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_FG_HEADER}) message(STATUS "FidelityFX-SDK Kits layout detected at ${WOWEE_AMD_FFX_SDK_KITS_DIR}, " diff --git a/include/third_party/ffx_fsr3_legacy_compat.h b/include/third_party/ffx_fsr3_legacy_compat.h new file mode 100644 index 00000000..64afbec1 --- /dev/null +++ b/include/third_party/ffx_fsr3_legacy_compat.h @@ -0,0 +1,143 @@ +#pragma once + +#include +#include +#include +#include + +// Kits SDK uses FfxApi* type names. Preserve the legacy aliases expected by +// the existing runtime/wrapper code so we can compile against either layout. +using FfxSurfaceFormat = FfxApiSurfaceFormat; +using FfxDimensions2D = FfxApiDimensions2D; +using FfxFloatCoords2D = FfxApiFloatCoords2D; +using FfxResource = FfxApiResource; +using FfxResourceDescription = FfxApiResourceDescription; +using FfxResourceUsage = FfxApiResourceUsage; + +#ifndef FFX_FSR3_CONTEXT_SIZE +#define FFX_FSR3_CONTEXT_SIZE (FFX_SDK_DEFAULT_CONTEXT_SIZE) +#endif + +#ifndef FFX_FSR3_CONTEXT_COUNT +// Combined FSR3 path uses shared + upscaler + frame interpolation contexts. +#define FFX_FSR3_CONTEXT_COUNT (3) +#endif + +#ifndef FFX_RESOURCE_TYPE_TEXTURE2D +#define FFX_RESOURCE_TYPE_TEXTURE2D FFX_API_RESOURCE_TYPE_TEXTURE2D +#endif +#ifndef FFX_RESOURCE_FLAGS_NONE +#define FFX_RESOURCE_FLAGS_NONE FFX_API_RESOURCE_FLAGS_NONE +#endif +#ifndef FFX_RESOURCE_USAGE_READ_ONLY +#define FFX_RESOURCE_USAGE_READ_ONLY FFX_API_RESOURCE_USAGE_READ_ONLY +#endif +#ifndef FFX_RESOURCE_USAGE_UAV +#define FFX_RESOURCE_USAGE_UAV FFX_API_RESOURCE_USAGE_UAV +#endif +#ifndef FFX_RESOURCE_USAGE_DEPTHTARGET +#define FFX_RESOURCE_USAGE_DEPTHTARGET FFX_API_RESOURCE_USAGE_DEPTHTARGET +#endif +#ifndef FFX_RESOURCE_STATE_COMPUTE_READ +#define FFX_RESOURCE_STATE_COMPUTE_READ FFX_API_RESOURCE_STATE_COMPUTE_READ +#endif +#ifndef FFX_RESOURCE_STATE_UNORDERED_ACCESS +#define FFX_RESOURCE_STATE_UNORDERED_ACCESS FFX_API_RESOURCE_STATE_UNORDERED_ACCESS +#endif + +#ifndef FFX_SURFACE_FORMAT_UNKNOWN +#define FFX_SURFACE_FORMAT_UNKNOWN FFX_API_SURFACE_FORMAT_UNKNOWN +#define FFX_SURFACE_FORMAT_R32_FLOAT FFX_API_SURFACE_FORMAT_R32_FLOAT +#define FFX_SURFACE_FORMAT_R16_UNORM FFX_API_SURFACE_FORMAT_R16_UNORM +#define FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT FFX_API_SURFACE_FORMAT_R16G16B16A16_FLOAT +#define FFX_SURFACE_FORMAT_R8G8B8A8_UNORM FFX_API_SURFACE_FORMAT_R8G8B8A8_UNORM +#define FFX_SURFACE_FORMAT_R8G8B8A8_SRGB FFX_API_SURFACE_FORMAT_R8G8B8A8_SRGB +#define FFX_SURFACE_FORMAT_R10G10B10A2_UNORM FFX_API_SURFACE_FORMAT_R10G10B10A2_UNORM +#define FFX_SURFACE_FORMAT_R11G11B10_FLOAT FFX_API_SURFACE_FORMAT_R11G11B10_FLOAT +#define FFX_SURFACE_FORMAT_R16G16_FLOAT FFX_API_SURFACE_FORMAT_R16G16_FLOAT +#define FFX_SURFACE_FORMAT_R16G16_UINT FFX_API_SURFACE_FORMAT_R16G16_UINT +#define FFX_SURFACE_FORMAT_R16_FLOAT FFX_API_SURFACE_FORMAT_R16_FLOAT +#define FFX_SURFACE_FORMAT_R16_UINT FFX_API_SURFACE_FORMAT_R16_UINT +#define FFX_SURFACE_FORMAT_R16_SNORM FFX_API_SURFACE_FORMAT_R16_SNORM +#define FFX_SURFACE_FORMAT_R8_UNORM FFX_API_SURFACE_FORMAT_R8_UNORM +#define FFX_SURFACE_FORMAT_R8_UINT FFX_API_SURFACE_FORMAT_R8_UINT +#define FFX_SURFACE_FORMAT_R8G8_UNORM FFX_API_SURFACE_FORMAT_R8G8_UNORM +#define FFX_SURFACE_FORMAT_R32_UINT FFX_API_SURFACE_FORMAT_R32_UINT +#endif + +#ifndef FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB +#define FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB FFX_API_BACKBUFFER_TRANSFER_FUNCTION_SRGB +#define FFX_BACKBUFFER_TRANSFER_FUNCTION_SCRGB FFX_API_BACKBUFFER_TRANSFER_FUNCTION_SCRGB +#endif + +enum FfxFsr3InitializationFlagBitsCompat { + FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE = (1u << 0), + FFX_FSR3_ENABLE_DISPLAY_RESOLUTION_MOTION_VECTORS = (1u << 1), + FFX_FSR3_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION = (1u << 2), + FFX_FSR3_ENABLE_DEPTH_INVERTED = (1u << 3), + FFX_FSR3_ENABLE_DEPTH_INFINITE = (1u << 4), + FFX_FSR3_ENABLE_AUTO_EXPOSURE = (1u << 5), + FFX_FSR3_ENABLE_DYNAMIC_RESOLUTION = (1u << 6), + FFX_FSR3_ENABLE_UPSCALING_ONLY = (1u << 7) +}; + +typedef struct FfxFsr3ContextDescription { + uint32_t flags; + FfxApiDimensions2D maxRenderSize; + FfxApiDimensions2D displaySize; + FfxApiDimensions2D upscaleOutputSize; + FfxFsr3UpscalerMessage fpMessage; + FfxInterface backendInterfaceSharedResources; + FfxInterface backendInterfaceUpscaling; + FfxInterface backendInterfaceFrameInterpolation; + FfxApiSurfaceFormat backBufferFormat; +} FfxFsr3ContextDescription; + +typedef struct FfxFsr3Context { + uint32_t data[FFX_FSR3_CONTEXT_SIZE]; +} FfxFsr3Context; + +typedef struct FfxFsr3DispatchUpscaleDescription { + FfxCommandList commandList; + FfxApiResource color; + FfxApiResource depth; + FfxApiResource motionVectors; + FfxApiResource exposure; + FfxApiResource reactive; + FfxApiResource transparencyAndComposition; + FfxApiResource upscaleOutput; + FfxApiFloatCoords2D jitterOffset; + FfxApiFloatCoords2D motionVectorScale; + FfxApiDimensions2D renderSize; + bool enableSharpening; + float sharpness; + float frameTimeDelta; + float preExposure; + bool reset; + float cameraNear; + float cameraFar; + float cameraFovAngleVertical; + float viewSpaceToMetersFactor; +} FfxFsr3DispatchUpscaleDescription; + +typedef struct FfxFrameGenerationDispatchDescription { + FfxCommandList commandList; + FfxApiResource presentColor; + FfxApiResource outputs[4]; + uint32_t numInterpolatedFrames; + bool reset; + uint32_t backBufferTransferFunction; + float minMaxLuminance[2]; +} FfxFrameGenerationDispatchDescription; + +#if defined(__cplusplus) +extern "C" { +#endif +FFX_API FfxErrorCode ffxFsr3ContextCreate(FfxFsr3Context* context, const FfxFsr3ContextDescription* contextDescription); +FFX_API FfxErrorCode ffxFsr3ContextDispatchUpscale(FfxFsr3Context* context, const FfxFsr3DispatchUpscaleDescription* dispatchDescription); +FFX_API FfxErrorCode ffxFsr3ConfigureFrameGeneration(FfxFsr3Context* context, const FfxFrameGenerationConfig* config); +FFX_API FfxErrorCode ffxFsr3DispatchFrameGeneration(const FfxFrameGenerationDispatchDescription* dispatchDescription); +FFX_API FfxErrorCode ffxFsr3ContextDestroy(FfxFsr3Context* context); +#if defined(__cplusplus) +} +#endif diff --git a/src/rendering/amd_fsr3_framegen_probe.cpp b/src/rendering/amd_fsr3_framegen_probe.cpp index 7968d1c5..9441cf5d 100644 --- a/src/rendering/amd_fsr3_framegen_probe.cpp +++ b/src/rendering/amd_fsr3_framegen_probe.cpp @@ -1,8 +1,15 @@ #include +#if WOWEE_AMD_FFX_SDK_KITS +#include +#include +#include +#include +#else #include #include #include #include +#endif namespace wowee::rendering { @@ -14,11 +21,14 @@ bool amdFsr3FramegenCompileProbe() { FfxFrameInterpolationContext fiContext{}; FfxOpticalflowContext ofContext{}; FfxInterface backend{}; +#if WOWEE_AMD_FFX_SDK_KITS + FfxApiDimensions2D renderSize{}; +#else FfxDimensions2D renderSize{}; +#endif static_assert(FFX_FSR3UPSCALER_VERSION_MAJOR >= 3, "Expected FSR3 upscaler v3+"); static_assert(FFX_FRAMEINTERPOLATION_VERSION_MAJOR >= 1, "Expected frame interpolation v1+"); - static_assert(FFX_OPTICALFLOW_VERSION_MAJOR >= 1, "Expected optical flow v1+"); (void)fsr3Context; (void)fiContext; diff --git a/src/rendering/amd_fsr3_runtime.cpp b/src/rendering/amd_fsr3_runtime.cpp index 49b716c5..3e03436b 100644 --- a/src/rendering/amd_fsr3_runtime.cpp +++ b/src/rendering/amd_fsr3_runtime.cpp @@ -1,5 +1,4 @@ #include "rendering/amd_fsr3_runtime.hpp" - #include "rendering/amd_fsr3_wrapper_abi.h" #include @@ -18,9 +17,14 @@ #endif #if WOWEE_HAS_AMD_FSR3_FRAMEGEN +#if WOWEE_AMD_FFX_SDK_KITS +#include "third_party/ffx_fsr3_legacy_compat.h" +#include +#else #include #include #endif +#endif namespace wowee::rendering { @@ -57,10 +61,7 @@ AmdFsr3Runtime::~AmdFsr3Runtime() { shutdown(); } -bool AmdFsr3Runtime::hasWrapperExternalInterop() const { - if (loadPathKind_ != LoadPathKind::Wrapper) return false; - return (wrapperCapabilities_ & WOWEE_FSR3_WRAPPER_CAP_EXTERNAL_INTEROP) != 0u; -} +bool AmdFsr3Runtime::hasWrapperExternalInterop() const { return false; } #if WOWEE_HAS_AMD_FSR3_FRAMEGEN namespace { @@ -191,28 +192,22 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) { if (const char* envPath = std::getenv("WOWEE_FFX_SDK_RUNTIME_LIB")) { if (*envPath) candidates.push_back({envPath, LoadPathKind::Official}); } - if (const char* wrapperEnv = std::getenv("WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB")) { - if (*wrapperEnv) candidates.push_back({wrapperEnv, LoadPathKind::Wrapper}); - } #if defined(_WIN32) + candidates.push_back({"amd_fidelityfx_vk.dll", LoadPathKind::Official}); + candidates.push_back({"libamd_fidelityfx_vk.dll", LoadPathKind::Official}); candidates.push_back({"ffx_fsr3_vk.dll", LoadPathKind::Official}); candidates.push_back({"ffx_fsr3.dll", LoadPathKind::Official}); - candidates.push_back({"ffx_fsr3_vk_wrapper.dll", LoadPathKind::Wrapper}); - candidates.push_back({"ffx_fsr3_bridge.dll", LoadPathKind::Wrapper}); #elif defined(__APPLE__) + candidates.push_back({"libamd_fidelityfx_vk.dylib", LoadPathKind::Official}); candidates.push_back({"libffx_fsr3_vk.dylib", LoadPathKind::Official}); candidates.push_back({"libffx_fsr3.dylib", LoadPathKind::Official}); - candidates.push_back({"libffx_fsr3_vk_wrapper.dylib", LoadPathKind::Wrapper}); - candidates.push_back({"libffx_fsr3_bridge.dylib", LoadPathKind::Wrapper}); #else + candidates.push_back({"./libamd_fidelityfx_vk.so", LoadPathKind::Official}); + candidates.push_back({"libamd_fidelityfx_vk.so", LoadPathKind::Official}); candidates.push_back({"./libffx_fsr3_vk.so", LoadPathKind::Official}); candidates.push_back({"libffx_fsr3_vk.so", LoadPathKind::Official}); candidates.push_back({"libffx_fsr3.so", LoadPathKind::Official}); - candidates.push_back({"./libffx_fsr3_vk_wrapper.so", LoadPathKind::Wrapper}); - candidates.push_back({"libffx_fsr3_vk_wrapper.so", LoadPathKind::Wrapper}); - candidates.push_back({"libffx_fsr3_bridge.so", LoadPathKind::Wrapper}); #endif - for (const Candidate& candidate : candidates) { #if defined(_WIN32) HMODULE h = LoadLibraryA(candidate.path.c_str()); @@ -228,7 +223,7 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) { break; } if (!libHandle_) { - lastError_ = "no official runtime (Path A) or wrapper runtime (Path B) found"; + lastError_ = "no official runtime (Path A) found"; return false; } @@ -353,7 +348,11 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) { return false; } +#if WOWEE_AMD_FFX_SDK_KITS + scratchBufferSize_ = fns_->getScratchMemorySizeVK(FFX_FSR3_CONTEXT_COUNT); +#else scratchBufferSize_ = fns_->getScratchMemorySizeVK(desc.physicalDevice, FFX_FSR3_CONTEXT_COUNT); +#endif if (scratchBufferSize_ == 0) { LOG_WARNING("FSR3 runtime: scratch buffer size query returned 0."); lastError_ = "scratch buffer size query returned 0"; @@ -368,14 +367,23 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) { return false; } +#if WOWEE_AMD_FFX_SDK_KITS + FfxDevice ffxDevice = fns_->getDeviceVK(desc.device); +#else VkDeviceContext vkDevCtx{}; vkDevCtx.vkDevice = desc.device; vkDevCtx.vkPhysicalDevice = desc.physicalDevice; vkDevCtx.vkDeviceProcAddr = desc.getDeviceProcAddr; - FfxDevice ffxDevice = fns_->getDeviceVK(&vkDevCtx); +#endif FfxInterface backendShared{}; - FfxErrorCode ifaceErr = fns_->getInterfaceVK(&backendShared, ffxDevice, scratchBuffer_, scratchBufferSize_, FFX_FSR3_CONTEXT_COUNT); +#if WOWEE_AMD_FFX_SDK_KITS + FfxErrorCode ifaceErr = fns_->getInterfaceVK( + &backendShared, ffxDevice, desc.physicalDevice, scratchBuffer_, scratchBufferSize_, FFX_FSR3_CONTEXT_COUNT); +#else + FfxErrorCode ifaceErr = fns_->getInterfaceVK( + &backendShared, ffxDevice, scratchBuffer_, scratchBufferSize_, FFX_FSR3_CONTEXT_COUNT); +#endif if (ifaceErr != FFX_OK) { LOG_WARNING("FSR3 runtime: ffxGetInterfaceVK failed (", static_cast(ifaceErr), ")."); lastError_ = "ffxGetInterfaceVK failed"; @@ -541,13 +549,23 @@ bool AmdFsr3Runtime::dispatchUpscale(const AmdFsr3RuntimeDispatchDesc& desc) { static wchar_t kDepthName[] = L"FSR3_Depth"; static wchar_t kMotionName[] = L"FSR3_MotionVectors"; static wchar_t kOutputName[] = L"FSR3_Output"; + #if WOWEE_AMD_FFX_SDK_KITS + dispatch.color = fns_->getResourceVK(desc.colorImage, colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ); + dispatch.depth = fns_->getResourceVK(desc.depthImage, depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ); + dispatch.motionVectors = fns_->getResourceVK(desc.motionVectorImage, mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ); + #else dispatch.color = fns_->getResourceVK(reinterpret_cast(desc.colorImage), colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ); dispatch.depth = fns_->getResourceVK(reinterpret_cast(desc.depthImage), depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ); dispatch.motionVectors = fns_->getResourceVK(reinterpret_cast(desc.motionVectorImage), mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ); + #endif dispatch.exposure = FfxResource{}; dispatch.reactive = FfxResource{}; dispatch.transparencyAndComposition = FfxResource{}; + #if WOWEE_AMD_FFX_SDK_KITS + dispatch.upscaleOutput = fns_->getResourceVK(desc.outputImage, outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); + #else dispatch.upscaleOutput = fns_->getResourceVK(reinterpret_cast(desc.outputImage), outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); + #endif dispatch.jitterOffset.x = desc.jitterX; dispatch.jitterOffset.y = desc.jitterY; dispatch.motionVectorScale.x = desc.motionScaleX; @@ -658,10 +676,17 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d static wchar_t kInterpolatedName[] = L"FSR3_InterpolatedOutput"; FfxFrameGenerationDispatchDescription fgDispatch{}; fgDispatch.commandList = fns_->getCommandListVK(desc.commandBuffer); + #if WOWEE_AMD_FFX_SDK_KITS + fgDispatch.presentColor = fns_->getResourceVK( + desc.outputImage, presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ); + fgDispatch.outputs[0] = fns_->getResourceVK( + desc.frameGenOutputImage, fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); + #else fgDispatch.presentColor = fns_->getResourceVK( reinterpret_cast(desc.outputImage), presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ); fgDispatch.outputs[0] = fns_->getResourceVK( reinterpret_cast(desc.frameGenOutputImage), fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); + #endif fgDispatch.numInterpolatedFrames = 1; fgDispatch.reset = desc.reset; fgDispatch.backBufferTransferFunction = FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB; diff --git a/src/rendering/amd_fsr3_wrapper_impl.cpp b/src/rendering/amd_fsr3_wrapper_impl.cpp index eede6a72..fd30c976 100644 --- a/src/rendering/amd_fsr3_wrapper_impl.cpp +++ b/src/rendering/amd_fsr3_wrapper_impl.cpp @@ -1,12 +1,20 @@ #include "rendering/amd_fsr3_wrapper_abi.h" #if WOWEE_HAS_AMD_FSR3_FRAMEGEN +#if WOWEE_AMD_FFX_SDK_KITS +#include "third_party/ffx_fsr3_legacy_compat.h" +#include +#if defined(_WIN32) +#include +#endif +#else #include #if defined(_WIN32) #include #endif #include #endif +#endif #include #include @@ -878,7 +886,11 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3W ctx->scratchBufferSize = 0; #endif } else { +#if WOWEE_AMD_FFX_SDK_KITS + ctx->scratchBufferSize = ctx->fns.getScratchMemorySizeVK(FFX_FSR3_CONTEXT_COUNT); +#else ctx->scratchBufferSize = ctx->fns.getScratchMemorySizeVK(initDesc->physicalDevice, FFX_FSR3_CONTEXT_COUNT); +#endif } if (ctx->scratchBufferSize == 0) { destroyContext(ctx); @@ -901,6 +913,11 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3W &backendShared, ffxDevice, ctx->scratchBuffer, ctx->scratchBufferSize, FFX_FSR3_CONTEXT_COUNT); #endif } else { +#if WOWEE_AMD_FFX_SDK_KITS + FfxDevice ffxDevice = ctx->fns.getDeviceVK(initDesc->device); + ifaceErr = ctx->fns.getInterfaceVK( + &backendShared, ffxDevice, initDesc->physicalDevice, ctx->scratchBuffer, ctx->scratchBufferSize, FFX_FSR3_CONTEXT_COUNT); +#else VkDeviceContext vkDevCtx{}; vkDevCtx.vkDevice = initDesc->device; vkDevCtx.vkPhysicalDevice = initDesc->physicalDevice; @@ -908,6 +925,7 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3W FfxDevice ffxDevice = ctx->fns.getDeviceVK(&vkDevCtx); ifaceErr = ctx->fns.getInterfaceVK( &backendShared, ffxDevice, ctx->scratchBuffer, ctx->scratchBufferSize, FFX_FSR3_CONTEXT_COUNT); +#endif } if (ifaceErr != FFX_OK) { const bool wasDx12Backend = (ctx->backend == WrapperBackend::Dx12Bridge); @@ -1108,10 +1126,17 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_dispatch_upscale(WoweeFsr3W #endif } else { dispatch.commandList = ctx->fns.getCommandListVK(dispatchDesc->commandBuffer); +#if WOWEE_AMD_FFX_SDK_KITS + dispatch.color = ctx->fns.getResourceVK(dispatchDesc->colorImage, colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ); + dispatch.depth = ctx->fns.getResourceVK(dispatchDesc->depthImage, depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ); + dispatch.motionVectors = ctx->fns.getResourceVK(dispatchDesc->motionVectorImage, mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ); + dispatch.upscaleOutput = ctx->fns.getResourceVK(dispatchDesc->outputImage, outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); +#else dispatch.color = ctx->fns.getResourceVK(reinterpret_cast(dispatchDesc->colorImage), colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ); dispatch.depth = ctx->fns.getResourceVK(reinterpret_cast(dispatchDesc->depthImage), depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ); dispatch.motionVectors = ctx->fns.getResourceVK(reinterpret_cast(dispatchDesc->motionVectorImage), mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ); dispatch.upscaleOutput = ctx->fns.getResourceVK(reinterpret_cast(dispatchDesc->outputImage), outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); +#endif } dispatch.exposure = FfxResource{}; dispatch.reactive = FfxResource{}; @@ -1289,8 +1314,13 @@ WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_dispatch_framegen(WoweeFsr3 #endif } else { fgDispatch.commandList = ctx->fns.getCommandListVK(dispatchDesc->commandBuffer); +#if WOWEE_AMD_FFX_SDK_KITS + fgDispatch.presentColor = ctx->fns.getResourceVK(dispatchDesc->outputImage, presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ); + fgDispatch.outputs[0] = ctx->fns.getResourceVK(dispatchDesc->frameGenOutputImage, fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); +#else fgDispatch.presentColor = ctx->fns.getResourceVK(reinterpret_cast(dispatchDesc->outputImage), presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ); fgDispatch.outputs[0] = ctx->fns.getResourceVK(reinterpret_cast(dispatchDesc->frameGenOutputImage), fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS); +#endif } fgDispatch.numInterpolatedFrames = 1; fgDispatch.reset = (dispatchDesc->reset != 0u); diff --git a/src/rendering/renderer.cpp b/src/rendering/renderer.cpp index 9319b18d..7f9b6628 100644 --- a/src/rendering/renderer.cpp +++ b/src/rendering/renderer.cpp @@ -119,13 +119,7 @@ static int envIntOrDefault(const char* key, int defaultValue) { #if defined(_WIN32) static uint64_t exportImageMemoryHandleWin32(VkDevice device, PFN_vkGetDeviceProcAddr getDeviceProcAddr, VmaAllocator allocator, const AllocatedImage& image) { -#if !defined(VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR) || !defined(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT) - (void)device; - (void)getDeviceProcAddr; - (void)allocator; - (void)image; - return 0; -#else +#if defined(VK_USE_PLATFORM_WIN32_KHR) && defined(VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR) && defined(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT) if (!device || !getDeviceProcAddr || !allocator || !image.allocation) return 0; auto getMemHandle = reinterpret_cast( getDeviceProcAddr(device, "vkGetMemoryWin32HandleKHR")); @@ -143,17 +137,18 @@ static uint64_t exportImageMemoryHandleWin32(VkDevice device, PFN_vkGetDevicePro HANDLE outHandle = nullptr; if (getMemHandle(device, &handleInfo, &outHandle) != VK_SUCCESS || !outHandle) return 0; return reinterpret_cast(outHandle); +#else + (void)device; + (void)getDeviceProcAddr; + (void)allocator; + (void)image; + return 0; #endif } static uint64_t exportSemaphoreHandleWin32(VkDevice device, PFN_vkGetDeviceProcAddr getDeviceProcAddr, VkSemaphore semaphore) { -#if !defined(VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR) || !defined(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) - (void)device; - (void)getDeviceProcAddr; - (void)semaphore; - return 0; -#else +#if defined(VK_USE_PLATFORM_WIN32_KHR) && defined(VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR) && defined(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT) if (!device || !getDeviceProcAddr || !semaphore) return 0; auto getSemHandle = reinterpret_cast( getDeviceProcAddr(device, "vkGetSemaphoreWin32HandleKHR")); @@ -167,6 +162,11 @@ static uint64_t exportSemaphoreHandleWin32(VkDevice device, PFN_vkGetDeviceProcA HANDLE outHandle = nullptr; if (getSemHandle(device, &handleInfo, &outHandle) != VK_SUCCESS || !outHandle) return 0; return reinterpret_cast(outHandle); +#else + (void)device; + (void)getDeviceProcAddr; + (void)semaphore; + return 0; #endif } #endif @@ -4001,16 +4001,7 @@ bool Renderer::initFSR2Resources() { fsr2_.amdFsr3FramegenRuntimeReady = fsr2_.amdFsr3Runtime->initialize(fgInit); if (fsr2_.amdFsr3FramegenRuntimeReady) { fsr2_.amdFsr3RuntimeLastError.clear(); - if (fsr2_.amdFsr3Runtime->loadPathKind() == AmdFsr3Runtime::LoadPathKind::Wrapper) { - const std::string& wrapperBackend = fsr2_.amdFsr3Runtime->wrapperBackendName(); - if (!wrapperBackend.empty()) { - fsr2_.amdFsr3RuntimePath = "Path B (" + wrapperBackend + ")"; - } else { - fsr2_.amdFsr3RuntimePath = "Path B"; - } - } else { - fsr2_.amdFsr3RuntimePath = "Path A"; - } + fsr2_.amdFsr3RuntimePath = "Path A"; LOG_INFO("FSR3 framegen runtime library loaded from ", fsr2_.amdFsr3Runtime->loadedLibraryPath(), " (upscale+framegen dispatch enabled)"); } else {