Refactor code

This commit is contained in:
2020-09-25 01:55:18 +02:00
parent 9f105a4397
commit 4f2122a2be
12 changed files with 457 additions and 358 deletions

View File

@@ -1,5 +1,11 @@
/*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
*/
#pragma once
#include <stdexcept>
#include "../Base/Render/IRenderer.hpp"
#include "../Base/UI/IWindow.hpp"
#include "../Base/Logger.hpp"
@@ -9,198 +15,56 @@
#include "CommandHelper.hpp"
#include "../Base/EngineConfiguration.hpp"
namespace openVulkanoCpp
namespace openVulkanoCpp::Vulkan
{
namespace Vulkan
struct WaitSemaphores
{
struct WaitSemaphores
{
std::vector<vk::Semaphore> renderReady, renderComplete;
};
std::vector<vk::Semaphore> renderReady, renderComplete;
};
class Renderer : public IRenderer
{
Context context;
std::shared_ptr<spdlog::logger> logger;
std::vector<WaitSemaphores> waitSemaphores;
Scene::Scene* scene = nullptr;
ResourceManager resourceManager;
uint32_t currentImageId = -1;
std::vector<std::thread> threadPool;
std::vector<std::vector<CommandHelper>> commands;
std::vector<std::vector<vk::CommandBuffer>> submitBuffers;
VulkanShader* shader;
class Renderer final : public IRenderer
{
Context context;
std::shared_ptr<spdlog::logger> logger;
std::vector<WaitSemaphores> waitSemaphores;
Scene::Scene* scene = nullptr;
ResourceManager resourceManager;
uint32_t currentImageId = -1;
std::vector<std::thread> threadPool;
std::vector<std::vector<CommandHelper>> commands;
std::vector<std::vector<vk::CommandBuffer>> submitBuffers;
VulkanShader* shader;
public:
Renderer() = default;
virtual ~Renderer() = default;
public:
Renderer() = default;
virtual ~Renderer() = default;
void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) override
{
logger = Logger::RENDER;
logger->info("Initializing Vulkan renderer ...");
IVulkanWindow* vulkanWindow = window->GetVulkanWindow();
if (!vulkanWindow)
{
logger->error("The provided window is not compatible with Vulkan.");
throw std::runtime_error("The provided window is not compatible with Vulkan.");
}
context.Init(graphicsAppManager, vulkanWindow);
for (int i = 0; i < context.swapChain.GetImageCount(); i++)
{
waitSemaphores.emplace_back();
waitSemaphores[i].renderComplete.push_back(context.device->device.createSemaphore({}));
waitSemaphores[i].renderReady.resize(2);
}
resourceManager.Init(&context, context.swapChain.GetImageCount());
threadPool.resize(EngineConfiguration::GetEngineConfiguration()->GetNumThreads() - 1);
void Init(IGraphicsAppManager* graphicsAppManager, IWindow* window) override;
//Setup cmd pools and buffers
commands.resize(threadPool.size() + 2); // One extra cmd object for the primary buffer and one for the main thread
for(uint32_t i = 0; i < commands.size(); i++)
{
commands[i] = std::vector<CommandHelper>(context.swapChain.GetImageCount());
for(size_t j = 0; j < commands[i].size(); j++)
{
commands[i][j].Init(context.device->device, context.device->queueIndices.GetGraphics(),
(i == commands.size() - 1) ? vk::CommandBufferLevel::ePrimary : vk::CommandBufferLevel::eSecondary);
}
}
submitBuffers.resize(context.swapChain.GetImageCount());
for(uint32_t i = 0; i < submitBuffers.size(); i++)
{
submitBuffers[i].resize(commands.size() - 1);
for (size_t j = 0; j < submitBuffers[i].size(); j++)
{
submitBuffers[i][j] = commands[j][i].cmdBuffer;
}
}
void Tick() override;
shader = resourceManager.CreateShader(scene->shader);
void Close() override;
logger->info("Vulkan renderer initialized");
}
std::string GetMainRenderDeviceName() override;
void Tick() override
{
currentImageId = context.swapChain.AcquireNextImage();
Render();
}
void Resize(uint32_t newWidth, uint32_t newHeight) override;
void Close() override
{
//context.Close();
}
void SetScene(Scene::Scene* scene) override { this->scene = scene; }
std::string GetMainRenderDeviceName() override
{
return (context.device) ? context.device->GetDeviceName() : "Unknown";
}
Scene::Scene* GetScene() override { return scene; }
void Resize(const uint32_t newWidth, const uint32_t newHeight) override
{
context.Resize(newWidth, newHeight);
resourceManager.Resize();
}
CommandHelper* GetCommandData(uint32_t poolId);
void SetScene(Scene::Scene* scene) override
{
this->scene = scene;
}
static void RunThread(Renderer* renderer, Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t id);
Scene::Scene* GetScene() override
{
return scene;
}
void StartThreads(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue);
CommandHelper* GetCommandData(uint32_t poolId)
{
return &commands[poolId][currentImageId];
}
void RecordPrimaryBuffer();
static void RunThread(Renderer* renderer, Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t id)
{
renderer->RecordSecondaryBuffer(jobQueue, id);
}
void Submit();
void StartThreads(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue)
{
for(uint32_t i = 0; i < threadPool.size(); i++)
{
threadPool[i] = std::thread(RunThread, this, jobQueue, i);
}
}
void Render();
void RecordPrimaryBuffer()
{
CommandHelper* cmdHelper = GetCommandData(commands.size() - 1);
cmdHelper->Reset();
cmdHelper->cmdBuffer.begin(vk::CommandBufferBeginInfo(vk::CommandBufferUsageFlagBits::eOneTimeSubmit));
context.swapChainRenderPass.Begin(cmdHelper->cmdBuffer);
}
void Submit()
{
for (auto& thread : threadPool) { thread.join(); } // Wait till everything is recorded
CommandHelper* cmdHelper = GetCommandData(commands.size() - 1);
cmdHelper->cmdBuffer.executeCommands(submitBuffers[currentImageId].size(), submitBuffers[currentImageId].data());
context.swapChainRenderPass.End(cmdHelper->cmdBuffer);
cmdHelper->cmdBuffer.end();
std::array<vk::PipelineStageFlags, 2> stateFlags = { vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput), vk::PipelineStageFlags(vk::PipelineStageFlagBits::eColorAttachmentOutput) };
waitSemaphores[currentImageId].renderReady[0] = resourceManager.EndFrame();
waitSemaphores[currentImageId].renderReady[1] = context.swapChain.imageAvailableSemaphore;
vk::SubmitInfo si = vk::SubmitInfo(
waitSemaphores[currentImageId].renderReady.size(), waitSemaphores[currentImageId].renderReady.data(), stateFlags.data(),
1, &cmdHelper->cmdBuffer,
waitSemaphores[currentImageId].renderComplete.size(), waitSemaphores[currentImageId].renderComplete.data());
context.device->graphicsQueue.submit(1, &si, context.swapChain.GetCurrentSubmitFence());
context.swapChain.Present(context.device->graphicsQueue, waitSemaphores[currentImageId].renderComplete);
}
void Render()
{
resourceManager.StartFrame(currentImageId);
Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*> jobQueue(scene->shapeList);
StartThreads(&jobQueue);
RecordPrimaryBuffer();
RecordSecondaryBuffer(&jobQueue, threadPool.size());
Submit();
}
void RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t poolId)
{
Scene::Geometry* lastGeo = nullptr;
Scene::Node* lastNode = nullptr;
CommandHelper* cmdHelper = GetCommandData(poolId);
cmdHelper->Reset();
vk::CommandBufferInheritanceInfo inheritance = { context.swapChainRenderPass.renderPass, 0, context.swapChainRenderPass.GetFrameBuffer()->GetCurrentFrameBuffer() };
cmdHelper->cmdBuffer.begin(vk::CommandBufferBeginInfo{ vk::CommandBufferUsageFlagBits::eOneTimeSubmit | vk::CommandBufferUsageFlagBits::eRenderPassContinue, &inheritance });
shader->Record(cmdHelper->cmdBuffer, currentImageId);
cmdHelper->cmdBuffer.pushConstants(context.pipeline.pipelineLayout, vk::ShaderStageFlagBits::eVertex, 0, 64, scene->GetCamera()->GetViewProjectionMatrixPointer());
Scene::Drawable** drawablePointer;
while((drawablePointer = jobQueue->Pop()) != nullptr)
{
Scene::Drawable* drawable = *drawablePointer;
Scene::Geometry* mesh = drawable->mesh;
if (mesh != lastGeo)
{
if (!mesh->renderGeo) resourceManager.PrepareGeometry(mesh);
dynamic_cast<VulkanGeometry*>(mesh->renderGeo)->Record(cmdHelper->cmdBuffer, currentImageId);
lastGeo = mesh;
}
for(Scene::Node* node : drawable->nodes)
{
if (node != lastNode)
{
if (!node->renderNode) resourceManager.PrepareNode(node);
dynamic_cast<VulkanNode*>(node->renderNode)->Record(cmdHelper->cmdBuffer, currentImageId);
lastNode = node;
}
cmdHelper->cmdBuffer.drawIndexed(mesh->GetIndexCount(), 1, 0, 0, 0);
}
}
cmdHelper->cmdBuffer.end();
}
};
}
void RecordSecondaryBuffer(Data::ReadOnlyAtomicArrayQueue<Scene::Drawable*>* jobQueue, uint32_t poolId);
};
}