057367bf4f
Introduces support for FSR2 as a new upscaler option available from the project settings. Also introduces an specific render list for surfaces that require motion and the ability to derive motion vectors from depth buffer and camera motion.
395 lines
19 KiB
C++
395 lines
19 KiB
C++
// This file is part of the FidelityFX SDK.
|
|
//
|
|
// Copyright (c) 2022-2023 Advanced Micro Devices, Inc. All rights reserved.
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
// of this software and associated documentation files (the "Software"), to deal
|
|
// in the Software without restriction, including without limitation the rights
|
|
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
// copies of the Software, and to permit persons to whom the Software is
|
|
// furnished to do so, subject to the following conditions:
|
|
// The above copyright notice and this permission notice shall be included in
|
|
// all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
// THE SOFTWARE.
|
|
|
|
#pragma once
|
|
|
|
#include "ffx_assert.h"
|
|
#include "ffx_types.h"
|
|
#include "ffx_error.h"
|
|
|
|
// Include the FSR2 resources defined in the HLSL code. This shared here to avoid getting out of sync.
|
|
#define FFX_CPU
|
|
#include "shaders/ffx_fsr2_resources.h"
|
|
#include "shaders/ffx_fsr2_common.h"
|
|
|
|
#if defined(__cplusplus)
|
|
extern "C" {
|
|
#endif // #if defined(__cplusplus)
|
|
|
|
FFX_FORWARD_DECLARE(FfxFsr2Interface);
|
|
|
|
/// An enumeration of all the passes which constitute the FSR2 algorithm.
|
|
///
|
|
/// FSR2 is implemented as a composite of several compute passes each
|
|
/// computing a key part of the final result. Each call to the
|
|
/// <c><i>FfxFsr2ScheduleGpuJobFunc</i></c> callback function will
|
|
/// correspond to a single pass included in <c><i>FfxFsr2Pass</i></c>. For a
|
|
/// more comprehensive description of each pass, please refer to the FSR2
|
|
/// reference documentation.
|
|
///
|
|
/// Please note in some cases e.g.: <c><i>FFX_FSR2_PASS_ACCUMULATE</i></c>
|
|
/// and <c><i>FFX_FSR2_PASS_ACCUMULATE_SHARPEN</i></c> either one pass or the
|
|
/// other will be used (they are mutually exclusive). The choice of which will
|
|
/// depend on the way the <c><i>FfxFsr2Context</i></c> is created and the
|
|
/// precise contents of <c><i>FfxFsr2DispatchParamters</i></c> each time a call
|
|
/// is made to <c><i>ffxFsr2ContextDispatch</i></c>.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef enum FfxFsr2Pass {
|
|
|
|
FFX_FSR2_PASS_DEPTH_CLIP = 0, ///< A pass which performs depth clipping.
|
|
FFX_FSR2_PASS_RECONSTRUCT_PREVIOUS_DEPTH = 1, ///< A pass which performs reconstruction of previous frame's depth.
|
|
FFX_FSR2_PASS_LOCK = 2, ///< A pass which calculates pixel locks.
|
|
FFX_FSR2_PASS_ACCUMULATE = 3, ///< A pass which performs upscaling.
|
|
FFX_FSR2_PASS_ACCUMULATE_SHARPEN = 4, ///< A pass which performs upscaling when sharpening is used.
|
|
FFX_FSR2_PASS_RCAS = 5, ///< A pass which performs sharpening.
|
|
FFX_FSR2_PASS_COMPUTE_LUMINANCE_PYRAMID = 6, ///< A pass which generates the luminance mipmap chain for the current frame.
|
|
FFX_FSR2_PASS_GENERATE_REACTIVE = 7, ///< An optional pass to generate a reactive mask
|
|
FFX_FSR2_PASS_TCR_AUTOGENERATE = 8, ///< An optional pass to generate a texture-and-composition and reactive masks
|
|
|
|
FFX_FSR2_PASS_COUNT ///< The number of passes performed by FSR2.
|
|
} FfxFsr2Pass;
|
|
|
|
typedef enum FfxFsr2MsgType {
|
|
FFX_FSR2_MESSAGE_TYPE_ERROR = 0,
|
|
FFX_FSR2_MESSAGE_TYPE_WARNING = 1,
|
|
FFX_FSR2_MESSAGE_TYPE_COUNT
|
|
} FfxFsr2MsgType;
|
|
|
|
/// Create and initialize the backend context.
|
|
///
|
|
/// The callback function sets up the backend context for rendering.
|
|
/// It will create or reference the device and create required internal data structures.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] device The FfxDevice obtained by ffxGetDevice(DX12/VK/...).
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2CreateBackendContextFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxDevice device);
|
|
|
|
/// Get a list of capabilities of the device.
|
|
///
|
|
/// When creating an <c><i>FfxFsr2Context</i></c> it is desirable for the FSR2
|
|
/// core implementation to be aware of certain characteristics of the platform
|
|
/// that is being targetted. This is because some optimizations which FSR2
|
|
/// attempts to perform are more effective on certain classes of hardware than
|
|
/// others, or are not supported by older hardware. In order to avoid cases
|
|
/// where optimizations actually have the effect of decreasing performance, or
|
|
/// reduce the breadth of support provided by FSR2, FSR2 queries the
|
|
/// capabilities of the device to make such decisions.
|
|
///
|
|
/// For target platforms with fixed hardware support you need not implement
|
|
/// this callback function by querying the device, but instead may hardcore
|
|
/// what features are available on the platform.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [out] outDeviceCapabilities The device capabilities structure to fill out.
|
|
/// @param [in] device The device to query for capabilities.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode(*FfxFsr2GetDeviceCapabilitiesFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxDeviceCapabilities* outDeviceCapabilities,
|
|
FfxDevice device);
|
|
|
|
/// Destroy the backend context and dereference the device.
|
|
///
|
|
/// This function is called when the <c><i>FfxFsr2Context</i></c> is destroyed.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode(*FfxFsr2DestroyBackendContextFunc)(
|
|
FfxFsr2Interface* backendInterface);
|
|
|
|
/// Create a resource.
|
|
///
|
|
/// This callback is intended for the backend to create internal resources.
|
|
///
|
|
/// Please note: It is also possible that the creation of resources might
|
|
/// itself cause additional resources to be created by simply calling the
|
|
/// <c><i>FfxFsr2CreateResourceFunc</i></c> function pointer again. This is
|
|
/// useful when handling the initial creation of resources which must be
|
|
/// initialized. The flow in such a case would be an initial call to create the
|
|
/// CPU-side resource, another to create the GPU-side resource, and then a call
|
|
/// to schedule a copy render job to move the data between the two. Typically
|
|
/// this type of function call flow is only seen during the creation of an
|
|
/// <c><i>FfxFsr2Context</i></c>.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] createResourceDescription A pointer to a <c><i>FfxCreateResourceDescription</i></c>.
|
|
/// @param [out] outResource A pointer to a <c><i>FfxResource</i></c> object.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2CreateResourceFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
const FfxCreateResourceDescription* createResourceDescription,
|
|
FfxResourceInternal* outResource);
|
|
|
|
/// Register a resource in the backend for the current frame.
|
|
///
|
|
/// Since FSR2 and the backend are not aware how many different
|
|
/// resources will get passed to FSR2 over time, it's not safe
|
|
/// to register all resources simultaneously in the backend.
|
|
/// Also passed resources may not be valid after the dispatch call.
|
|
/// As a result it's safest to register them as FfxResourceInternal
|
|
/// and clear them at the end of the dispatch call.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] inResource A pointer to a <c><i>FfxResource</i></c>.
|
|
/// @param [out] outResource A pointer to a <c><i>FfxResourceInternal</i></c> object.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode(*FfxFsr2RegisterResourceFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
const FfxResource* inResource,
|
|
FfxResourceInternal* outResource);
|
|
|
|
/// Unregister all temporary FfxResourceInternal from the backend.
|
|
///
|
|
/// Unregister FfxResourceInternal referencing resources passed to
|
|
/// a function as a parameter.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode(*FfxFsr2UnregisterResourcesFunc)(
|
|
FfxFsr2Interface* backendInterface);
|
|
|
|
/// Retrieve a <c><i>FfxResourceDescription</i></c> matching a
|
|
/// <c><i>FfxResource</i></c> structure.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] resource A pointer to a <c><i>FfxResource</i></c> object.
|
|
///
|
|
/// @returns
|
|
/// A description of the resource.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxResourceDescription (*FfxFsr2GetResourceDescriptionFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxResourceInternal resource);
|
|
|
|
/// Destroy a resource
|
|
///
|
|
/// This callback is intended for the backend to release an internal resource.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] resource A pointer to a <c><i>FfxResource</i></c> object.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2DestroyResourceFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxResourceInternal resource);
|
|
|
|
/// Create a render pipeline.
|
|
///
|
|
/// A rendering pipeline contains the shader as well as resource bindpoints
|
|
/// and samplers.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] pass The identifier for the pass.
|
|
/// @param [in] pipelineDescription A pointer to a <c><i>FfxPipelineDescription</i></c> describing the pipeline to be created.
|
|
/// @param [out] outPipeline A pointer to a <c><i>FfxPipelineState</i></c> structure which should be populated.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2CreatePipelineFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxFsr2Pass pass,
|
|
const FfxPipelineDescription* pipelineDescription,
|
|
FfxPipelineState* outPipeline);
|
|
|
|
/// Destroy a render pipeline.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [out] pipeline A pointer to a <c><i>FfxPipelineState</i></c> structure which should be released.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2DestroyPipelineFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxPipelineState* pipeline);
|
|
|
|
/// Schedule a render job to be executed on the next call of
|
|
/// <c><i>FfxFsr2ExecuteGpuJobsFunc</i></c>.
|
|
///
|
|
/// Render jobs can perform one of three different tasks: clear, copy or
|
|
/// compute dispatches.
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] job A pointer to a <c><i>FfxGpuJobDescription</i></c> structure.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2ScheduleGpuJobFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
const FfxGpuJobDescription* job);
|
|
|
|
/// Execute scheduled render jobs on the <c><i>comandList</i></c> provided.
|
|
///
|
|
/// The recording of the graphics API commands should take place in this
|
|
/// callback function, the render jobs which were previously enqueued (via
|
|
/// callbacks made to <c><i>FfxFsr2ScheduleGpuJobFunc</i></c>) should be
|
|
/// processed in the order they were received. Advanced users might choose to
|
|
/// reorder the rendering jobs, but should do so with care to respect the
|
|
/// resource dependencies.
|
|
///
|
|
/// Depending on the precise contents of <c><i>FfxFsr2DispatchDescription</i></c> a
|
|
/// different number of render jobs might have previously been enqueued (for
|
|
/// example if sharpening is toggled on and off).
|
|
///
|
|
/// @param [in] backendInterface A pointer to the backend interface.
|
|
/// @param [in] commandList A pointer to a <c><i>FfxCommandList</i></c> structure.
|
|
///
|
|
/// @retval
|
|
/// FFX_OK The operation completed successfully.
|
|
/// @retval
|
|
/// Anything else The operation failed.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef FfxErrorCode (*FfxFsr2ExecuteGpuJobsFunc)(
|
|
FfxFsr2Interface* backendInterface,
|
|
FfxCommandList commandList);
|
|
|
|
/// Pass a string message
|
|
///
|
|
/// Used for debug messages.
|
|
///
|
|
/// @param [in] type The type of message.
|
|
/// @param [in] message A string message to pass.
|
|
///
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef void(*FfxFsr2Message)(
|
|
FfxFsr2MsgType type,
|
|
const wchar_t* message);
|
|
|
|
/// A structure encapsulating the interface between the core implentation of
|
|
/// the FSR2 algorithm and any graphics API that it should ultimately call.
|
|
///
|
|
/// This set of functions serves as an abstraction layer between FSR2 and the
|
|
/// API used to implement it. While FSR2 ships with backends for DirectX12 and
|
|
/// Vulkan, it is possible to implement your own backend for other platforms or
|
|
/// which sits ontop of your engine's own abstraction layer. For details on the
|
|
/// expectations of what each function should do you should refer the
|
|
/// description of the following function pointer types:
|
|
///
|
|
/// <c><i>FfxFsr2CreateDeviceFunc</i></c>
|
|
/// <c><i>FfxFsr2GetDeviceCapabilitiesFunc</i></c>
|
|
/// <c><i>FfxFsr2DestroyDeviceFunc</i></c>
|
|
/// <c><i>FfxFsr2CreateResourceFunc</i></c>
|
|
/// <c><i>FfxFsr2GetResourceDescriptionFunc</i></c>
|
|
/// <c><i>FfxFsr2DestroyResourceFunc</i></c>
|
|
/// <c><i>FfxFsr2CreatePipelineFunc</i></c>
|
|
/// <c><i>FfxFsr2DestroyPipelineFunc</i></c>
|
|
/// <c><i>FfxFsr2ScheduleGpuJobFunc</i></c>
|
|
/// <c><i>FfxFsr2ExecuteGpuJobsFunc</i></c>
|
|
///
|
|
/// Depending on the graphics API that is abstracted by the backend, it may be
|
|
/// required that the backend is to some extent stateful. To ensure that
|
|
/// applications retain full control to manage the memory used by FSR2, the
|
|
/// <c><i>scratchBuffer</i></c> and <c><i>scratchBufferSize</i></c> fields are
|
|
/// provided. A backend should provide a means of specifying how much scratch
|
|
/// memory is required for its internal implementation (e.g: via a function
|
|
/// or constant value). The application is that responsible for allocating that
|
|
/// memory and providing it when setting up the FSR2 backend. Backends provided
|
|
/// with FSR2 do not perform dynamic memory allocations, and instead
|
|
/// suballocate all memory from the scratch buffers provided.
|
|
///
|
|
/// The <c><i>scratchBuffer</i></c> and <c><i>scratchBufferSize</i></c> fields
|
|
/// should be populated according to the requirements of each backend. For
|
|
/// example, if using the DirectX 12 backend you should call the
|
|
/// <c><i>ffxFsr2GetScratchMemorySizeDX12</i></c> function. It is not required
|
|
/// that custom backend implementations use a scratch buffer.
|
|
///
|
|
/// @ingroup FSR2
|
|
typedef struct FfxFsr2Interface {
|
|
|
|
FfxFsr2CreateBackendContextFunc fpCreateBackendContext; ///< A callback function to create and initialize the backend context.
|
|
FfxFsr2GetDeviceCapabilitiesFunc fpGetDeviceCapabilities; ///< A callback function to query device capabilites.
|
|
FfxFsr2DestroyBackendContextFunc fpDestroyBackendContext; ///< A callback function to destroy the backendcontext. This also dereferences the device.
|
|
FfxFsr2CreateResourceFunc fpCreateResource; ///< A callback function to create a resource.
|
|
FfxFsr2RegisterResourceFunc fpRegisterResource; ///< A callback function to register an external resource.
|
|
FfxFsr2UnregisterResourcesFunc fpUnregisterResources; ///< A callback function to unregister external resource.
|
|
FfxFsr2GetResourceDescriptionFunc fpGetResourceDescription; ///< A callback function to retrieve a resource description.
|
|
FfxFsr2DestroyResourceFunc fpDestroyResource; ///< A callback function to destroy a resource.
|
|
FfxFsr2CreatePipelineFunc fpCreatePipeline; ///< A callback function to create a render or compute pipeline.
|
|
FfxFsr2DestroyPipelineFunc fpDestroyPipeline; ///< A callback function to destroy a render or compute pipeline.
|
|
FfxFsr2ScheduleGpuJobFunc fpScheduleGpuJob; ///< A callback function to schedule a render job.
|
|
FfxFsr2ExecuteGpuJobsFunc fpExecuteGpuJobs; ///< A callback function to execute all queued render jobs.
|
|
|
|
void* scratchBuffer; ///< A preallocated buffer for memory utilized internally by the backend.
|
|
size_t scratchBufferSize; ///< Size of the buffer pointed to by <c><i>scratchBuffer</i></c>.
|
|
} FfxFsr2Interface;
|
|
|
|
#if defined(__cplusplus)
|
|
}
|
|
#endif // #if defined(__cplusplus)
|