目录

示例代码

算法:FF_PREDICTION_ALGORITHM_GRIDWARP

此算法支持使用内插和外插两种方案,外插示例代码如下:
// 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);
}