You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
360 lines
16 KiB
360 lines
16 KiB
// This file is part of the FidelityFX SDK.
|
|
//
|
|
// Copyright (C) 2024 Advanced Micro Devices, Inc.
|
|
//
|
|
// 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_api.h"
|
|
#include "../ffx_api_types.h"
|
|
#include <vulkan/vulkan.h>
|
|
|
|
/// FFX specific callback type when submitting a command buffer to a queue.
|
|
typedef VkResult (*PFN_vkQueueSubmitFFXAPI)(uint32_t submitCount, const VkSubmitInfo* pSubmits, VkFence fence);
|
|
|
|
/// Helper stucture
|
|
struct VkQueueInfoFFXAPI
|
|
{
|
|
VkQueue queue; ///< the vulkan queue
|
|
uint32_t familyIndex; ///< the queue family index, that will be used to perform queue family ownership transfer
|
|
PFN_vkQueueSubmitFFXAPI submitFunc; ///< an optional submit function in case there might be some concurrent submissions
|
|
};
|
|
|
|
#define FFX_API_CREATE_CONTEXT_DESC_TYPE_BACKEND_VK 0x0000003u
|
|
struct ffxCreateBackendVKDesc
|
|
{
|
|
ffxCreateContextDescHeader header;
|
|
VkDevice vkDevice; ///< the logical device used by the program.
|
|
VkPhysicalDevice vkPhysicalDevice; ///< the physical device used by the program.
|
|
PFN_vkGetDeviceProcAddr vkDeviceProcAddr; ///< function pointer to get device procedure addresses
|
|
};
|
|
|
|
#define FFX_API_EFFECT_ID_FGSC_VK 0x00040000u
|
|
|
|
#define FFX_API_CREATE_CONTEXT_DESC_TYPE_FGSWAPCHAIN_VK 0x40001u
|
|
struct ffxCreateContextDescFrameGenerationSwapChainVK
|
|
{
|
|
ffxCreateContextDescHeader header;
|
|
VkPhysicalDevice physicalDevice; ///< the physicak device used by the program.
|
|
VkDevice device; ///< the logical device used by the program.
|
|
VkSwapchainKHR* swapchain; ///< the current swapchain to be replaced. Will be destroyed when the context is created. This can be VK_NULL_HANDLE. Will contain the new swapchain on return.
|
|
VkAllocationCallbacks* allocator; ///< optional allocation callbacks.
|
|
VkSwapchainCreateInfoKHR createInfo; ///< the description of the desired swapchain. If its VkSwapchainCreateInfoKHR::oldSwapchain field isn't VK_NULL_HANDLE, it should be the same as the ffxCreateContextDescFrameGenerationSwapChainVK::swapchain field above.
|
|
VkQueueInfoFFXAPI gameQueue; ///< the main graphics queue, where Present is called.
|
|
VkQueueInfoFFXAPI asyncComputeQueue; ///< A queue with Compute capability.
|
|
VkQueueInfoFFXAPI presentQueue; ///< A queue with Transfer and Present capabilities.
|
|
VkQueueInfoFFXAPI imageAcquireQueue; ///< A queue with no capability required.
|
|
};
|
|
|
|
#define FFX_API_CONFIGURE_DESC_TYPE_FGSWAPCHAIN_REGISTERUIRESOURCE_VK 0x40002u
|
|
struct ffxConfigureDescFrameGenerationSwapChainRegisterUiResourceVK
|
|
{
|
|
ffxConfigureDescHeader header;
|
|
struct FfxApiResource uiResource; ///< Resource containing user interface for composition. May be empty.
|
|
uint32_t flags; ///< Zero or combination of values from FfxApiUiCompositionFlags.
|
|
};
|
|
|
|
#define FFX_API_QUERY_DESC_TYPE_FGSWAPCHAIN_INTERPOLATIONCOMMANDLIST_VK 0x40003u
|
|
struct ffxQueryDescFrameGenerationSwapChainInterpolationCommandListVK
|
|
{
|
|
ffxQueryDescHeader header;
|
|
void** pOutCommandList; ///< Output command nuffer (VkCommandBuffer) to be used for frame generation dispatch.
|
|
};
|
|
|
|
#define FFX_API_QUERY_DESC_TYPE_FGSWAPCHAIN_INTERPOLATIONTEXTURE_VK 0x40004u
|
|
struct ffxQueryDescFrameGenerationSwapChainInterpolationTextureVK
|
|
{
|
|
ffxQueryDescHeader header;
|
|
struct FfxApiResource* pOutTexture; ///< Output resource in which the frame interpolation result should be placed.
|
|
};
|
|
|
|
#define FFX_API_DISPATCH_DESC_TYPE_FGSWAPCHAIN_WAIT_FOR_PRESENTS_VK 0x40007u
|
|
struct ffxDispatchDescFrameGenerationSwapChainWaitForPresentsVK
|
|
{
|
|
ffxDispatchDescHeader header;
|
|
};
|
|
|
|
#define FFX_API_CONFIGURE_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_KEYVALUE_VK 0x40008u
|
|
struct ffxConfigureDescFrameGenerationSwapChainKeyValueVK
|
|
{
|
|
ffxConfigureDescHeader header;
|
|
uint64_t key; ///< Configuration key, member of the FfxApiConfigureFrameGenerationSwapChainKeyVK enumeration.
|
|
uint64_t u64; ///< Integer value or enum value to set.
|
|
void* ptr; ///< Pointer to set or pointer to value to set.
|
|
};
|
|
|
|
//enum value matches enum FfxFrameInterpolationSwapchainConfigureKey
|
|
enum FfxApiConfigureFrameGenerationSwapChainKeyVK
|
|
{
|
|
FFX_API_CONFIGURE_FG_SWAPCHAIN_KEY_WAITCALLBACK_VK = 0, ///< Sets FfxWaitCallbackFunc
|
|
FFX_API_CONFIGURE_FG_SWAPCHAIN_KEY_FRAMEPACINGTUNING_VK = 2, ///< Sets FfxApiSwapchainFramePacingTuning casted from ptr
|
|
};
|
|
|
|
#define FFX_API_QUERY_DESC_TYPE_FRAMEGENERATIONSWAPCHAIN_GPU_MEMORY_USAGE_VK 0x00040009u
|
|
struct ffxQueryFrameGenerationSwapChainGetGPUMemoryUsageVK
|
|
{
|
|
ffxQueryDescHeader header;
|
|
struct FfxApiEffectMemoryUsage* gpuMemoryUsageFrameGenerationSwapchain;
|
|
};
|
|
|
|
/// Function to get the number of presents. This is useful when using frame interpolation
|
|
typedef uint64_t (*PFN_getLastPresentCountFFXAPI)(VkSwapchainKHR);
|
|
|
|
/// FFX API specific functions to create and destroy a swapchain
|
|
typedef VkResult(*PFN_vkCreateSwapchainFFXAPI)(VkDevice device, const VkSwapchainCreateInfoKHR* pCreateInfo, const VkAllocationCallbacks* pAllocator, VkSwapchainKHR* pSwapchain, void* pContext);
|
|
typedef void(*PFN_vkDestroySwapchainFFXAPI)(VkDevice device, VkSwapchainKHR swapchain, const VkAllocationCallbacks* pAllocator, void* pContext);
|
|
|
|
#define FFX_API_QUERY_DESC_TYPE_FGSWAPCHAIN_FUNCTIONS_VK 0x40005u
|
|
struct ffxQueryDescSwapchainReplacementFunctionsVK
|
|
{
|
|
ffxQueryDescHeader header;
|
|
PFN_vkCreateSwapchainFFXAPI pOutCreateSwapchainFFXAPI; ///< Replacement of vkCreateSwapchainKHR. Can be called when swapchain is recreated but swapchain context isn't (for example when toggling vsync).
|
|
PFN_vkDestroySwapchainFFXAPI pOutDestroySwapchainFFXAPI; ///< Replacement of vkDestroySwapchainKHR. Can be called when swapchain is destroyed but swapchain context isn't.
|
|
PFN_vkGetSwapchainImagesKHR pOutGetSwapchainImagesKHR; ///< Replacement of vkGetSwapchainImagesKHR.
|
|
PFN_vkAcquireNextImageKHR pOutAcquireNextImageKHR; ///< Replacement of vkAcquireNextImageKHR.
|
|
PFN_vkQueuePresentKHR pOutQueuePresentKHR; ///< Replacement of vkQueuePresentKHR.
|
|
PFN_vkSetHdrMetadataEXT pOutSetHdrMetadataEXT; ///< Replacement of vkSetHdrMetadataEXT.
|
|
PFN_getLastPresentCountFFXAPI pOutGetLastPresentCountFFXAPI; ///< Additional function to get the number of times present has been called since the swapchain creation.
|
|
};
|
|
|
|
#define FFX_API_CREATE_CONTEXT_DESC_TYPE_FGSWAPCHAIN_MODE_VK 0x40010u
|
|
struct ffxCreateContextDescFrameGenerationSwapChainModeVK
|
|
{
|
|
ffxCreateContextDescHeader header;
|
|
bool composeOnPresentQueue; ///< flags indicating that composition will happen on the present queue
|
|
};
|
|
|
|
static inline uint32_t ffxApiGetSurfaceFormatVK(VkFormat fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case VK_FORMAT_R32G32B32A32_SFLOAT:
|
|
return FFX_API_SURFACE_FORMAT_R32G32B32A32_FLOAT;
|
|
case VK_FORMAT_R32G32B32_SFLOAT:
|
|
return FFX_API_SURFACE_FORMAT_R32G32B32_FLOAT;
|
|
case VK_FORMAT_R32G32B32A32_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R32G32B32A32_UINT;
|
|
case VK_FORMAT_R16G16B16A16_SFLOAT:
|
|
return FFX_API_SURFACE_FORMAT_R16G16B16A16_FLOAT;
|
|
case VK_FORMAT_R32G32_SFLOAT:
|
|
return FFX_API_SURFACE_FORMAT_R32G32_FLOAT;
|
|
case VK_FORMAT_R32_UINT:
|
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
|
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
|
return FFX_API_SURFACE_FORMAT_R32_UINT;
|
|
case VK_FORMAT_R8G8B8A8_UNORM:
|
|
return FFX_API_SURFACE_FORMAT_R8G8B8A8_UNORM;
|
|
case VK_FORMAT_R8G8B8A8_SNORM:
|
|
return FFX_API_SURFACE_FORMAT_R8G8B8A8_SNORM;
|
|
case VK_FORMAT_R8G8B8A8_SRGB:
|
|
return FFX_API_SURFACE_FORMAT_R8G8B8A8_SRGB;
|
|
case VK_FORMAT_B8G8R8A8_UNORM:
|
|
return FFX_API_SURFACE_FORMAT_B8G8R8A8_UNORM;
|
|
case VK_FORMAT_B8G8R8A8_SRGB:
|
|
return FFX_API_SURFACE_FORMAT_B8G8R8A8_SRGB;
|
|
case VK_FORMAT_B10G11R11_UFLOAT_PACK32:
|
|
return FFX_API_SURFACE_FORMAT_R11G11B10_FLOAT;
|
|
case VK_FORMAT_A2B10G10R10_UNORM_PACK32:
|
|
return FFX_API_SURFACE_FORMAT_R10G10B10A2_UNORM;
|
|
case VK_FORMAT_R16G16_SFLOAT:
|
|
return FFX_API_SURFACE_FORMAT_R16G16_FLOAT;
|
|
case VK_FORMAT_R16G16_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R16G16_UINT;
|
|
case VK_FORMAT_R16G16_SINT:
|
|
return FFX_API_SURFACE_FORMAT_R16G16_SINT;
|
|
case VK_FORMAT_R16_SFLOAT:
|
|
return FFX_API_SURFACE_FORMAT_R16_FLOAT;
|
|
case VK_FORMAT_R16_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R16_UINT;
|
|
case VK_FORMAT_R16_UNORM:
|
|
case VK_FORMAT_D16_UNORM:
|
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R16_UNORM;
|
|
case VK_FORMAT_R16_SNORM:
|
|
return FFX_API_SURFACE_FORMAT_R16_SNORM;
|
|
case VK_FORMAT_R8_UNORM:
|
|
return FFX_API_SURFACE_FORMAT_R8_UNORM;
|
|
case VK_FORMAT_R8_UINT:
|
|
case VK_FORMAT_S8_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R8_UINT;
|
|
case VK_FORMAT_R8G8_UNORM:
|
|
return FFX_API_SURFACE_FORMAT_R8G8_UNORM;
|
|
case VK_FORMAT_R8G8_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R8G8_UINT;
|
|
case VK_FORMAT_R32_SFLOAT:
|
|
case VK_FORMAT_D32_SFLOAT:
|
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
|
return FFX_API_SURFACE_FORMAT_R32_FLOAT;
|
|
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32:
|
|
return FFX_API_SURFACE_FORMAT_R9G9B9E5_SHAREDEXP;
|
|
case VK_FORMAT_UNDEFINED:
|
|
return FFX_API_SURFACE_FORMAT_UNKNOWN;
|
|
|
|
default:
|
|
// NOTE: we do not support typeless formats here
|
|
//FFX_ASSERT_MESSAGE(false, "Format not yet supported");
|
|
return FFX_API_SURFACE_FORMAT_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
static inline uint32_t ffxApiGetSurfaceFormatToGamma(uint32_t fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case (FFX_API_SURFACE_FORMAT_R8G8B8A8_UNORM):
|
|
return FFX_API_SURFACE_FORMAT_R8G8B8A8_SRGB;
|
|
case (FFX_API_SURFACE_FORMAT_B8G8R8A8_UNORM):
|
|
return FFX_API_SURFACE_FORMAT_B8G8R8A8_SRGB;
|
|
default:
|
|
return fmt;
|
|
}
|
|
}
|
|
|
|
static inline bool ffxApiIsDepthFormat(VkFormat fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case VK_FORMAT_D16_UNORM:
|
|
case VK_FORMAT_X8_D24_UNORM_PACK32:
|
|
case VK_FORMAT_D32_SFLOAT:
|
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static inline bool ffxApiIsStencilFormat(VkFormat fmt)
|
|
{
|
|
switch (fmt)
|
|
{
|
|
case VK_FORMAT_S8_UINT:
|
|
case VK_FORMAT_D16_UNORM_S8_UINT:
|
|
case VK_FORMAT_D24_UNORM_S8_UINT:
|
|
case VK_FORMAT_D32_SFLOAT_S8_UINT:
|
|
return true;
|
|
|
|
default:
|
|
return false;
|
|
}
|
|
}
|
|
|
|
static inline FfxApiResourceDescription ffxApiGetBufferResourceDescriptionVK(const VkBuffer buffer,
|
|
const VkBufferCreateInfo createInfo,
|
|
uint32_t additionalUsages)
|
|
{
|
|
FfxApiResourceDescription resourceDescription = {};
|
|
|
|
// This is valid
|
|
if (buffer == VK_NULL_HANDLE)
|
|
return resourceDescription;
|
|
|
|
resourceDescription.flags = FFX_API_RESOURCE_FLAGS_NONE;
|
|
resourceDescription.usage = additionalUsages;
|
|
resourceDescription.size = (uint32_t)createInfo.size;
|
|
resourceDescription.stride = 0;
|
|
resourceDescription.format = FFX_API_SURFACE_FORMAT_UNKNOWN;
|
|
|
|
if ((createInfo.usage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) != 0)
|
|
resourceDescription.usage |= FFX_API_RESOURCE_USAGE_UAV;
|
|
if ((createInfo.usage & VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT) != 0)
|
|
resourceDescription.usage |= FFX_API_RESOURCE_USAGE_INDIRECT;
|
|
|
|
// What should we initialize this to?? No case for this yet
|
|
resourceDescription.depth = 0;
|
|
resourceDescription.mipCount = 0;
|
|
|
|
// Set the type
|
|
resourceDescription.type = FFX_API_RESOURCE_TYPE_BUFFER;
|
|
|
|
return resourceDescription;
|
|
}
|
|
|
|
static inline FfxApiResourceDescription ffxApiGetImageResourceDescriptionVK(const VkImage image, const VkImageCreateInfo createInfo, uint32_t additionalUsages)
|
|
{
|
|
FfxApiResourceDescription resourceDescription = {};
|
|
|
|
// This is valid
|
|
if (image == VK_NULL_HANDLE)
|
|
return resourceDescription;
|
|
|
|
// Set flags properly for resource registration
|
|
resourceDescription.flags = FFX_API_RESOURCE_FLAGS_NONE;
|
|
resourceDescription.usage = FFX_API_RESOURCE_USAGE_READ_ONLY;
|
|
|
|
// Check for depth stencil use
|
|
if (ffxApiIsDepthFormat(createInfo.format))
|
|
resourceDescription.usage |= FFX_API_RESOURCE_USAGE_DEPTHTARGET;
|
|
if (ffxApiIsStencilFormat(createInfo.format))
|
|
resourceDescription.usage |= FFX_API_RESOURCE_USAGE_STENCILTARGET;
|
|
|
|
// Unordered access use
|
|
if ((createInfo.usage & VK_IMAGE_USAGE_STORAGE_BIT) != 0)
|
|
resourceDescription.usage |= FFX_API_RESOURCE_USAGE_UAV;
|
|
|
|
// Resource-specific supplemental use flags
|
|
resourceDescription.usage |= additionalUsages;
|
|
|
|
resourceDescription.width = createInfo.extent.width;
|
|
resourceDescription.height = createInfo.extent.height;
|
|
resourceDescription.mipCount = createInfo.mipLevels;
|
|
resourceDescription.format = ffxApiGetSurfaceFormatVK(createInfo.format);
|
|
|
|
// if the mutable flag is present, assume that the real format is sRGB
|
|
if ((createInfo.flags & VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT) != 0)
|
|
resourceDescription.format = ffxApiGetSurfaceFormatToGamma(resourceDescription.format);
|
|
|
|
switch (createInfo.imageType)
|
|
{
|
|
case VK_IMAGE_TYPE_1D:
|
|
resourceDescription.type = FFX_API_RESOURCE_TYPE_TEXTURE1D;
|
|
break;
|
|
case VK_IMAGE_TYPE_2D:
|
|
resourceDescription.depth = createInfo.arrayLayers;
|
|
if ((additionalUsages & FFX_API_RESOURCE_USAGE_ARRAYVIEW) != 0)
|
|
resourceDescription.type = FFX_API_RESOURCE_TYPE_TEXTURE2D;
|
|
else if ((createInfo.flags & VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT) != 0)
|
|
resourceDescription.type = FFX_API_RESOURCE_TYPE_TEXTURE_CUBE;
|
|
else
|
|
resourceDescription.type = FFX_API_RESOURCE_TYPE_TEXTURE2D;
|
|
break;
|
|
case VK_IMAGE_TYPE_3D:
|
|
resourceDescription.depth = createInfo.extent.depth;
|
|
resourceDescription.type = FFX_API_RESOURCE_TYPE_TEXTURE3D;
|
|
break;
|
|
default:
|
|
//FFX_ASSERT_MESSAGE(false, "FFXInterface: VK: Unsupported texture dimension requested. Please implement.");
|
|
break;
|
|
}
|
|
|
|
return resourceDescription;
|
|
}
|
|
|
|
static inline FfxApiResource ffxApiGetResourceVK(void* vkResource, FfxApiResourceDescription ffxResDescription, uint32_t state)
|
|
{
|
|
FfxApiResource resource = {};
|
|
resource.resource = vkResource;
|
|
resource.state = state;
|
|
resource.description = ffxResDescription;
|
|
|
|
return resource;
|
|
}
|