// 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 <stdint.h>

#if defined(FFX_GCC)
/// FidelityFX exported functions
#define FFX_API
#else
/// FidelityFX exported functions
#define FFX_API __declspec(dllexport)
#endif // #if defined (FFX_GCC)

/// Maximum supported number of simultaneously bound SRVs.
#define FFX_MAX_NUM_SRVS 16

/// Maximum supported number of simultaneously bound UAVs.
#define FFX_MAX_NUM_UAVS 8

/// Maximum number of constant buffers bound.
#define FFX_MAX_NUM_CONST_BUFFERS 2

/// Maximum size of bound constant buffers.
#define FFX_MAX_CONST_SIZE 64

/// Off by default warnings
#if defined(_MSC_VER)
#pragma warning(disable : 4365 4710 4820 5039)
#elif defined(__clang__)
#pragma clang diagnostic ignored "-Wunused-parameter"
#pragma clang diagnostic ignored "-Wmissing-field-initializers"
#pragma clang diagnostic ignored "-Wsign-compare"
#pragma clang diagnostic ignored "-Wunused-function"
#pragma clang diagnostic ignored "-Wignored-qualifiers"
#elif defined(__GNUC__)
#pragma GCC diagnostic ignored "-Wunused-function"
#endif

#ifdef __cplusplus
extern "C"
{
#endif // #ifdef __cplusplus

    /// An enumeration of surface formats.
    typedef enum FfxSurfaceFormat
    {

        FFX_SURFACE_FORMAT_UNKNOWN,               ///< Unknown format
        FFX_SURFACE_FORMAT_R32G32B32A32_TYPELESS, ///< 32 bit per channel, 4 channel typeless format
        FFX_SURFACE_FORMAT_R32G32B32A32_FLOAT,    ///< 32 bit per channel, 4 channel float format
        FFX_SURFACE_FORMAT_R16G16B16A16_FLOAT,    ///< 16 bit per channel, 4 channel float format
        FFX_SURFACE_FORMAT_R16G16B16A16_UNORM,    ///< 16 bit per channel, 4 channel unsigned normalized format
        FFX_SURFACE_FORMAT_R32G32_FLOAT,          ///< 32 bit per channel, 2 channel float format
        FFX_SURFACE_FORMAT_R32_UINT,              ///< 32 bit per channel, 1 channel float format
        FFX_SURFACE_FORMAT_R8G8B8A8_TYPELESS,     ///<  8 bit per channel, 4 channel float format
        FFX_SURFACE_FORMAT_R8G8B8A8_UNORM,        ///<  8 bit per channel, 4 channel unsigned normalized format
        FFX_SURFACE_FORMAT_R11G11B10_FLOAT,       ///< 32 bit 3 channel float format
        FFX_SURFACE_FORMAT_R16G16_FLOAT,          ///< 16 bit per channel, 2 channel float format
        FFX_SURFACE_FORMAT_R16G16_UINT,           ///< 16 bit per channel, 2 channel unsigned int format
        FFX_SURFACE_FORMAT_R16_FLOAT,             ///< 16 bit per channel, 1 channel float format
        FFX_SURFACE_FORMAT_R16_UINT,              ///< 16 bit per channel, 1 channel unsigned int format
        FFX_SURFACE_FORMAT_R16_UNORM,             ///< 16 bit per channel, 1 channel unsigned normalized format
        FFX_SURFACE_FORMAT_R16_SNORM,             ///< 16 bit per channel, 1 channel signed normalized format
        FFX_SURFACE_FORMAT_R8_UNORM,              ///<  8 bit per channel, 1 channel unsigned normalized format
        FFX_SURFACE_FORMAT_R8_UINT,               ///<  8 bit per channel, 1 channel unsigned int format
        FFX_SURFACE_FORMAT_R8G8_UNORM,            ///<  8 bit per channel, 2 channel unsigned normalized format
        FFX_SURFACE_FORMAT_R32_FLOAT              ///< 32 bit per channel, 1 channel float format
    } FfxSurfaceFormat;

    /// An enumeration of resource usage.
    typedef enum FfxResourceUsage
    {

        FFX_RESOURCE_USAGE_READ_ONLY = 0,           ///< No usage flags indicate a resource is read only.
        FFX_RESOURCE_USAGE_RENDERTARGET = (1 << 0), ///< Indicates a resource will be used as render target.
        FFX_RESOURCE_USAGE_UAV = (1 << 1),          ///< Indicates a resource will be used as UAV.
    } FfxResourceUsage;

    /// An enumeration of resource states.
    typedef enum FfxResourceStates
    {

        FFX_RESOURCE_STATE_UNORDERED_ACCESS = (1 << 0), ///< Indicates a resource is in the state to be used as UAV.
        FFX_RESOURCE_STATE_COMPUTE_READ =
            (1 << 1), ///< Indicates a resource is in the state to be read by compute shaders.
        FFX_RESOURCE_STATE_COPY_SRC =
            (1 << 2), ///< Indicates a resource is in the state to be used as source in a copy command.
        FFX_RESOURCE_STATE_COPY_DEST =
            (1 << 3), ///< Indicates a resource is in the state to be used as destination in a copy command.
        FFX_RESOURCE_STATE_GENERIC_READ =
            (FFX_RESOURCE_STATE_COPY_SRC |
             FFX_RESOURCE_STATE_COMPUTE_READ), ///< Indicates a resource is in generic (slow) read state.
    } FfxResourceStates;

    /// An enumeration of surface dimensions.
    typedef enum FfxResourceDimension
    {

        FFX_RESOURCE_DIMENSION_TEXTURE_1D, ///< A resource with a single dimension.
        FFX_RESOURCE_DIMENSION_TEXTURE_2D, ///< A resource with two dimensions.
    } FfxResourceDimension;

    /// An enumeration of surface dimensions.
    typedef enum FfxResourceFlags
    {

        FFX_RESOURCE_FLAGS_NONE = 0, ///< No flags.
        FFX_RESOURCE_FLAGS_ALIASABLE =
            (1 << 0), ///< A bit indicating a resource does not need to persist across frames.
    } FfxResourceFlags;

    /// An enumeration of all resource view types.
    typedef enum FfxResourceViewType
    {

        FFX_RESOURCE_VIEW_UNORDERED_ACCESS, ///< The resource view is an unordered access view (UAV).
        FFX_RESOURCE_VIEW_SHADER_READ,      ///< The resource view is a shader resource view (SRV).
    } FfxResourceViewType;

    /// The type of filtering to perform when reading a texture.
    typedef enum FfxFilterType
    {

        FFX_FILTER_TYPE_POINT, ///< Point sampling.
        FFX_FILTER_TYPE_LINEAR ///< Sampling with interpolation.
    } FfxFilterType;

    /// An enumeration of all supported shader models.
    typedef enum FfxShaderModel
    {

        FFX_SHADER_MODEL_5_1, ///< Shader model 5.1.
        FFX_SHADER_MODEL_6_0, ///< Shader model 6.0.
        FFX_SHADER_MODEL_6_1, ///< Shader model 6.1.
        FFX_SHADER_MODEL_6_2, ///< Shader model 6.2.
        FFX_SHADER_MODEL_6_3, ///< Shader model 6.3.
        FFX_SHADER_MODEL_6_4, ///< Shader model 6.4.
        FFX_SHADER_MODEL_6_5, ///< Shader model 6.5.
        FFX_SHADER_MODEL_6_6, ///< Shader model 6.6.
        FFX_SHADER_MODEL_6_7, ///< Shader model 6.7.
    } FfxShaderModel;

    // An enumeration for different resource types
    typedef enum FfxResourceType
    {

        FFX_RESOURCE_TYPE_BUFFER,    ///< The resource is a buffer.
        FFX_RESOURCE_TYPE_TEXTURE1D, ///< The resource is a 1-dimensional texture.
        FFX_RESOURCE_TYPE_TEXTURE2D, ///< The resource is a 2-dimensional texture.
        FFX_RESOURCE_TYPE_TEXTURE3D, ///< The resource is a 3-dimensional texture.
    } FfxResourceType;

    /// An enumeration for different heap types
    typedef enum FfxHeapType
    {

        FFX_HEAP_TYPE_DEFAULT = 0, ///< Local memory.
        FFX_HEAP_TYPE_UPLOAD       ///< Heap used for uploading resources.
    } FfxHeapType;

    /// An enumberation for different render job types
    typedef enum FfxGpuJobType
    {

        FFX_GPU_JOB_CLEAR_FLOAT = 0, ///< The GPU job is performing a floating-point clear.
        FFX_GPU_JOB_COPY = 1,        ///< The GPU job is performing a copy.
        FFX_GPU_JOB_COMPUTE = 2,     ///< The GPU job is performing a compute dispatch.
    } FfxGpuJobType;

    /// A typedef representing the graphics device.
    typedef void* FfxDevice;

    /// A typedef representing a command list or command buffer.
    typedef void* FfxCommandList;

    /// A typedef for a root signature.
    typedef void* FfxRootSignature;

    /// A typedef for a pipeline state object.
    typedef void* FfxPipeline;

    /// A structure encapasulating a collection of device capabilities.
    typedef struct FfxDeviceCapabilities
    {

        FfxShaderModel minimumSupportedShaderModel; ///< The minimum shader model supported by the device.
        uint32_t waveLaneCountMin;                  ///< The minimum supported wavefront width.
        uint32_t waveLaneCountMax;                  ///< The maximum supported wavefront width.
        bool fp16Supported;                         ///< The device supports FP16 in hardware.
        bool raytracingSupported;                   ///< The device supports raytracing.
    } FfxDeviceCapabilities;

    /// A structure encapsulating a 2-dimensional point, using 32bit unsigned integers.
    typedef struct FfxDimensions2D
    {

        uint32_t width;  ///< The width of a 2-dimensional range.
        uint32_t height; ///< The height of a 2-dimensional range.
    } FfxDimensions2D;

    /// A structure encapsulating a 2-dimensional point,
    typedef struct FfxIntCoords2D
    {

        int32_t x; ///< The x coordinate of a 2-dimensional point.
        int32_t y; ///< The y coordinate of a 2-dimensional point.
    } FfxIntCoords2D;

    /// A structure encapsulating a 2-dimensional set of floating point coordinates.
    typedef struct FfxFloatCoords2D
    {

        float x; ///< The x coordinate of a 2-dimensional point.
        float y; ///< The y coordinate of a 2-dimensional point.
    } FfxFloatCoords2D;

    /// A structure describing a resource.
    typedef struct FfxResourceDescription
    {

        FfxResourceType type;    ///< The type of the resource.
        FfxSurfaceFormat format; ///< The surface format.
        uint32_t width;          ///< The width of the resource.
        uint32_t height;         ///< The height of the resource.
        uint32_t depth;          ///< The depth of the resource.
        uint32_t mipCount;       ///< Number of mips (or 0 for full mipchain).
        FfxResourceFlags flags;  ///< A set of <c><i>FfxResourceFlags</i></c> flags.
    } FfxResourceDescription;

    /// An outward facing structure containing a resource
    typedef struct FfxResource
    {
        void* resource; ///< pointer to the resource.
        wchar_t name[64];
        FfxResourceDescription description;
        FfxResourceStates state;
        bool isDepth;
        uint64_t descriptorData;
    } FfxResource;

    /// An internal structure containing a handle to a resource and resource views
    typedef struct FfxResourceInternal
    {
        int32_t internalIndex; ///< The index of the resource.
    } FfxResourceInternal;

    /// A structure defining a resource bind point
    typedef struct FfxResourceBinding
    {
        uint32_t slotIndex;
        uint32_t resourceIdentifier;
        wchar_t name[64];
    } FfxResourceBinding;

    /// A structure encapsulating a single pass of an algorithm.
    typedef struct FfxPipelineState
    {

        FfxRootSignature rootSignature; ///< The pipelines rootSignature
        FfxPipeline pipeline;           ///< The pipeline object
        uint32_t uavCount;              ///< Count of UAVs used in this pipeline
        uint32_t srvCount;              ///< Count of SRVs used in this pipeline
        uint32_t constCount;            ///< Count of constant buffers used in this pipeline

        FfxResourceBinding uavResourceBindings[FFX_MAX_NUM_UAVS]; ///< Array of ResourceIdentifiers bound as UAVs
        FfxResourceBinding srvResourceBindings[FFX_MAX_NUM_SRVS]; ///< Array of ResourceIdentifiers bound as SRVs
        FfxResourceBinding cbResourceBindings[FFX_MAX_NUM_CONST_BUFFERS]; ///< Array of ResourceIdentifiers bound as CBs
    } FfxPipelineState;

    /// A structure containing the data required to create a resource.
    typedef struct FfxCreateResourceDescription
    {

        FfxHeapType heapType; ///< The heap type to hold the resource, typically <c><i>FFX_HEAP_TYPE_DEFAULT</i></c>.
        FfxResourceDescription resourceDescription; ///< A resource description.
        FfxResourceStates initalState;              ///< The initial resource state.
        uint32_t initDataSize;                      ///< Size of initial data buffer.
        void* initData;                             ///< Buffer containing data to fill the resource.
        const wchar_t* name;                        ///< Name of the resource.
        FfxResourceUsage usage;                     ///< Resource usage flags.
        uint32_t id;                                ///< Internal resource ID.
    } FfxCreateResourceDescription;

    /// A structure containing the description used to create a
    /// <c><i>FfxPipeline</i></c> structure.
    ///
    /// A pipeline is the name given to a shader and the collection of state that
    /// is required to dispatch it. In the context of FSR2 and its architecture
    /// this means that a <c><i>FfxPipelineDescription</i></c> will map to either a
    /// monolithic object in an explicit API (such as a
    /// <c><i>PipelineStateObject</i></c> in DirectX 12). Or a shader and some
    /// ancillary API objects (in something like DirectX 11).
    ///
    /// The <c><i>contextFlags</i></c> field contains a copy of the flags passed
    /// to <c><i>ffxFsr2ContextCreate</i></c> via the <c><i>flags</i></c> field of
    /// the <c><i>FfxFsr2InitializationParams</i></c> structure. These flags are
    /// used to determine which permutation of a pipeline for a specific
    /// <c><i>FfxFsr2Pass</i></c> should be used to implement the features required
    /// by each application, as well as to acheive the best performance on specific
    /// target hardware configurations.
    ///
    /// When using one of the provided backends for FSR2 (such as DirectX 12 or
    /// Vulkan) the data required to create a pipeline is compiled offline and
    /// included into the backend library that you are using. For cases where the
    /// backend interface is overriden by providing custom callback function
    /// implementations care should be taken to respect the contents of the
    /// <c><i>contextFlags</i></c> field in order to correctly support the options
    /// provided by FSR2, and acheive best performance.
    ///
    /// @ingroup FSR2
    typedef struct FfxPipelineDescription
    {

        uint32_t contextFlags; ///< A collection of <c><i>FfxFsr2InitializationFlagBits</i></c> which were passed to the
                               ///< context.
        FfxFilterType* samplers;                 ///< Array of static samplers.
        size_t samplerCount;                     ///< The number of samples contained inside <c><i>samplers</i></c>.
        const uint32_t* rootConstantBufferSizes; ///< Array containing the sizes of the root constant buffers (count of
                                                 ///< 32 bit elements).
        uint32_t rootConstantBufferCount;        ///< The number of root constants contained within
                                                 ///< <c><i>rootConstantBufferSizes</i></c>.
    } FfxPipelineDescription;

    /// A structure containing a constant buffer.
    typedef struct FfxConstantBuffer
    {

        uint32_t uint32Size;               ///< Size of 32 bit chunks used in the constant buffer
        uint32_t data[FFX_MAX_CONST_SIZE]; ///< Constant buffer data
    } FfxConstantBuffer;

    /// A structure describing a clear render job.
    typedef struct FfxClearFloatJobDescription
    {

        float color[4];             ///< The clear color of the resource.
        FfxResourceInternal target; ///< The resource to be cleared.
    } FfxClearFloatJobDescription;

    /// A structure describing a compute render job.
    typedef struct FfxComputeJobDescription
    {

        FfxPipelineState pipeline;                  ///< Compute pipeline for the render job.
        uint32_t dimensions[3];                     ///< Dispatch dimensions.
        FfxResourceInternal srvs[FFX_MAX_NUM_SRVS]; ///< SRV resources to be bound in the compute job.
        wchar_t srvNames[FFX_MAX_NUM_SRVS][64];
        FfxResourceInternal uavs[FFX_MAX_NUM_UAVS]; ///< UAV resources to be bound in the compute job.
        uint32_t uavMip[FFX_MAX_NUM_UAVS];          ///< Mip level of UAV resources to be bound in the compute job.
        wchar_t uavNames[FFX_MAX_NUM_UAVS][64];
        FfxConstantBuffer cbs[FFX_MAX_NUM_CONST_BUFFERS]; ///< Constant buffers to be bound in the compute job.
        wchar_t cbNames[FFX_MAX_NUM_CONST_BUFFERS][64];
        uint32_t cbSlotIndex[FFX_MAX_NUM_CONST_BUFFERS]; ///< Slot index in the descriptor table
    } FfxComputeJobDescription;

    /// A structure describing a copy render job.
    typedef struct FfxCopyJobDescription
    {
        FfxResourceInternal src; ///< Source resource for the copy.
        FfxResourceInternal dst; ///< Destination resource for the copy.
    } FfxCopyJobDescription;

    /// A structure describing a single render job.
    typedef struct FfxGpuJobDescription
    {

        FfxGpuJobType jobType; ///< Type of the job.

        union
        {
            FfxClearFloatJobDescription clearJobDescriptor; ///< Clear job descriptor. Valid when <c><i>jobType</i></c>
                                                            ///< is <c><i>FFX_RENDER_JOB_CLEAR_FLOAT</i></c>.
            FfxCopyJobDescription copyJobDescriptor;       ///< Copy job descriptor. Valid when <c><i>jobType</i></c> is
                                                           ///< <c><i>FFX_RENDER_JOB_COPY</i></c>.
            FfxComputeJobDescription computeJobDescriptor; ///< Compute job descriptor. Valid when <c><i>jobType</i></c>
                                                           ///< is <c><i>FFX_RENDER_JOB_COMPUTE</i></c>.
        };
    } FfxGpuJobDescription;

#ifdef __cplusplus
}
#endif // #ifdef __cplusplus
