Michael-Lfx / GPU_Tuning

MIT License
9 stars 0 forks source link

[Vulkan | Metal] 多缓冲 #16

Open Michael-Lfx opened 5 years ago

Michael-Lfx commented 5 years ago

Frames in flight

If you run your application with validation layers enabled and you monitor the memory usage of your application, you may notice that it is slowly growing. The reason for this is that the application is rapidly submitting work in the drawFrame function, but doesn’t actually check if any of it finishes. If the CPU is submitting work faster than the GPU can keep up with then the queue will slowly fill up with work. Worse, even, is that we are reusing the imageAvailableSemaphore and renderFinishedSemaphore for multiple frames at the same time.

The easy way to solve this is to wait for work to finish right after submitting it, for example by using vkQueueWaitIdle:

void drawFrame() {
    ...
    vkQueuePresentKHR(presentQueue, &presentInfo);
    vkQueueWaitIdle(presentQueue);
}

However, we are likely not optimally using the GPU in this way, because the whole graphics pipeline is only used for one frame at a time right now. The stages that the current frame has already progressed through are idle and could already be used for a next frame. We will now extend our application to allow for multiple frames to be in-flight while still bounding the amount of work that piles up.

Start by adding a constant at the top of the program that defines how many frames should be processed concurrently:

const int MAX_FRAMES_IN_FLIGHT = 2;

Each frame should have its own set of semaphores:

std::vector<VkSemaphore> imageAvailableSemaphores;
std::vector<VkSemaphore> renderFinishedSemaphores;

The createSemaphores function should be changed to create all of these:

void createSemaphores() {
    imageAvailableSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
    renderFinishedSemaphores.resize(MAX_FRAMES_IN_FLIGHT);
    VkSemaphoreCreateInfo semaphoreInfo = {};
    semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
    for (size_t i = 0; i < MAX_FRAMES_IN_FLIGHT; i++) {
        if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphores[i]) != VK_SUCCESS ||
            vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphores[i]) != VK_SUCCESS) {
               throw std::runtime_error("failed to create semaphores for a frame!");
        } 
    } 

Ref: Vulkan Tutorial