此算法支持使用内插和外插两种方案,外插示例代码如下:
// Vulkan插帧SDK集成代码参考
#include "frame_flow.h"
void InitFFInstance()
{
FFVKInstanceCreateInfo instCreateInfo; // need to init other members
instCreateInfo.pfnVulkanLoaderFunction = vkGetInstanceProcAddr;
instCreateInfo.framesInFlight = 1;
FFVKInstance m_ffInstance = FrameFlowVK_Create(&instCreateInfo);
FFPredictionAlgorithmInfo algorithmInfo = {
.sType = FF_STRUCTURE_TYPE_PREDICTION_ALGORITHM_INFO,
.pNext = nullptr,
.algorithm = FF_PREDICTION_ALGORITHM_GRIDWARP,
.extrapolation = FF_TRUE
};
FFAlgorithmCapabilitiesInfo capabilitiesInfo = {
.sType = FF_STRUCTURE_TYPE_ALGORITHM_CAPABILITIES_INFO,
.pNext = nullptr,
};
FFResult result = FrameFlowVK_SetPredictionAlgorithm(m_ffInstance, &algorithmInfo, &capabilitiesInfo);
FFCvvZSemanticInfo cvvZSemantic = {
.sType = FF_STRUCTURE_TYPE_CVV_Z_SEMANTIC_INFO,
.pNext = nullptr,
.semantic = FF_CVV_Z_SEMANTIC_ZERO_TO_ONE_FORWARD_Z
};
FFVKOutputFormatInfo ffOutputFormat = {
.sType = FF_STRUCTURE_TYPE_OUTPUT_FORMAT_INFO,
.pNext = &cvvZSemantic,
.format = m_swapChainImageFormat
};
FFVKSceneColorFormatInfo ffSceneColorFormat = {
.sType = FF_STRUCTURE_TYPE_SCENE_COLOR_FORMAT_INFO,
.pNext = &ffOutputFormat,
.format = m_swapChainImageFormat
};
FFVKDepthStencilFormatInfo ffZsformat = {
.sType = FF_STRUCTURE_TYPE_DEPTH_STENCIL_FORMAT_INFO,
.pNext = &ffSceneColorFormat,
.format = m_depthTexture.GetFormat()
};
FFResolutionInfo2 resolutionInfo2 = {
.sType = FF_STRUCTURE_TYPE_RESOLUTION_INFO_2,
.pNext = &ffZsformat,
.sceneColorResolution = { m_ffWidth, m_ffHeight },
};
FFInputDescription ffInputDescription {
.sType = FF_STRUCTURE_TYPE_INPUT_DESCRIPTION,
.pNext = &resolutionInfo2,
.flags = 0U
};
result = FrameFlowVK_SetInputDescription(m_ffInstance, &ffInputDescription);
FFStencilRemapInfo remapInfo = {
.sType = FF_STRUCTURE_TYPE_STENCIL_REMAP_INFO,
.pNext = nullptr,
.remapTable{}
};
auto &table = remapInfo.remapTable;
for (int i = 0; i < FF_STENCIL_CAPACITY; ++i)
{
// FF_STENCIL_VALUE_SEMANTIC_REPROJECTIBLE_DYNAMIC_OBJECT/FF_STENCIL_VALUE_SEMANTIC_GENERIC_DYNAMIC_OBJECT
table[i] = FF_STENCIL_VALUE_SEMANTIC_STATIC_OBJECT;
}
result = FrameFlowVK_SetStencilRemapInfo(m_ffInstance, &remapInfo);
result = FrameFlowVK_Activate(m_ffInstance);
}
void Prepare()
{
InitFFInstance();
FFVKImage m_ffSceneColor = FrameFlowVK_RegisterImage(m_ffInstance, m_sceneColorImage.GetNativeImage(), m_sceneColorImage.GetNativeImageView());
FFVKImage m_ffDepthStencil = FrameFlowVK_RegisterImage(m_ffInstance, m_depthTexture.GetNativeImage(), m_depthTexture.GetNativeImageView());
FFVKImage m_ffPredictedColor = FrameFlowVK_RegisterImage(m_ffInstance, m_predictedImage.GetNativeImage(), m_predictedImage.GetNativeImageView());
}
void Render()
{
uint32_t imageIndex = 0;
// Render origin frame
vkAcquireNextImageKHR(m_device, m_swapChain, UINT64_MAX, m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex); // wait imageIndex available, signal imageAvailable
vkWaitForFences(m_device, 1, &m_inFlightFence, VK_TRUE, UINT64_MAX); // wait last submit commands inFlightFence
vkResetFences(m_device, 1, &m_inFlightFence);
FFUpdateMainScene(); // update main scene buffer, such as camera, object transform
FFUpdateUI(); // update ui buffer, such as fps text
vkResetCommandBuffer(m_commandBuffer, 0);
vkBeginCommandBuffer(m_commandBuffer, &beginInfo);
{
FFRenderMainScene(m_commandBuffer); // Render to m_sceneColorImage
SceneColorToSwapChain(); // Blit to swapchain
FFRenderUI(m_commandBuffer, imageIndex); // render ui on swapchain
TransitionSwapChainToPresent();
}
vkEndCommandBuffer(m_commandBuffer);
VK::QueueSubmit(m_commandBuffer, m_imageAvailableSemaphore, m_renderFinishedSemaphore, m_inFlightFence); // wait imageAvailable, signal GPU renderFinish and CPU inFlightFence
VK::Present(m_presentQueue, imageIndex, m_renderFinishedSemaphore); // wait renderFinish, signal imageIndex can be available
// Render predicted frame
FFVKPerFrameData m_perFrameData = VK::PrepareFFVKPerFrameData(m_ffSceneColor, m_ffDepthStencil, cameraViewProjMatrix, objectMatrices);
FFVKDrawFrameInfo m_drawFrameInfo = VK::PrepareFFDrawFrameInfo(m_ffPredictedColor);
vkAcquireNextImageKHR(m_device, m_swapChain, UINT64_MAX, m_imageAvailableSemaphore, VK_NULL_HANDLE, &imageIndex);
vkWaitForFences(m_device, 1, &m_inFlightFence, VK_TRUE, UINT64_MAX);
vkResetFences(m_device, 1, &m_inFlightFence);
vkResetCommandBuffer(m_commandBuffer, 0);
vkBeginCommandBuffer(m_commandBuffer, &beginInfo);
{
FFResult ffResult = FrameFlowVK_ProvidePerFrameData(m_ffInstance, &m_perFrameData);
ffResult = FrameFlowVK_DrawFrame(m_ffInstance, &m_drawFrameInfo);
PredictColorToSwapChain();
FFRenderUI(m_commandBuffer, imageIndex);
TransitionSwapChainToPresent();
}
vkEndCommandBuffer(m_commandBuffer);
VK::QueueSubmit(m_commandBuffer, m_imageAvailableSemaphore, m_renderFinishedSemaphore, m_inFlightFence);
VK::Present(m_presentQueue, imageIndex, m_renderFinishedSemaphore);
}
void TransitionSwapChainToPresent(uint32_t imageIndex)
{
TransitionImageLayout(m_commandBuffer, m_swapChainImages[imageIndex],
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT);
}
void PredictColorToSwapChain(uint32_t imageIndex)
{
// modify image layout to src/dst for transfer, recovery sceneColor
TransitionImageLayout(m_commandBuffer, m_sceneColorImage.GetNativeImage(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
TransitionImageLayout(m_commandBuffer, m_swapChainImages[imageIndex],
VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VK::BlitImage(m_commandBuffer, m_predictedImage.GetNativeImage(), m_swapChainImages[imageIndex]); // use vkCmdBlitImage
// recovery image layout
TransitionImageLayout(m_commandBuffer, m_predictedImage.GetNativeImage(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
TransitionImageLayout(m_commandBuffer, m_swapChainImages[imageIndex],
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
}
void SceneColorToSwapChain(uint32_t imageIndex)
{
// modify image layout to src/dst for transfer
TransitionImageLayout(m_commandBuffer, m_sceneColorImage.GetNativeImage(),
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
TransitionImageLayout(m_commandBuffer, m_swapChainImages[imageIndex],
VK_IMAGE_LAYOUT_UNDEFINED, 0, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VK::BlitImage(m_commandBuffer, m_sceneColorImage.GetNativeImage(), m_swapChainImages[imageIndex]); // use vkCmdBlitImage
// recovery image layout
TransitionImageLayout(m_commandBuffer, m_sceneColorImage.GetNativeImage(),
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
TransitionImageLayout(m_commandBuffer, m_swapChainImages[imageIndex],
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
}