/* Created on: Oct 8, 2019 Copyright 2019 flyinghead This file is part of Flycast. Flycast is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 2 of the License, or (at your option) any later version. Flycast is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Flycast. If not, see . */ #pragma once #include "vulkan_context.h" class CommandPool { public: void Init() { if (commandPools.size() > chainSize) { commandPools.resize(chainSize); fences.resize(chainSize); } else { while (commandPools.size() < chainSize) { commandPools.push_back(VulkanContext::Instance()->GetDevice().createCommandPoolUnique( vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlagBits::eTransient, VulkanContext::Instance()->GetGraphicsQueueFamilyIndex()))); fences.push_back(VulkanContext::Instance()->GetDevice().createFenceUnique(vk::FenceCreateInfo(vk::FenceCreateFlagBits::eSignaled))); } } if (freeBuffers.size() != chainSize) freeBuffers.resize(chainSize); if (inFlightBuffers.size() != chainSize) inFlightBuffers.resize(chainSize); } void Term() { freeBuffers.clear(); inFlightBuffers.clear(); fences.clear(); commandPools.clear(); } void EndFrame() { std::vector commandBuffers = vk::uniqueToRaw(inFlightBuffers[index]); VulkanContext::Instance()->SubmitCommandBuffers(commandBuffers, *fences[index]); } void BeginFrame() { index = (index + 1) % chainSize; VulkanContext::Instance()->GetDevice().waitForFences(fences[index].get(), true, UINT64_MAX); VulkanContext::Instance()->GetDevice().resetFences(fences[index].get()); std::vector& inFlight = inFlightBuffers[index]; std::vector& freeBuf = freeBuffers[index]; std::move(inFlight.begin(), inFlight.end(), std::back_inserter(freeBuf)); inFlight.clear(); VulkanContext::Instance()->GetDevice().resetCommandPool(*commandPools[index], vk::CommandPoolResetFlagBits::eReleaseResources); } vk::CommandBuffer Allocate() { if (freeBuffers[index].empty()) { inFlightBuffers[index].emplace_back(std::move( VulkanContext::Instance()->GetDevice().allocateCommandBuffersUnique(vk::CommandBufferAllocateInfo(*commandPools[index], vk::CommandBufferLevel::ePrimary, 1)) .front())); } else { inFlightBuffers[index].emplace_back(std::move(freeBuffers[index].back())); freeBuffers[index].pop_back(); } return *inFlightBuffers[index].back(); } vk::Fence GetCurrentFence() { return *fences[index]; } int GetIndex() const { return index; } private: int index = 0; std::vector> freeBuffers; std::vector> inFlightBuffers; std::vector commandPools; std::vector fences; // size should be the same as used by client: 2 for renderer (texCommandPool) static constexpr size_t chainSize = 2; };