mirror of
https://github.com/Kelsidavis/WoWee.git
synced 2026-03-22 23:30:14 +00:00
Implement clean Path-B FSR3 wrapper ABI for framegen
This commit is contained in:
parent
93850ac6dc
commit
a1c4244a27
5 changed files with 254 additions and 5 deletions
|
|
@ -200,7 +200,14 @@ make -j$(nproc)
|
|||
- Runtime library auto-probe checks for `libffx_fsr3_vk`/`ffx_fsr3_vk` in default loader paths.
|
||||
- Override runtime library path with:
|
||||
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (platform extension varies).
|
||||
- Current state is still dispatch-staged until full FI/OF dispatch activation is linked.
|
||||
- Wrapper override path:
|
||||
- `WOWEE_FFX_SDK_RUNTIME_WRAPPER_LIB=/absolute/path/to/libffx_fsr3_vk_wrapper.so` (platform extension varies).
|
||||
- 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_initialize`
|
||||
- `wowee_fsr3_wrapper_dispatch_upscale`
|
||||
- `wowee_fsr3_wrapper_shutdown`
|
||||
- Optional FG hook: `wowee_fsr3_wrapper_dispatch_framegen`
|
||||
|
||||
### Current FSR Defaults
|
||||
|
||||
|
|
|
|||
|
|
@ -36,10 +36,22 @@ Detection expects:
|
|||
Runtime note:
|
||||
|
||||
- Renderer/UI now expose a persisted experimental framegen toggle.
|
||||
- Runtime loader now probes for AMD FSR3 SDK runtime binaries.
|
||||
- Runtime loader now supports:
|
||||
- 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:
|
||||
- `WOWEE_FFX_SDK_RUNTIME_LIB=/absolute/path/to/libffx_fsr3_vk.so` (or `.dll` / `.dylib`).
|
||||
- Current runtime status is still `dispatch staged` (FI/OF dispatch activation pending).
|
||||
- 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`).
|
||||
- Path B wrapper ABI contract is declared in:
|
||||
- `include/rendering/amd_fsr3_wrapper_abi.h`
|
||||
- Required wrapper exports:
|
||||
- `wowee_fsr3_wrapper_get_abi_version`
|
||||
- `wowee_fsr3_wrapper_initialize`
|
||||
- `wowee_fsr3_wrapper_dispatch_upscale`
|
||||
- `wowee_fsr3_wrapper_shutdown`
|
||||
- Optional wrapper export:
|
||||
- `wowee_fsr3_wrapper_dispatch_framegen`
|
||||
|
||||
## Current Status
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,12 @@ public:
|
|||
const std::string& lastError() const { return lastError_; }
|
||||
|
||||
private:
|
||||
enum class RuntimeBackend {
|
||||
None,
|
||||
Official,
|
||||
Wrapper
|
||||
};
|
||||
|
||||
void* libHandle_ = nullptr;
|
||||
std::string loadedLibraryPath_;
|
||||
void* scratchBuffer_ = nullptr;
|
||||
|
|
@ -81,6 +87,8 @@ private:
|
|||
struct RuntimeFns;
|
||||
RuntimeFns* fns_ = nullptr;
|
||||
void* contextStorage_ = nullptr;
|
||||
void* wrapperContext_ = nullptr;
|
||||
RuntimeBackend backend_ = RuntimeBackend::None;
|
||||
};
|
||||
|
||||
} // namespace wowee::rendering
|
||||
|
|
|
|||
75
include/rendering/amd_fsr3_wrapper_abi.h
Normal file
75
include/rendering/amd_fsr3_wrapper_abi.h
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define WOWEE_FSR3_WRAPPER_ABI_VERSION 1u
|
||||
|
||||
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;
|
||||
} 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
|
||||
};
|
||||
|
||||
uint32_t wowee_fsr3_wrapper_get_abi_version(void);
|
||||
const char* wowee_fsr3_wrapper_get_name(void);
|
||||
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);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
@ -1,5 +1,7 @@
|
|||
#include "rendering/amd_fsr3_runtime.hpp"
|
||||
|
||||
#include "rendering/amd_fsr3_wrapper_abi.h"
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
|
|
@ -23,6 +25,13 @@ namespace wowee::rendering {
|
|||
|
||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||
struct AmdFsr3Runtime::RuntimeFns {
|
||||
uint32_t (*wrapperGetAbiVersion)() = nullptr;
|
||||
const char* (*wrapperGetName)() = 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;
|
||||
|
||||
decltype(&ffxGetScratchMemorySizeVK) getScratchMemorySizeVK = nullptr;
|
||||
decltype(&ffxGetDeviceVK) getDeviceVK = nullptr;
|
||||
decltype(&ffxGetInterfaceVK) getInterfaceVK = nullptr;
|
||||
|
|
@ -147,6 +156,7 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
|||
shutdown();
|
||||
lastError_.clear();
|
||||
loadPathKind_ = LoadPathKind::None;
|
||||
backend_ = RuntimeBackend::None;
|
||||
|
||||
#if !WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||
(void)desc;
|
||||
|
|
@ -220,6 +230,75 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
|||
};
|
||||
|
||||
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_->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"));
|
||||
|
||||
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_ = desc.enableFrameGeneration;
|
||||
ready_ = true;
|
||||
backend_ = RuntimeBackend::Wrapper;
|
||||
if (fns_->wrapperGetName) {
|
||||
const char* wrapperName = fns_->wrapperGetName();
|
||||
if (wrapperName && *wrapperName) {
|
||||
LOG_INFO("FSR3 runtime: wrapper active: ", wrapperName);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
fns_->getScratchMemorySizeVK = reinterpret_cast<decltype(fns_->getScratchMemorySizeVK)>(resolveSym("ffxGetScratchMemorySizeVK"));
|
||||
fns_->getDeviceVK = reinterpret_cast<decltype(fns_->getDeviceVK)>(resolveSym("ffxGetDeviceVK"));
|
||||
fns_->getInterfaceVK = reinterpret_cast<decltype(fns_->getInterfaceVK)>(resolveSym("ffxGetInterfaceVK"));
|
||||
|
|
@ -333,6 +412,7 @@ bool AmdFsr3Runtime::initialize(const AmdFsr3RuntimeInitDesc& desc) {
|
|||
}
|
||||
|
||||
ready_ = true;
|
||||
backend_ = RuntimeBackend::Official;
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
|
@ -342,8 +422,39 @@ bool AmdFsr3Runtime::dispatchUpscale(const AmdFsr3RuntimeDispatchDesc& desc) {
|
|||
(void)desc;
|
||||
return false;
|
||||
#else
|
||||
if (!ready_ || !contextStorage_ || !fns_ || !fns_->fsr3ContextDispatchUpscale) return false;
|
||||
if (!ready_ || !fns_) return false;
|
||||
if (!desc.commandBuffer || !desc.colorImage || !desc.depthImage || !desc.motionVectorImage || !desc.outputImage) return false;
|
||||
if (backend_ == RuntimeBackend::Wrapper) {
|
||||
if (!wrapperContext_ || !fns_->wrapperDispatchUpscale) 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;
|
||||
return fns_->wrapperDispatchUpscale(static_cast<WoweeFsr3WrapperContext>(wrapperContext_), &wrapperDesc) == 0;
|
||||
}
|
||||
|
||||
if (!contextStorage_ || !fns_->fsr3ContextDispatchUpscale) return false;
|
||||
|
||||
FfxResourceDescription colorDesc = makeResourceDescription(
|
||||
desc.colorFormat, desc.renderWidth, desc.renderHeight, FFX_RESOURCE_USAGE_READ_ONLY);
|
||||
|
|
@ -394,9 +505,40 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
|||
(void)desc;
|
||||
return false;
|
||||
#else
|
||||
if (!ready_ || !frameGenerationReady_ || !contextStorage_ || !fns_ || !fns_->fsr3DispatchFrameGeneration) return false;
|
||||
if (!ready_ || !frameGenerationReady_ || !fns_) return false;
|
||||
if (!desc.commandBuffer || !desc.outputImage || !desc.frameGenOutputImage ||
|
||||
desc.outputWidth == 0 || desc.outputHeight == 0 || desc.outputFormat == VK_FORMAT_UNDEFINED) return false;
|
||||
if (backend_ == RuntimeBackend::Wrapper) {
|
||||
if (!wrapperContext_ || !fns_->wrapperDispatchFramegen) 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;
|
||||
return fns_->wrapperDispatchFramegen(static_cast<WoweeFsr3WrapperContext>(wrapperContext_), &wrapperDesc) == 0;
|
||||
}
|
||||
|
||||
if (!contextStorage_ || !fns_->fsr3DispatchFrameGeneration) return false;
|
||||
|
||||
FfxResourceDescription presentDesc = makeResourceDescription(
|
||||
desc.outputFormat, desc.outputWidth, desc.outputHeight, FFX_RESOURCE_USAGE_READ_ONLY);
|
||||
|
|
@ -424,6 +566,10 @@ bool AmdFsr3Runtime::dispatchFrameGeneration(const AmdFsr3RuntimeDispatchDesc& d
|
|||
|
||||
void AmdFsr3Runtime::shutdown() {
|
||||
#if WOWEE_HAS_AMD_FSR3_FRAMEGEN
|
||||
if (wrapperContext_ && fns_ && fns_->wrapperShutdown) {
|
||||
fns_->wrapperShutdown(static_cast<WoweeFsr3WrapperContext>(wrapperContext_));
|
||||
}
|
||||
wrapperContext_ = nullptr;
|
||||
if (contextStorage_ && fns_ && fns_->fsr3ContextDestroy) {
|
||||
fns_->fsr3ContextDestroy(reinterpret_cast<FfxFsr3Context*>(contextStorage_));
|
||||
}
|
||||
|
|
@ -451,6 +597,7 @@ void AmdFsr3Runtime::shutdown() {
|
|||
libHandle_ = nullptr;
|
||||
loadedLibraryPath_.clear();
|
||||
loadPathKind_ = LoadPathKind::None;
|
||||
backend_ = RuntimeBackend::None;
|
||||
}
|
||||
|
||||
} // namespace wowee::rendering
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue