Skip to content

Commit

Permalink
Refactor FfxFrameInterpolationContext code into FFInterpolator
Browse files Browse the repository at this point in the history
  • Loading branch information
Nukem9 committed Dec 21, 2023
1 parent 25ce7ec commit 6569477
Show file tree
Hide file tree
Showing 2 changed files with 224 additions and 0 deletions.
153 changes: 153 additions & 0 deletions source/maindll/FFInterpolator.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
#include "FFInterpolator.h"

FFInterpolator::FFInterpolator(const FfxInterface& BackendInterface, uint32_t MaxRenderWidth, uint32_t MaxRenderHeight)
: m_BackendInterface(BackendInterface),
m_MaxRenderWidth(MaxRenderWidth),
m_MaxRenderHeight(MaxRenderHeight)
{
}

FFInterpolator::~FFInterpolator()
{
if (m_ResourceCreationHackActive)
{
const uint32_t resourceId = FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE;
auto context = reinterpret_cast<FfxFrameInterpolationContext_Private *>(&m_Context);

context->srvResources[resourceId] = m_OriginalPreviousInterpolationSource;
context->uavResources[resourceId] = m_OriginalPreviousInterpolationSource;

context->contextDescription.backendInterface.fpDestroyResource(
&context->contextDescription.backendInterface,
m_HackPreviousInterpolationSource,
context->effectContextId);
}

if (m_ContextCreated)
ffxFrameInterpolationContextDestroy(&m_Context);
}

FfxErrorCode FFInterpolator::Dispatch(const FFInterpolatorDispatchParameters& Parameters)
{
FFX_RETURN_ON_FAIL(InternalDeferredSetupContext(Parameters)); // Massive frame hitch on first call

FfxFrameInterpolationDispatchDescription desc = {};

if (Parameters.DebugTearLines)
desc.flags |= FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_TEAR_LINES;

if (Parameters.DebugView)
desc.flags |= FFX_FRAMEINTERPOLATION_DISPATCH_DRAW_DEBUG_VIEW;

desc.commandList = Parameters.CommandList;
desc.displaySize = Parameters.OutputSize;
desc.renderSize = Parameters.RenderSize;

desc.currentBackBuffer = Parameters.InputColorBuffer;
desc.currentBackBuffer_HUDLess = Parameters.InputHUDLessColorBuffer;
desc.output = Parameters.OutputColorBuffer;
desc.dilatedDepth = Parameters.InputDilatedDepth;
desc.dilatedMotionVectors = Parameters.InputDilatedMotionVectors;
desc.reconstructPrevNearDepth = Parameters.InputReconstructedPreviousNearDepth;

desc.interpolationRect = { 0, 0, static_cast<int>(desc.displaySize.width), static_cast<int>(desc.displaySize.height) };

desc.opticalFlowVector = Parameters.InputOpticalFlowVector;
desc.opticalFlowSceneChangeDetection = Parameters.InputOpticalFlowSceneChangeDetection;
desc.opticalFlowBufferSize = Parameters.OpticalFlowBufferSize;
desc.opticalFlowScale = Parameters.OpticalFlowScale;
desc.opticalFlowBlockSize = Parameters.OpticalFlowBlockSize;

desc.cameraNear = Parameters.CameraNear;
desc.cameraFar = Parameters.CameraFar;
desc.cameraFovAngleVertical = Parameters.CameraFovAngleVertical;
desc.viewSpaceToMetersFactor = Parameters.ViewSpaceToMetersFactor;

desc.frameTimeDelta = 1000.0f / 60.0f; // Unused
desc.reset = Parameters.Reset;

desc.backBufferTransferFunction = Parameters.HDR ? FFX_BACKBUFFER_TRANSFER_FUNCTION_PQ : FFX_BACKBUFFER_TRANSFER_FUNCTION_SRGB;
desc.minMaxLuminance[0] = Parameters.MinMaxLuminance.x;
desc.minMaxLuminance[1] = Parameters.MinMaxLuminance.y;

return ffxFrameInterpolationDispatch(&m_Context, &desc);
}

FfxErrorCode FFInterpolator::InternalDeferredSetupContext(const FFInterpolatorDispatchParameters& Parameters)
{
if (!m_ContextCreated)
{
FfxFrameInterpolationContextDescription desc = {};
desc.backendInterface = m_BackendInterface;

if (Parameters.HDR)
desc.flags |= FFX_FRAMEINTERPOLATION_ENABLE_HDR_COLOR_INPUT;

if (Parameters.DepthInverted)
desc.flags |= FFX_FRAMEINTERPOLATION_ENABLE_DEPTH_INVERTED;

desc.maxRenderSize = { m_MaxRenderWidth, m_MaxRenderHeight };
desc.displaySize = desc.maxRenderSize;

// If provided, pretend the input hudless color format is the back buffer format
desc.backBufferFormat = Parameters.InputColorBuffer.description.format;

if (Parameters.InputHUDLessColorBuffer.resource)
desc.backBufferFormat = Parameters.InputHUDLessColorBuffer.description.format;

FFX_RETURN_ON_FAIL(ffxFrameInterpolationContextCreate(&m_Context, &desc));

m_InitialBackBufferFormat = desc.backBufferFormat;
m_ContextCreated = true;
}

// What FFX calls "backBufferFormat" is actually the format of the input color buffer. The input
// color buffer could be the back buffer, or it could be a HUD-less equivalent. Either way, code
// assumes they're identical formats and trips an assert if they're not. The assert is bogus since
// AMD's new implementation is format-agnostic. We can work around this limitation by swapping
// internal resource handles around.
auto& currentInputColor = Parameters.InputHUDLessColorBuffer.resource ? Parameters.InputHUDLessColorBuffer
: Parameters.InputColorBuffer;

if (currentInputColor.description.format != m_InitialBackBufferFormat)
FFX_RETURN_ON_FAIL(InternalSwapResources(currentInputColor.description.format));

return FFX_OK;
}

FfxErrorCode FFInterpolator::InternalSwapResources(FfxSurfaceFormat NewFormat)
{
if (m_ResourceCreationHackActive)
return FFX_OK;

const uint32_t resourceId = FFX_FRAMEINTERPOLATION_RESOURCE_IDENTIFIER_PREVIOUS_INTERPOLATION_SOURCE;
auto context = reinterpret_cast<FfxFrameInterpolationContext_Private *>(&m_Context);

// Create an exact texture copy but with the new format
auto newCopyDescription = context->contextDescription.backendInterface.fpGetResourceDescription(
&context->contextDescription.backendInterface,
context->srvResources[resourceId]);

newCopyDescription.format = NewFormat;

const FfxCreateResourceDescription createResourceDescription = { FFX_HEAP_TYPE_DEFAULT,
newCopyDescription,
FFX_RESOURCE_STATE_UNORDERED_ACCESS,
0,
nullptr,
L"FI_PreviousInterpolationSourceHACK",
resourceId };

FFX_RETURN_ON_FAIL(context->contextDescription.backendInterface.fpCreateResource(
&context->contextDescription.backendInterface,
&createResourceDescription,
context->effectContextId,
&m_HackPreviousInterpolationSource));

m_OriginalPreviousInterpolationSource = context->srvResources[resourceId];
context->srvResources[resourceId] = m_HackPreviousInterpolationSource;
context->uavResources[resourceId] = m_HackPreviousInterpolationSource;

m_ResourceCreationHackActive = true;
return FFX_OK;
}
71 changes: 71 additions & 0 deletions source/maindll/FFInterpolator.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
#pragma once

#include <FidelityFX/host/ffx_frameinterpolation.h>
#include <FidelityFX/components/frameinterpolation/ffx_frameinterpolation_private.h>
#include <FidelityFX/host/backends/dx12/ffx_dx12.h>
#include "FFXCommon.h"

struct FFInterpolatorDispatchParameters
{
FfxCommandList CommandList;

FfxDimensions2D RenderSize;
FfxDimensions2D OutputSize;

FfxResource InputColorBuffer;
FfxResource InputHUDLessColorBuffer;
FfxResource InputDilatedDepth;
FfxResource InputDilatedMotionVectors;
FfxResource InputReconstructedPreviousNearDepth;

FfxResource InputOpticalFlowVector;
FfxResource InputOpticalFlowSceneChangeDetection;
FfxDimensions2D OpticalFlowBufferSize;
FfxFloatCoords2D OpticalFlowScale;
int OpticalFlowBlockSize;

FfxResource OutputColorBuffer;

bool HDR;
bool DepthInverted;
bool Reset;
bool DebugTearLines;
bool DebugView;

float CameraNear;
float CameraFar;
float CameraFovAngleVertical;
float ViewSpaceToMetersFactor;
FfxFloatCoords2D MinMaxLuminance;
};

class FFInterpolator
{
private:
const uint32_t m_MaxRenderWidth;
const uint32_t m_MaxRenderHeight;

FfxSurfaceFormat m_InitialBackBufferFormat = {};

FfxInterface m_BackendInterface = {};
uint32_t m_EffectContextId = 0;

FfxFrameInterpolationContext m_Context = {};
bool m_ContextCreated = false;

FfxResourceInternal m_HackPreviousInterpolationSource = {};
FfxResourceInternal m_OriginalPreviousInterpolationSource = {};
bool m_ResourceCreationHackActive = false;

public:
FFInterpolator(const FfxInterface& BackendInterface, uint32_t MaxRenderWidth, uint32_t MaxRenderHeight);
FFInterpolator(const FFInterpolator&) = delete;
FFInterpolator& operator=(const FFInterpolator&) = delete;
~FFInterpolator();

FfxErrorCode Dispatch(const FFInterpolatorDispatchParameters& Parameters);

private:
FfxErrorCode InternalDeferredSetupContext(const FFInterpolatorDispatchParameters& Parameters);
FfxErrorCode InternalSwapResources(FfxSurfaceFormat NewFormat);
};

0 comments on commit 6569477

Please sign in to comment.