mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Add FSR3 Generic API path and harden runtime diagnostics
- AmdFsr3Runtime now probes both the legacy ffxFsr3* API and the newer generic ffxCreateContext/ffxDispatch API; selects whichever the loaded runtime library exports (GenericApi takes priority fallback) - Generic API path implements full upscale + frame-generation context creation, configure, dispatch, and destroy lifecycle - dlopen error captured and surfaced in lastError_ on Linux so runtime initialization failures are actionable - FSR3 runtime init failure log now includes path kind, error string, and loaded library path for easier debugging - tools/generate_ffx_sdk_vk_permutations.sh added: auto-bootstraps missing VK permutation headers; DXC auto-downloaded on Linux/Windows MSYS2; macOS reads from PATH (CI installs via brew dxc) - CMakeLists: add upscalers/include to probe include dirs, invoke permutation script before SDK build, scope FFX pragma/ODR warning suppressions to affected TUs, add runtime-copy dependency on wowee - UI labels updated from "FSR2" → "FSR3" in settings, tuning panel, performance HUD, and combo boxes - CI macOS job now installs dxc via Homebrew for permutation codegen
This commit is contained in:
parent
ae48e4d7a6
commit
bae32c1823
11 changed files with 537 additions and 16 deletions
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
|
|
@ -138,7 +138,7 @@ jobs:
|
|||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
brew install cmake pkg-config sdl2 glew glm openssl@3 zlib ffmpeg unicorn \
|
||||
brew install cmake pkg-config sdl2 glew glm openssl@3 zlib ffmpeg unicorn dxc \
|
||||
stormlib vulkan-loader vulkan-headers shaderc dylibbundler || true
|
||||
# dylibbundler may not be in all brew mirrors; install separately to not block others
|
||||
brew install dylibbundler 2>/dev/null || true
|
||||
|
|
|
|||
|
|
@ -118,6 +118,7 @@ if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_KITS_READY)
|
|||
CXX_STANDARD_REQUIRED ON
|
||||
)
|
||||
target_include_directories(wowee_fsr3_framegen_amd_vk_probe PUBLIC
|
||||
${WOWEE_AMD_FFX_SDK_KITS_DIR}/upscalers/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
|
||||
|
|
@ -163,6 +164,8 @@ if(WOWEE_ENABLE_AMD_FSR3_FRAMEGEN AND WOWEE_AMD_FFX_SDK_KITS_READY)
|
|||
-DFFX_BUILD_VK=ON
|
||||
-DFFX_BUILD_FRAMEGENERATION=ON
|
||||
-DFFX_BUILD_UPSCALER=ON
|
||||
COMMAND bash ${CMAKE_SOURCE_DIR}/tools/generate_ffx_sdk_vk_permutations.sh
|
||||
${CMAKE_SOURCE_DIR}/extern/FidelityFX-SDK
|
||||
COMMAND ${CMAKE_COMMAND}
|
||||
--build ${WOWEE_AMD_FSR3_RUNTIME_BUILD_DIR}
|
||||
--config $<CONFIG>
|
||||
|
|
@ -641,6 +644,14 @@ if(TARGET opcodes-generate)
|
|||
add_dependencies(wowee opcodes-generate)
|
||||
endif()
|
||||
|
||||
# FidelityFX-SDK headers can trigger compiler-specific pragma/unused-static noise
|
||||
# when included through the runtime bridge; keep suppression scoped to that TU.
|
||||
if(CMAKE_CXX_COMPILER_ID MATCHES "GNU|Clang")
|
||||
set_source_files_properties(src/rendering/amd_fsr3_runtime.cpp PROPERTIES
|
||||
COMPILE_OPTIONS "-Wno-unknown-pragmas;-Wno-unused-variable"
|
||||
)
|
||||
endif()
|
||||
|
||||
# Compile GLSL shaders to SPIR-V
|
||||
if(GLSLC)
|
||||
compile_shaders(wowee)
|
||||
|
|
@ -715,6 +726,10 @@ endif()
|
|||
if(TARGET wowee_fsr3_framegen_amd_vk_probe)
|
||||
target_link_libraries(wowee PRIVATE wowee_fsr3_framegen_amd_vk_probe)
|
||||
endif()
|
||||
if(TARGET wowee_fsr3_official_runtime_copy)
|
||||
# Ensure Path A runtime is available in bin/ whenever wowee is built.
|
||||
add_dependencies(wowee wowee_fsr3_official_runtime_copy)
|
||||
endif()
|
||||
|
||||
# Link Unicorn if available
|
||||
if(HAVE_UNICORN)
|
||||
|
|
@ -735,6 +750,13 @@ if(MSVC)
|
|||
target_compile_options(wowee PRIVATE /W4)
|
||||
else()
|
||||
target_compile_options(wowee PRIVATE -Wall -Wextra -Wpedantic -Wno-missing-field-initializers)
|
||||
# GCC LTO emits -Wodr for FFX enum-name mismatches across SDK generations.
|
||||
# We intentionally keep FSR2+FSR3 integrations in separate TUs and suppress
|
||||
# this linker-time diagnostic to avoid CI noise.
|
||||
if(CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
|
||||
target_compile_options(wowee PRIVATE -Wno-odr)
|
||||
target_link_options(wowee PRIVATE -Wno-odr)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# Debug build flags
|
||||
|
|
|
|||
|
|
@ -278,6 +278,7 @@ make -j$(nproc)
|
|||
- 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)
|
||||
- Linux CI validates FidelityFX-SDK Kits framegen headers
|
||||
- FSR3 Path A runtime build auto-bootstraps missing VK permutation headers via `tools/generate_ffx_sdk_vk_permutations.sh`
|
||||
- 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`
|
||||
- Container build via `container/build-in-container.sh` (Podman)
|
||||
|
|
|
|||
|
|
@ -42,6 +42,7 @@ Runtime note:
|
|||
|
||||
- Renderer/UI expose a persisted experimental framegen toggle.
|
||||
- Runtime loader is Path A only (official AMD runtime library).
|
||||
- Path A runtime build now auto-runs `tools/generate_ffx_sdk_vk_permutations.sh` to ensure required VK permutation headers exist for FSR2/FSR3 upscaler shader blobs.
|
||||
- You can point to an explicit runtime binary with:
|
||||
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (or `.dll` / `.dylib`).
|
||||
- If no official runtime is found, frame generation is disabled cleanly (Path C).
|
||||
|
|
@ -76,6 +77,10 @@ Runtime note:
|
|||
- `framegeneration/fsr3/include/ffx_frameinterpolation.h`
|
||||
- `framegeneration/fsr3/include/ffx_opticalflow.h`
|
||||
- `backend/vk/ffx_vk.h`
|
||||
- Runtime build path auto-bootstrap:
|
||||
- Linux downloads DXC automatically when missing.
|
||||
- Windows (MSYS2) downloads DXC automatically when missing.
|
||||
- macOS expects `dxc` to be available in `PATH` (CI installs it via Homebrew).
|
||||
- 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.
|
||||
- WoWee bootstraps those headers from the vendored snapshot so AMD backend builds remain cross-platform and deterministic.
|
||||
|
|
|
|||
|
|
@ -68,6 +68,11 @@ public:
|
|||
const std::string& lastError() const { return lastError_; }
|
||||
|
||||
private:
|
||||
enum class ApiMode {
|
||||
LegacyFsr3,
|
||||
GenericApi
|
||||
};
|
||||
|
||||
void* libHandle_ = nullptr;
|
||||
std::string loadedLibraryPath_;
|
||||
void* scratchBuffer_ = nullptr;
|
||||
|
|
@ -80,6 +85,10 @@ private:
|
|||
struct RuntimeFns;
|
||||
RuntimeFns* fns_ = nullptr;
|
||||
void* contextStorage_ = nullptr;
|
||||
ApiMode apiMode_ = ApiMode::LegacyFsr3;
|
||||
void* genericUpscaleContext_ = nullptr;
|
||||
void* genericFramegenContext_ = nullptr;
|
||||
uint64_t genericFrameId_ = 1;
|
||||
};
|
||||
|
||||
} // namespace wowee::rendering
|
||||
|
|
|
|||
|
|
@ -117,7 +117,7 @@ private:
|
|||
bool pendingPOM = true; // on by default
|
||||
int pendingPOMQuality = 1; // 0=Low(16), 1=Medium(32), 2=High(64)
|
||||
bool pendingFSR = false;
|
||||
int pendingUpscalingMode = 0; // 0=Off, 1=FSR1, 2=FSR2
|
||||
int pendingUpscalingMode = 0; // 0=Off, 1=FSR1, 2=FSR3
|
||||
int pendingFSRQuality = 3; // 0=UltraQuality, 1=Quality, 2=Balanced, 3=Native(100%)
|
||||
float pendingFSRSharpness = 1.6f;
|
||||
float pendingFSR2JitterSign = 0.38f;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,11 @@
|
|||
|
||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||
#include "third_party/ffx_fsr3_legacy_compat.h"
|
||||
#include <ffx_api.h>
|
||||
#include <ffx_framegeneration.h>
|
||||
#include <ffx_upscale.h>
|
||||
#include <ffx_vk.h>
|
||||
#include <vk/ffx_api_vk.h>
|
||||
#endif
|
||||
|
||||
namespace wowee::rendering {
|
||||
|
|
@ -34,6 +38,10 @@ struct AmdFsr3Runtime::RuntimeFns {
|
|||
decltype(&ffxFsr3ConfigureFrameGeneration) fsr3ConfigureFrameGeneration = nullptr;
|
||||
decltype(&ffxFsr3DispatchFrameGeneration) fsr3DispatchFrameGeneration = nullptr;
|
||||
decltype(&ffxFsr3ContextDestroy) fsr3ContextDestroy = nullptr;
|
||||
PfnFfxCreateContext createContext = nullptr;
|
||||
PfnFfxDestroyContext destroyContext = nullptr;
|
||||
PfnFfxConfigure configure = nullptr;
|
||||
PfnFfxDispatch dispatch = nullptr;
|
||||
};
|
||||
#else
|
||||
struct AmdFsr3Runtime::RuntimeFns {};
|
||||
|
|
@ -51,6 +59,43 @@ FfxErrorCode vkSwapchainConfigureNoop(const FfxFrameGenerationConfig*) {
|
|||
return FFX_OK;
|
||||
}
|
||||
|
||||
std::string narrowWString(const wchar_t* msg) {
|
||||
if (!msg) return {};
|
||||
std::string out;
|
||||
for (const wchar_t* p = msg; *p; ++p) {
|
||||
const wchar_t wc = *p;
|
||||
if (wc >= 0 && wc <= 0x7f) {
|
||||
out.push_back(static_cast<char>(wc));
|
||||
} else {
|
||||
out.push_back('?');
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
void ffxApiLogMessage(uint32_t type, const wchar_t* message) {
|
||||
const std::string narrowed = narrowWString(message);
|
||||
if (type == FFX_API_MESSAGE_TYPE_ERROR) {
|
||||
LOG_ERROR("FSR3 runtime/API: ", narrowed);
|
||||
} else {
|
||||
LOG_WARNING("FSR3 runtime/API: ", narrowed);
|
||||
}
|
||||
}
|
||||
|
||||
const char* ffxApiReturnCodeName(ffxReturnCode_t rc) {
|
||||
switch (rc) {
|
||||
case FFX_API_RETURN_OK: return "OK";
|
||||
case FFX_API_RETURN_ERROR: return "ERROR";
|
||||
case FFX_API_RETURN_ERROR_UNKNOWN_DESCTYPE: return "ERROR_UNKNOWN_DESCTYPE";
|
||||
case FFX_API_RETURN_ERROR_RUNTIME_ERROR: return "ERROR_RUNTIME_ERROR";
|
||||
case FFX_API_RETURN_NO_PROVIDER: return "NO_PROVIDER";
|
||||
case FFX_API_RETURN_ERROR_MEMORY: return "ERROR_MEMORY";
|
||||
case FFX_API_RETURN_ERROR_PARAMETER: return "ERROR_PARAMETER";
|
||||
case FFX_API_RETURN_PROVIDER_NO_SUPPORT_NEW_DESCTYPE: return "PROVIDER_NO_SUPPORT_NEW_DESCTYPE";
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename = void>
|
||||
struct HasUpscaleOutputSize : std::false_type {};
|
||||
|
||||
|
|
@ -141,6 +186,7 @@ FfxResourceDescription makeResourceDescription(VkFormat format,
|
|||
description.usage = usage;
|
||||
return description;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
|
|
@ -184,23 +230,36 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
|||
candidates.emplace_back("libffx_fsr3.so");
|
||||
#endif
|
||||
|
||||
std::string lastDlopenError;
|
||||
for (const std::string& path : candidates) {
|
||||
#if defined(_WIN32)
|
||||
HMODULE h = LoadLibraryA(path.c_str());
|
||||
if (!h) continue;
|
||||
libHandle_ = reinterpret_cast<void*>(h);
|
||||
#else
|
||||
dlerror();
|
||||
void* h = dlopen(path.c_str(), RTLD_NOW | RTLD_LOCAL);
|
||||
if (!h) continue;
|
||||
if (!h) {
|
||||
const char* err = dlerror();
|
||||
if (err && *err) lastDlopenError = err;
|
||||
continue;
|
||||
}
|
||||
libHandle_ = h;
|
||||
#endif
|
||||
loadedLibraryPath_ = path;
|
||||
loadPathKind_ = LoadPathKind::Official;
|
||||
LOG_INFO("FSR3 runtime: opened library candidate ", loadedLibraryPath_);
|
||||
break;
|
||||
}
|
||||
|
||||
if (!libHandle_) {
|
||||
lastError_ = "no official runtime (Path A) found";
|
||||
#if !defined(_WIN32)
|
||||
if (!lastDlopenError.empty()) {
|
||||
lastError_ += " dlopen error: ";
|
||||
lastError_ += lastDlopenError;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -223,16 +282,127 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
|||
fns_->fsr3ConfigureFrameGeneration = reinterpret_cast<decltype(fns_->fsr3ConfigureFrameGeneration)>(resolveSym("ffxFsr3ConfigureFrameGeneration"));
|
||||
fns_->fsr3DispatchFrameGeneration = reinterpret_cast<decltype(fns_->fsr3DispatchFrameGeneration)>(resolveSym("ffxFsr3DispatchFrameGeneration"));
|
||||
fns_->fsr3ContextDestroy = reinterpret_cast<decltype(fns_->fsr3ContextDestroy)>(resolveSym("ffxFsr3ContextDestroy"));
|
||||
fns_->createContext = reinterpret_cast<decltype(fns_->createContext)>(resolveSym("ffxCreateContext"));
|
||||
fns_->destroyContext = reinterpret_cast<decltype(fns_->destroyContext)>(resolveSym("ffxDestroyContext"));
|
||||
fns_->configure = reinterpret_cast<decltype(fns_->configure)>(resolveSym("ffxConfigure"));
|
||||
fns_->dispatch = reinterpret_cast<decltype(fns_->dispatch)>(resolveSym("ffxDispatch"));
|
||||
|
||||
if (!fns_->getScratchMemorySizeVK || !fns_->getDeviceVK || !fns_->getInterfaceVK ||
|
||||
!fns_->getCommandListVK || !fns_->getResourceVK || !fns_->fsr3ContextCreate || !fns_->fsr3ContextDispatchUpscale ||
|
||||
!fns_->fsr3ContextDestroy) {
|
||||
LOG_WARNING("FSR3 runtime: required symbols not found in ", loadedLibraryPath_);
|
||||
lastError_ = "missing required Vulkan FSR3 symbols in runtime library";
|
||||
const bool hasLegacyApi = (fns_->getScratchMemorySizeVK && fns_->getDeviceVK && fns_->getInterfaceVK &&
|
||||
fns_->getCommandListVK && fns_->getResourceVK && fns_->fsr3ContextCreate &&
|
||||
fns_->fsr3ContextDispatchUpscale && fns_->fsr3ContextDestroy);
|
||||
const bool hasGenericApi = (fns_->createContext && fns_->destroyContext && fns_->configure && fns_->dispatch);
|
||||
|
||||
if (!hasLegacyApi && !hasGenericApi) {
|
||||
LOG_WARNING("FSR3 runtime: required symbols not found in ", loadedLibraryPath_,
|
||||
" (need legacy ffxFsr3* or generic ffxCreateContext/ffxDispatch)");
|
||||
lastError_ = "missing required Vulkan FSR3 symbols in runtime library (legacy and generic APIs unavailable)";
|
||||
shutdown();
|
||||
return false;
|
||||
}
|
||||
|
||||
apiMode_ = hasLegacyApi ? ApiMode::LegacyFsr3 : ApiMode::GenericApi;
|
||||
if (apiMode_ == ApiMode::GenericApi) {
|
||||
ffxConfigureDescGlobalDebug1 globalDebug{};
|
||||
globalDebug.header.type = FFX_API_CONFIGURE_DESC_TYPE_GLOBALDEBUG1;
|
||||
globalDebug.header.pNext = nullptr;
|
||||
globalDebug.fpMessage = &ffxApiLogMessage;
|
||||
globalDebug.debugLevel = FFX_API_CONFIGURE_GLOBALDEBUG_LEVEL_VERBOSE;
|
||||
(void)fns_->configure(nullptr, reinterpret_cast<ffxConfigureDescHeader*>(&globalDebug));
|
||||
|
||||
ffxCreateBackendVKDesc backendDesc{};
|
||||
backendDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_BACKEND_VK;
|
||||
backendDesc.header.pNext = nullptr;
|
||||
backendDesc.vkDevice = desc.device;
|
||||
backendDesc.vkPhysicalDevice = desc.physicalDevice;
|
||||
|
||||
ffxCreateContextDescUpscaleVersion upVerDesc{};
|
||||
upVerDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE_VERSION;
|
||||
upVerDesc.header.pNext = nullptr;
|
||||
upVerDesc.version = FFX_UPSCALER_VERSION;
|
||||
|
||||
ffxCreateContextDescUpscale upDesc{};
|
||||
upDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_UPSCALE;
|
||||
upDesc.header.pNext = reinterpret_cast<ffxApiHeader*>(&backendDesc);
|
||||
upDesc.flags = FFX_UPSCALE_ENABLE_AUTO_EXPOSURE | FFX_UPSCALE_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION;
|
||||
upDesc.flags |= FFX_UPSCALE_ENABLE_DEBUG_CHECKING;
|
||||
if (desc.hdrInput) upDesc.flags |= FFX_UPSCALE_ENABLE_HIGH_DYNAMIC_RANGE;
|
||||
if (desc.depthInverted) upDesc.flags |= FFX_UPSCALE_ENABLE_DEPTH_INVERTED;
|
||||
upDesc.maxRenderSize.width = desc.maxRenderWidth;
|
||||
upDesc.maxRenderSize.height = desc.maxRenderHeight;
|
||||
upDesc.maxUpscaleSize.width = desc.displayWidth;
|
||||
upDesc.maxUpscaleSize.height = desc.displayHeight;
|
||||
upDesc.fpMessage = &ffxApiLogMessage;
|
||||
backendDesc.header.pNext = reinterpret_cast<ffxApiHeader*>(&upVerDesc);
|
||||
|
||||
ffxContext upscaleCtx = nullptr;
|
||||
const ffxReturnCode_t upCreateRc =
|
||||
fns_->createContext(&upscaleCtx, reinterpret_cast<ffxCreateContextDescHeader*>(&upDesc), nullptr);
|
||||
if (upCreateRc != FFX_API_RETURN_OK) {
|
||||
const std::string loadedPath = loadedLibraryPath_;
|
||||
lastError_ = "ffxCreateContext (upscale) failed rc=" + std::to_string(upCreateRc) +
|
||||
" (" + ffxApiReturnCodeName(upCreateRc) + "), runtimeLib=" + loadedPath;
|
||||
shutdown();
|
||||
return false;
|
||||
}
|
||||
genericUpscaleContext_ = upscaleCtx;
|
||||
backendDesc.header.pNext = nullptr;
|
||||
|
||||
if (desc.enableFrameGeneration) {
|
||||
ffxCreateContextDescFrameGenerationVersion fgVerDesc{};
|
||||
fgVerDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_FRAMEGENERATION_VERSION;
|
||||
fgVerDesc.header.pNext = nullptr;
|
||||
fgVerDesc.version = FFX_FRAMEGENERATION_VERSION;
|
||||
|
||||
ffxCreateContextDescFrameGeneration fgDesc{};
|
||||
fgDesc.header.type = FFX_API_CREATE_CONTEXT_DESC_TYPE_FRAMEGENERATION;
|
||||
fgDesc.header.pNext = reinterpret_cast<ffxApiHeader*>(&backendDesc);
|
||||
fgDesc.flags = FFX_FRAMEGENERATION_ENABLE_MOTION_VECTORS_JITTER_CANCELLATION;
|
||||
fgDesc.flags |= FFX_FRAMEGENERATION_ENABLE_DEBUG_CHECKING;
|
||||
if (desc.hdrInput) fgDesc.flags |= FFX_FRAMEGENERATION_ENABLE_HIGH_DYNAMIC_RANGE;
|
||||
if (desc.depthInverted) fgDesc.flags |= FFX_FRAMEGENERATION_ENABLE_DEPTH_INVERTED;
|
||||
fgDesc.displaySize.width = desc.displayWidth;
|
||||
fgDesc.displaySize.height = desc.displayHeight;
|
||||
fgDesc.maxRenderSize.width = desc.maxRenderWidth;
|
||||
fgDesc.maxRenderSize.height = desc.maxRenderHeight;
|
||||
fgDesc.backBufferFormat = ffxApiGetSurfaceFormatVK(desc.colorFormat);
|
||||
backendDesc.header.pNext = reinterpret_cast<ffxApiHeader*>(&fgVerDesc);
|
||||
|
||||
ffxContext fgCtx = nullptr;
|
||||
const ffxReturnCode_t fgCreateRc =
|
||||
fns_->createContext(&fgCtx, reinterpret_cast<ffxCreateContextDescHeader*>(&fgDesc), nullptr);
|
||||
if (fgCreateRc != FFX_API_RETURN_OK) {
|
||||
const std::string loadedPath = loadedLibraryPath_;
|
||||
lastError_ = "ffxCreateContext (framegeneration) failed rc=" + std::to_string(fgCreateRc) +
|
||||
" (" + ffxApiReturnCodeName(fgCreateRc) + "), runtimeLib=" + loadedPath;
|
||||
shutdown();
|
||||
return false;
|
||||
}
|
||||
genericFramegenContext_ = fgCtx;
|
||||
backendDesc.header.pNext = nullptr;
|
||||
|
||||
ffxConfigureDescFrameGeneration fgCfg{};
|
||||
fgCfg.header.type = FFX_API_CONFIGURE_DESC_TYPE_FRAMEGENERATION;
|
||||
fgCfg.header.pNext = nullptr;
|
||||
fgCfg.frameGenerationEnabled = true;
|
||||
fgCfg.allowAsyncWorkloads = false;
|
||||
fgCfg.flags = FFX_FRAMEGENERATION_FLAG_NO_SWAPCHAIN_CONTEXT_NOTIFY;
|
||||
fgCfg.onlyPresentGenerated = false;
|
||||
fgCfg.frameID = genericFrameId_;
|
||||
if (fns_->configure(reinterpret_cast<ffxContext*>(&genericFramegenContext_),
|
||||
reinterpret_cast<ffxConfigureDescHeader*>(&fgCfg)) != FFX_API_RETURN_OK) {
|
||||
lastError_ = "ffxConfigure (framegeneration) failed";
|
||||
shutdown();
|
||||
return false;
|
||||
}
|
||||
frameGenerationReady_ = true;
|
||||
}
|
||||
|
||||
ready_ = true;
|
||||
LOG_INFO("FSR3 runtime: loaded generic API from ", loadedLibraryPath_,
|
||||
" framegenReady=", frameGenerationReady_ ? "yes" : "no");
|
||||
return true;
|
||||
}
|
||||
|
||||
scratchBufferSize_ = fns_->getScratchMemorySizeVK(FFX_FSR3_CONTEXT_COUNT);
|
||||
if (scratchBufferSize_ == 0) {
|
||||
LOG_WARNING("FSR3 runtime: scratch buffer size query returned 0.");
|
||||
|
|
@ -344,6 +514,49 @@ bool AmdFsr3Runtime::dispatchUpscale(const AmdFsr3RuntimeDispatchDesc& desc) {
|
|||
lastError_ = "invalid upscale dispatch resources";
|
||||
return false;
|
||||
}
|
||||
if (apiMode_ == ApiMode::GenericApi) {
|
||||
if (!genericUpscaleContext_ || !fns_->dispatch) {
|
||||
lastError_ = "generic API upscale context unavailable";
|
||||
return false;
|
||||
}
|
||||
ffxDispatchDescUpscale up{};
|
||||
up.header.type = FFX_API_DISPATCH_DESC_TYPE_UPSCALE;
|
||||
up.header.pNext = nullptr;
|
||||
up.commandList = reinterpret_cast<void*>(desc.commandBuffer);
|
||||
up.color = ffxApiGetResourceVK(desc.colorImage, desc.colorFormat, desc.renderWidth, desc.renderHeight, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
up.depth = ffxApiGetResourceVK(desc.depthImage, desc.depthFormat, desc.renderWidth, desc.renderHeight, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
up.motionVectors = ffxApiGetResourceVK(desc.motionVectorImage, desc.motionVectorFormat, desc.renderWidth, desc.renderHeight, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
up.exposure = FfxApiResource{};
|
||||
up.reactive = FfxApiResource{};
|
||||
up.transparencyAndComposition = FfxApiResource{};
|
||||
up.output = ffxApiGetResourceVK(desc.outputImage, desc.outputFormat, desc.outputWidth, desc.outputHeight, FFX_API_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||
up.jitterOffset.x = desc.jitterX;
|
||||
up.jitterOffset.y = desc.jitterY;
|
||||
up.motionVectorScale.x = desc.motionScaleX;
|
||||
up.motionVectorScale.y = desc.motionScaleY;
|
||||
up.renderSize.width = desc.renderWidth;
|
||||
up.renderSize.height = desc.renderHeight;
|
||||
up.upscaleSize.width = desc.outputWidth;
|
||||
up.upscaleSize.height = desc.outputHeight;
|
||||
up.enableSharpening = false;
|
||||
up.sharpness = 0.0f;
|
||||
up.frameTimeDelta = std::max(0.001f, desc.frameTimeDeltaMs);
|
||||
up.preExposure = 1.0f;
|
||||
up.reset = desc.reset;
|
||||
up.cameraNear = desc.cameraNear;
|
||||
up.cameraFar = desc.cameraFar;
|
||||
up.cameraFovAngleVertical = desc.cameraFovYRadians;
|
||||
up.viewSpaceToMetersFactor = 1.0f;
|
||||
up.flags = 0;
|
||||
if (fns_->dispatch(reinterpret_cast<ffxContext*>(&genericUpscaleContext_),
|
||||
reinterpret_cast<ffxDispatchDescHeader*>(&up)) != FFX_API_RETURN_OK) {
|
||||
lastError_ = "ffxDispatch (upscale) failed";
|
||||
return false;
|
||||
}
|
||||
lastError_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!contextStorage_ || !fns_->fsr3ContextDispatchUpscale) {
|
||||
lastError_ = "official runtime upscale context unavailable";
|
||||
return false;
|
||||
|
|
@ -413,6 +626,67 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
|||
lastError_ = "invalid frame generation dispatch resources";
|
||||
return false;
|
||||
}
|
||||
if (apiMode_ == ApiMode::GenericApi) {
|
||||
if (!genericFramegenContext_ || !fns_->dispatch) {
|
||||
lastError_ = "generic API frame generation context unavailable";
|
||||
return false;
|
||||
}
|
||||
ffxDispatchDescFrameGenerationPrepareV2 prep{};
|
||||
prep.header.type = FFX_API_DISPATCH_DESC_TYPE_FRAMEGENERATION_PREPARE_V2;
|
||||
prep.header.pNext = nullptr;
|
||||
prep.frameID = genericFrameId_;
|
||||
prep.flags = 0;
|
||||
prep.commandList = reinterpret_cast<void*>(desc.commandBuffer);
|
||||
prep.renderSize.width = desc.renderWidth;
|
||||
prep.renderSize.height = desc.renderHeight;
|
||||
prep.jitterOffset.x = desc.jitterX;
|
||||
prep.jitterOffset.y = desc.jitterY;
|
||||
prep.motionVectorScale.x = desc.motionScaleX;
|
||||
prep.motionVectorScale.y = desc.motionScaleY;
|
||||
prep.frameTimeDelta = std::max(0.001f, desc.frameTimeDeltaMs);
|
||||
prep.reset = desc.reset;
|
||||
prep.cameraNear = desc.cameraNear;
|
||||
prep.cameraFar = desc.cameraFar;
|
||||
prep.cameraFovAngleVertical = desc.cameraFovYRadians;
|
||||
prep.viewSpaceToMetersFactor = 1.0f;
|
||||
prep.depth = ffxApiGetResourceVK(desc.depthImage, desc.depthFormat, desc.renderWidth, desc.renderHeight, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
prep.motionVectors = ffxApiGetResourceVK(desc.motionVectorImage, desc.motionVectorFormat, desc.renderWidth, desc.renderHeight, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
prep.cameraPosition[0] = prep.cameraPosition[1] = prep.cameraPosition[2] = 0.0f;
|
||||
prep.cameraUp[0] = 0.0f; prep.cameraUp[1] = 1.0f; prep.cameraUp[2] = 0.0f;
|
||||
prep.cameraRight[0] = 1.0f; prep.cameraRight[1] = 0.0f; prep.cameraRight[2] = 0.0f;
|
||||
prep.cameraForward[0] = 0.0f; prep.cameraForward[1] = 0.0f; prep.cameraForward[2] = -1.0f;
|
||||
if (fns_->dispatch(reinterpret_cast<ffxContext*>(&genericFramegenContext_),
|
||||
reinterpret_cast<ffxDispatchDescHeader*>(&prep)) != FFX_API_RETURN_OK) {
|
||||
lastError_ = "ffxDispatch (framegeneration prepare) failed";
|
||||
return false;
|
||||
}
|
||||
|
||||
ffxDispatchDescFrameGeneration fg{};
|
||||
fg.header.type = FFX_API_DISPATCH_DESC_TYPE_FRAMEGENERATION;
|
||||
fg.header.pNext = nullptr;
|
||||
fg.commandList = reinterpret_cast<void*>(desc.commandBuffer);
|
||||
fg.presentColor = ffxApiGetResourceVK(desc.outputImage, desc.outputFormat, desc.outputWidth, desc.outputHeight, FFX_API_RESOURCE_STATE_COMPUTE_READ);
|
||||
fg.outputs[0] = ffxApiGetResourceVK(desc.frameGenOutputImage, desc.outputFormat, desc.outputWidth, desc.outputHeight, FFX_API_RESOURCE_STATE_UNORDERED_ACCESS);
|
||||
fg.numGeneratedFrames = 1;
|
||||
fg.reset = desc.reset;
|
||||
fg.backbufferTransferFunction = FFX_API_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
|
||||
fg.minMaxLuminance[0] = 0.0f;
|
||||
fg.minMaxLuminance[1] = 1.0f;
|
||||
fg.generationRect.left = 0;
|
||||
fg.generationRect.top = 0;
|
||||
fg.generationRect.width = desc.outputWidth;
|
||||
fg.generationRect.height = desc.outputHeight;
|
||||
fg.frameID = genericFrameId_;
|
||||
if (fns_->dispatch(reinterpret_cast<ffxContext*>(&genericFramegenContext_),
|
||||
reinterpret_cast<ffxDispatchDescHeader*>(&fg)) != FFX_API_RETURN_OK) {
|
||||
lastError_ = "ffxDispatch (framegeneration) failed";
|
||||
return false;
|
||||
}
|
||||
++genericFrameId_;
|
||||
lastError_.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!contextStorage_ || !fns_->fsr3DispatchFrameGeneration) {
|
||||
lastError_ = "official runtime frame generation context unavailable";
|
||||
return false;
|
||||
|
|
@ -449,7 +723,18 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
|||
|
||||
void AmdFsr3Runtime::shutdown() {
|
||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||
if (contextStorage_ && fns_ && fns_->fsr3ContextDestroy) {
|
||||
if (apiMode_ == ApiMode::GenericApi && fns_ && fns_->destroyContext) {
|
||||
if (genericFramegenContext_) {
|
||||
auto ctx = reinterpret_cast<ffxContext*>(&genericFramegenContext_);
|
||||
fns_->destroyContext(ctx, nullptr);
|
||||
genericFramegenContext_ = nullptr;
|
||||
}
|
||||
if (genericUpscaleContext_) {
|
||||
auto ctx = reinterpret_cast<ffxContext*>(&genericUpscaleContext_);
|
||||
fns_->destroyContext(ctx, nullptr);
|
||||
genericUpscaleContext_ = nullptr;
|
||||
}
|
||||
} else if (contextStorage_ && fns_ && fns_->fsr3ContextDestroy) {
|
||||
fns_->fsr3ContextDestroy(reinterpret_cast<FfxFsr3Context*>(contextStorage_));
|
||||
}
|
||||
#endif
|
||||
|
|
@ -476,6 +761,8 @@ void AmdFsr3Runtime::shutdown() {
|
|||
libHandle_ = nullptr;
|
||||
loadedLibraryPath_.clear();
|
||||
loadPathKind_ = LoadPathKind::None;
|
||||
apiMode_ = ApiMode::LegacyFsr3;
|
||||
genericFrameId_ = 1;
|
||||
}
|
||||
|
||||
} // namespace wowee::rendering
|
||||
|
|
|
|||
|
|
@ -201,7 +201,7 @@ void PerformanceHUD::render(const Renderer* renderer, const Camera* camera) {
|
|||
}
|
||||
}
|
||||
if (renderer->isFSR2Enabled()) {
|
||||
ImGui::TextColored(ImVec4(0.4f, 0.9f, 1.0f, 1.0f), "FSR 2.2: ON");
|
||||
ImGui::TextColored(ImVec4(0.4f, 0.9f, 1.0f, 1.0f), "FSR 3 Upscale: ON");
|
||||
ImGui::Text(" JitterSign=%.2f", renderer->getFSR2JitterSign());
|
||||
const bool fgEnabled = renderer->isAmdFsr3FramegenEnabled();
|
||||
const bool fgReady = renderer->isAmdFsr3FramegenRuntimeReady();
|
||||
|
|
|
|||
|
|
@ -3899,7 +3899,9 @@ bool Renderer::initFSR2Resources() {
|
|||
fsr2_.amdFsr3RuntimePath = "Path C";
|
||||
fsr2_.amdFsr3RuntimeLastError = fsr2_.amdFsr3Runtime->lastError();
|
||||
LOG_WARNING("FSR3 framegen toggle is enabled, but runtime initialization failed. ",
|
||||
"Set WOWEE_FFX_SDK_RUNTIME_LIB to the SDK runtime binary path.");
|
||||
"path=", fsr2_.amdFsr3RuntimePath,
|
||||
" error=", fsr2_.amdFsr3RuntimeLastError.empty() ? "(none)" : fsr2_.amdFsr3RuntimeLastError,
|
||||
" runtimeLib=", fsr2_.amdFsr3Runtime->loadedLibraryPath().empty() ? "(not loaded)" : fsr2_.amdFsr3Runtime->loadedLibraryPath());
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -6308,7 +6308,7 @@ void GameScreen::renderSettingsWindow() {
|
|||
if (fsr2Active) {
|
||||
ImGui::BeginDisabled();
|
||||
int disabled = 0;
|
||||
ImGui::Combo("Anti-Aliasing (FSR2)", &disabled, "Off (FSR2 active)\0", 1);
|
||||
ImGui::Combo("Anti-Aliasing (FSR3)", &disabled, "Off (FSR3 active)\0", 1);
|
||||
ImGui::EndDisabled();
|
||||
} else if (ImGui::Combo("Anti-Aliasing", &pendingAntiAliasing, aaLabels, 4)) {
|
||||
static const VkSampleCountFlagBits aaSamples[] = {
|
||||
|
|
@ -6321,8 +6321,8 @@ void GameScreen::renderSettingsWindow() {
|
|||
}
|
||||
// FSR Upscaling
|
||||
{
|
||||
// FSR mode selection: Off, FSR 1.0 (Spatial), FSR 2.2 (Temporal)
|
||||
const char* fsrModeLabels[] = { "Off", "FSR 1.0 (Spatial)", "FSR 2.2 (Temporal)" };
|
||||
// FSR mode selection: Off, FSR 1.0 (Spatial), FSR 3.x (Temporal)
|
||||
const char* fsrModeLabels[] = { "Off", "FSR 1.0 (Spatial)", "FSR 3.x (Temporal)" };
|
||||
int fsrMode = pendingUpscalingMode;
|
||||
if (ImGui::Combo("Upscaling", &fsrMode, fsrModeLabels, 3)) {
|
||||
pendingUpscalingMode = fsrMode;
|
||||
|
|
@ -6335,7 +6335,7 @@ void GameScreen::renderSettingsWindow() {
|
|||
}
|
||||
if (fsrMode > 0) {
|
||||
if (fsrMode == 2 && renderer) {
|
||||
ImGui::TextDisabled("FSR2 backend: %s",
|
||||
ImGui::TextDisabled("FSR3 backend: %s",
|
||||
renderer->isAmdFsr2SdkAvailable() ? "AMD FidelityFX SDK" : "Internal fallback");
|
||||
if (renderer->isAmdFsr3FramegenSdkAvailable()) {
|
||||
if (ImGui::Checkbox("AMD FSR3 Frame Generation (Experimental)", &pendingAMDFramegen)) {
|
||||
|
|
@ -6387,7 +6387,7 @@ void GameScreen::renderSettingsWindow() {
|
|||
saveSettings();
|
||||
}
|
||||
if (fsrMode == 2) {
|
||||
ImGui::SeparatorText("FSR2 Tuning");
|
||||
ImGui::SeparatorText("FSR3 Tuning");
|
||||
if (ImGui::SliderFloat("Jitter Sign", &pendingFSR2JitterSign, -2.0f, 2.0f, "%.2f")) {
|
||||
if (renderer) {
|
||||
renderer->setFSR2DebugTuning(
|
||||
|
|
|
|||
195
tools/generate_ffx_sdk_vk_permutations.sh
Executable file
195
tools/generate_ffx_sdk_vk_permutations.sh
Executable file
|
|
@ -0,0 +1,195 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
SDK_ROOT="${1:-$ROOT_DIR/extern/FidelityFX-SDK}"
|
||||
KITS_DIR="$SDK_ROOT/Kits/FidelityFX"
|
||||
FFX_SC="$KITS_DIR/tools/ffx_sc/ffx_sc.py"
|
||||
OUT_DIR="$KITS_DIR/framegeneration/fsr3/internal/permutations/vk"
|
||||
SHADER_DIR="$KITS_DIR/upscalers/fsr3/internal/shaders"
|
||||
|
||||
if [[ ! -f "$FFX_SC" ]]; then
|
||||
echo "Missing ffx_sc.py at $FFX_SC" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
required_headers=(
|
||||
"$OUT_DIR/ffx_fsr2_accumulate_pass_wave64_16bit_permutations.h"
|
||||
"$OUT_DIR/ffx_fsr3upscaler_accumulate_pass_wave64_16bit_permutations.h"
|
||||
"$OUT_DIR/ffx_fsr3upscaler_autogen_reactive_pass_permutations.h"
|
||||
)
|
||||
if [[ "${WOWEE_FORCE_REGEN_PERMS:-0}" != "1" ]]; then
|
||||
missing=0
|
||||
for h in "${required_headers[@]}"; do
|
||||
[[ -f "$h" ]] || missing=1
|
||||
done
|
||||
if [[ $missing -eq 0 ]]; then
|
||||
echo "FidelityFX VK permutation headers already present."
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
if [[ -z "${DXC:-}" ]]; then
|
||||
if [[ -x /tmp/dxc/bin/dxc ]]; then
|
||||
export DXC=/tmp/dxc/bin/dxc
|
||||
elif command -v dxc >/dev/null 2>&1; then
|
||||
export DXC="$(command -v dxc)"
|
||||
elif [[ "$(uname -s)" == "Linux" ]]; then
|
||||
echo "DXC not found; downloading Linux DXC release to /tmp/dxc ..."
|
||||
tmp_json="$(mktemp)"
|
||||
curl -sS https://api.github.com/repos/microsoft/DirectXShaderCompiler/releases/latest > "$tmp_json"
|
||||
dxc_url="$(python3 - << 'PY' "$tmp_json"
|
||||
import json, sys
|
||||
with open(sys.argv[1], 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
for a in data.get('assets', []):
|
||||
name = a.get('name', '')
|
||||
if name.startswith('linux_dxc_') and name.endswith('.x86_64.tar.gz'):
|
||||
print(a.get('browser_download_url', ''))
|
||||
break
|
||||
PY
|
||||
)"
|
||||
rm -f "$tmp_json"
|
||||
if [[ -z "$dxc_url" ]]; then
|
||||
echo "Failed to locate Linux DXC release asset URL." >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -rf /tmp/dxc /tmp/linux_dxc.tar.gz
|
||||
curl -L --fail "$dxc_url" -o /tmp/linux_dxc.tar.gz
|
||||
mkdir -p /tmp/dxc
|
||||
tar -xzf /tmp/linux_dxc.tar.gz -C /tmp/dxc --strip-components=1
|
||||
export DXC=/tmp/dxc/bin/dxc
|
||||
elif [[ "$(uname -s)" =~ MINGW|MSYS|CYGWIN ]]; then
|
||||
echo "DXC not found; downloading Windows DXC release to /tmp/dxc ..."
|
||||
tmp_json="$(mktemp)"
|
||||
curl -sS https://api.github.com/repos/microsoft/DirectXShaderCompiler/releases/latest > "$tmp_json"
|
||||
dxc_url="$(python3 - << 'PY' "$tmp_json"
|
||||
import json, sys
|
||||
with open(sys.argv[1], 'r', encoding='utf-8') as f:
|
||||
data = json.load(f)
|
||||
for a in data.get('assets', []):
|
||||
name = a.get('name', '')
|
||||
if name.startswith('dxc_') and name.endswith('.zip'):
|
||||
print(a.get('browser_download_url', ''))
|
||||
break
|
||||
PY
|
||||
)"
|
||||
rm -f "$tmp_json"
|
||||
if [[ -z "$dxc_url" ]]; then
|
||||
echo "Failed to locate Windows DXC release asset URL." >&2
|
||||
exit 1
|
||||
fi
|
||||
rm -rf /tmp/dxc /tmp/dxc_win.zip
|
||||
curl -L --fail "$dxc_url" -o /tmp/dxc_win.zip
|
||||
mkdir -p /tmp/dxc
|
||||
unzip -q /tmp/dxc_win.zip -d /tmp/dxc
|
||||
if [[ -x /tmp/dxc/bin/x64/dxc.exe ]]; then
|
||||
export DXC=/tmp/dxc/bin/x64/dxc.exe
|
||||
elif [[ -x /tmp/dxc/bin/x86/dxc.exe ]]; then
|
||||
export DXC=/tmp/dxc/bin/x86/dxc.exe
|
||||
else
|
||||
echo "DXC download succeeded, but dxc.exe was not found." >&2
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
echo "DXC not found. Set DXC=/path/to/dxc or install to /tmp/dxc/bin/dxc" >&2
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
mkdir -p "$OUT_DIR"
|
||||
|
||||
# First generate frame interpolation + optical flow permutations via SDK script.
|
||||
(
|
||||
cd "$SDK_ROOT"
|
||||
./generate_vk_permutations.sh
|
||||
)
|
||||
|
||||
BASE_ARGS=(-reflection -embed-arguments -E CS -Wno-for-redefinition -Wno-ambig-lit-shift -DFFX_GPU=1 -DFFX_HLSL=1 -DFFX_IMPLICIT_SHADER_REGISTER_BINDING_HLSL=0)
|
||||
WAVE32=(-DFFX_HLSL_SM=62 -T cs_6_2)
|
||||
WAVE64=("-DFFX_PREFER_WAVE64=[WaveSize(64)]" -DFFX_HLSL_SM=66 -T cs_6_6)
|
||||
BIT16=(-DFFX_HALF=1 -enable-16bit-types)
|
||||
|
||||
compile_shader() {
|
||||
local file="$1"; shift
|
||||
local name="$1"; shift
|
||||
python3 "$FFX_SC" "${BASE_ARGS[@]}" "$@" -name="$name" -output="$OUT_DIR" "$file"
|
||||
}
|
||||
|
||||
# FSR2 (for upscalers/fsr3/internal/ffx_fsr2_shaderblobs.cpp)
|
||||
FSR2_COMMON=(
|
||||
-DFFX_FSR2_EMBED_ROOTSIG=0
|
||||
-DFFX_FSR2_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF=0
|
||||
-DFFX_FSR2_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF=0
|
||||
-DFFX_FSR2_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF=1
|
||||
-DFFX_FSR2_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF=0
|
||||
-DFFX_FSR2_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2
|
||||
"-DFFX_FSR2_OPTION_REPROJECT_USE_LANCZOS_TYPE={0,1}"
|
||||
"-DFFX_FSR2_OPTION_HDR_COLOR_INPUT={0,1}"
|
||||
"-DFFX_FSR2_OPTION_LOW_RESOLUTION_MOTION_VECTORS={0,1}"
|
||||
"-DFFX_FSR2_OPTION_JITTERED_MOTION_VECTORS={0,1}"
|
||||
"-DFFX_FSR2_OPTION_INVERTED_DEPTH={0,1}"
|
||||
"-DFFX_FSR2_OPTION_APPLY_SHARPENING={0,1}"
|
||||
-I "$KITS_DIR/api/internal/include/gpu"
|
||||
-I "$KITS_DIR/upscalers/fsr3/include/gpu"
|
||||
)
|
||||
FSR2_SHADERS=(
|
||||
ffx_fsr2_autogen_reactive_pass
|
||||
ffx_fsr2_accumulate_pass
|
||||
ffx_fsr2_compute_luminance_pyramid_pass
|
||||
ffx_fsr2_depth_clip_pass
|
||||
ffx_fsr2_lock_pass
|
||||
ffx_fsr2_reconstruct_previous_depth_pass
|
||||
ffx_fsr2_rcas_pass
|
||||
ffx_fsr2_tcr_autogen_pass
|
||||
)
|
||||
|
||||
for shader in "${FSR2_SHADERS[@]}"; do
|
||||
file="$SHADER_DIR/$shader.hlsl"
|
||||
[[ -f "$file" ]] || continue
|
||||
compile_shader "$file" "$shader" -DFFX_HALF=0 "${WAVE32[@]}" "${FSR2_COMMON[@]}"
|
||||
compile_shader "$file" "${shader}_wave64" -DFFX_HALF=0 "${WAVE64[@]}" "${FSR2_COMMON[@]}"
|
||||
compile_shader "$file" "${shader}_16bit" "${BIT16[@]}" "${WAVE32[@]}" "${FSR2_COMMON[@]}"
|
||||
compile_shader "$file" "${shader}_wave64_16bit" "${BIT16[@]}" "${WAVE64[@]}" "${FSR2_COMMON[@]}"
|
||||
done
|
||||
|
||||
# FSR3 upscaler (for upscalers/fsr3/internal/ffx_fsr3upscaler_shaderblobs.cpp)
|
||||
FSR3_COMMON=(
|
||||
-DFFX_FSR3UPSCALER_EMBED_ROOTSIG=0
|
||||
-DFFX_FSR3UPSCALER_OPTION_UPSAMPLE_SAMPLERS_USE_DATA_HALF=0
|
||||
-DFFX_FSR3UPSCALER_OPTION_ACCUMULATE_SAMPLERS_USE_DATA_HALF=0
|
||||
-DFFX_FSR3UPSCALER_OPTION_REPROJECT_SAMPLERS_USE_DATA_HALF=1
|
||||
-DFFX_FSR3UPSCALER_OPTION_POSTPROCESSLOCKSTATUS_SAMPLERS_USE_DATA_HALF=0
|
||||
-DFFX_FSR3UPSCALER_OPTION_UPSAMPLE_USE_LANCZOS_TYPE=2
|
||||
"-DFFX_FSR3UPSCALER_OPTION_REPROJECT_USE_LANCZOS_TYPE={0,1}"
|
||||
"-DFFX_FSR3UPSCALER_OPTION_HDR_COLOR_INPUT={0,1}"
|
||||
"-DFFX_FSR3UPSCALER_OPTION_LOW_RESOLUTION_MOTION_VECTORS={0,1}"
|
||||
"-DFFX_FSR3UPSCALER_OPTION_JITTERED_MOTION_VECTORS={0,1}"
|
||||
"-DFFX_FSR3UPSCALER_OPTION_INVERTED_DEPTH={0,1}"
|
||||
"-DFFX_FSR3UPSCALER_OPTION_APPLY_SHARPENING={0,1}"
|
||||
-I "$KITS_DIR/api/internal/gpu"
|
||||
-I "$KITS_DIR/upscalers/fsr3/include/gpu"
|
||||
)
|
||||
FSR3_SHADERS=(
|
||||
ffx_fsr3upscaler_autogen_reactive_pass
|
||||
ffx_fsr3upscaler_accumulate_pass
|
||||
ffx_fsr3upscaler_luma_pyramid_pass
|
||||
ffx_fsr3upscaler_prepare_reactivity_pass
|
||||
ffx_fsr3upscaler_prepare_inputs_pass
|
||||
ffx_fsr3upscaler_shading_change_pass
|
||||
ffx_fsr3upscaler_rcas_pass
|
||||
ffx_fsr3upscaler_shading_change_pyramid_pass
|
||||
ffx_fsr3upscaler_luma_instability_pass
|
||||
ffx_fsr3upscaler_debug_view_pass
|
||||
)
|
||||
|
||||
for shader in "${FSR3_SHADERS[@]}"; do
|
||||
file="$SHADER_DIR/$shader.hlsl"
|
||||
[[ -f "$file" ]] || continue
|
||||
compile_shader "$file" "$shader" -DFFX_HALF=0 "${WAVE32[@]}" "${FSR3_COMMON[@]}"
|
||||
compile_shader "$file" "${shader}_wave64" -DFFX_HALF=0 "${WAVE64[@]}" "${FSR3_COMMON[@]}"
|
||||
compile_shader "$file" "${shader}_16bit" "${BIT16[@]}" "${WAVE32[@]}" "${FSR3_COMMON[@]}"
|
||||
compile_shader "$file" "${shader}_wave64_16bit" "${BIT16[@]}" "${WAVE64[@]}" "${FSR3_COMMON[@]}"
|
||||
done
|
||||
|
||||
echo "Generated VK permutation headers in $OUT_DIR"
|
||||
Loading…
Add table
Add a link
Reference in a new issue