mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-05-02 15:53:51 +00:00
Add in-tree FSR3 wrapper target and forkable FidelityFX SDK source overrides
This commit is contained in:
parent
73055c507f
commit
036e102fa0
8 changed files with 526 additions and 12 deletions
|
|
@ -113,6 +113,24 @@ if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN
|
||||||
${WOWEE_AMD_FFX_SDK_DIR}/include
|
${WOWEE_AMD_FFX_SDK_DIR}/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
|
||||||
|
src/rendering/amd_fsr3_wrapper_impl.cpp
|
||||||
|
include/rendering/amd_fsr3_wrapper_abi.h
|
||||||
|
)
|
||||||
|
set_target_properties(wowee_fsr3_vk_wrapper PROPERTIES
|
||||||
|
CXX_STANDARD 17
|
||||||
|
CXX_STANDARD_REQUIRED ON
|
||||||
|
OUTPUT_NAME ffx_fsr3_vk_wrapper
|
||||||
|
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||||
|
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}
|
||||||
|
ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_ARCHIVE_OUTPUT_DIRECTORY}
|
||||||
|
)
|
||||||
|
target_include_directories(wowee_fsr3_vk_wrapper PUBLIC
|
||||||
|
${CMAKE_SOURCE_DIR}/include
|
||||||
|
${WOWEE_AMD_FFX_SDK_DIR}/include
|
||||||
|
)
|
||||||
|
target_link_libraries(wowee_fsr3_vk_wrapper PUBLIC Vulkan::Vulkan ${CMAKE_DL_LIBS})
|
||||||
else()
|
else()
|
||||||
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=0)
|
add_compile_definitions(WOWEE_HAS_AMD_FSR3_FRAMEGEN=0)
|
||||||
if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN)
|
if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN)
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,9 @@ make -j$(nproc)
|
||||||
- `https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git`
|
- `https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git`
|
||||||
- Ref:
|
- Ref:
|
||||||
- `v1.1.4` (depth-1 clone)
|
- `v1.1.4` (depth-1 clone)
|
||||||
|
- Override with env vars:
|
||||||
|
- `WOWEE_FFX_SDK_REPO=https://github.com/<you>/FidelityFX-SDK.git`
|
||||||
|
- `WOWEE_FFX_SDK_REF=<branch-or-tag>`
|
||||||
- This ref includes Vulkan framegen building blocks (`frameinterpolation` + `opticalflow`) and Vulkan shader manifests:
|
- This ref includes Vulkan framegen building blocks (`frameinterpolation` + `opticalflow`) and Vulkan shader manifests:
|
||||||
- `sdk/src/backends/vk/CMakeShadersFrameinterpolation.txt`
|
- `sdk/src/backends/vk/CMakeShadersFrameinterpolation.txt`
|
||||||
- `sdk/src/backends/vk/CMakeShadersOpticalflow.txt`
|
- `sdk/src/backends/vk/CMakeShadersOpticalflow.txt`
|
||||||
|
|
@ -202,6 +205,9 @@ make -j$(nproc)
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (platform extension varies).
|
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (platform extension varies).
|
||||||
- Wrapper override path:
|
- Wrapper override path:
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB=/absolute/path/to/libffx_fsr3_vk_wrapper.so` (platform extension varies).
|
- `WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB=/absolute/path/to/libffx_fsr3_vk_wrapper.so` (platform extension varies).
|
||||||
|
- 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`.
|
||||||
- Path B wrapper libraries must export the clean wrapper ABI (`include/rendering/amd_fsr3_wrapper_abi.h`):
|
- Path B wrapper libraries must export the clean wrapper ABI (`include/rendering/amd_fsr3_wrapper_abi.h`):
|
||||||
- `wowee_fsr3_wrapper_get_abi_version`
|
- `wowee_fsr3_wrapper_get_abi_version`
|
||||||
- `wowee_fsr3_wrapper_initialize`
|
- `wowee_fsr3_wrapper_initialize`
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ function Ensure-Fsr2Sdk {
|
||||||
function Ensure-FidelityFxSdk {
|
function Ensure-FidelityFxSdk {
|
||||||
$sdkDir = Join-Path $ScriptDir "extern\FidelityFX-SDK"
|
$sdkDir = Join-Path $ScriptDir "extern\FidelityFX-SDK"
|
||||||
$sdkHeader = Join-Path $sdkDir "sdk\include\FidelityFX\host\ffx_frameinterpolation.h"
|
$sdkHeader = Join-Path $sdkDir "sdk\include\FidelityFX\host\ffx_frameinterpolation.h"
|
||||||
$sdkRef = "v1.1.4"
|
$sdkRepo = if ($env:WOWEE_FFX_SDK_REPO) { $env:WOWEE_FFX_SDK_REPO } else { "https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git" }
|
||||||
|
$sdkRef = if ($env:WOWEE_FFX_SDK_REF) { $env:WOWEE_FFX_SDK_REF } else { "v1.1.4" }
|
||||||
if (Test-Path $sdkHeader) { return }
|
if (Test-Path $sdkHeader) { return }
|
||||||
|
|
||||||
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
||||||
|
|
@ -41,9 +42,9 @@ function Ensure-FidelityFxSdk {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Fetching AMD FidelityFX SDK ($sdkRef) into $sdkDir ..."
|
Write-Host "Fetching AMD FidelityFX SDK ($sdkRef from $sdkRepo) into $sdkDir ..."
|
||||||
New-Item -ItemType Directory -Path (Join-Path $ScriptDir "extern") -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $ScriptDir "extern") -Force | Out-Null
|
||||||
& git clone --depth 1 --branch $sdkRef https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git $sdkDir
|
& git clone --depth 1 --branch $sdkRef $sdkRepo $sdkDir
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Write-Warning "Failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
Write-Warning "Failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
7
build.sh
7
build.sh
|
|
@ -25,7 +25,8 @@ ensure_fsr2_sdk() {
|
||||||
ensure_fidelityfx_sdk() {
|
ensure_fidelityfx_sdk() {
|
||||||
local sdk_dir="extern/FidelityFX-SDK"
|
local sdk_dir="extern/FidelityFX-SDK"
|
||||||
local sdk_header="$sdk_dir/sdk/include/FidelityFX/host/ffx_frameinterpolation.h"
|
local sdk_header="$sdk_dir/sdk/include/FidelityFX/host/ffx_frameinterpolation.h"
|
||||||
local sdk_ref="v1.1.4"
|
local sdk_repo="${WOWEE_FFX_SDK_REPO:-https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git}"
|
||||||
|
local sdk_ref="${WOWEE_FFX_SDK_REF:-v1.1.4}"
|
||||||
if [ -f "$sdk_header" ]; then
|
if [ -f "$sdk_header" ]; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
@ -33,9 +34,9 @@ ensure_fidelityfx_sdk() {
|
||||||
echo "Warning: git not found; cannot auto-fetch AMD FidelityFX SDK."
|
echo "Warning: git not found; cannot auto-fetch AMD FidelityFX SDK."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo "Fetching AMD FidelityFX SDK ($sdk_ref) into $sdk_dir ..."
|
echo "Fetching AMD FidelityFX SDK ($sdk_ref from $sdk_repo) into $sdk_dir ..."
|
||||||
mkdir -p extern
|
mkdir -p extern
|
||||||
git clone --depth 1 --branch "$sdk_ref" https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git "$sdk_dir" || {
|
git clone --depth 1 --branch "$sdk_ref" "$sdk_repo" "$sdk_dir" || {
|
||||||
echo "Warning: failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
echo "Warning: failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,11 @@ FidelityFX SDK checkout path (framegen extern):
|
||||||
|
|
||||||
`extern/FidelityFX-SDK` (pinned to `v1.1.4` in build scripts and CI)
|
`extern/FidelityFX-SDK` (pinned to `v1.1.4` in build scripts and CI)
|
||||||
|
|
||||||
|
Override knobs for local build scripts:
|
||||||
|
|
||||||
|
- `WOWEE_FFX_SDK_REPO` (default: `https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git`)
|
||||||
|
- `WOWEE_FFX_SDK_REF` (default: `v1.1.4`)
|
||||||
|
|
||||||
Detection expects:
|
Detection expects:
|
||||||
|
|
||||||
- `extern/FidelityFX-FSR2/src/ffx-fsr2-api/ffx_fsr2.h`
|
- `extern/FidelityFX-FSR2/src/ffx-fsr2-api/ffx_fsr2.h`
|
||||||
|
|
@ -43,6 +48,10 @@ Runtime note:
|
||||||
- `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:
|
- You can point to an explicit wrapper binary with:
|
||||||
- `WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB=/absolute/path/to/libffx_fsr3_vk_wrapper.so` (or `.dll` / `.dylib`).
|
- `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`).
|
||||||
- Path B wrapper ABI contract is declared in:
|
- Path B wrapper ABI contract is declared in:
|
||||||
- `include/rendering/amd_fsr3_wrapper_abi.h`
|
- `include/rendering/amd_fsr3_wrapper_abi.h`
|
||||||
- Required wrapper exports:
|
- Required wrapper exports:
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,8 @@ function Ensure-Fsr2Sdk {
|
||||||
function Ensure-FidelityFxSdk {
|
function Ensure-FidelityFxSdk {
|
||||||
$sdkDir = Join-Path $ScriptDir "extern\FidelityFX-SDK"
|
$sdkDir = Join-Path $ScriptDir "extern\FidelityFX-SDK"
|
||||||
$sdkHeader = Join-Path $sdkDir "sdk\include\FidelityFX\host\ffx_frameinterpolation.h"
|
$sdkHeader = Join-Path $sdkDir "sdk\include\FidelityFX\host\ffx_frameinterpolation.h"
|
||||||
$sdkRef = "v1.1.4"
|
$sdkRepo = if ($env:WOWEE_FFX_SDK_REPO) { $env:WOWEE_FFX_SDK_REPO } else { "https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git" }
|
||||||
|
$sdkRef = if ($env:WOWEE_FFX_SDK_REF) { $env:WOWEE_FFX_SDK_REF } else { "v1.1.4" }
|
||||||
if (Test-Path $sdkHeader) { return }
|
if (Test-Path $sdkHeader) { return }
|
||||||
|
|
||||||
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
if (-not (Get-Command git -ErrorAction SilentlyContinue)) {
|
||||||
|
|
@ -41,9 +42,9 @@ function Ensure-FidelityFxSdk {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
Write-Host "Fetching AMD FidelityFX SDK ($sdkRef) into $sdkDir ..."
|
Write-Host "Fetching AMD FidelityFX SDK ($sdkRef from $sdkRepo) into $sdkDir ..."
|
||||||
New-Item -ItemType Directory -Path (Join-Path $ScriptDir "extern") -Force | Out-Null
|
New-Item -ItemType Directory -Path (Join-Path $ScriptDir "extern") -Force | Out-Null
|
||||||
& git clone --depth 1 --branch $sdkRef https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git $sdkDir
|
& git clone --depth 1 --branch $sdkRef $sdkRepo $sdkDir
|
||||||
if ($LASTEXITCODE -ne 0) {
|
if ($LASTEXITCODE -ne 0) {
|
||||||
Write-Warning "Failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
Write-Warning "Failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,8 @@ ensure_fsr2_sdk() {
|
||||||
ensure_fidelityfx_sdk() {
|
ensure_fidelityfx_sdk() {
|
||||||
local sdk_dir="extern/FidelityFX-SDK"
|
local sdk_dir="extern/FidelityFX-SDK"
|
||||||
local sdk_header="$sdk_dir/sdk/include/FidelityFX/host/ffx_frameinterpolation.h"
|
local sdk_header="$sdk_dir/sdk/include/FidelityFX/host/ffx_frameinterpolation.h"
|
||||||
local sdk_ref="v1.1.4"
|
local sdk_repo="${WOWEE_FFX_SDK_REPO:-https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git}"
|
||||||
|
local sdk_ref="${WOWEE_FFX_SDK_REF:-v1.1.4}"
|
||||||
if [ -f "$sdk_header" ]; then
|
if [ -f "$sdk_header" ]; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
@ -33,9 +34,9 @@ ensure_fidelityfx_sdk() {
|
||||||
echo "Warning: git not found; cannot auto-fetch AMD FidelityFX SDK."
|
echo "Warning: git not found; cannot auto-fetch AMD FidelityFX SDK."
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
echo "Fetching AMD FidelityFX SDK ($sdk_ref) into $sdk_dir ..."
|
echo "Fetching AMD FidelityFX SDK ($sdk_ref from $sdk_repo) into $sdk_dir ..."
|
||||||
mkdir -p extern
|
mkdir -p extern
|
||||||
git clone --depth 1 --branch "$sdk_ref" https://github.com/GPUOpen-LibrariesAndSDKs/FidelityFX-SDK.git "$sdk_dir" || {
|
git clone --depth 1 --branch "$sdk_ref" "$sdk_repo" "$sdk_dir" || {
|
||||||
echo "Warning: failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
echo "Warning: failed to clone AMD FidelityFX SDK. FSR3 framegen extern will be unavailable."
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
477
src/rendering/amd_fsr3_wrapper_impl.cpp
Normal file
477
src/rendering/amd_fsr3_wrapper_impl.cpp
Normal file
|
|
@ -0,0 +1,477 @@
|
||||||
|
#include "rendering/amd_fsr3_wrapper_abi.h"
|
||||||
|
|
||||||
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
|
#include <FidelityFX/host/backends/vk/ffx_vk.h>
|
||||||
|
#include <FidelityFX/host/ffx_fsr3.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <array>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <cstring>
|
||||||
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#include <windows.h>
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#define WOWEE_FSR3_WRAPPER_EXPORT extern "C" __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define WOWEE_FSR3_WRAPPER_EXPORT extern "C" __attribute__((visibility("default")))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
void writeError(char* outErrorText, uint32_t outErrorTextCapacity, const char* message) {
|
||||||
|
if (!outErrorText || outErrorTextCapacity == 0) return;
|
||||||
|
if (!message) message = "unknown error";
|
||||||
|
std::strncpy(outErrorText, message, static_cast<size_t>(outErrorTextCapacity - 1));
|
||||||
|
outErrorText[outErrorTextCapacity - 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
|
FfxErrorCode vkSwapchainConfigureNoop(const FfxFrameGenerationConfig*) {
|
||||||
|
return FFX_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T, typename = void>
|
||||||
|
struct HasUpscaleOutputSize : std::false_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
struct HasUpscaleOutputSize<T, std::void_t<decltype(std::declval<T&>().upscaleOutputSize)>> : std::true_type {};
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
inline void setUpscaleOutputSizeIfPresent(T& ctxDesc, uint32_t width, uint32_t height) {
|
||||||
|
if constexpr (HasUpscaleOutputSize<T>::value) {
|
||||||
|
ctxDesc.upscaleOutputSize.width = width;
|
||||||
|
ctxDesc.upscaleOutputSize.height = height;
|
||||||
|
} else {
|
||||||
|
(void)ctxDesc;
|
||||||
|
(void)width;
|
||||||
|
(void)height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FfxSurfaceFormat mapVkFormatToFfxSurfaceFormat(VkFormat format, bool isDepth) {
|
||||||
|
if (isDepth) {
|
||||||
|
switch (format) {
|
||||||
|
case VK_FORMAT_D32_SFLOAT:
|
||||||
|
return FFX_SURFACE_FORMAT_R32_FLOAT;
|
||||||
|
case VK_FORMAT_D16_UNORM:
|
||||||
|
return FFX_SURFACE_FORMAT_R16_UNORM;
|
||||||
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
||||||
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
||||||
|
return FFX_SURFACE_FORMAT_R32_FLOAT;
|
||||||
|
default:
|
||||||
|
return FFX_SURFACE_FORMAT_R32_FLOAT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (format) {
|
||||||
|
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
||||||
|
return FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT;
|
||||||
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
||||||
|
case VK_FORMAT_B8G8R8A8_UNORM:
|
||||||
|
return FFX_SURFACE_FORMAT_R8G8B8A8_UNORM;
|
||||||
|
case VK_FORMAT_R8G8B8A8_SRGB:
|
||||||
|
case VK_FORMAT_B8G8R8A8_SRGB:
|
||||||
|
return FFX_SURFACE_FORMAT_R8G8B8A8_SRGB;
|
||||||
|
case VK_FORMAT_A2R10G10B10_UNORM_PACK32:
|
||||||
|
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
||||||
|
return FFX_SURFACE_FORMAT_R10G10B10A2_UNORM;
|
||||||
|
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
|
||||||
|
return FFX_SURFACE_FORMAT_R11G11B10_FLOAT;
|
||||||
|
case VK_FORMAT_R16G16_SFLOAT:
|
||||||
|
return FFX_SURFACE_FORMAT_R16G16_FLOAT;
|
||||||
|
case VK_FORMAT_R16G16_UINT:
|
||||||
|
return FFX_SURFACE_FORMAT_R16G16_UINT;
|
||||||
|
case VK_FORMAT_R16_SFLOAT:
|
||||||
|
return FFX_SURFACE_FORMAT_R16_FLOAT;
|
||||||
|
case VK_FORMAT_R16_UINT:
|
||||||
|
return FFX_SURFACE_FORMAT_R16_UINT;
|
||||||
|
case VK_FORMAT_R16_UNORM:
|
||||||
|
return FFX_SURFACE_FORMAT_R16_UNORM;
|
||||||
|
case VK_FORMAT_R16_SNORM:
|
||||||
|
return FFX_SURFACE_FORMAT_R16_SNORM;
|
||||||
|
case VK_FORMAT_R8_UNORM:
|
||||||
|
return FFX_SURFACE_FORMAT_R8_UNORM;
|
||||||
|
case VK_FORMAT_R8_UINT:
|
||||||
|
return FFX_SURFACE_FORMAT_R8_UINT;
|
||||||
|
case VK_FORMAT_R8G8_UNORM:
|
||||||
|
return FFX_SURFACE_FORMAT_R8G8_UNORM;
|
||||||
|
case VK_FORMAT_R32_SFLOAT:
|
||||||
|
return FFX_SURFACE_FORMAT_R32_FLOAT;
|
||||||
|
case VK_FORMAT_R32_UINT:
|
||||||
|
return FFX_SURFACE_FORMAT_R32_UINT;
|
||||||
|
default:
|
||||||
|
return FFX_SURFACE_FORMAT_UNKNOWN;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FfxResourceDescription makeResourceDescription(VkFormat format,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
FfxResourceUsage usage,
|
||||||
|
bool isDepth = false) {
|
||||||
|
FfxResourceDescription description{};
|
||||||
|
description.type = FFX_RESOURCE_TYPE_TEXTURE2D;
|
||||||
|
description.format = mapVkFormatToFfxSurfaceFormat(format, isDepth);
|
||||||
|
description.width = width;
|
||||||
|
description.height = height;
|
||||||
|
description.depth = 1;
|
||||||
|
description.mipCount = 1;
|
||||||
|
description.flags = FFX_RESOURCE_FLAGS_NONE;
|
||||||
|
description.usage = usage;
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RuntimeFns {
|
||||||
|
decltype(&ffxGetScratchMemorySizeVK) getScratchMemorySizeVK = nullptr;
|
||||||
|
decltype(&ffxGetDeviceVK) getDeviceVK = nullptr;
|
||||||
|
decltype(&ffxGetInterfaceVK) getInterfaceVK = nullptr;
|
||||||
|
decltype(&ffxGetCommandListVK) getCommandListVK = nullptr;
|
||||||
|
decltype(&ffxGetResourceVK) getResourceVK = nullptr;
|
||||||
|
decltype(&ffxFsr3ContextCreate) fsr3ContextCreate = nullptr;
|
||||||
|
decltype(&ffxFsr3ContextDispatchUpscale) fsr3ContextDispatchUpscale = nullptr;
|
||||||
|
decltype(&ffxFsr3ConfigureFrameGeneration) fsr3ConfigureFrameGeneration = nullptr;
|
||||||
|
decltype(&ffxFsr3DispatchFrameGeneration) fsr3DispatchFrameGeneration = nullptr;
|
||||||
|
decltype(&ffxFsr3ContextDestroy) fsr3ContextDestroy = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct WrapperContext {
|
||||||
|
void* backendLibHandle = nullptr;
|
||||||
|
RuntimeFns fns{};
|
||||||
|
void* scratchBuffer = nullptr;
|
||||||
|
size_t scratchBufferSize = 0;
|
||||||
|
void* fsr3ContextStorage = nullptr;
|
||||||
|
bool frameGenerationReady = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
void closeLibrary(void* handle) {
|
||||||
|
if (!handle) return;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
FreeLibrary(reinterpret_cast<HMODULE>(handle));
|
||||||
|
#else
|
||||||
|
dlclose(handle);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* openLibrary(const char* path) {
|
||||||
|
if (!path || !*path) return nullptr;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return reinterpret_cast<void*>(LoadLibraryA(path));
|
||||||
|
#else
|
||||||
|
return dlopen(path, RTLD_NOW | RTLD_LOCAL);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void* resolveSymbol(void* handle, const char* symbol) {
|
||||||
|
if (!handle || !symbol) return nullptr;
|
||||||
|
#if defined(_WIN32)
|
||||||
|
return reinterpret_cast<void*>(GetProcAddress(reinterpret_cast<HMODULE>(handle), symbol));
|
||||||
|
#else
|
||||||
|
return dlsym(handle, symbol);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void destroyContext(WrapperContext* ctx) {
|
||||||
|
if (!ctx) return;
|
||||||
|
if (ctx->fsr3ContextStorage && ctx->fns.fsr3ContextDestroy) {
|
||||||
|
ctx->fns.fsr3ContextDestroy(reinterpret_cast<FfxFsr3Context*>(ctx->fsr3ContextStorage));
|
||||||
|
}
|
||||||
|
if (ctx->fsr3ContextStorage) {
|
||||||
|
std::free(ctx->fsr3ContextStorage);
|
||||||
|
ctx->fsr3ContextStorage = nullptr;
|
||||||
|
}
|
||||||
|
if (ctx->scratchBuffer) {
|
||||||
|
std::free(ctx->scratchBuffer);
|
||||||
|
ctx->scratchBuffer = nullptr;
|
||||||
|
}
|
||||||
|
ctx->scratchBufferSize = 0;
|
||||||
|
closeLibrary(ctx->backendLibHandle);
|
||||||
|
ctx->backendLibHandle = nullptr;
|
||||||
|
delete ctx;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
WOWEE_FSR3_WRAPPER_EXPORT uint32_t wowee_fsr3_wrapper_get_abi_version(void) {
|
||||||
|
return WOWEE_FSR3_WRAPPER_ABI_VERSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
WOWEE_FSR3_WRAPPER_EXPORT const char* wowee_fsr3_wrapper_get_name(void) {
|
||||||
|
return "WoWee FSR3 DX12/VK Wrapper";
|
||||||
|
}
|
||||||
|
|
||||||
|
WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_initialize(const WoweeFsr3WrapperInitDesc* initDesc,
|
||||||
|
WoweeFsr3WrapperContext* outContext,
|
||||||
|
char* outErrorText,
|
||||||
|
uint32_t outErrorTextCapacity) {
|
||||||
|
if (outContext) *outContext = nullptr;
|
||||||
|
#if !WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
|
(void)initDesc;
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "wrapper built without WOWEE_HAS_AMD_FSR3_FRAMEGEN");
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
if (!initDesc || !outContext) {
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "invalid init args");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (initDesc->structSize < sizeof(WoweeFsr3WrapperInitDesc) ||
|
||||||
|
initDesc->abiVersion != WOWEE_FSR3_WRAPPER_ABI_VERSION) {
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "wrapper ABI/version mismatch");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!initDesc->physicalDevice || !initDesc->device || !initDesc->getDeviceProcAddr ||
|
||||||
|
initDesc->maxRenderWidth == 0 || initDesc->maxRenderHeight == 0 ||
|
||||||
|
initDesc->displayWidth == 0 || initDesc->displayHeight == 0 ||
|
||||||
|
initDesc->colorFormat == VK_FORMAT_UNDEFINED) {
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "invalid init descriptor values");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> candidates;
|
||||||
|
if (const char* backendEnv = std::getenv("WOWEE_FSR3_WRAPPER_BACKEND_LIB")) {
|
||||||
|
if (*backendEnv) candidates.emplace_back(backendEnv);
|
||||||
|
}
|
||||||
|
if (const char* runtimeEnv = std::getenv("WOWEE_FFX_SDK_RUNTIME_LIB")) {
|
||||||
|
if (*runtimeEnv) candidates.emplace_back(runtimeEnv);
|
||||||
|
}
|
||||||
|
#if defined(_WIN32)
|
||||||
|
candidates.emplace_back("ffx_fsr3_vk.dll");
|
||||||
|
candidates.emplace_back("ffx_fsr3.dll");
|
||||||
|
candidates.emplace_back("ffx_fsr3_bridge.dll");
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
candidates.emplace_back("libffx_fsr3_vk.dylib");
|
||||||
|
candidates.emplace_back("libffx_fsr3.dylib");
|
||||||
|
candidates.emplace_back("libffx_fsr3_bridge.dylib");
|
||||||
|
#else
|
||||||
|
candidates.emplace_back("./libffx_fsr3_vk.so");
|
||||||
|
candidates.emplace_back("libffx_fsr3_vk.so");
|
||||||
|
candidates.emplace_back("libffx_fsr3.so");
|
||||||
|
candidates.emplace_back("libffx_fsr3_bridge.so");
|
||||||
|
#endif
|
||||||
|
|
||||||
|
WrapperContext* ctx = new WrapperContext{};
|
||||||
|
for (const std::string& path : candidates) {
|
||||||
|
ctx->backendLibHandle = openLibrary(path.c_str());
|
||||||
|
if (ctx->backendLibHandle) break;
|
||||||
|
}
|
||||||
|
if (!ctx->backendLibHandle) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "no FSR3 backend runtime found for wrapper");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->fns.getScratchMemorySizeVK = reinterpret_cast<decltype(ctx->fns.getScratchMemorySizeVK)>(resolveSymbol(ctx->backendLibHandle, "ffxGetScratchMemorySizeVK"));
|
||||||
|
ctx->fns.getDeviceVK = reinterpret_cast<decltype(ctx->fns.getDeviceVK)>(resolveSymbol(ctx->backendLibHandle, "ffxGetDeviceVK"));
|
||||||
|
ctx->fns.getInterfaceVK = reinterpret_cast<decltype(ctx->fns.getInterfaceVK)>(resolveSymbol(ctx->backendLibHandle, "ffxGetInterfaceVK"));
|
||||||
|
ctx->fns.getCommandListVK = reinterpret_cast<decltype(ctx->fns.getCommandListVK)>(resolveSymbol(ctx->backendLibHandle, "ffxGetCommandListVK"));
|
||||||
|
ctx->fns.getResourceVK = reinterpret_cast<decltype(ctx->fns.getResourceVK)>(resolveSymbol(ctx->backendLibHandle, "ffxGetResourceVK"));
|
||||||
|
ctx->fns.fsr3ContextCreate = reinterpret_cast<decltype(ctx->fns.fsr3ContextCreate)>(resolveSymbol(ctx->backendLibHandle, "ffxFsr3ContextCreate"));
|
||||||
|
ctx->fns.fsr3ContextDispatchUpscale = reinterpret_cast<decltype(ctx->fns.fsr3ContextDispatchUpscale)>(resolveSymbol(ctx->backendLibHandle, "ffxFsr3ContextDispatchUpscale"));
|
||||||
|
ctx->fns.fsr3ConfigureFrameGeneration = reinterpret_cast<decltype(ctx->fns.fsr3ConfigureFrameGeneration)>(resolveSymbol(ctx->backendLibHandle, "ffxFsr3ConfigureFrameGeneration"));
|
||||||
|
ctx->fns.fsr3DispatchFrameGeneration = reinterpret_cast<decltype(ctx->fns.fsr3DispatchFrameGeneration)>(resolveSymbol(ctx->backendLibHandle, "ffxFsr3DispatchFrameGeneration"));
|
||||||
|
ctx->fns.fsr3ContextDestroy = reinterpret_cast<decltype(ctx->fns.fsr3ContextDestroy)>(resolveSymbol(ctx->backendLibHandle, "ffxFsr3ContextDestroy"));
|
||||||
|
|
||||||
|
if (!ctx->fns.getScratchMemorySizeVK || !ctx->fns.getDeviceVK || !ctx->fns.getInterfaceVK ||
|
||||||
|
!ctx->fns.getCommandListVK || !ctx->fns.getResourceVK || !ctx->fns.fsr3ContextCreate ||
|
||||||
|
!ctx->fns.fsr3ContextDispatchUpscale || !ctx->fns.fsr3ContextDestroy) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "backend missing required ffx symbols");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
const bool enableFrameGeneration = (initDesc->enableFlags & WOWEE_FSR3_WRAPPER_ENABLE_FRAME_GENERATION) != 0u;
|
||||||
|
if (enableFrameGeneration && (!ctx->fns.fsr3ConfigureFrameGeneration || !ctx->fns.fsr3DispatchFrameGeneration)) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "backend missing frame generation symbols");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->scratchBufferSize = ctx->fns.getScratchMemorySizeVK(initDesc->physicalDevice, FFX_FSR3_CONTEXT_COUNT);
|
||||||
|
if (ctx->scratchBufferSize == 0) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "scratch buffer size query returned 0");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ctx->scratchBuffer = std::malloc(ctx->scratchBufferSize);
|
||||||
|
if (!ctx->scratchBuffer) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "scratch buffer allocation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkDeviceContext vkDevCtx{};
|
||||||
|
vkDevCtx.vkDevice = initDesc->device;
|
||||||
|
vkDevCtx.vkPhysicalDevice = initDesc->physicalDevice;
|
||||||
|
vkDevCtx.vkDeviceProcAddr = initDesc->getDeviceProcAddr;
|
||||||
|
|
||||||
|
FfxDevice ffxDevice = ctx->fns.getDeviceVK(&vkDevCtx);
|
||||||
|
FfxInterface backendShared{};
|
||||||
|
FfxErrorCode ifaceErr = ctx->fns.getInterfaceVK(
|
||||||
|
&backendShared, ffxDevice, ctx->scratchBuffer, ctx->scratchBufferSize, FFX_FSR3_CONTEXT_COUNT);
|
||||||
|
if (ifaceErr != FFX_OK) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "ffxGetInterfaceVK failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
FfxFsr3ContextDescription fsr3Desc{};
|
||||||
|
fsr3Desc.flags = FFX_FSR3_ENABLE_AUTO_EXPOSURE | FFX_FSR3_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION;
|
||||||
|
if (!enableFrameGeneration) fsr3Desc.flags |= FFX_FSR3_ENABLE_UPSCALING_ONLY;
|
||||||
|
if (initDesc->enableFlags & WOWEE_FSR3_WRAPPER_ENABLE_HDR_INPUT) fsr3Desc.flags |= FFX_FSR3_ENABLE_HIGH_DYNAMIC_RANGE;
|
||||||
|
if (initDesc->enableFlags & WOWEE_FSR3_WRAPPER_ENABLE_DEPTH_INVERTED) fsr3Desc.flags |= FFX_FSR3_ENABLE_DEPTH_INVERTED;
|
||||||
|
fsr3Desc.maxRenderSize.width = initDesc->maxRenderWidth;
|
||||||
|
fsr3Desc.maxRenderSize.height = initDesc->maxRenderHeight;
|
||||||
|
setUpscaleOutputSizeIfPresent(fsr3Desc, initDesc->displayWidth, initDesc->displayHeight);
|
||||||
|
fsr3Desc.displaySize.width = initDesc->displayWidth;
|
||||||
|
fsr3Desc.displaySize.height = initDesc->displayHeight;
|
||||||
|
if (!backendShared.fpSwapChainConfigureFrameGeneration) {
|
||||||
|
backendShared.fpSwapChainConfigureFrameGeneration = vkSwapchainConfigureNoop;
|
||||||
|
}
|
||||||
|
fsr3Desc.backendInterfaceSharedResources = backendShared;
|
||||||
|
fsr3Desc.backendInterfaceUpscaling = backendShared;
|
||||||
|
fsr3Desc.backendInterfaceFrameInterpolation = backendShared;
|
||||||
|
fsr3Desc.backBufferFormat = mapVkFormatToFfxSurfaceFormat(initDesc->colorFormat, false);
|
||||||
|
|
||||||
|
ctx->fsr3ContextStorage = std::malloc(sizeof(FfxFsr3Context));
|
||||||
|
if (!ctx->fsr3ContextStorage) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "FSR3 context allocation failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
std::memset(ctx->fsr3ContextStorage, 0, sizeof(FfxFsr3Context));
|
||||||
|
|
||||||
|
FfxErrorCode createErr = ctx->fns.fsr3ContextCreate(reinterpret_cast<FfxFsr3Context*>(ctx->fsr3ContextStorage), &fsr3Desc);
|
||||||
|
if (createErr != FFX_OK) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "ffxFsr3ContextCreate failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (enableFrameGeneration) {
|
||||||
|
FfxFrameGenerationConfig fgCfg{};
|
||||||
|
fgCfg.frameGenerationEnabled = true;
|
||||||
|
fgCfg.allowAsyncWorkloads = false;
|
||||||
|
fgCfg.flags = 0;
|
||||||
|
fgCfg.onlyPresentInterpolated = false;
|
||||||
|
FfxErrorCode cfgErr = ctx->fns.fsr3ConfigureFrameGeneration(reinterpret_cast<FfxFsr3Context*>(ctx->fsr3ContextStorage), &fgCfg);
|
||||||
|
if (cfgErr != FFX_OK) {
|
||||||
|
destroyContext(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "ffxFsr3ConfigureFrameGeneration failed");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
ctx->frameGenerationReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
*outContext = reinterpret_cast<WoweeFsr3WrapperContext>(ctx);
|
||||||
|
writeError(outErrorText, outErrorTextCapacity, "");
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_dispatch_upscale(WoweeFsr3WrapperContext context,
|
||||||
|
const WoweeFsr3WrapperDispatchDesc* dispatchDesc) {
|
||||||
|
#if !WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
|
(void)context;
|
||||||
|
(void)dispatchDesc;
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
if (!context || !dispatchDesc) return -1;
|
||||||
|
if (dispatchDesc->structSize < sizeof(WoweeFsr3WrapperDispatchDesc)) return -1;
|
||||||
|
if (!dispatchDesc->commandBuffer || !dispatchDesc->colorImage || !dispatchDesc->depthImage ||
|
||||||
|
!dispatchDesc->motionVectorImage || !dispatchDesc->outputImage) return -1;
|
||||||
|
WrapperContext* ctx = reinterpret_cast<WrapperContext*>(context);
|
||||||
|
|
||||||
|
FfxResourceDescription colorDesc = makeResourceDescription(
|
||||||
|
dispatchDesc->colorFormat, dispatchDesc->renderWidth, dispatchDesc->renderHeight, FFX_RESOURCE_USAGE_READ_ONLY);
|
||||||
|
FfxResourceDescription depthDesc = makeResourceDescription(
|
||||||
|
dispatchDesc->depthFormat, dispatchDesc->renderWidth, dispatchDesc->renderHeight, FFX_RESOURCE_USAGE_DEPTHTARGET, true);
|
||||||
|
FfxResourceDescription mvDesc = makeResourceDescription(
|
||||||
|
dispatchDesc->motionVectorFormat, dispatchDesc->renderWidth, dispatchDesc->renderHeight, FFX_RESOURCE_USAGE_READ_ONLY);
|
||||||
|
FfxResourceDescription outDesc = makeResourceDescription(
|
||||||
|
dispatchDesc->outputFormat, dispatchDesc->outputWidth, dispatchDesc->outputHeight, FFX_RESOURCE_USAGE_UAV);
|
||||||
|
|
||||||
|
static wchar_t kColorName[] = L"FSR3_Color";
|
||||||
|
static wchar_t kDepthName[] = L"FSR3_Depth";
|
||||||
|
static wchar_t kMotionName[] = L"FSR3_MotionVectors";
|
||||||
|
static wchar_t kOutputName[] = L"FSR3_Output";
|
||||||
|
FfxFsr3DispatchUpscaleDescription dispatch{};
|
||||||
|
dispatch.commandList = ctx->fns.getCommandListVK(dispatchDesc->commandBuffer);
|
||||||
|
dispatch.color = ctx->fns.getResourceVK(reinterpret_cast<void*>(dispatchDesc->colorImage), colorDesc, kColorName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
|
dispatch.depth = ctx->fns.getResourceVK(reinterpret_cast<void*>(dispatchDesc->depthImage), depthDesc, kDepthName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
|
dispatch.motionVectors = ctx->fns.getResourceVK(reinterpret_cast<void*>(dispatchDesc->motionVectorImage), mvDesc, kMotionName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
|
dispatch.exposure = FfxResource{};
|
||||||
|
dispatch.reactive = FfxResource{};
|
||||||
|
dispatch.transparencyAndComposition = FfxResource{};
|
||||||
|
dispatch.upscaleOutput = ctx->fns.getResourceVK(reinterpret_cast<void*>(dispatchDesc->outputImage), outDesc, kOutputName, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||||
|
dispatch.jitterOffset.x = dispatchDesc->jitterX;
|
||||||
|
dispatch.jitterOffset.y = dispatchDesc->jitterY;
|
||||||
|
dispatch.motionVectorScale.x = dispatchDesc->motionScaleX;
|
||||||
|
dispatch.motionVectorScale.y = dispatchDesc->motionScaleY;
|
||||||
|
dispatch.renderSize.width = dispatchDesc->renderWidth;
|
||||||
|
dispatch.renderSize.height = dispatchDesc->renderHeight;
|
||||||
|
dispatch.enableSharpening = false;
|
||||||
|
dispatch.sharpness = 0.0f;
|
||||||
|
dispatch.frameTimeDelta = std::max(0.001f, dispatchDesc->frameTimeDeltaMs);
|
||||||
|
dispatch.preExposure = 1.0f;
|
||||||
|
dispatch.reset = (dispatchDesc->reset != 0u);
|
||||||
|
dispatch.cameraNear = dispatchDesc->cameraNear;
|
||||||
|
dispatch.cameraFar = dispatchDesc->cameraFar;
|
||||||
|
dispatch.cameraFovAngleVertical = dispatchDesc->cameraFovYRadians;
|
||||||
|
dispatch.viewSpaceToMetersFactor = 1.0f;
|
||||||
|
|
||||||
|
return (ctx->fns.fsr3ContextDispatchUpscale(reinterpret_cast<FfxFsr3Context*>(ctx->fsr3ContextStorage), &dispatch) == FFX_OK) ? 0 : -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WOWEE_FSR3_WRAPPER_EXPORT int32_t wowee_fsr3_wrapper_dispatch_framegen(WoweeFsr3WrapperContext context,
|
||||||
|
const WoweeFsr3WrapperDispatchDesc* dispatchDesc) {
|
||||||
|
#if !WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
|
(void)context;
|
||||||
|
(void)dispatchDesc;
|
||||||
|
return -1;
|
||||||
|
#else
|
||||||
|
if (!context || !dispatchDesc) return -1;
|
||||||
|
if (dispatchDesc->structSize < sizeof(WoweeFsr3WrapperDispatchDesc)) return -1;
|
||||||
|
if (!dispatchDesc->commandBuffer || !dispatchDesc->outputImage || !dispatchDesc->frameGenOutputImage) return -1;
|
||||||
|
WrapperContext* ctx = reinterpret_cast<WrapperContext*>(context);
|
||||||
|
if (!ctx->frameGenerationReady || !ctx->fns.fsr3DispatchFrameGeneration) return -1;
|
||||||
|
|
||||||
|
FfxResourceDescription presentDesc = makeResourceDescription(
|
||||||
|
dispatchDesc->outputFormat, dispatchDesc->outputWidth, dispatchDesc->outputHeight, FFX_RESOURCE_USAGE_READ_ONLY);
|
||||||
|
FfxResourceDescription fgOutDesc = makeResourceDescription(
|
||||||
|
dispatchDesc->outputFormat, dispatchDesc->outputWidth, dispatchDesc->outputHeight, FFX_RESOURCE_USAGE_UAV);
|
||||||
|
|
||||||
|
static wchar_t kPresentName[] = L"FSR3_PresentColor";
|
||||||
|
static wchar_t kInterpolatedName[] = L"FSR3_InterpolatedOutput";
|
||||||
|
FfxFrameGenerationDispatchDescription fgDispatch{};
|
||||||
|
fgDispatch.commandList = ctx->fns.getCommandListVK(dispatchDesc->commandBuffer);
|
||||||
|
fgDispatch.presentColor = ctx->fns.getResourceVK(reinterpret_cast<void*>(dispatchDesc->outputImage), presentDesc, kPresentName, FFX_RESOURCE_STATE_COMPUTE_READ);
|
||||||
|
fgDispatch.outputs[0] = ctx->fns.getResourceVK(reinterpret_cast<void*>(dispatchDesc->frameGenOutputImage), fgOutDesc, kInterpolatedName, FFX_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||||
|
fgDispatch.numInterpolatedFrames = 1;
|
||||||
|
fgDispatch.reset = (dispatchDesc->reset != 0u);
|
||||||
|
fgDispatch.backBufferTransferFunction = FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
|
||||||
|
fgDispatch.minMaxLuminance[0] = 0.0f;
|
||||||
|
fgDispatch.minMaxLuminance[1] = 1.0f;
|
||||||
|
|
||||||
|
return (ctx->fns.fsr3DispatchFrameGeneration(&fgDispatch) == FFX_OK) ? 0 : -1;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
WOWEE_FSR3_WRAPPER_EXPORT void wowee_fsr3_wrapper_shutdown(WoweeFsr3WrapperContext context) {
|
||||||
|
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||||
|
WrapperContext* ctx = reinterpret_cast<WrapperContext*>(context);
|
||||||
|
destroyContext(ctx);
|
||||||
|
#else
|
||||||
|
(void)context;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue