Skip to content

File vulkan_objects.hpp

File List > illixr > vk > vulkan_objects.hpp

Go to the documentation of this file

#pragma once

#if defined(_WIN32) || defined(_WIN64)
#    include 
#else
#    include "illixr/vk/third_party/vk_mem_alloc.h"
#endif
#include 

namespace ILLIXR::vulkan {

typedef int8_t image_index_t;

struct vk_image {
    VkImageCreateInfo               image_info;
    VkExternalMemoryImageCreateInfo export_image_info;
    VkImage                         image;
    VkImageView                     image_view;
    VmaAllocation                   allocation;
    VmaAllocationInfo               allocation_info;
    int                             fd;
};

template<typename T>
struct buffer_pool {
    enum image_state { FREE, SRC_IN_FLIGHT, AVAILABLE, POST_PROCESSING_IN_FLIGHT };

    std::vector<std::array<vk_image, 2>> image_pool;
    std::vector<std::array<vk_image, 2>> depth_image_pool;

    std::vector<image_state> image_states{};
    std::vector<T>           image_data{};
    std::mutex               image_state_mutex{};

    image_index_t latest_decoded_image = -1;

    explicit buffer_pool(const std::vector<std::array<vk_image, 2>>& image_pool,
                         const std::vector<std::array<vk_image, 2>>& depth_image_pool)
        : image_pool(image_pool)
        , depth_image_pool(depth_image_pool) {
        image_states.resize(image_pool.size());
        image_data.resize(image_pool.size());
    }

    image_index_t src_acquire_image() {
        std::lock_guard<std::mutex> lock(image_state_mutex);
        for (image_index_t i = 0; i < image_states.size(); i++) {
            if (image_states[i] == FREE) {
                image_states[i] = SRC_IN_FLIGHT;
                // std::cout << "Src acquire image " << (int) i << std::endl;
                return i;
            }
        }
        assert(false && "No free images in buffer pool");
        return -1;
    }

    void src_release_image(image_index_t image_index, T&& data) {
        std::lock_guard<std::mutex> lock(image_state_mutex);
        // Mark the previous images as free
        for (image_index_t i = 0; i < image_states.size(); i++) {
            if (image_states[i] == AVAILABLE) {
                image_states[i] = FREE;
            }
        }
        assert(image_states[image_index] == SRC_IN_FLIGHT);
        image_states[image_index]     = AVAILABLE;
        this->image_data[image_index] = std::move(data);
        latest_decoded_image          = image_index;

        // std::cout << "Src release image " << (int) image_index << std::endl;
    }

    std::pair<image_index_t, T> post_processing_acquire_image(image_index_t last_image_index = -1) {
        std::lock_guard<std::mutex> lock(image_state_mutex);
        if (latest_decoded_image == -1) {
            return {-1, {}};
        }
        if (latest_decoded_image == last_image_index) {
            return {-1, {}};
        }
        assert(latest_decoded_image != -1);
        assert(image_states[latest_decoded_image] == AVAILABLE);
        image_states[latest_decoded_image] = POST_PROCESSING_IN_FLIGHT;

        // std::cout << "Post processing acquire image " << (int) latest_decoded_image << std::endl;
        return {latest_decoded_image, image_data[latest_decoded_image]};
    }

    void post_processing_release_image(image_index_t image_index) {
        std::lock_guard<std::mutex> lock(image_state_mutex);
        assert(image_states[image_index] == POST_PROCESSING_IN_FLIGHT);
        if (image_index != latest_decoded_image) {
            image_states[image_index] = FREE;
        } else {
            image_states[image_index] = AVAILABLE;
        }

        // std::cout << "Post processing release image " << (int) image_index << std::endl;
    }
};

} // namespace ILLIXR::vulkan