/* 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.h" class CommandPool { public: void Init() { size_t size = VulkanContext::Instance()->GetSwapChainSize(); if (commandPools.size() > size) { commandPools.resize(size); fences.resize(size); } else { while (commandPools.size() < size) { commandPools.emplace_back(std::move(VulkanContext::Instance()->GetDevice()->createCommandPoolUnique( vk::CommandPoolCreateInfo(vk::CommandPoolCreateFlagBits::eTransient, VulkanContext::Instance()->GetGraphicsQueueFamilyIndex())))); fences.emplace_back(std::move(VulkanContext::Instance()->GetDevice()->createFenceUnique(vk::FenceCreateInfo(vk::FenceCreateFlagBits::eSignaled)))); } } if (freeBuffers.size() != size) freeBuffers.resize(size); if (inFlightBuffers.size() != size) inFlightBuffers.resize(size); } void Term() { freeBuffers.clear(); inFlightBuffers.clear(); fences.clear(); commandPools.clear(); } void EndFrame() { vk::CommandBuffer commandBuffer = Allocate(); commandBuffer.begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit)); commandBuffer.end(); VulkanContext::Instance()->GetGraphicsQueue().submit(vk::SubmitInfo(0, nullptr, nullptr, 1, &commandBuffer), *fences[index]); } void BeginFrame() { index = (index + 1) % VulkanContext::Instance()->GetSwapChainSize(); VulkanContext::Instance()->GetDevice()->waitForFences(1, &fences[index].get(), true, UINT64_MAX); VulkanContext::Instance()->GetDevice()->resetFences(1, &fences[index].get()); std::vector& inFlight = inFlightBuffers[index]; std::vector& freeBuf = freeBuffers[index]; while (!inFlight.empty()) { freeBuf.emplace_back(std::move(inFlight.back())); inFlight.pop_back(); } 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(); } private: int index = 0; std::vector> freeBuffers; std::vector> inFlightBuffers; std::vector commandPools; std::vector fences; };