mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-02 15:53:51 +00:00
Compare commits
5 commits
78fa10c6ba
...
ae48e4d7a6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ae48e4d7a6 | ||
|
|
e916ef9bda | ||
|
|
1c7b87ee78 | ||
|
|
9ff9f2f1f1 | ||
|
|
725602b5e5 |
14 changed files with 348 additions and 2357 deletions
89
.github/workflows/build.yml
vendored
89
.github/workflows/build.yml
vendored
|
|
@ -82,30 +82,15 @@ jobs:
|
||||||
echo "WoWee CMake will bootstrap vendored headers."
|
echo "WoWee CMake will bootstrap vendored headers."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
- name: Check FidelityFX-SDK Vulkan framegen files
|
- name: Check FidelityFX-SDK Kits framegen headers
|
||||||
run: |
|
run: |
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
SDK_DIR="$PWD/extern/FidelityFX-SDK/sdk"
|
|
||||||
KITS_DIR="$PWD/extern/FidelityFX-SDK/Kits/FidelityFX"
|
KITS_DIR="$PWD/extern/FidelityFX-SDK/Kits/FidelityFX"
|
||||||
LEGACY_OK=0
|
test -f "$KITS_DIR/upscalers/fsr3/include/ffx_fsr3upscaler.h"
|
||||||
KITS_OK=0
|
test -f "$KITS_DIR/framegeneration/fsr3/include/ffx_frameinterpolation.h"
|
||||||
if [ -f "$SDK_DIR/include/FidelityFX/host/ffx_frameinterpolation.h" ]; then
|
test -f "$KITS_DIR/framegeneration/fsr3/include/ffx_opticalflow.h"
|
||||||
LEGACY_OK=1
|
test -f "$KITS_DIR/backend/vk/ffx_vk.h"
|
||||||
fi
|
echo "FidelityFX-SDK Kits framegen headers detected."
|
||||||
if [ -f "$KITS_DIR/framegeneration/include/ffx_framegeneration.h" ]; then
|
|
||||||
KITS_OK=1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$LEGACY_OK" -eq 1 ] && [ -f "$SDK_DIR/include/FidelityFX/gpu/frameinterpolation/ffx_frameinterpolation_callbacks_glsl.h" ] \
|
|
||||||
&& [ -f "$SDK_DIR/include/FidelityFX/gpu/opticalflow/ffx_opticalflow_callbacks_glsl.h" ] \
|
|
||||||
&& [ -f "$SDK_DIR/src/backends/vk/CMakeShadersFrameinterpolation.txt" ] \
|
|
||||||
&& [ -f "$SDK_DIR/src/backends/vk/CMakeShadersOpticalflow.txt" ]; then
|
|
||||||
echo "FidelityFX-SDK legacy Vulkan framegen files detected."
|
|
||||||
elif [ "$KITS_OK" -eq 1 ]; then
|
|
||||||
echo "FidelityFX-SDK Kits layout detected (DX12-focused framegeneration APIs available)."
|
|
||||||
else
|
|
||||||
echo "FidelityFX-SDK Vulkan framegen files are missing in this checkout; build continues."
|
|
||||||
fi
|
|
||||||
|
|
||||||
- name: Configure (AMD ON)
|
- name: Configure (AMD ON)
|
||||||
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWOWEE_ENABLE_AMD_FSR2=ON
|
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DWOWEE_ENABLE_AMD_FSR2=ON
|
||||||
|
|
@ -125,41 +110,6 @@ jobs:
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cmake --build build --parallel $(nproc)
|
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)
|
- name: Package (DEB)
|
||||||
run: cd build && cpack -G DEB
|
run: cd build && cpack -G DEB
|
||||||
|
|
||||||
|
|
@ -267,7 +217,32 @@ jobs:
|
||||||
codesign --force --deep --sign - Wowee.app
|
codesign --force --deep --sign - Wowee.app
|
||||||
|
|
||||||
- name: Create DMG
|
- name: Create DMG
|
||||||
run: hdiutil create -volname Wowee -srcfolder Wowee.app -ov -format UDZO Wowee.dmg
|
run: |
|
||||||
|
set -euo pipefail
|
||||||
|
rm -f Wowee.dmg
|
||||||
|
# CI runners can occasionally leave a mounted volume around; detach if present.
|
||||||
|
if [ -d "/Volumes/Wowee" ]; then
|
||||||
|
hdiutil detach "/Volumes/Wowee" -force || true
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
ok=0
|
||||||
|
for attempt in 1 2 3 4 5; do
|
||||||
|
if hdiutil create -volname Wowee -srcfolder Wowee.app -ov -format UDZO Wowee.dmg; then
|
||||||
|
ok=1
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
echo "hdiutil create failed on attempt ${attempt}; retrying..."
|
||||||
|
if [ -d "/Volumes/Wowee" ]; then
|
||||||
|
hdiutil detach "/Volumes/Wowee" -force || true
|
||||||
|
fi
|
||||||
|
sleep 3
|
||||||
|
done
|
||||||
|
|
||||||
|
if [ "$ok" -ne 1 ] || [ ! -f Wowee.dmg ]; then
|
||||||
|
echo "Failed to create Wowee.dmg after retries."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Upload DMG
|
- name: Upload DMG
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
|
|
|
||||||
127
CMakeLists.txt
127
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_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
|
||||||
set(CMAKE_ARCHIVE_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
|
# Options
|
||||||
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
option(BUILD_SHARED_LIBS "Build shared libraries" OFF)
|
||||||
option(WOWEE_BUILD_TESTS "Build tests" OFF)
|
option(WOWEE_BUILD_TESTS "Build tests" OFF)
|
||||||
option(WOWEE_ENABLE_ASAN "Enable AddressSanitizer (Debug builds)" 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_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_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)
|
# AMD FidelityFX FSR2 SDK detection (drop-in under extern/FidelityFX-FSR2)
|
||||||
set(WOWEE_AMD_FSR2_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-FSR2)
|
set(WOWEE_AMD_FSR2_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-FSR2)
|
||||||
|
|
@ -89,24 +95,20 @@ else()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
# AMD FidelityFX SDK (FSR3 frame generation interfaces) detection under extern/FidelityFX-SDK
|
# AMD FidelityFX SDK (FSR3 frame generation interfaces) detection under extern/FidelityFX-SDK
|
||||||
set(WOWEE_AMD_FFX_SDK_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-SDK/sdk)
|
|
||||||
set(WOWEE_AMD_FFX_SDK_KITS_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-SDK/Kits/FidelityFX)
|
set(WOWEE_AMD_FFX_SDK_KITS_DIR ${CMAKE_SOURCE_DIR}/extern/FidelityFX-SDK/Kits/FidelityFX)
|
||||||
set(WOWEE_AMD_FFX_SDK_FI_HEADER ${WOWEE_AMD_FFX_SDK_DIR}/include/FidelityFX/host/ffx_frameinterpolation.h)
|
|
||||||
set(WOWEE_AMD_FFX_SDK_OF_HEADER ${WOWEE_AMD_FFX_SDK_DIR}/include/FidelityFX/host/ffx_opticalflow.h)
|
|
||||||
set(WOWEE_AMD_FFX_SDK_FSR3_HEADER ${WOWEE_AMD_FFX_SDK_DIR}/include/FidelityFX/host/ffx_fsr3upscaler.h)
|
|
||||||
set(WOWEE_AMD_FFX_SDK_VK_HEADER ${WOWEE_AMD_FFX_SDK_DIR}/include/FidelityFX/host/backends/vk/ffx_vk.h)
|
|
||||||
set(WOWEE_AMD_FFX_SDK_KITS_FG_HEADER ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/include/ffx_framegeneration.h)
|
set(WOWEE_AMD_FFX_SDK_KITS_FG_HEADER ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/include/ffx_framegeneration.h)
|
||||||
|
|
||||||
set(WOWEE_AMD_FFX_SDK_LEGACY_READY FALSE)
|
set(WOWEE_AMD_FFX_SDK_KITS_READY FALSE)
|
||||||
if(EXISTS ${WOWEE_AMD_FFX_SDK_FI_HEADER}
|
if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/fsr3/include/ffx_fsr3upscaler.h
|
||||||
AND EXISTS ${WOWEE_AMD_FFX_SDK_OF_HEADER}
|
AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include/ffx_frameinterpolation.h
|
||||||
AND EXISTS ${WOWEE_AMD_FFX_SDK_FSR3_HEADER}
|
AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/framegeneration/fsr3/include/ffx_opticalflow.h
|
||||||
AND EXISTS ${WOWEE_AMD_FFX_SDK_VK_HEADER})
|
AND EXISTS ${WOWEE_AMD_FFX_SDK_KITS_DIR}/backend/vk/ffx_vk.h)
|
||||||
set(WOWEE_AMD_FFX_SDK_LEGACY_READY TRUE)
|
set(WOWEE_AMD_FFX_SDK_KITS_READY TRUE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_LEGACY_READY)
|
if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_KITS_READY)
|
||||||
message(STATUS "AMD FidelityFX-SDK framegen headers detected at ${WOWEE_AMD_FFX_SDK_DIR}")
|
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)
|
||||||
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=1)
|
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=1)
|
||||||
add_library(wowee_fsr3_framegen_amd_vk_probe STATIC
|
add_library(wowee_fsr3_framegen_amd_vk_probe STATIC
|
||||||
src/rendering/amd_fsr3_framegen_probe.cpp
|
src/rendering/amd_fsr3_framegen_probe.cpp
|
||||||
|
|
@ -116,51 +118,78 @@ if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_LEGACY_READY)
|
||||||
CXX_STANDARD_REQUIRED ON
|
CXX_STANDARD_REQUIRED ON
|
||||||
)
|
)
|
||||||
target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC
|
target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC
|
||||||
${WOWEE_AMD_FFX_SDK_DIR}/include
|
${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
|
||||||
)
|
)
|
||||||
target_link_libraries(wowee_fsr3_framegen_amd_vk_probe PUBLIC Vulkan::Vulkan)
|
target_link_libraries(wowee_fsr3_framegen_amd_vk_probe PUBLIC Vulkan::Vulkan)
|
||||||
|
|
||||||
add_library(wowee_fsr3_vk_wrapper SHARED
|
if(WOWEE_BUILD_AMD_FSR3_RUNTIME)
|
||||||
src/rendering/amd_fsr3_wrapper_impl.cpp
|
message(STATUS "AMD FSR3 Path A runtime target enabled: build with target 'wowee_fsr3_official_runtime_copy'")
|
||||||
include/rendering/amd_fsr3_wrapper_abi.h
|
set(WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR ${CMAKE_BINARY_DIR}/ffx_sdk_runtime_build)
|
||||||
)
|
if(WIN32)
|
||||||
set_target_properties(wowee_fsr3_vk_wrapper PROPERTIES
|
set(WOWEE_AMD_FSR3_RUNTIME_NAME amd_fidelityfx_vk.dll)
|
||||||
CXX_STANDARD 17
|
if(CMAKE_CONFIGURATION_TYPES)
|
||||||
CXX_STANDARD_REQUIRED ON
|
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/$<CONFIG>/amd_fidelityfx_vk.dll)
|
||||||
OUTPUT_NAME ffx_fsr3_vk_wrapper
|
else()
|
||||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/amd_fidelityfx_vk.dll)
|
||||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
endif()
|
||||||
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
|
elseif(APPLE)
|
||||||
)
|
set(WOWEE_AMD_FSR3_RUNTIME_NAME libamd_fidelityfx_vk.dylib)
|
||||||
target_include_directories(wowee_fsr3_vk_wrapper PUBLIC
|
if(CMAKE_CONFIGURATION_TYPES)
|
||||||
${CMAKE_SOURCE_DIR}/include
|
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/$<CONFIG>/libamd_fidelityfx_vk.dylib)
|
||||||
${WOWEE_AMD_FFX_SDK_DIR}/include
|
else()
|
||||||
)
|
set(WOWEE_AMD_FSR3_RUNTIME_SRC ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}/libamd_fidelityfx_vk.dylib)
|
||||||
target_link_libraries(wowee_fsr3_vk_wrapper PUBLIC Vulkan::Vulkan ${CMAKE_DL_LIBS})
|
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 $<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()
|
else()
|
||||||
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=0)
|
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(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN)
|
||||||
if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_FG_HEADER})
|
if(EXISTS ${WOWEE_AMD_FFX_SDK_KITS_FG_HEADER})
|
||||||
message(STATUS "FidelityFX-SDK Kits layout detected at ${WOWEE_AMD_FFX_SDK_KITS_DIR}, "
|
message(STATUS "FidelityFX-SDK Kits layout detected at ${WOWEE_AMD_FFX_SDK_KITS_DIR}, but required FSR3 headers are incomplete. FSR3 framegen interface probe disabled.")
|
||||||
"but legacy sdk/include headers required by WoWee FSR3 probe/wrapper are not present. "
|
|
||||||
"FSR3 framegen interface probe disabled.")
|
|
||||||
else()
|
else()
|
||||||
message(WARNING "AMD FidelityFX-SDK framegen headers not found at ${WOWEE_AMD_FFX_SDK_DIR}; "
|
message(WARNING "AMD FidelityFX-SDK Kits headers not found at ${WOWEE_AMD_FFX_SDK_KITS_DIR}; FSR3 framegen interface probe disabled.")
|
||||||
"FSR3 framegen interface probe disabled.")
|
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
|
||||||
39
README.md
39
README.md
|
|
@ -200,37 +200,12 @@ make -j$(nproc)
|
||||||
- `WOWEE_ENABLE_AMD_FSR3_FRAMEGEN=ON` enables a compile-probe target (`wowee_fsr3_framegen_amd_vk_probe`) that validates SDK FI/OF/FSR3/Vulkan interface headers at build time.
|
- `WOWEE_ENABLE_AMD_FSR3_FRAMEGEN=ON` enables a compile-probe target (`wowee_fsr3_framegen_amd_vk_probe`) that validates SDK FI/OF/FSR3/Vulkan interface headers at build time.
|
||||||
- Runtime toggle:
|
- Runtime toggle:
|
||||||
- In settings, `AMD FSR3 Frame Generation (Experimental)` persists to config.
|
- In settings, `AMD FSR3 Frame Generation (Experimental)` persists to config.
|
||||||
- Runtime library auto-probe checks for `libffx_fsr3_vk`/`ffx_fsr3_vk` in default loader paths.
|
- Runtime library loader is Path A only (official AMD runtime).
|
||||||
- Override runtime library path with:
|
- Auto-probe checks common names (for example `amd_fidelityfx_vk` / `ffx_fsr3_vk`) in loader paths.
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (platform extension varies).
|
- Override runtime path with:
|
||||||
- Wrapper override path:
|
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/<amd-runtime-library>`
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB=/absolute/path/to/libffx_fsr3_vk_wrapper.so` (platform extension varies).
|
- If runtime is missing, FG is cleanly unavailable (Path C).
|
||||||
- In-tree wrapper build:
|
|
||||||
- `wowee_fsr3_vk_wrapper` now builds automatically when FSR3 SDK headers are present and outputs to `build/bin/libffx_fsr3_vk_wrapper.*`.
|
|
||||||
- Wrapper backend override (what the wrapper loads underneath): `WOWEE_FSR3_WRAPPER_BACKEND_LIB=/absolute/path/to/libffx_fsr3_vk.so`.
|
|
||||||
- Wrapper backend mode:
|
|
||||||
- `WOWEE_FSR3_WRAPPER_BACKEND=vulkan_runtime` (default on all platforms)
|
|
||||||
- `WOWEE_FSR3_WRAPPER_BACKEND=dx12_bridge` (opt-in)
|
|
||||||
- If backend mode is not explicitly set and Vulkan-runtime backend loading fails, wrapper now auto-falls back to `dx12_bridge` on Windows and Linux.
|
|
||||||
- DX12 runtime override (for `dx12_bridge`):
|
|
||||||
- `WOWEE_FSR3_DX12_RUNTIME_LIB=C:\\path\\to\\amd_fidelityfx_framegeneration_dx12.dll`
|
|
||||||
- DX12 device validation probe (default on):
|
|
||||||
- `WOWEE_FSR3_WRAPPER_DX12_VALIDATE_DEVICE=1`
|
|
||||||
- Set to `0` to skip adapter/device preflight.
|
|
||||||
- Windows `dx12_bridge` preflight checks Vulkan Win32 interop funcs/extensions before enabling DX12 path.
|
|
||||||
- Linux `dx12_bridge` is enabled for wrapper runtime compatibility mode and uses Vulkan dispatch symbols in this build.
|
|
||||||
- Linux `dx12_bridge` preflight validates Vulkan FD interop funcs/extensions:
|
|
||||||
- `vkGetMemoryFdKHR`, `vkGetSemaphoreFdKHR`
|
|
||||||
- `VK_KHR_external_memory`, `VK_KHR_external_memory_fd`, `VK_KHR_external_semaphore`, `VK_KHR_external_semaphore_fd`
|
|
||||||
- Path B wrapper libraries must export the clean wrapper ABI (`include/rendering/amd_fsr3_wrapper_abi.h`):
|
|
||||||
- ABI version is currently `3` (dispatch includes external-memory/semaphore handles plus acquire/release fence values for bridge sync).
|
|
||||||
- `wowee_fsr3_wrapper_get_abi_version`
|
|
||||||
- `wowee_fsr3_wrapper_get_backend`
|
|
||||||
- `wowee_fsr3_wrapper_initialize`
|
|
||||||
- `wowee_fsr3_wrapper_dispatch_upscale`
|
|
||||||
- `wowee_fsr3_wrapper_shutdown`
|
|
||||||
- Optional FG hook: `wowee_fsr3_wrapper_dispatch_framegen`
|
|
||||||
- Optional diagnostics: `wowee_fsr3_wrapper_get_last_error`, `wowee_fsr3_wrapper_get_capabilities`
|
|
||||||
|
|
||||||
### Current FSR Defaults
|
### Current FSR Defaults
|
||||||
|
|
||||||
|
|
@ -302,7 +277,7 @@ make -j$(nproc)
|
||||||
- GitHub Actions builds on every push: Linux (x86-64, ARM64), Windows (x86-64, ARM64 via MSYS2), macOS (ARM64)
|
- GitHub Actions builds on every push: Linux (x86-64, ARM64), Windows (x86-64, ARM64 via MSYS2), macOS (ARM64)
|
||||||
- All build jobs are AMD-FSR2-only (`WOWEE_ENABLE_AMD_FSR2=ON`) and explicitly build `wowee_fsr2_amd_vk`
|
- All build jobs are AMD-FSR2-only (`WOWEE_ENABLE_AMD_FSR2=ON`) and explicitly build `wowee_fsr2_amd_vk`
|
||||||
- Each job clones AMD's FSR2 SDK and FidelityFX-SDK (`Kelsidavis/FidelityFX-SDK`, `main` by default)
|
- Each job clones AMD's FSR2 SDK and FidelityFX-SDK (`Kelsidavis/FidelityFX-SDK`, `main` by default)
|
||||||
- Linux CI checks FidelityFX-SDK framegen files and supports both legacy (`sdk/...`) and Kits layouts
|
- Linux CI validates FidelityFX-SDK Kits framegen headers
|
||||||
- CI builds `wowee_fsr3_framegen_amd_vk_probe` when that target is generated for the detected SDK layout
|
- CI builds `wowee_fsr3_framegen_amd_vk_probe` when that target is generated for the detected SDK layout
|
||||||
- If FSR2 generated Vulkan permutation headers are absent upstream, WoWee bootstraps them from `third_party/fsr2_vk_permutations`
|
- If FSR2 generated Vulkan permutation headers are absent upstream, WoWee bootstraps them from `third_party/fsr2_vk_permutations`
|
||||||
- Container build via `container/build-in-container.sh` (Podman)
|
- Container build via `container/build-in-container.sh` (Podman)
|
||||||
|
|
|
||||||
|
|
@ -40,50 +40,12 @@ Detection expects:
|
||||||
|
|
||||||
Runtime note:
|
Runtime note:
|
||||||
|
|
||||||
- Renderer/UI now expose a persisted experimental framegen toggle.
|
- Renderer/UI expose a persisted experimental framegen toggle.
|
||||||
- Runtime loader now supports:
|
- Runtime loader is Path A only (official AMD runtime library).
|
||||||
- Path A: AMD SDK runtime binaries (`ffx_fsr3_vk`).
|
|
||||||
- Path B: wrapper runtime libraries implementing WoWee's wrapper ABI.
|
|
||||||
- You can point to an explicit runtime binary with:
|
- You can point to an explicit runtime binary with:
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (or `.dll` / `.dylib`).
|
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (or `.dll` / `.dylib`).
|
||||||
- You can point to an explicit wrapper binary with:
|
- If no official runtime is found, frame generation is disabled cleanly (Path C).
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB=/absolute/path/to/libffx_fsr3_vk_wrapper.so` (or `.dll` / `.dylib`).
|
|
||||||
- WoWee now ships an in-tree wrapper target:
|
|
||||||
- `wowee_fsr3_vk_wrapper` (output in `build/bin`).
|
|
||||||
- Wrapper backend runtime override:
|
|
||||||
- `WOWEE_FSR3_WRAPPER_BACKEND_LIB=/absolute/path/to/libffx_fsr3_vk.so` (or `.dll` / `.dylib`).
|
|
||||||
- Wrapper backend mode selection:
|
|
||||||
- `WOWEE_FSR3_WRAPPER_BACKEND=vulkan_runtime`
|
|
||||||
- `WOWEE_FSR3_WRAPPER_BACKEND=dx12_bridge`
|
|
||||||
- Default is `vulkan_runtime` on all platforms.
|
|
||||||
- If backend mode is not explicitly set and Vulkan-runtime backend loading fails, wrapper auto-falls back to `dx12_bridge` on Windows and Linux.
|
|
||||||
- `dx12_bridge` is opt-in.
|
|
||||||
- On Windows: `dx12_bridge` performs DX12/Vulkan preflight, then loads the first runtime library exposing the required FSR3 dispatch exports.
|
|
||||||
- On Linux: `dx12_bridge` is enabled for wrapper runtime compatibility mode and uses Vulkan dispatch symbols in this build.
|
|
||||||
- Linux bridge preflight validates Vulkan FD interop support:
|
|
||||||
- required device functions: `vkGetMemoryFdKHR`, `vkGetSemaphoreFdKHR`
|
|
||||||
- required device extensions: `VK_KHR_external_memory`, `VK_KHR_external_memory_fd`, `VK_KHR_external_semaphore`, `VK_KHR_external_semaphore_fd`
|
|
||||||
- DX12 bridge runtime override:
|
|
||||||
- `WOWEE_FSR3_DX12_RUNTIME_LIB=<path-to-amd_fidelityfx_framegeneration_dx12.dll>`
|
|
||||||
- DX12 bridge device preflight toggle:
|
|
||||||
- `WOWEE_FSR3_WRAPPER_DX12_VALIDATE_DEVICE=1` (default)
|
|
||||||
- `WOWEE_FSR3_WRAPPER_DX12_VALIDATE_DEVICE=0` to skip DXGI/D3D12 device creation probe
|
|
||||||
- DX12 bridge preflight also validates Vulkan Win32 interop support:
|
|
||||||
- required device functions: `vkGetMemoryWin32HandleKHR`, `vkImportSemaphoreWin32HandleKHR`, `vkGetSemaphoreWin32HandleKHR`
|
|
||||||
- required device extensions: `VK_KHR_external_memory`, `VK_KHR_external_memory_win32`, `VK_KHR_external_semaphore`, `VK_KHR_external_semaphore_win32`
|
|
||||||
- Path B wrapper ABI contract is declared in:
|
|
||||||
- `include/rendering/amd_fsr3_wrapper_abi.h`
|
|
||||||
- Current wrapper ABI version: `3` (dispatch payload carries external memory/semaphore handles and acquire/release fence values for bridge synchronization).
|
|
||||||
- Required wrapper exports:
|
|
||||||
- `wowee_fsr3_wrapper_get_abi_version`
|
|
||||||
- `wowee_fsr3_wrapper_get_backend`
|
|
||||||
- `wowee_fsr3_wrapper_initialize`
|
|
||||||
- `wowee_fsr3_wrapper_dispatch_upscale`
|
|
||||||
- `wowee_fsr3_wrapper_shutdown`
|
|
||||||
- Optional wrapper export:
|
|
||||||
- `wowee_fsr3_wrapper_dispatch_framegen`
|
|
||||||
- `wowee_fsr3_wrapper_get_last_error`
|
|
||||||
- `wowee_fsr3_wrapper_get_capabilities`
|
|
||||||
|
|
||||||
## Current Status
|
## Current Status
|
||||||
|
|
||||||
|
|
@ -109,11 +71,11 @@ Runtime note:
|
||||||
- All build jobs clone:
|
- All build jobs clone:
|
||||||
- `GPUOpen-Effects/FidelityFX-FSR2` (`master`)
|
- `GPUOpen-Effects/FidelityFX-FSR2` (`master`)
|
||||||
- `Kelsidavis/FidelityFX-SDK` (`main`) by default
|
- `Kelsidavis/FidelityFX-SDK` (`main`) by default
|
||||||
- Linux CI additionally checks FidelityFX-SDK framegen files (legacy `sdk/...` and Kits layouts):
|
- Linux CI validates FidelityFX-SDK Kits framegen headers:
|
||||||
- `ffx_frameinterpolation_callbacks_glsl.h`
|
- `upscalers/fsr3/include/ffx_fsr3upscaler.h`
|
||||||
- `ffx_opticalflow_callbacks_glsl.h`
|
- `framegeneration/fsr3/include/ffx_frameinterpolation.h`
|
||||||
- `CMakeShadersFrameinterpolation.txt`
|
- `framegeneration/fsr3/include/ffx_opticalflow.h`
|
||||||
- `CMakeShadersOpticalflow.txt`
|
- `backend/vk/ffx_vk.h`
|
||||||
- CI builds `wowee_fsr3_framegen_amd_vk_probe` when that target is generated by CMake for the detected SDK layout.
|
- CI builds `wowee_fsr3_framegen_amd_vk_probe` when that target is generated by CMake for the detected SDK layout.
|
||||||
- Some upstream SDK checkouts do not include generated Vulkan permutation headers.
|
- Some upstream SDK checkouts do not include generated Vulkan permutation headers.
|
||||||
- WoWee bootstraps those headers from the vendored snapshot so AMD backend builds remain cross-platform and deterministic.
|
- WoWee bootstraps those headers from the vendored snapshot so AMD backend builds remain cross-platform and deterministic.
|
||||||
|
|
|
||||||
|
|
@ -44,24 +44,13 @@ struct AmdFsr3RuntimeDispatchDesc {
|
||||||
float cameraFar = 1000.0f;
|
float cameraFar = 1000.0f;
|
||||||
float cameraFovYRadians = 1.0f;
|
float cameraFovYRadians = 1.0f;
|
||||||
bool reset = false;
|
bool reset = false;
|
||||||
uint32_t externalFlags = 0;
|
|
||||||
uint64_t colorMemoryHandle = 0;
|
|
||||||
uint64_t depthMemoryHandle = 0;
|
|
||||||
uint64_t motionVectorMemoryHandle = 0;
|
|
||||||
uint64_t outputMemoryHandle = 0;
|
|
||||||
uint64_t frameGenOutputMemoryHandle = 0;
|
|
||||||
uint64_t acquireSemaphoreHandle = 0;
|
|
||||||
uint64_t releaseSemaphoreHandle = 0;
|
|
||||||
uint64_t acquireSemaphoreValue = 0;
|
|
||||||
uint64_t releaseSemaphoreValue = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class AmdFsr3Runtime {
|
class AmdFsr3Runtime {
|
||||||
public:
|
public:
|
||||||
enum class LoadPathKind {
|
enum class LoadPathKind {
|
||||||
None,
|
None,
|
||||||
Official,
|
Official
|
||||||
Wrapper
|
|
||||||
};
|
};
|
||||||
|
|
||||||
AmdFsr3Runtime();
|
AmdFsr3Runtime();
|
||||||
|
|
@ -76,18 +65,9 @@ public:
|
||||||
bool isFrameGenerationReady() const { return frameGenerationReady_; }
|
bool isFrameGenerationReady() const { return frameGenerationReady_; }
|
||||||
const std::string& loadedLibraryPath() const { return loadedLibraryPath_; }
|
const std::string& loadedLibraryPath() const { return loadedLibraryPath_; }
|
||||||
LoadPathKind loadPathKind() const { return loadPathKind_; }
|
LoadPathKind loadPathKind() const { return loadPathKind_; }
|
||||||
const std::string& wrapperBackendName() const { return wrapperBackendName_; }
|
|
||||||
uint32_t wrapperCapabilities() const { return wrapperCapabilities_; }
|
|
||||||
bool hasWrapperExternalInterop() const;
|
|
||||||
const std::string& lastError() const { return lastError_; }
|
const std::string& lastError() const { return lastError_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum class RuntimeBackend {
|
|
||||||
None,
|
|
||||||
Official,
|
|
||||||
Wrapper
|
|
||||||
};
|
|
||||||
|
|
||||||
void* libHandle_ = nullptr;
|
void* libHandle_ = nullptr;
|
||||||
std::string loadedLibraryPath_;
|
std::string loadedLibraryPath_;
|
||||||
void* scratchBuffer_ = nullptr;
|
void* scratchBuffer_ = nullptr;
|
||||||
|
|
@ -95,15 +75,11 @@ private:
|
||||||
bool ready_ = false;
|
bool ready_ = false;
|
||||||
bool frameGenerationReady_ = false;
|
bool frameGenerationReady_ = false;
|
||||||
LoadPathKind loadPathKind_ = LoadPathKind::None;
|
LoadPathKind loadPathKind_ = LoadPathKind::None;
|
||||||
std::string wrapperBackendName_;
|
|
||||||
uint32_t wrapperCapabilities_ = 0;
|
|
||||||
std::string lastError_;
|
std::string lastError_;
|
||||||
|
|
||||||
struct RuntimeFns;
|
struct RuntimeFns;
|
||||||
RuntimeFns* fns_ = nullptr;
|
RuntimeFns* fns_ = nullptr;
|
||||||
void* contextStorage_ = nullptr;
|
void* contextStorage_ = nullptr;
|
||||||
void* wrapperContext_ = nullptr;
|
|
||||||
RuntimeBackend backend_ = RuntimeBackend::None;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace wowee::rendering
|
} // namespace wowee::rendering
|
||||||
|
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <vulkan/vulkan.h>
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
extern "C" {
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define WOWEE_FSR3_WRAPPER_ABI_VERSION 3u
|
|
||||||
|
|
||||||
typedef void* WoweeFsr3WrapperContext;
|
|
||||||
|
|
||||||
typedef struct WoweeFsr3WrapperInitDesc {
|
|
||||||
uint32_t structSize;
|
|
||||||
uint32_t abiVersion;
|
|
||||||
VkPhysicalDevice physicalDevice;
|
|
||||||
VkDevice device;
|
|
||||||
PFN_vkGetDeviceProcAddr getDeviceProcAddr;
|
|
||||||
uint32_t maxRenderWidth;
|
|
||||||
uint32_t maxRenderHeight;
|
|
||||||
uint32_t displayWidth;
|
|
||||||
uint32_t displayHeight;
|
|
||||||
VkFormat colorFormat;
|
|
||||||
uint32_t enableFlags;
|
|
||||||
} WoweeFsr3WrapperInitDesc;
|
|
||||||
|
|
||||||
typedef struct WoweeFsr3WrapperDispatchDesc {
|
|
||||||
uint32_t structSize;
|
|
||||||
VkCommandBuffer commandBuffer;
|
|
||||||
VkImage colorImage;
|
|
||||||
VkImage depthImage;
|
|
||||||
VkImage motionVectorImage;
|
|
||||||
VkImage outputImage;
|
|
||||||
VkImage frameGenOutputImage;
|
|
||||||
uint32_t renderWidth;
|
|
||||||
uint32_t renderHeight;
|
|
||||||
uint32_t outputWidth;
|
|
||||||
uint32_t outputHeight;
|
|
||||||
VkFormat colorFormat;
|
|
||||||
VkFormat depthFormat;
|
|
||||||
VkFormat motionVectorFormat;
|
|
||||||
VkFormat outputFormat;
|
|
||||||
float jitterX;
|
|
||||||
float jitterY;
|
|
||||||
float motionScaleX;
|
|
||||||
float motionScaleY;
|
|
||||||
float frameTimeDeltaMs;
|
|
||||||
float cameraNear;
|
|
||||||
float cameraFar;
|
|
||||||
float cameraFovYRadians;
|
|
||||||
uint32_t reset;
|
|
||||||
uint32_t externalFlags;
|
|
||||||
uint64_t colorMemoryHandle;
|
|
||||||
uint64_t depthMemoryHandle;
|
|
||||||
uint64_t motionVectorMemoryHandle;
|
|
||||||
uint64_t outputMemoryHandle;
|
|
||||||
uint64_t frameGenOutputMemoryHandle;
|
|
||||||
uint64_t acquireSemaphoreHandle;
|
|
||||||
uint64_t releaseSemaphoreHandle;
|
|
||||||
uint64_t acquireSemaphoreValue;
|
|
||||||
uint64_t releaseSemaphoreValue;
|
|
||||||
} WoweeFsr3WrapperDispatchDesc;
|
|
||||||
|
|
||||||
enum {
|
|
||||||
WOWEE_FSR3_WRAPPER_ENABLE_HDR_INPUT = 1u << 0,
|
|
||||||
WOWEE_FSR3_WRAPPER_ENABLE_DEPTH_INVERTED = 1u << 1,
|
|
||||||
WOWEE_FSR3_WRAPPER_ENABLE_FRAME_GENERATION = 1u << 2
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_COLOR_MEMORY = 1u << 0,
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_DEPTH_MEMORY = 1u << 1,
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_MOTION_MEMORY = 1u << 2,
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_OUTPUT_MEMORY = 1u << 3,
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_FRAMEGEN_OUTPUT_MEMORY = 1u << 4,
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_ACQUIRE_SEMAPHORE = 1u << 5,
|
|
||||||
WOWEE_FSR3_WRAPPER_EXTERNAL_RELEASE_SEMAPHORE = 1u << 6
|
|
||||||
};
|
|
||||||
|
|
||||||
enum {
|
|
||||||
WOWEE_FSR3_WRAPPER_CAP_UPSCALE = 1u << 0,
|
|
||||||
WOWEE_FSR3_WRAPPER_CAP_FRAME_GENERATION = 1u << 1,
|
|
||||||
WOWEE_FSR3_WRAPPER_CAP_EXTERNAL_INTEROP = 1u << 2
|
|
||||||
};
|
|
||||||
|
|
||||||
uint32_t wowee_fsr3_wrapper_get_abi_version(void);
|
|
||||||
const char* wowee_fsr3_wrapper_get_name(void);
|
|
||||||
const char* wowee_fsr3_wrapper_get_backend(WoweeFsr3WrapperContext context);
|
|
||||||
uint32_t wowee_fsr3_wrapper_get_capabilities(WoweeFsr3WrapperContext context);
|
|
||||||
int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3WrapperInitDesc* initDesc,
|
|
||||||
WoweeFsr3WrapperContext* outContext,
|
|
||||||
char* outErrorText,
|
|
||||||
uint32_t outErrorTextCapacity);
|
|
||||||
int32_t wowee_fsr3_wrapper_dispatch_upscale(WoweeFsr3WrapperContext context,
|
|
||||||
const WoweeFsr3WrapperDispatchDesc* dispatchDesc);
|
|
||||||
int32_t wowee_fsr3_wrapper_dispatch_framegen(WoweeFsr3WrapperContext context,
|
|
||||||
const WoweeFsr3WrapperDispatchDesc* dispatchDesc);
|
|
||||||
void wowee_fsr3_wrapper_shutdown(WoweeFsr3WrapperContext context);
|
|
||||||
const char* wowee_fsr3_wrapper_get_last_error(WoweeFsr3WrapperContext context);
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
@ -33,12 +33,12 @@ struct Plane {
|
||||||
class Frustum {
|
class Frustum {
|
||||||
public:
|
public:
|
||||||
enum Side {
|
enum Side {
|
||||||
LEFT = 0,
|
PLANE_LEFT = 0,
|
||||||
RIGHT,
|
PLANE_RIGHT,
|
||||||
BOTTOM,
|
PLANE_BOTTOM,
|
||||||
TOP,
|
PLANE_TOP,
|
||||||
NEAR,
|
PLANE_NEAR,
|
||||||
FAR
|
PLANE_FAR
|
||||||
};
|
};
|
||||||
|
|
||||||
Frustum() = default;
|
Frustum() = default;
|
||||||
|
|
|
||||||
143
include/third_party/ffx_fsr3_legacy_compat.h
vendored
Normal file
143
include/third_party/ffx_fsr3_legacy_compat.h
vendored
Normal file
|
|
@ -0,0 +1,143 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <ffx_fsr3upscaler.h>
|
||||||
|
#include <ffx_frameinterpolation.h>
|
||||||
|
#include <ffx_opticalflow.h>
|
||||||
|
#include <ffx_framegeneration.h>
|
||||||
|
|
||||||
|
// 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
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <FidelityFX/host/ffx_fsr3upscaler.h>
|
#include <ffx_fsr3upscaler.h>
|
||||||
#include <FidelityFX/host/ffx_frameinterpolation.h>
|
#include <ffx_frameinterpolation.h>
|
||||||
#include <FidelityFX/host/ffx_opticalflow.h>
|
#include <ffx_opticalflow.h>
|
||||||
#include <FidelityFX/host/backends/vk/ffx_vk.h>
|
#include <ffx_vk.h>
|
||||||
|
|
||||||
namespace wowee::rendering {
|
namespace wowee::rendering {
|
||||||
|
|
||||||
|
|
@ -14,11 +14,10 @@ bool amdFsr3FramegenCompileProbe() {
|
||||||
FfxFrameInterpolationContext fiContext{};
|
FfxFrameInterpolationContext fiContext{};
|
||||||
FfxOpticalflowContext ofContext{};
|
FfxOpticalflowContext ofContext{};
|
||||||
FfxInterface backend{};
|
FfxInterface backend{};
|
||||||
FfxDimensions2D renderSize{};
|
FfxApiDimensions2D renderSize{};
|
||||||
|
|
||||||
static_assert(FFX_FSR3UPSCALER_VERSION_MAJOR >= 3, "Expected FSR3 upscaler v3+");
|
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_FRAMEINTERPOLATION_VERSION_MAJOR >= 1, "Expected frame interpolation v1+");
|
||||||
static_assert(FFX_OPTICALFLOW_VERSION_MAJOR >= 1, "Expected optical flow v1+");
|
|
||||||
|
|
||||||
(void)fsr3Context;
|
(void)fsr3Context;
|
||||||
(void)fiContext;
|
(void)fiContext;
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,5 @@
|
||||||
#include "rendering/amd_fsr3_runtime.hpp"
|
#include "rendering/amd_fsr3_runtime.hpp"
|
||||||
|
|
||||||
#include "rendering/amd_fsr3_wrapper_abi.h"
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
@ -18,24 +16,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
#include <FidelityFX/host/ffx_fsr3.h>
|
#include "third_party/ffx_fsr3_legacy_compat.h"
|
||||||
#include <FidelityFX/host/backends/vk/ffx_vk.h>
|
#include <ffx_vk.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace wowee::rendering {
|
namespace wowee::rendering {
|
||||||
|
|
||||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
struct AmdFsr3Runtime::RuntimeFns {
|
struct AmdFsr3Runtime::RuntimeFns {
|
||||||
uint32_t (*wrapperGetAbiVersion)() = nullptr;
|
|
||||||
const char* (*wrapperGetName)() = nullptr;
|
|
||||||
const char* (*wrapperGetBackend)(WoweeFsr3WrapperContext) = nullptr;
|
|
||||||
uint32_t (*wrapperGetCapabilities)(WoweeFsr3WrapperContext) = nullptr;
|
|
||||||
int32_t (*wrapperInitialize)(const WoweeFsr3WrapperInitDesc*, WoweeFsr3WrapperContext*, char*, uint32_t) = nullptr;
|
|
||||||
int32_t (*wrapperDispatchUpscale)(WoweeFsr3WrapperContext, const WoweeFsr3WrapperDispatchDesc*) = nullptr;
|
|
||||||
int32_t (*wrapperDispatchFramegen)(WoweeFsr3WrapperContext, const WoweeFsr3WrapperDispatchDesc*) = nullptr;
|
|
||||||
void (*wrapperShutdown)(WoweeFsr3WrapperContext) = nullptr;
|
|
||||||
const char* (*wrapperGetLastError)(WoweeFsr3WrapperContext) = nullptr;
|
|
||||||
|
|
||||||
decltype(&ffxGetScratchMemorySizeVK) getScratchMemorySizeVK = nullptr;
|
decltype(&ffxGetScratchMemorySizeVK) getScratchMemorySizeVK = nullptr;
|
||||||
decltype(&ffxGetDeviceVK) getDeviceVK = nullptr;
|
decltype(&ffxGetDeviceVK) getDeviceVK = nullptr;
|
||||||
decltype(&ffxGetInterfaceVK) getInterfaceVK = nullptr;
|
decltype(&ffxGetInterfaceVK) getInterfaceVK = nullptr;
|
||||||
|
|
@ -57,11 +45,6 @@ AmdFsr3Runtime::~AmdFsr3Runtime() {
|
||||||
shutdown();
|
shutdown();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool AmdFsr3Runtime::hasWrapperExternalInterop() const {
|
|
||||||
if (loadPathKind_ != LoadPathKind::Wrapper) return false;
|
|
||||||
return (wrapperCapabilities_ & WOWEE_FSR3_WRAPPER_CAP_EXTERNAL_INTEROP) != 0u;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
namespace {
|
namespace {
|
||||||
FfxErrorCode vkSwapchainConfigureNoop(const FfxFrameGenerationConfig*) {
|
FfxErrorCode vkSwapchainConfigureNoop(const FfxFrameGenerationConfig*) {
|
||||||
|
|
@ -165,9 +148,6 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
||||||
shutdown();
|
shutdown();
|
||||||
lastError_.clear();
|
lastError_.clear();
|
||||||
loadPathKind_ = LoadPathKind::None;
|
loadPathKind_ = LoadPathKind::None;
|
||||||
wrapperBackendName_.clear();
|
|
||||||
wrapperCapabilities_ = 0;
|
|
||||||
backend_ = RuntimeBackend::None;
|
|
||||||
|
|
||||||
#if !WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
#if !WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
(void)desc;
|
(void)desc;
|
||||||
|
|
@ -183,52 +163,44 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct Candidate {
|
std::vector<std::string> candidates;
|
||||||
std::string path;
|
|
||||||
LoadPathKind kind = LoadPathKind::Official;
|
|
||||||
};
|
|
||||||
std::vector<Candidate> candidates;
|
|
||||||
if (const char* envPath = std::getenv("WOWEE_FFX_SDK_RUNTIME_LIB")) {
|
if (const char* envPath = std::getenv("WOWEE_FFX_SDK_RUNTIME_LIB")) {
|
||||||
if (*envPath) candidates.push_back({envPath, LoadPathKind::Official});
|
if (*envPath) candidates.emplace_back(envPath);
|
||||||
}
|
|
||||||
if (const char* wrapperEnv = std::getenv("WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB")) {
|
|
||||||
if (*wrapperEnv) candidates.push_back({wrapperEnv, LoadPathKind::Wrapper});
|
|
||||||
}
|
}
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
candidates.push_back({"ffx_fsr3_vk.dll", LoadPathKind::Official});
|
candidates.emplace_back("amd_fidelityfx_vk.dll");
|
||||||
candidates.push_back({"ffx_fsr3.dll", LoadPathKind::Official});
|
candidates.emplace_back("libamd_fidelityfx_vk.dll");
|
||||||
candidates.push_back({"ffx_fsr3_vk_wrapper.dll", LoadPathKind::Wrapper});
|
candidates.emplace_back("ffx_fsr3_vk.dll");
|
||||||
candidates.push_back({"ffx_fsr3_bridge.dll", LoadPathKind::Wrapper});
|
candidates.emplace_back("ffx_fsr3.dll");
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
candidates.push_back({"libffx_fsr3_vk.dylib", LoadPathKind::Official});
|
candidates.emplace_back("libamd_fidelityfx_vk.dylib");
|
||||||
candidates.push_back({"libffx_fsr3.dylib", LoadPathKind::Official});
|
candidates.emplace_back("libffx_fsr3_vk.dylib");
|
||||||
candidates.push_back({"libffx_fsr3_vk_wrapper.dylib", LoadPathKind::Wrapper});
|
candidates.emplace_back("libffx_fsr3.dylib");
|
||||||
candidates.push_back({"libffx_fsr3_bridge.dylib", LoadPathKind::Wrapper});
|
|
||||||
#else
|
#else
|
||||||
candidates.push_back({"./libffx_fsr3_vk.so", LoadPathKind::Official});
|
candidates.emplace_back("./libamd_fidelityfx_vk.so");
|
||||||
candidates.push_back({"libffx_fsr3_vk.so", LoadPathKind::Official});
|
candidates.emplace_back("libamd_fidelityfx_vk.so");
|
||||||
candidates.push_back({"libffx_fsr3.so", LoadPathKind::Official});
|
candidates.emplace_back("./libffx_fsr3_vk.so");
|
||||||
candidates.push_back({"./libffx_fsr3_vk_wrapper.so", LoadPathKind::Wrapper});
|
candidates.emplace_back("libffx_fsr3_vk.so");
|
||||||
candidates.push_back({"libffx_fsr3_vk_wrapper.so", LoadPathKind::Wrapper});
|
candidates.emplace_back("libffx_fsr3.so");
|
||||||
candidates.push_back({"libffx_fsr3_bridge.so", LoadPathKind::Wrapper});
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
for (const Candidate& candidate : candidates) {
|
for (const std::string& path : candidates) {
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
HMODULE h = LoadLibraryA(candidate.path.c_str());
|
HMODULE h = LoadLibraryA(path.c_str());
|
||||||
if (!h) continue;
|
if (!h) continue;
|
||||||
libHandle_ = reinterpret_cast<void*>(h);
|
libHandle_ = reinterpret_cast<void*>(h);
|
||||||
#else
|
#else
|
||||||
void* h = dlopen(candidate.path.c_str(), RTLD_NOW | RTLD_LOCAL);
|
void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
|
||||||
if (!h) continue;
|
if (!h) continue;
|
||||||
libHandle_ = h;
|
libHandle_ = h;
|
||||||
#endif
|
#endif
|
||||||
loadedLibraryPath_ = candidate.path;
|
loadedLibraryPath_ = path;
|
||||||
loadPathKind_ = candidate.kind;
|
loadPathKind_ = LoadPathKind::Official;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!libHandle_) {
|
if (!libHandle_) {
|
||||||
lastError_ = "no official runtime (Path A) or wrapper runtime (Path B) found";
|
lastError_ = "no official runtime (Path A) found";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -241,98 +213,6 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
||||||
};
|
};
|
||||||
|
|
||||||
fns_ = new RuntimeFns{};
|
fns_ = new RuntimeFns{};
|
||||||
if (loadPathKind_ == LoadPathKind::Wrapper) {
|
|
||||||
fns_->wrapperGetAbiVersion = reinterpret_cast<decltype(fns_->wrapperGetAbiVersion)>(resolveSym("wowee_fsr3_wrapper_get_abi_version"));
|
|
||||||
fns_->wrapperGetName = reinterpret_cast<decltype(fns_->wrapperGetName)>(resolveSym("wowee_fsr3_wrapper_get_name"));
|
|
||||||
fns_->wrapperGetBackend = reinterpret_cast<decltype(fns_->wrapperGetBackend)>(resolveSym("wowee_fsr3_wrapper_get_backend"));
|
|
||||||
fns_->wrapperGetCapabilities = reinterpret_cast<decltype(fns_->wrapperGetCapabilities)>(resolveSym("wowee_fsr3_wrapper_get_capabilities"));
|
|
||||||
fns_->wrapperInitialize = reinterpret_cast<decltype(fns_->wrapperInitialize)>(resolveSym("wowee_fsr3_wrapper_initialize"));
|
|
||||||
fns_->wrapperDispatchUpscale = reinterpret_cast<decltype(fns_->wrapperDispatchUpscale)>(resolveSym("wowee_fsr3_wrapper_dispatch_upscale"));
|
|
||||||
fns_->wrapperDispatchFramegen = reinterpret_cast<decltype(fns_->wrapperDispatchFramegen)>(resolveSym("wowee_fsr3_wrapper_dispatch_framegen"));
|
|
||||||
fns_->wrapperShutdown = reinterpret_cast<decltype(fns_->wrapperShutdown)>(resolveSym("wowee_fsr3_wrapper_shutdown"));
|
|
||||||
fns_->wrapperGetLastError = reinterpret_cast<decltype(fns_->wrapperGetLastError)>(resolveSym("wowee_fsr3_wrapper_get_last_error"));
|
|
||||||
|
|
||||||
if (!fns_->wrapperGetAbiVersion || !fns_->wrapperInitialize ||
|
|
||||||
!fns_->wrapperDispatchUpscale || !fns_->wrapperShutdown) {
|
|
||||||
LOG_WARNING("FSR3 runtime: required wrapper ABI symbols not found in ", loadedLibraryPath_);
|
|
||||||
lastError_ = "missing required wowee_fsr3_wrapper_* symbols";
|
|
||||||
shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32_t abiVersion = fns_->wrapperGetAbiVersion();
|
|
||||||
if (abiVersion != WOWEE_FSR3_WRAPPER_ABI_VERSION) {
|
|
||||||
LOG_WARNING("FSR3 runtime: wrapper ABI mismatch. expected=", WOWEE_FSR3_WRAPPER_ABI_VERSION,
|
|
||||||
" got=", abiVersion);
|
|
||||||
lastError_ = "wrapper ABI version mismatch";
|
|
||||||
shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (desc.enableFrameGeneration && !fns_->wrapperDispatchFramegen) {
|
|
||||||
LOG_WARNING("FSR3 runtime: wrapper runtime missing framegen dispatch symbol.");
|
|
||||||
lastError_ = "wrapper missing frame generation entry points";
|
|
||||||
shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
WoweeFsr3WrapperInitDesc wrapperInit{};
|
|
||||||
wrapperInit.structSize = sizeof(wrapperInit);
|
|
||||||
wrapperInit.abiVersion = WOWEE_FSR3_WRAPPER_ABI_VERSION;
|
|
||||||
wrapperInit.physicalDevice = desc.physicalDevice;
|
|
||||||
wrapperInit.device = desc.device;
|
|
||||||
wrapperInit.getDeviceProcAddr = desc.getDeviceProcAddr;
|
|
||||||
wrapperInit.maxRenderWidth = desc.maxRenderWidth;
|
|
||||||
wrapperInit.maxRenderHeight = desc.maxRenderHeight;
|
|
||||||
wrapperInit.displayWidth = desc.displayWidth;
|
|
||||||
wrapperInit.displayHeight = desc.displayHeight;
|
|
||||||
wrapperInit.colorFormat = desc.colorFormat;
|
|
||||||
wrapperInit.enableFlags = 0;
|
|
||||||
if (desc.hdrInput) wrapperInit.enableFlags |= WOWEE_FSR3_WRAPPER_ENABLE_HDR_INPUT;
|
|
||||||
if (desc.depthInverted) wrapperInit.enableFlags |= WOWEE_FSR3_WRAPPER_ENABLE_DEPTH_INVERTED;
|
|
||||||
if (desc.enableFrameGeneration) wrapperInit.enableFlags |= WOWEE_FSR3_WRAPPER_ENABLE_FRAME_GENERATION;
|
|
||||||
|
|
||||||
char errorText[256] = {};
|
|
||||||
WoweeFsr3WrapperContext wrapperCtx = nullptr;
|
|
||||||
if (fns_->wrapperInitialize(&wrapperInit, &wrapperCtx, errorText, static_cast<uint32_t>(sizeof(errorText))) != 0 || !wrapperCtx) {
|
|
||||||
LOG_WARNING("FSR3 runtime: wrapper initialization failed: ", errorText[0] ? errorText : "unknown error");
|
|
||||||
lastError_ = errorText[0] ? errorText : "wrapper initialization failed";
|
|
||||||
shutdown();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
wrapperContext_ = wrapperCtx;
|
|
||||||
frameGenerationReady_ = false;
|
|
||||||
ready_ = true;
|
|
||||||
backend_ = RuntimeBackend::Wrapper;
|
|
||||||
uint32_t wrapperCaps = 0;
|
|
||||||
if (fns_->wrapperGetCapabilities) {
|
|
||||||
wrapperCaps = fns_->wrapperGetCapabilities(wrapperCtx);
|
|
||||||
} else {
|
|
||||||
wrapperCaps = WOWEE_FSR3_WRAPPER_CAP_UPSCALE;
|
|
||||||
if (fns_->wrapperDispatchFramegen) {
|
|
||||||
wrapperCaps |= WOWEE_FSR3_WRAPPER_CAP_FRAME_GENERATION;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
wrapperCapabilities_ = wrapperCaps;
|
|
||||||
frameGenerationReady_ = desc.enableFrameGeneration &&
|
|
||||||
((wrapperCaps & WOWEE_FSR3_WRAPPER_CAP_FRAME_GENERATION) != 0u);
|
|
||||||
if (fns_->wrapperGetBackend) {
|
|
||||||
const char* backendName = fns_->wrapperGetBackend(wrapperCtx);
|
|
||||||
if (backendName && *backendName) wrapperBackendName_ = backendName;
|
|
||||||
}
|
|
||||||
if (fns_->wrapperGetName) {
|
|
||||||
const char* wrapperName = fns_->wrapperGetName();
|
|
||||||
if (wrapperName && *wrapperName) {
|
|
||||||
LOG_INFO("FSR3 runtime: wrapper active: ", wrapperName,
|
|
||||||
" backend=", wrapperBackendName_.empty() ? "unknown" : wrapperBackendName_,
|
|
||||||
" caps=0x", static_cast<unsigned int>(wrapperCaps));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
LOG_INFO("FSR3 runtime: loaded wrapper library ", loadedLibraryPath_,
|
|
||||||
" framegenReady=", frameGenerationReady_ ? "yes" : "no");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
fns_->getScratchMemorySizeVK = reinterpret_cast<decltype(fns_->getScratchMemorySizeVK)>(resolveSym("ffxGetScratchMemorySizeVK"));
|
fns_->getScratchMemorySizeVK = reinterpret_cast<decltype(fns_->getScratchMemorySizeVK)>(resolveSym("ffxGetScratchMemorySizeVK"));
|
||||||
fns_->getDeviceVK = reinterpret_cast<decltype(fns_->getDeviceVK)>(resolveSym("ffxGetDeviceVK"));
|
fns_->getDeviceVK = reinterpret_cast<decltype(fns_->getDeviceVK)>(resolveSym("ffxGetDeviceVK"));
|
||||||
fns_->getInterfaceVK = reinterpret_cast<decltype(fns_->getInterfaceVK)>(resolveSym("ffxGetInterfaceVK"));
|
fns_->getInterfaceVK = reinterpret_cast<decltype(fns_->getInterfaceVK)>(resolveSym("ffxGetInterfaceVK"));
|
||||||
|
|
@ -353,13 +233,14 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scratchBufferSize_ = fns_->getScratchMemorySizeVK(desc.physicalDevice, FFX_FSR3_CONTEXT_COUNT);
|
scratchBufferSize_ = fns_->getScratchMemorySizeVK(FFX_FSR3_CONTEXT_COUNT);
|
||||||
if (scratchBufferSize_ == 0) {
|
if (scratchBufferSize_ == 0) {
|
||||||
LOG_WARNING("FSR3 runtime: scratch buffer size query returned 0.");
|
LOG_WARNING("FSR3 runtime: scratch buffer size query returned 0.");
|
||||||
lastError_ = "scratch buffer size query returned 0";
|
lastError_ = "scratch buffer size query returned 0";
|
||||||
shutdown();
|
shutdown();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
scratchBuffer_ = std::malloc(scratchBufferSize_);
|
scratchBuffer_ = std::malloc(scratchBufferSize_);
|
||||||
if (!scratchBuffer_) {
|
if (!scratchBuffer_) {
|
||||||
LOG_WARNING("FSR3 runtime: failed to allocate scratch buffer.");
|
LOG_WARNING("FSR3 runtime: failed to allocate scratch buffer.");
|
||||||
|
|
@ -368,14 +249,11 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
VkDeviceContext vkDevCtx{};
|
FfxDevice ffxDevice = fns_->getDeviceVK(desc.device);
|
||||||
vkDevCtx.vkDevice = desc.device;
|
|
||||||
vkDevCtx.vkPhysicalDevice = desc.physicalDevice;
|
|
||||||
vkDevCtx.vkDeviceProcAddr = desc.getDeviceProcAddr;
|
|
||||||
|
|
||||||
FfxDevice ffxDevice = fns_->getDeviceVK(&vkDevCtx);
|
|
||||||
FfxInterface backendShared{};
|
FfxInterface backendShared{};
|
||||||
FfxErrorCode ifaceErr = fns_->getInterfaceVK(&backendShared, ffxDevice, scratchBuffer_, scratchBufferSize_, FFX_FSR3_CONTEXT_COUNT);
|
FfxErrorCode ifaceErr = fns_->getInterfaceVK(
|
||||||
|
&backendShared, ffxDevice, desc.physicalDevice, scratchBuffer_, scratchBufferSize_, FFX_FSR3_CONTEXT_COUNT);
|
||||||
if (ifaceErr != FFX_OK) {
|
if (ifaceErr != FFX_OK) {
|
||||||
LOG_WARNING("FSR3 runtime: ffxGetInterfaceVK failed (", static_cast<int>(ifaceErr), ").");
|
LOG_WARNING("FSR3 runtime: ffxGetInterfaceVK failed (", static_cast<int>(ifaceErr), ").");
|
||||||
lastError_ = "ffxGetInterfaceVK failed";
|
lastError_ = "ffxGetInterfaceVK failed";
|
||||||
|
|
@ -446,7 +324,6 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ready_ = true;
|
ready_ = true;
|
||||||
backend_ = RuntimeBackend::Official;
|
|
||||||
LOG_INFO("FSR3 runtime: loaded official library ", loadedLibraryPath_,
|
LOG_INFO("FSR3 runtime: loaded official library ", loadedLibraryPath_,
|
||||||
" framegenReady=", frameGenerationReady_ ? "yes" : "no");
|
" framegenReady=", frameGenerationReady_ ? "yes" : "no");
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -467,60 +344,6 @@ bool AmdFsr3Runtime::dispatchUpscale(const AmdFsr3RuntimeDispatchDesc& desc) {
|
||||||
lastError_ = "invalid upscale dispatch resources";
|
lastError_ = "invalid upscale dispatch resources";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (backend_ == RuntimeBackend::Wrapper) {
|
|
||||||
if (!wrapperContext_ || !fns_->wrapperDispatchUpscale) {
|
|
||||||
lastError_ = "wrapper upscale entry points unavailable";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
WoweeFsr3WrapperDispatchDesc wrapperDesc{};
|
|
||||||
wrapperDesc.structSize = sizeof(wrapperDesc);
|
|
||||||
wrapperDesc.commandBuffer = desc.commandBuffer;
|
|
||||||
wrapperDesc.colorImage = desc.colorImage;
|
|
||||||
wrapperDesc.depthImage = desc.depthImage;
|
|
||||||
wrapperDesc.motionVectorImage = desc.motionVectorImage;
|
|
||||||
wrapperDesc.outputImage = desc.outputImage;
|
|
||||||
wrapperDesc.frameGenOutputImage = desc.frameGenOutputImage;
|
|
||||||
wrapperDesc.renderWidth = desc.renderWidth;
|
|
||||||
wrapperDesc.renderHeight = desc.renderHeight;
|
|
||||||
wrapperDesc.outputWidth = desc.outputWidth;
|
|
||||||
wrapperDesc.outputHeight = desc.outputHeight;
|
|
||||||
wrapperDesc.colorFormat = desc.colorFormat;
|
|
||||||
wrapperDesc.depthFormat = desc.depthFormat;
|
|
||||||
wrapperDesc.motionVectorFormat = desc.motionVectorFormat;
|
|
||||||
wrapperDesc.outputFormat = desc.outputFormat;
|
|
||||||
wrapperDesc.jitterX = desc.jitterX;
|
|
||||||
wrapperDesc.jitterY = desc.jitterY;
|
|
||||||
wrapperDesc.motionScaleX = desc.motionScaleX;
|
|
||||||
wrapperDesc.motionScaleY = desc.motionScaleY;
|
|
||||||
wrapperDesc.frameTimeDeltaMs = desc.frameTimeDeltaMs;
|
|
||||||
wrapperDesc.cameraNear = desc.cameraNear;
|
|
||||||
wrapperDesc.cameraFar = desc.cameraFar;
|
|
||||||
wrapperDesc.cameraFovYRadians = desc.cameraFovYRadians;
|
|
||||||
wrapperDesc.reset = desc.reset ? 1u : 0u;
|
|
||||||
wrapperDesc.externalFlags = desc.externalFlags;
|
|
||||||
wrapperDesc.colorMemoryHandle = desc.colorMemoryHandle;
|
|
||||||
wrapperDesc.depthMemoryHandle = desc.depthMemoryHandle;
|
|
||||||
wrapperDesc.motionVectorMemoryHandle = desc.motionVectorMemoryHandle;
|
|
||||||
wrapperDesc.outputMemoryHandle = desc.outputMemoryHandle;
|
|
||||||
wrapperDesc.frameGenOutputMemoryHandle = desc.frameGenOutputMemoryHandle;
|
|
||||||
wrapperDesc.acquireSemaphoreHandle = desc.acquireSemaphoreHandle;
|
|
||||||
wrapperDesc.releaseSemaphoreHandle = desc.releaseSemaphoreHandle;
|
|
||||||
wrapperDesc.acquireSemaphoreValue = desc.acquireSemaphoreValue;
|
|
||||||
wrapperDesc.releaseSemaphoreValue = desc.releaseSemaphoreValue;
|
|
||||||
const bool ok = fns_->wrapperDispatchUpscale(static_cast<WoweeFsr3WrapperContext>(wrapperContext_), &wrapperDesc) == 0;
|
|
||||||
if (!ok) {
|
|
||||||
if (fns_->wrapperGetLastError) {
|
|
||||||
const char* err = fns_->wrapperGetLastError(static_cast<WoweeFsr3WrapperContext>(wrapperContext_));
|
|
||||||
lastError_ = (err && *err) ? err : "wrapper upscale dispatch failed";
|
|
||||||
} else {
|
|
||||||
lastError_ = "wrapper upscale dispatch failed";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lastError_.clear();
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contextStorage_ || !fns_->fsr3ContextDispatchUpscale) {
|
if (!contextStorage_ || !fns_->fsr3ContextDispatchUpscale) {
|
||||||
lastError_ = "official runtime upscale context unavailable";
|
lastError_ = "official runtime upscale context unavailable";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -541,13 +364,13 @@ bool AmdFsr3Runtime::dispatchUpscale(const AmdFsr3RuntimeDispatchDesc& desc) {
|
||||||
static wchar_t kDepthName[] = L"FSR3_Depth";
|
static wchar_t kDepthName[] = L"FSR3_Depth";
|
||||||
static wchar_t kMotionName[] = L"FSR3_MotionVectors";
|
static wchar_t kMotionName[] = L"FSR3_MotionVectors";
|
||||||
static wchar_t kOutputName[] = L"FSR3_Output";
|
static wchar_t kOutputName[] = L"FSR3_Output";
|
||||||
dispatch.color = fns_->getResourceVK(reinterpret_cast<void*>(desc.colorImage), colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
dispatch.color = fns_->getResourceVK(desc.colorImage, colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
dispatch.depth = fns_->getResourceVK(reinterpret_cast<void*>(desc.depthImage), depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
dispatch.depth = fns_->getResourceVK(desc.depthImage, depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
dispatch.motionVectors = fns_->getResourceVK(reinterpret_cast<void*>(desc.motionVectorImage), mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
dispatch.motionVectors = fns_->getResourceVK(desc.motionVectorImage, mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
dispatch.exposure = FfxResource{};
|
dispatch.exposure = FfxResource{};
|
||||||
dispatch.reactive = FfxResource{};
|
dispatch.reactive = FfxResource{};
|
||||||
dispatch.transparencyAndComposition = FfxResource{};
|
dispatch.transparencyAndComposition = FfxResource{};
|
||||||
dispatch.upscaleOutput = fns_->getResourceVK(reinterpret_cast<void*>(desc.outputImage), outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
dispatch.upscaleOutput = fns_->getResourceVK(desc.outputImage, outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||||
dispatch.jitterOffset.x = desc.jitterX;
|
dispatch.jitterOffset.x = desc.jitterX;
|
||||||
dispatch.jitterOffset.y = desc.jitterY;
|
dispatch.jitterOffset.y = desc.jitterY;
|
||||||
dispatch.motionVectorScale.x = desc.motionScaleX;
|
dispatch.motionVectorScale.x = desc.motionScaleX;
|
||||||
|
|
@ -590,60 +413,6 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
||||||
lastError_ = "invalid frame generation dispatch resources";
|
lastError_ = "invalid frame generation dispatch resources";
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (backend_ == RuntimeBackend::Wrapper) {
|
|
||||||
if (!wrapperContext_ || !fns_->wrapperDispatchFramegen) {
|
|
||||||
lastError_ = "wrapper frame generation entry points unavailable";
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
WoweeFsr3WrapperDispatchDesc wrapperDesc{};
|
|
||||||
wrapperDesc.structSize = sizeof(wrapperDesc);
|
|
||||||
wrapperDesc.commandBuffer = desc.commandBuffer;
|
|
||||||
wrapperDesc.colorImage = desc.colorImage;
|
|
||||||
wrapperDesc.depthImage = desc.depthImage;
|
|
||||||
wrapperDesc.motionVectorImage = desc.motionVectorImage;
|
|
||||||
wrapperDesc.outputImage = desc.outputImage;
|
|
||||||
wrapperDesc.frameGenOutputImage = desc.frameGenOutputImage;
|
|
||||||
wrapperDesc.renderWidth = desc.renderWidth;
|
|
||||||
wrapperDesc.renderHeight = desc.renderHeight;
|
|
||||||
wrapperDesc.outputWidth = desc.outputWidth;
|
|
||||||
wrapperDesc.outputHeight = desc.outputHeight;
|
|
||||||
wrapperDesc.colorFormat = desc.colorFormat;
|
|
||||||
wrapperDesc.depthFormat = desc.depthFormat;
|
|
||||||
wrapperDesc.motionVectorFormat = desc.motionVectorFormat;
|
|
||||||
wrapperDesc.outputFormat = desc.outputFormat;
|
|
||||||
wrapperDesc.jitterX = desc.jitterX;
|
|
||||||
wrapperDesc.jitterY = desc.jitterY;
|
|
||||||
wrapperDesc.motionScaleX = desc.motionScaleX;
|
|
||||||
wrapperDesc.motionScaleY = desc.motionScaleY;
|
|
||||||
wrapperDesc.frameTimeDeltaMs = desc.frameTimeDeltaMs;
|
|
||||||
wrapperDesc.cameraNear = desc.cameraNear;
|
|
||||||
wrapperDesc.cameraFar = desc.cameraFar;
|
|
||||||
wrapperDesc.cameraFovYRadians = desc.cameraFovYRadians;
|
|
||||||
wrapperDesc.reset = desc.reset ? 1u : 0u;
|
|
||||||
wrapperDesc.externalFlags = desc.externalFlags;
|
|
||||||
wrapperDesc.colorMemoryHandle = desc.colorMemoryHandle;
|
|
||||||
wrapperDesc.depthMemoryHandle = desc.depthMemoryHandle;
|
|
||||||
wrapperDesc.motionVectorMemoryHandle = desc.motionVectorMemoryHandle;
|
|
||||||
wrapperDesc.outputMemoryHandle = desc.outputMemoryHandle;
|
|
||||||
wrapperDesc.frameGenOutputMemoryHandle = desc.frameGenOutputMemoryHandle;
|
|
||||||
wrapperDesc.acquireSemaphoreHandle = desc.acquireSemaphoreHandle;
|
|
||||||
wrapperDesc.releaseSemaphoreHandle = desc.releaseSemaphoreHandle;
|
|
||||||
wrapperDesc.acquireSemaphoreValue = desc.acquireSemaphoreValue;
|
|
||||||
wrapperDesc.releaseSemaphoreValue = desc.releaseSemaphoreValue;
|
|
||||||
const bool ok = fns_->wrapperDispatchFramegen(static_cast<WoweeFsr3WrapperContext>(wrapperContext_), &wrapperDesc) == 0;
|
|
||||||
if (!ok) {
|
|
||||||
if (fns_->wrapperGetLastError) {
|
|
||||||
const char* err = fns_->wrapperGetLastError(static_cast<WoweeFsr3WrapperContext>(wrapperContext_));
|
|
||||||
lastError_ = (err && *err) ? err : "wrapper frame generation dispatch failed";
|
|
||||||
} else {
|
|
||||||
lastError_ = "wrapper frame generation dispatch failed";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
lastError_.clear();
|
|
||||||
}
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!contextStorage_ || !fns_->fsr3DispatchFrameGeneration) {
|
if (!contextStorage_ || !fns_->fsr3DispatchFrameGeneration) {
|
||||||
lastError_ = "official runtime frame generation context unavailable";
|
lastError_ = "official runtime frame generation context unavailable";
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -659,9 +428,9 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
||||||
FfxFrameGenerationDispatchDescription fgDispatch{};
|
FfxFrameGenerationDispatchDescription fgDispatch{};
|
||||||
fgDispatch.commandList = fns_->getCommandListVK(desc.commandBuffer);
|
fgDispatch.commandList = fns_->getCommandListVK(desc.commandBuffer);
|
||||||
fgDispatch.presentColor = fns_->getResourceVK(
|
fgDispatch.presentColor = fns_->getResourceVK(
|
||||||
reinterpret_cast<void*>(desc.outputImage), presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
desc.outputImage, presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
fgDispatch.outputs[0] = fns_->getResourceVK(
|
fgDispatch.outputs[0] = fns_->getResourceVK(
|
||||||
reinterpret_cast<void*>(desc.frameGenOutputImage), fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
desc.frameGenOutputImage, fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||||
fgDispatch.numInterpolatedFrames = 1;
|
fgDispatch.numInterpolatedFrames = 1;
|
||||||
fgDispatch.reset = desc.reset;
|
fgDispatch.reset = desc.reset;
|
||||||
fgDispatch.backBufferTransferFunction = FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
|
fgDispatch.backBufferTransferFunction = FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
|
||||||
|
|
@ -680,10 +449,6 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
||||||
|
|
||||||
void AmdFsr3Runtime::shutdown() {
|
void AmdFsr3Runtime::shutdown() {
|
||||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
if (wrapperContext_ && fns_ && fns_->wrapperShutdown) {
|
|
||||||
fns_->wrapperShutdown(static_cast<WoweeFsr3WrapperContext>(wrapperContext_));
|
|
||||||
}
|
|
||||||
wrapperContext_ = nullptr;
|
|
||||||
if (contextStorage_ && fns_ && fns_->fsr3ContextDestroy) {
|
if (contextStorage_ && fns_ && fns_->fsr3ContextDestroy) {
|
||||||
fns_->fsr3ContextDestroy(reinterpret_cast<FfxFsr3Context*>(contextStorage_));
|
fns_->fsr3ContextDestroy(reinterpret_cast<FfxFsr3Context*>(contextStorage_));
|
||||||
}
|
}
|
||||||
|
|
@ -711,9 +476,6 @@ void AmdFsr3Runtime::shutdown() {
|
||||||
libHandle_ = nullptr;
|
libHandle_ = nullptr;
|
||||||
loadedLibraryPath_.clear();
|
loadedLibraryPath_.clear();
|
||||||
loadPathKind_ = LoadPathKind::None;
|
loadPathKind_ = LoadPathKind::None;
|
||||||
wrapperBackendName_.clear();
|
|
||||||
wrapperCapabilities_ = 0;
|
|
||||||
backend_ = RuntimeBackend::None;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace wowee::rendering
|
} // namespace wowee::rendering
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
|
|
@ -1,107 +0,0 @@
|
||||||
#include "rendering/amd_fsr3_wrapper_abi.h"
|
|
||||||
|
|
||||||
#include <cstdint>
|
|
||||||
#include <cstring>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
|
||||||
#include <windows.h>
|
|
||||||
using LibHandle = HMODULE;
|
|
||||||
static LibHandle openLibrary(const char* path) { return LoadLibraryA(path); }
|
|
||||||
static void* loadSymbol(LibHandle lib, const char* name) {
|
|
||||||
return lib ? reinterpret_cast<void*>(GetProcAddress(lib, name)) : nullptr;
|
|
||||||
}
|
|
||||||
static void closeLibrary(LibHandle lib) {
|
|
||||||
if (lib) FreeLibrary(lib);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
#include <dlfcn.h>
|
|
||||||
using LibHandle = void*;
|
|
||||||
static LibHandle openLibrary(const char* path) { return dlopen(path, RTLD_NOW | RTLD_LOCAL); }
|
|
||||||
static void* loadSymbol(LibHandle lib, const char* name) { return lib ? dlsym(lib, name) : nullptr; }
|
|
||||||
static void closeLibrary(LibHandle lib) {
|
|
||||||
if (lib) dlclose(lib);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
|
||||||
const char* libPath = (argc > 1) ? argv[1]
|
|
||||||
#if defined(_WIN32)
|
|
||||||
: "ffx_fsr3_vk_wrapper.dll";
|
|
||||||
#elif defined(__APPLE__)
|
|
||||||
: "libffx_fsr3_vk_wrapper.dylib";
|
|
||||||
#else
|
|
||||||
: "./build/bin/libffx_fsr3_vk_wrapper.so";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LibHandle lib = openLibrary(libPath);
|
|
||||||
if (!lib) {
|
|
||||||
std::cerr << "smoke: failed to load wrapper library: " << libPath << "\n";
|
|
||||||
return 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto getAbiVersion = reinterpret_cast<uint32_t (*)()>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_get_abi_version"));
|
|
||||||
auto getName = reinterpret_cast<const char* (*)()>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_get_name"));
|
|
||||||
auto getBackend = reinterpret_cast<const char* (*)(WoweeFsr3WrapperContext)>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_get_backend"));
|
|
||||||
auto getCaps = reinterpret_cast<uint32_t (*)(WoweeFsr3WrapperContext)>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_get_capabilities"));
|
|
||||||
auto initialize = reinterpret_cast<int32_t (*)(const WoweeFsr3WrapperInitDesc*, WoweeFsr3WrapperContext*, char*, uint32_t)>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_initialize"));
|
|
||||||
auto dispatchUpscale = reinterpret_cast<int32_t (*)(WoweeFsr3WrapperContext, const WoweeFsr3WrapperDispatchDesc*)>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_dispatch_upscale"));
|
|
||||||
auto shutdown = reinterpret_cast<void (*)(WoweeFsr3WrapperContext)>(
|
|
||||||
loadSymbol(lib, "wowee_fsr3_wrapper_shutdown"));
|
|
||||||
|
|
||||||
if (!getAbiVersion || !getName || !getBackend || !getCaps || !initialize || !dispatchUpscale || !shutdown) {
|
|
||||||
std::cerr << "smoke: required wrapper ABI symbol(s) missing\n";
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32_t abi = getAbiVersion();
|
|
||||||
if (abi != WOWEE_FSR3_WRAPPER_ABI_VERSION) {
|
|
||||||
std::cerr << "smoke: ABI mismatch: got " << abi
|
|
||||||
<< ", expected " << WOWEE_FSR3_WRAPPER_ABI_VERSION << "\n";
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 4;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* name = getName();
|
|
||||||
if (!name || !*name) {
|
|
||||||
std::cerr << "smoke: wrapper name is empty\n";
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* backendNull = getBackend(nullptr);
|
|
||||||
if (!backendNull || !*backendNull) {
|
|
||||||
std::cerr << "smoke: get_backend(null) returned empty\n";
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 6;
|
|
||||||
}
|
|
||||||
|
|
||||||
const uint32_t capsNull = getCaps(nullptr);
|
|
||||||
if (capsNull != 0u) {
|
|
||||||
std::cerr << "smoke: expected get_capabilities(null)=0, got " << capsNull << "\n";
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 7;
|
|
||||||
}
|
|
||||||
|
|
||||||
char errorBuf[128] = {};
|
|
||||||
WoweeFsr3WrapperContext ctx = nullptr;
|
|
||||||
const int32_t initRes = initialize(nullptr, &ctx, errorBuf, static_cast<uint32_t>(sizeof(errorBuf)));
|
|
||||||
if (initRes == 0) {
|
|
||||||
std::cerr << "smoke: initialize(nullptr, ...) unexpectedly succeeded\n";
|
|
||||||
shutdown(ctx);
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 8;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::cout << "smoke: OK abi=" << abi << " name=" << name
|
|
||||||
<< " backend(null)=" << backendNull << "\n";
|
|
||||||
closeLibrary(lib);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
@ -16,50 +16,50 @@ void Frustum::extractFromMatrix(const glm::mat4& vp) {
|
||||||
// assignments so the enum names match the geometric meaning.)
|
// assignments so the enum names match the geometric meaning.)
|
||||||
|
|
||||||
// Left plane: row4 + row1 (x_clip >= -w_clip)
|
// Left plane: row4 + row1 (x_clip >= -w_clip)
|
||||||
planes[LEFT].normal.x = vp[0][3] + vp[0][0];
|
planes[PLANE_LEFT].normal.x = vp[0][3] + vp[0][0];
|
||||||
planes[LEFT].normal.y = vp[1][3] + vp[1][0];
|
planes[PLANE_LEFT].normal.y = vp[1][3] + vp[1][0];
|
||||||
planes[LEFT].normal.z = vp[2][3] + vp[2][0];
|
planes[PLANE_LEFT].normal.z = vp[2][3] + vp[2][0];
|
||||||
planes[LEFT].distance = vp[3][3] + vp[3][0];
|
planes[PLANE_LEFT].distance = vp[3][3] + vp[3][0];
|
||||||
normalizePlane(planes[LEFT]);
|
normalizePlane(planes[PLANE_LEFT]);
|
||||||
|
|
||||||
// Right plane: row4 - row1 (x_clip <= w_clip)
|
// Right plane: row4 - row1 (x_clip <= w_clip)
|
||||||
planes[RIGHT].normal.x = vp[0][3] - vp[0][0];
|
planes[PLANE_RIGHT].normal.x = vp[0][3] - vp[0][0];
|
||||||
planes[RIGHT].normal.y = vp[1][3] - vp[1][0];
|
planes[PLANE_RIGHT].normal.y = vp[1][3] - vp[1][0];
|
||||||
planes[RIGHT].normal.z = vp[2][3] - vp[2][0];
|
planes[PLANE_RIGHT].normal.z = vp[2][3] - vp[2][0];
|
||||||
planes[RIGHT].distance = vp[3][3] - vp[3][0];
|
planes[PLANE_RIGHT].distance = vp[3][3] - vp[3][0];
|
||||||
normalizePlane(planes[RIGHT]);
|
normalizePlane(planes[PLANE_RIGHT]);
|
||||||
|
|
||||||
// With the Vulkan Y-flip (proj[1][1] negated), row4+row2 extracts
|
// With the Vulkan Y-flip (proj[1][1] negated), row4+row2 extracts
|
||||||
// what is geometrically the TOP plane and row4-row2 extracts BOTTOM.
|
// what is geometrically the TOP plane and row4-row2 extracts BOTTOM.
|
||||||
// Swap the assignments so enum labels match geometry.
|
// Swap the assignments so enum labels match geometry.
|
||||||
|
|
||||||
// Top plane (geometric): row4 - row2 after Y-flip
|
// Top plane (geometric): row4 - row2 after Y-flip
|
||||||
planes[TOP].normal.x = vp[0][3] + vp[0][1];
|
planes[PLANE_TOP].normal.x = vp[0][3] + vp[0][1];
|
||||||
planes[TOP].normal.y = vp[1][3] + vp[1][1];
|
planes[PLANE_TOP].normal.y = vp[1][3] + vp[1][1];
|
||||||
planes[TOP].normal.z = vp[2][3] + vp[2][1];
|
planes[PLANE_TOP].normal.z = vp[2][3] + vp[2][1];
|
||||||
planes[TOP].distance = vp[3][3] + vp[3][1];
|
planes[PLANE_TOP].distance = vp[3][3] + vp[3][1];
|
||||||
normalizePlane(planes[TOP]);
|
normalizePlane(planes[PLANE_TOP]);
|
||||||
|
|
||||||
// Bottom plane (geometric): row4 + row2 after Y-flip
|
// Bottom plane (geometric): row4 + row2 after Y-flip
|
||||||
planes[BOTTOM].normal.x = vp[0][3] - vp[0][1];
|
planes[PLANE_BOTTOM].normal.x = vp[0][3] - vp[0][1];
|
||||||
planes[BOTTOM].normal.y = vp[1][3] - vp[1][1];
|
planes[PLANE_BOTTOM].normal.y = vp[1][3] - vp[1][1];
|
||||||
planes[BOTTOM].normal.z = vp[2][3] - vp[2][1];
|
planes[PLANE_BOTTOM].normal.z = vp[2][3] - vp[2][1];
|
||||||
planes[BOTTOM].distance = vp[3][3] - vp[3][1];
|
planes[PLANE_BOTTOM].distance = vp[3][3] - vp[3][1];
|
||||||
normalizePlane(planes[BOTTOM]);
|
normalizePlane(planes[PLANE_BOTTOM]);
|
||||||
|
|
||||||
// Near plane: row3 (z_clip >= 0 in Vulkan depth [0,1])
|
// Near plane: row3 (z_clip >= 0 in Vulkan depth [0,1])
|
||||||
planes[NEAR].normal.x = vp[0][2];
|
planes[PLANE_NEAR].normal.x = vp[0][2];
|
||||||
planes[NEAR].normal.y = vp[1][2];
|
planes[PLANE_NEAR].normal.y = vp[1][2];
|
||||||
planes[NEAR].normal.z = vp[2][2];
|
planes[PLANE_NEAR].normal.z = vp[2][2];
|
||||||
planes[NEAR].distance = vp[3][2];
|
planes[PLANE_NEAR].distance = vp[3][2];
|
||||||
normalizePlane(planes[NEAR]);
|
normalizePlane(planes[PLANE_NEAR]);
|
||||||
|
|
||||||
// Far plane: row4 - row3 (z_clip <= w_clip)
|
// Far plane: row4 - row3 (z_clip <= w_clip)
|
||||||
planes[FAR].normal.x = vp[0][3] - vp[0][2];
|
planes[PLANE_FAR].normal.x = vp[0][3] - vp[0][2];
|
||||||
planes[FAR].normal.y = vp[1][3] - vp[1][2];
|
planes[PLANE_FAR].normal.y = vp[1][3] - vp[1][2];
|
||||||
planes[FAR].normal.z = vp[2][3] - vp[2][2];
|
planes[PLANE_FAR].normal.z = vp[2][3] - vp[2][2];
|
||||||
planes[FAR].distance = vp[3][3] - vp[3][2];
|
planes[PLANE_FAR].distance = vp[3][3] - vp[3][2];
|
||||||
normalizePlane(planes[FAR]);
|
normalizePlane(planes[PLANE_FAR]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Frustum::normalizePlane(Plane& plane) {
|
void Frustum::normalizePlane(Plane& plane) {
|
||||||
|
|
|
||||||
|
|
@ -58,7 +58,6 @@
|
||||||
#include "rendering/vk_pipeline.hpp"
|
#include "rendering/vk_pipeline.hpp"
|
||||||
#include "rendering/vk_utils.hpp"
|
#include "rendering/vk_utils.hpp"
|
||||||
#include "rendering/amd_fsr3_runtime.hpp"
|
#include "rendering/amd_fsr3_runtime.hpp"
|
||||||
#include "rendering/amd_fsr3_wrapper_abi.h"
|
|
||||||
#include <imgui.h>
|
#include <imgui.h>
|
||||||
#include <imgui_impl_vulkan.h>
|
#include <imgui_impl_vulkan.h>
|
||||||
#include <glm/gtc/matrix_transform.hpp>
|
#include <glm/gtc/matrix_transform.hpp>
|
||||||
|
|
@ -116,115 +115,7 @@ static int envIntOrDefault(const char* key, int defaultValue) {
|
||||||
return static_cast<int>(n);
|
return static_cast<int>(n);
|
||||||
}
|
}
|
||||||
|
|
||||||
#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 (!device || !getDeviceProcAddr || !allocator || !image.allocation) return 0;
|
|
||||||
auto getMemHandle = reinterpret_cast<PFN_vkGetMemoryWin32HandleKHR>(
|
|
||||||
getDeviceProcAddr(device, "vkGetMemoryWin32HandleKHR"));
|
|
||||||
if (!getMemHandle) return 0;
|
|
||||||
|
|
||||||
VmaAllocationInfo allocInfo{};
|
|
||||||
vmaGetAllocationInfo(allocator, image.allocation, &allocInfo);
|
|
||||||
if (allocInfo.deviceMemory == VK_NULL_HANDLE) return 0;
|
|
||||||
|
|
||||||
VkMemoryGetWin32HandleInfoKHR handleInfo{};
|
|
||||||
handleInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_WIN32_HANDLE_INFO_KHR;
|
|
||||||
handleInfo.memory = allocInfo.deviceMemory;
|
|
||||||
handleInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_WIN32_BIT;
|
|
||||||
|
|
||||||
HANDLE outHandle = nullptr;
|
|
||||||
if (getMemHandle(device, &handleInfo, &outHandle) != VK_SUCCESS || !outHandle) return 0;
|
|
||||||
return reinterpret_cast<uint64_t>(outHandle);
|
|
||||||
#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 (!device || !getDeviceProcAddr || !semaphore) return 0;
|
|
||||||
auto getSemHandle = reinterpret_cast<PFN_vkGetSemaphoreWin32HandleKHR>(
|
|
||||||
getDeviceProcAddr(device, "vkGetSemaphoreWin32HandleKHR"));
|
|
||||||
if (!getSemHandle) return 0;
|
|
||||||
|
|
||||||
VkSemaphoreGetWin32HandleInfoKHR handleInfo{};
|
|
||||||
handleInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_WIN32_HANDLE_INFO_KHR;
|
|
||||||
handleInfo.semaphore = semaphore;
|
|
||||||
handleInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_WIN32_BIT;
|
|
||||||
|
|
||||||
HANDLE outHandle = nullptr;
|
|
||||||
if (getSemHandle(device, &handleInfo, &outHandle) != VK_SUCCESS || !outHandle) return 0;
|
|
||||||
return reinterpret_cast<uint64_t>(outHandle);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(__linux__)
|
|
||||||
static uint64_t exportImageMemoryHandleFd(VkDevice device, PFN_vkGetDeviceProcAddr getDeviceProcAddr,
|
|
||||||
VmaAllocator allocator, const AllocatedImage& image) {
|
|
||||||
#if !defined(VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR) || !defined(VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT)
|
|
||||||
(void)device;
|
|
||||||
(void)getDeviceProcAddr;
|
|
||||||
(void)allocator;
|
|
||||||
(void)image;
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
if (!device || !getDeviceProcAddr || !allocator || !image.allocation) return 0;
|
|
||||||
auto getMemFd = reinterpret_cast<PFN_vkGetMemoryFdKHR>(
|
|
||||||
getDeviceProcAddr(device, "vkGetMemoryFdKHR"));
|
|
||||||
if (!getMemFd) return 0;
|
|
||||||
|
|
||||||
VmaAllocationInfo allocInfo{};
|
|
||||||
vmaGetAllocationInfo(allocator, image.allocation, &allocInfo);
|
|
||||||
if (allocInfo.deviceMemory == VK_NULL_HANDLE) return 0;
|
|
||||||
|
|
||||||
VkMemoryGetFdInfoKHR fdInfo{};
|
|
||||||
fdInfo.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
|
|
||||||
fdInfo.memory = allocInfo.deviceMemory;
|
|
||||||
fdInfo.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
||||||
|
|
||||||
int outFd = -1;
|
|
||||||
if (getMemFd(device, &fdInfo, &outFd) != VK_SUCCESS || outFd < 0) return 0;
|
|
||||||
return static_cast<uint64_t>(static_cast<uint32_t>(outFd));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint64_t exportSemaphoreHandleFd(VkDevice device, PFN_vkGetDeviceProcAddr getDeviceProcAddr,
|
|
||||||
VkSemaphore semaphore) {
|
|
||||||
#if !defined(VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR) || !defined(VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT)
|
|
||||||
(void)device;
|
|
||||||
(void)getDeviceProcAddr;
|
|
||||||
(void)semaphore;
|
|
||||||
return 0;
|
|
||||||
#else
|
|
||||||
if (!device || !getDeviceProcAddr || !semaphore) return 0;
|
|
||||||
auto getSemFd = reinterpret_cast<PFN_vkGetSemaphoreFdKHR>(
|
|
||||||
getDeviceProcAddr(device, "vkGetSemaphoreFdKHR"));
|
|
||||||
if (!getSemFd) return 0;
|
|
||||||
|
|
||||||
VkSemaphoreGetFdInfoKHR fdInfo{};
|
|
||||||
fdInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR;
|
|
||||||
fdInfo.semaphore = semaphore;
|
|
||||||
fdInfo.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT;
|
|
||||||
|
|
||||||
int outFd = -1;
|
|
||||||
if (getSemFd(device, &fdInfo, &outFd) != VK_SUCCESS || outFd < 0) return 0;
|
|
||||||
return static_cast<uint64_t>(static_cast<uint32_t>(outFd));
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
static std::vector<std::string> parseEmoteCommands(const std::string& raw) {
|
static std::vector<std::string> parseEmoteCommands(const std::string& raw) {
|
||||||
std::vector<std::string> out;
|
std::vector<std::string> out;
|
||||||
|
|
@ -3758,9 +3649,9 @@ bool Renderer::initFSRResources() {
|
||||||
|
|
||||||
void Renderer::destroyFSRResources() {
|
void Renderer::destroyFSRResources() {
|
||||||
if (!vkCtx) return;
|
if (!vkCtx) return;
|
||||||
|
|
||||||
VkDevice device = vkCtx->getDevice();
|
VkDevice device = vkCtx->getDevice();
|
||||||
VmaAllocator alloc = vkCtx->getAllocator();
|
VmaAllocator alloc = vkCtx->getAllocator();
|
||||||
|
|
||||||
vkDeviceWaitIdle(device);
|
vkDeviceWaitIdle(device);
|
||||||
|
|
||||||
if (fsr_.pipeline) { vkDestroyPipeline(device, fsr_.pipeline, nullptr); fsr_.pipeline = VK_NULL_HANDLE; }
|
if (fsr_.pipeline) { vkDestroyPipeline(device, fsr_.pipeline, nullptr); fsr_.pipeline = VK_NULL_HANDLE; }
|
||||||
|
|
@ -4001,16 +3892,7 @@ bool Renderer::initFSR2Resources() {
|
||||||
fsr2_.amdFsr3FramegenRuntimeReady = fsr2_.amdFsr3Runtime->initialize(fgInit);
|
fsr2_.amdFsr3FramegenRuntimeReady = fsr2_.amdFsr3Runtime->initialize(fgInit);
|
||||||
if (fsr2_.amdFsr3FramegenRuntimeReady) {
|
if (fsr2_.amdFsr3FramegenRuntimeReady) {
|
||||||
fsr2_.amdFsr3RuntimeLastError.clear();
|
fsr2_.amdFsr3RuntimeLastError.clear();
|
||||||
if (fsr2_.amdFsr3Runtime->loadPathKind() == AmdFsr3Runtime::LoadPathKind::Wrapper) {
|
fsr2_.amdFsr3RuntimePath = "Path A";
|
||||||
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";
|
|
||||||
}
|
|
||||||
LOG_INFO("FSR3 framegen runtime library loaded from ", fsr2_.amdFsr3Runtime->loadedLibraryPath(),
|
LOG_INFO("FSR3 framegen runtime library loaded from ", fsr2_.amdFsr3Runtime->loadedLibraryPath(),
|
||||||
" (upscale+framegen dispatch enabled)");
|
" (upscale+framegen dispatch enabled)");
|
||||||
} else {
|
} else {
|
||||||
|
|
@ -4302,9 +4184,9 @@ bool Renderer::initFSR2Resources() {
|
||||||
|
|
||||||
void Renderer::destroyFSR2Resources() {
|
void Renderer::destroyFSR2Resources() {
|
||||||
if (!vkCtx) return;
|
if (!vkCtx) return;
|
||||||
|
|
||||||
VkDevice device = vkCtx->getDevice();
|
VkDevice device = vkCtx->getDevice();
|
||||||
VmaAllocator alloc = vkCtx->getAllocator();
|
VmaAllocator alloc = vkCtx->getAllocator();
|
||||||
|
|
||||||
vkDeviceWaitIdle(device);
|
vkDeviceWaitIdle(device);
|
||||||
|
|
||||||
#if WOWEE_HAS_AMD_FSR2
|
#if WOWEE_HAS_AMD_FSR2
|
||||||
|
|
@ -4551,8 +4433,6 @@ void Renderer::dispatchAmdFsr2() {
|
||||||
|
|
||||||
void Renderer::dispatchAmdFsr3Framegen() {
|
void Renderer::dispatchAmdFsr3Framegen() {
|
||||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
VkDevice device = vkCtx->getDevice();
|
|
||||||
VmaAllocator alloc = vkCtx->getAllocator();
|
|
||||||
if (!fsr2_.amdFsr3FramegenEnabled) {
|
if (!fsr2_.amdFsr3FramegenEnabled) {
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
||||||
return;
|
return;
|
||||||
|
|
@ -4613,127 +4493,6 @@ void Renderer::dispatchAmdFsr3Framegen() {
|
||||||
fgDispatch.cameraFovYRadians = camera ? glm::radians(camera->getFovDegrees()) : 1.0f;
|
fgDispatch.cameraFovYRadians = camera ? glm::radians(camera->getFovDegrees()) : 1.0f;
|
||||||
fgDispatch.reset = fsr2_.needsHistoryReset;
|
fgDispatch.reset = fsr2_.needsHistoryReset;
|
||||||
|
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
|
||||||
#if defined(_WIN32)
|
|
||||||
using ExportHandle = HANDLE;
|
|
||||||
#else
|
|
||||||
using ExportHandle = int;
|
|
||||||
#endif
|
|
||||||
bool exportInteropHandles = false;
|
|
||||||
if (fsr2_.amdFsr3Runtime && fsr2_.amdFsr3Runtime->hasWrapperExternalInterop()) {
|
|
||||||
exportInteropHandles = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<ExportHandle> exportedHandles;
|
|
||||||
auto trackHandle = [&](uint64_t h) {
|
|
||||||
if (!h) return;
|
|
||||||
ExportHandle raw =
|
|
||||||
#if defined(_WIN32)
|
|
||||||
reinterpret_cast<ExportHandle>(h);
|
|
||||||
#else
|
|
||||||
static_cast<ExportHandle>(static_cast<int>(h));
|
|
||||||
#endif
|
|
||||||
exportedHandles.push_back(raw);
|
|
||||||
};
|
|
||||||
auto cleanupExportedHandles = [&]() {
|
|
||||||
for (ExportHandle h : exportedHandles) {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
if (h) CloseHandle(h);
|
|
||||||
#else
|
|
||||||
if (h >= 0) close(h);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
exportedHandles.clear();
|
|
||||||
};
|
|
||||||
|
|
||||||
fgDispatch.externalFlags = 0;
|
|
||||||
if (exportInteropHandles) {
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.colorMemoryHandle = exportImageMemoryHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.sceneColor);
|
|
||||||
#else
|
|
||||||
fgDispatch.colorMemoryHandle = exportImageMemoryHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.sceneColor);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.colorMemoryHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_COLOR_MEMORY;
|
|
||||||
trackHandle(fgDispatch.colorMemoryHandle);
|
|
||||||
}
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.depthMemoryHandle = exportImageMemoryHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.sceneDepth);
|
|
||||||
#else
|
|
||||||
fgDispatch.depthMemoryHandle = exportImageMemoryHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.sceneDepth);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.depthMemoryHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_DEPTH_MEMORY;
|
|
||||||
trackHandle(fgDispatch.depthMemoryHandle);
|
|
||||||
}
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.motionVectorMemoryHandle = exportImageMemoryHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.motionVectors);
|
|
||||||
#else
|
|
||||||
fgDispatch.motionVectorMemoryHandle = exportImageMemoryHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.motionVectors);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.motionVectorMemoryHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_MOTION_MEMORY;
|
|
||||||
trackHandle(fgDispatch.motionVectorMemoryHandle);
|
|
||||||
}
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.outputMemoryHandle = exportImageMemoryHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.history[fsr2_.currentHistory]);
|
|
||||||
#else
|
|
||||||
fgDispatch.outputMemoryHandle = exportImageMemoryHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.history[fsr2_.currentHistory]);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.outputMemoryHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_OUTPUT_MEMORY;
|
|
||||||
trackHandle(fgDispatch.outputMemoryHandle);
|
|
||||||
}
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.frameGenOutputMemoryHandle = exportImageMemoryHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.framegenOutput);
|
|
||||||
#else
|
|
||||||
fgDispatch.frameGenOutputMemoryHandle = exportImageMemoryHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, alloc, fsr2_.framegenOutput);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.frameGenOutputMemoryHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_FRAMEGEN_OUTPUT_MEMORY;
|
|
||||||
trackHandle(fgDispatch.frameGenOutputMemoryHandle);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FrameData& frameData = vkCtx->getCurrentFrameData();
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.acquireSemaphoreHandle = exportSemaphoreHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, frameData.imageAvailableSemaphore);
|
|
||||||
#else
|
|
||||||
fgDispatch.acquireSemaphoreHandle = exportSemaphoreHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, frameData.imageAvailableSemaphore);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.acquireSemaphoreHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_ACQUIRE_SEMAPHORE;
|
|
||||||
trackHandle(fgDispatch.acquireSemaphoreHandle);
|
|
||||||
}
|
|
||||||
#if defined(_WIN32)
|
|
||||||
fgDispatch.releaseSemaphoreHandle = exportSemaphoreHandleWin32(
|
|
||||||
device, vkGetDeviceProcAddr, frameData.renderFinishedSemaphore);
|
|
||||||
#else
|
|
||||||
fgDispatch.releaseSemaphoreHandle = exportSemaphoreHandleFd(
|
|
||||||
device, vkGetDeviceProcAddr, frameData.renderFinishedSemaphore);
|
|
||||||
#endif
|
|
||||||
if (fgDispatch.releaseSemaphoreHandle) {
|
|
||||||
fgDispatch.externalFlags |= WOWEE_FSR3_WRAPPER_EXTERNAL_RELEASE_SEMAPHORE;
|
|
||||||
trackHandle(fgDispatch.releaseSemaphoreHandle);
|
|
||||||
}
|
|
||||||
uint64_t syncValue = fsr2_.amdFsr3InteropSyncValue;
|
|
||||||
if (syncValue == 0) syncValue = 1;
|
|
||||||
fgDispatch.acquireSemaphoreValue = syncValue;
|
|
||||||
fgDispatch.releaseSemaphoreValue = syncValue;
|
|
||||||
fsr2_.amdFsr3InteropSyncValue = syncValue + 1;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (!fsr2_.amdFsr3Runtime->dispatchUpscale(fgDispatch)) {
|
if (!fsr2_.amdFsr3Runtime->dispatchUpscale(fgDispatch)) {
|
||||||
static bool warnedRuntimeDispatch = false;
|
static bool warnedRuntimeDispatch = false;
|
||||||
|
|
@ -4744,9 +4503,6 @@ void Renderer::dispatchAmdFsr3Framegen() {
|
||||||
fsr2_.amdFsr3RuntimeLastError = fsr2_.amdFsr3Runtime->lastError();
|
fsr2_.amdFsr3RuntimeLastError = fsr2_.amdFsr3Runtime->lastError();
|
||||||
fsr2_.amdFsr3FallbackCount++;
|
fsr2_.amdFsr3FallbackCount++;
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
|
||||||
cleanupExportedHandles();
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fsr2_.amdFsr3RuntimeLastError.clear();
|
fsr2_.amdFsr3RuntimeLastError.clear();
|
||||||
|
|
@ -4754,16 +4510,10 @@ void Renderer::dispatchAmdFsr3Framegen() {
|
||||||
|
|
||||||
if (!fsr2_.amdFsr3FramegenEnabled) {
|
if (!fsr2_.amdFsr3FramegenEnabled) {
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
|
||||||
cleanupExportedHandles();
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!fsr2_.amdFsr3Runtime->isFrameGenerationReady()) {
|
if (!fsr2_.amdFsr3Runtime->isFrameGenerationReady()) {
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
|
||||||
cleanupExportedHandles();
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!fsr2_.amdFsr3Runtime->dispatchFrameGeneration(fgDispatch)) {
|
if (!fsr2_.amdFsr3Runtime->dispatchFrameGeneration(fgDispatch)) {
|
||||||
|
|
@ -4775,18 +4525,12 @@ void Renderer::dispatchAmdFsr3Framegen() {
|
||||||
fsr2_.amdFsr3RuntimeLastError = fsr2_.amdFsr3Runtime->lastError();
|
fsr2_.amdFsr3RuntimeLastError = fsr2_.amdFsr3Runtime->lastError();
|
||||||
fsr2_.amdFsr3FallbackCount++;
|
fsr2_.amdFsr3FallbackCount++;
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
|
||||||
cleanupExportedHandles();
|
|
||||||
#endif
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
fsr2_.amdFsr3RuntimeLastError.clear();
|
fsr2_.amdFsr3RuntimeLastError.clear();
|
||||||
fsr2_.amdFsr3FramegenDispatchCount++;
|
fsr2_.amdFsr3FramegenDispatchCount++;
|
||||||
fsr2_.framegenOutputValid = true;
|
fsr2_.framegenOutputValid = true;
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = true;
|
fsr2_.amdFsr3FramegenRuntimeActive = true;
|
||||||
#if defined(_WIN32) || defined(__linux__)
|
|
||||||
cleanupExportedHandles();
|
|
||||||
#endif
|
|
||||||
#else
|
#else
|
||||||
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
fsr2_.amdFsr3FramegenRuntimeActive = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue