From 5fafdda770ccedd9b9c76c9d06f3b47c2837b278 Mon Sep 17 00:00:00 2001 From: Dynamitos Date: Wed, 24 Nov 2021 12:10:23 +0100 Subject: [PATCH] Async render passes --- .vscode/c_cpp_properties.json | 4 +- .vscode/launch.json | 1 - src/Engine/Containers/List.h | 5 +- src/Engine/Graphics/RenderPass/BasePass.cpp | 26 ++-- src/Engine/Graphics/RenderPass/BasePass.h | 12 +- .../Graphics/RenderPass/DepthPrepass.cpp | 24 ++-- src/Engine/Graphics/RenderPass/DepthPrepass.h | 12 +- .../Graphics/RenderPass/LightCullingPass.cpp | 10 +- .../Graphics/RenderPass/LightCullingPass.h | 6 +- .../Graphics/RenderPass/MeshProcessor.h | 9 +- src/Engine/Graphics/RenderPass/RenderPass.h | 7 +- src/Engine/Graphics/RenderPass/UIPass.cpp | 11 +- src/Engine/Graphics/RenderPass/UIPass.h | 6 +- src/Engine/Scene/Actor/Actor.cpp | 2 +- src/Engine/Scene/Scene.cpp | 2 +- src/Engine/ThreadPool.cpp | 43 +++--- src/Engine/ThreadPool.h | 129 +++++++++--------- src/Engine/Window/InspectorView.cpp | 17 ++- src/Engine/Window/InspectorView.h | 2 +- src/Engine/Window/SceneView.cpp | 22 +-- src/Engine/Window/SceneView.h | 2 +- src/Engine/Window/View.h | 5 +- src/Engine/Window/Window.cpp | 4 + 23 files changed, 199 insertions(+), 162 deletions(-) diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json index dbec570..afb5a75 100644 --- a/.vscode/c_cpp_properties.json +++ b/.vscode/c_cpp_properties.json @@ -30,15 +30,13 @@ "UNICODE", "_UNICODE" ], - "intelliSenseMode": "linux-gcc-x64", "configurationProvider": "ms-vscode.cmake-tools", "cppStandard": "c++20", "browse": { "path": [ "external/**" ] - }, - "compilerPath": "/usr/bin/g++" + } } ], "version": 4 diff --git a/.vscode/launch.json b/.vscode/launch.json index cba0aba..edebfa5 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -15,7 +15,6 @@ "console": "internalConsole", "environment": [], "externalConsole": false, - "MIMode": "gdb", "setupCommands": [ { "description": "Enable break on all exceptions", diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 2404f4d..a9ca027 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -208,9 +208,10 @@ public: deallocateNode(tmp->prev); } deallocateNode(tail); - markIteratorDirty(); tail = nullptr; root = nullptr; + markIteratorDirty(); + _size = 0; } //Insert at the end iterator add(const T &value) @@ -291,7 +292,7 @@ public: { value_type temp = std::move(root->data); popFront(); - return std::move(temp); + return temp; } iterator remove(iterator pos) { diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index c15e63f..d536abf 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -20,13 +20,13 @@ BasePassMeshProcessor::~BasePassMeshProcessor() { } -void BasePassMeshProcessor::addMeshBatch( +Job BasePassMeshProcessor::processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, - const Gfx::PRenderPass renderPass, + const Gfx::PRenderPass& renderPass, Gfx::PPipelineLayout pipelineLayout, Gfx::PDescriptorLayout primitiveLayout, - Array& descriptorSets, + Array descriptorSets, int32 /*staticMeshId*/) { PMaterialAsset material = batch.material; @@ -34,11 +34,12 @@ void BasePassMeshProcessor::addMeshBatch( const PVertexShaderInput vertexInput = batch.vertexInput; - const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType()); + const Gfx::ShaderCollection* collection = material->getShaders(Gfx::RenderPassType::BasePass, vertexInput->getType()); assert(collection != nullptr); Gfx::PRenderCommand renderCommand = graphics->createRenderCommand(); renderCommand->setViewport(target); + pipelineLayout->addDescriptorLayout(BasePass::INDEX_MATERIAL, material->getDescriptorLayout()); pipelineLayout->create(); Gfx::PDescriptorSet materialSet = material->createDescriptorSet(); @@ -63,6 +64,7 @@ void BasePassMeshProcessor::addMeshBatch( false); } renderCommands.add(renderCommand); + co_return; } Array BasePassMeshProcessor::getRenderCommands() @@ -120,7 +122,7 @@ BasePass::~BasePass() { } -void BasePass::beginFrame() +Job BasePass::beginFrame() { processor->clearCommands(); primitiveLayout->reset(); @@ -140,9 +142,10 @@ void BasePass::beginFrame() descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); + co_return; } -void BasePass::render() +Job BasePass::render() { oLightIndexList->pipelineBarrier( Gfx::SE_ACCESS_SHADER_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, @@ -159,16 +162,23 @@ void BasePass::render() descriptorSets[INDEX_LIGHT_ENV]->updateTexture(5, oLightGrid); descriptorSets[INDEX_LIGHT_ENV]->writeChanges(); graphics->beginRenderPass(renderPass); + List jobs; for (auto &&meshBatch : passData.staticDrawList) { - processor->addMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets); + jobs.add(processor->processMeshBatch(meshBatch, renderPass, basePassLayout, primitiveLayout, descriptorSets)); + } + for(auto& job : jobs) + { + co_await job; } graphics->executeCommands(processor->getRenderCommands()); graphics->endRenderPass(); + co_return; } -void BasePass::endFrame() +Job BasePass::endFrame() { + co_return; } void BasePass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index c69a8eb..24d3851 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -11,13 +11,13 @@ public: BasePassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics, uint8 translucentBasePass); virtual ~BasePassMeshProcessor(); - virtual void addMeshBatch( + virtual Job processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, - const Gfx::PRenderPass renderPass, + const Gfx::PRenderPass& renderPass, Gfx::PPipelineLayout pipelineLayout, Gfx::PDescriptorLayout primitiveLayout, - Array& descriptorSets, + Array descriptorSets, int32 staticMeshId = -1) override; Array getRenderCommands(); void clearCommands(); @@ -40,9 +40,9 @@ class BasePass : public RenderPass public: BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source); virtual ~BasePass(); - virtual void beginFrame() override; - virtual void render() override; - virtual void endFrame() override; + virtual Job beginFrame() override; + virtual Job render() override; + virtual Job endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; static void modifyRenderPassMacros(Map& defines); diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp index 70fba77..00e1a57 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -18,13 +18,13 @@ DepthPrepassMeshProcessor::~DepthPrepassMeshProcessor() { } -void DepthPrepassMeshProcessor::addMeshBatch( +Job DepthPrepassMeshProcessor::processMeshBatch( const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, - const Gfx::PRenderPass renderPass, + const Gfx::PRenderPass& renderPass, Gfx::PPipelineLayout pipelineLayout, Gfx::PDescriptorLayout primitiveLayout, - Array& descriptorSets, + Array descriptorSets, int32 /*staticMeshId*/) { PMaterialAsset material = batch.material; @@ -61,6 +61,7 @@ void DepthPrepassMeshProcessor::addMeshBatch( true); } renderCommands.add(renderCommand); + co_return; } Array DepthPrepassMeshProcessor::getRenderCommands() @@ -104,7 +105,7 @@ DepthPrepass::~DepthPrepass() { } -void DepthPrepass::beginFrame() +Job DepthPrepass::beginFrame() { processor->clearCommands(); primitiveLayout->reset(); @@ -122,26 +123,33 @@ void DepthPrepass::beginFrame() descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); + co_return; } -void DepthPrepass::render() +Job DepthPrepass::render() { - depthAttachment->getTexture()->pipelineBarrier( Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_COMPUTE_SHADER_BIT, Gfx::SE_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, Gfx::SE_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT); depthAttachment->getTexture()->transferOwnership(Gfx::QueueType::GRAPHICS); graphics->beginRenderPass(renderPass); + List jobs; for (auto &&meshBatch : passData.staticDrawList) { - processor->addMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets); + jobs.add(processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets)); + } + for(auto& job : jobs) + { + co_await job; } graphics->executeCommands(processor->getRenderCommands()); graphics->endRenderPass(); + co_return; } -void DepthPrepass::endFrame() +Job DepthPrepass::endFrame() { + co_return; } void DepthPrepass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index c94037b..59738cd 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -11,12 +11,12 @@ public: DepthPrepassMeshProcessor(Gfx::PViewport viewport, Gfx::PGraphics graphics); virtual ~DepthPrepassMeshProcessor(); - virtual void addMeshBatch( + virtual Job processMeshBatch( const MeshBatch& batch, - const Gfx::PRenderPass renderPass, + const Gfx::PRenderPass& renderPass, Gfx::PPipelineLayout pipelineLayout, Gfx::PDescriptorLayout primitiveLayout, - Array& descriptorSets, + Array descriptorSets, int32 staticMeshId = -1) override; Array getRenderCommands(); @@ -39,9 +39,9 @@ class DepthPrepass : public RenderPass public: DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source); ~DepthPrepass(); - virtual void beginFrame() override; - virtual void render() override; - virtual void endFrame() override; + virtual Job beginFrame() override; + virtual Job render() override; + virtual Job endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; static void modifyRenderPassMacros(Map& defines); diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp index 16e6b98..73fc453 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -18,7 +18,7 @@ LightCullingPass::~LightCullingPass() } -void LightCullingPass::beginFrame() +Job LightCullingPass::beginFrame() { uint32_t viewportWidth = viewport->getSizeX(); uint32_t viewportHeight = viewport->getSizeY(); @@ -75,9 +75,10 @@ void LightCullingPass::beginFrame() lightEnvDescriptorSet->updateBuffer(2, pointLightBuffer); lightEnvDescriptorSet->updateBuffer(3, numPointLightBuffer); lightEnvDescriptorSet->writeChanges(); + co_return; } -void LightCullingPass::render() +Job LightCullingPass::render() { oLightIndexList->pipelineBarrier( Gfx::SE_ACCESS_SHADER_READ_BIT, Gfx::SE_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, @@ -101,11 +102,12 @@ void LightCullingPass::render() graphics->executeCommands(commands); depthAttachment->changeLayout(Gfx::SE_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL); depthAttachment->transferOwnership(Gfx::QueueType::GRAPHICS); + co_return; } -void LightCullingPass::endFrame() +Job LightCullingPass::endFrame() { - + co_return; } void LightCullingPass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index fd10e17..cee2fa2 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.h +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.h @@ -18,9 +18,9 @@ class LightCullingPass : public RenderPass public: LightCullingPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor camera); virtual ~LightCullingPass(); - virtual void beginFrame() override; - virtual void render() override; - virtual void endFrame() override; + virtual Job beginFrame() override; + virtual Job render() override; + virtual Job endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; static void modifyRenderPassMacros(Map& defines); diff --git a/src/Engine/Graphics/RenderPass/MeshProcessor.h b/src/Engine/Graphics/RenderPass/MeshProcessor.h index cc655e0..b09594f 100644 --- a/src/Engine/Graphics/RenderPass/MeshProcessor.h +++ b/src/Engine/Graphics/RenderPass/MeshProcessor.h @@ -3,6 +3,7 @@ #include "Scene/Scene.h" #include "Graphics/GraphicsResources.h" #include "Graphics/MeshBatch.h" +#include "ThreadPool.h" namespace Seele { @@ -14,13 +15,13 @@ public: protected: PScene scene; Gfx::PGraphics graphics; - virtual void addMeshBatch( - const MeshBatch& meshBatch, + virtual Job processMeshBatch( + const MeshBatch& batch, // const PPrimitiveComponent primitiveComponent, - const Gfx::PRenderPass renderPass, + const Gfx::PRenderPass& renderPass, Gfx::PPipelineLayout pipelineLayout, Gfx::PDescriptorLayout primitiveLayout, - Array& descriptorSets, + Array descriptorSets, int32 staticMeshId = -1) = 0; void buildMeshDrawCommand( const MeshBatch& meshBatch, diff --git a/src/Engine/Graphics/RenderPass/RenderPass.h b/src/Engine/Graphics/RenderPass/RenderPass.h index 4d17db3..96da6f6 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.h +++ b/src/Engine/Graphics/RenderPass/RenderPass.h @@ -2,6 +2,7 @@ #include "MinimalEngine.h" #include "Math/Math.h" #include "RenderGraph.h" +#include "ThreadPool.h" namespace Seele { @@ -21,9 +22,9 @@ public: void updateViewFrame(RenderPassDataType viewFrame) { passData = std::move(viewFrame); } - virtual void beginFrame() = 0; - virtual void render() = 0; - virtual void endFrame() = 0; + virtual Job beginFrame() = 0; + virtual Job render() = 0; + virtual Job endFrame() = 0; virtual void publishOutputs() = 0; virtual void createRenderPass() = 0; void setResources(PRenderGraphResources resources) { this->resources = resources; } diff --git a/src/Engine/Graphics/RenderPass/UIPass.cpp b/src/Engine/Graphics/RenderPass/UIPass.cpp index 8649c3f..a2972b9 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -15,12 +15,12 @@ UIPass::~UIPass() } -void UIPass::beginFrame() +Job UIPass::beginFrame() { - + co_return; } -void UIPass::render() +Job UIPass::render() { graphics->beginRenderPass(renderPass); Gfx::PRenderCommand command = graphics->createRenderCommand("UIPassCommand"); @@ -29,11 +29,12 @@ void UIPass::render() command->draw(4, 1, 0, 0); graphics->executeCommands(Array({command})); graphics->endRenderPass(); + co_return; } -void UIPass::endFrame() +Job UIPass::endFrame() { - + co_return; } void UIPass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/UIPass.h b/src/Engine/Graphics/RenderPass/UIPass.h index 2e50cd0..d506d3d 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.h +++ b/src/Engine/Graphics/RenderPass/UIPass.h @@ -16,9 +16,9 @@ class UIPass : public RenderPass public: UIPass(Gfx::PGraphics graphics, Gfx::PViewport viewport, Gfx::PRenderTargetAttachment renderTarget); virtual ~UIPass(); - virtual void beginFrame() override; - virtual void render() override; - virtual void endFrame() override; + virtual Job beginFrame() override; + virtual Job render() override; + virtual Job endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; private: diff --git a/src/Engine/Scene/Actor/Actor.cpp b/src/Engine/Scene/Actor/Actor.cpp index 35091b9..dcc7dba 100644 --- a/src/Engine/Scene/Actor/Actor.cpp +++ b/src/Engine/Scene/Actor/Actor.cpp @@ -12,7 +12,7 @@ Actor::~Actor() { } -void Actor::tick(float deltaTime) +void Actor::tick(float) { } void Actor::notifySceneAttach(PScene scene) diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index 7c36567..be75c53 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -33,7 +33,7 @@ Scene::~Scene() { } -void Scene::tick(double deltaTime) +void Scene::tick(double) { } diff --git a/src/Engine/ThreadPool.cpp b/src/Engine/ThreadPool.cpp index 122d234..7c42cb7 100644 --- a/src/Engine/ThreadPool.cpp +++ b/src/Engine/ThreadPool.cpp @@ -14,7 +14,7 @@ Event::Event(const std::string& name) void Event::raise() { flag->store(1); - getGlobalThreadPool().notify(this); + getGlobalThreadPool().notify(*this); } void Event::reset() { @@ -47,51 +47,56 @@ ThreadPool::~ThreadPool() void ThreadPool::addJob(Job&& job) { std::unique_lock lock(jobQueueLock); - std::cout << "Adding job " << job.id << std::endl; + //std::cout << "Adding job " << job.id << std::endl; jobQueue.add(std::move(job)); jobQueueCV.notify_one(); } void ThreadPool::addJob(MainJob&& job) { std::unique_lock lock(mainJobLock); - std::cout << "Adding main job " << job.id << std::endl; + //std::cout << "Adding main job " << job.id << std::endl; mainJobs.add(std::move(job)); mainJobCV.notify_one(); } -void ThreadPool::enqueueWaiting(Event* event, Job&& job) +void ThreadPool::enqueueWaiting(Event& event, Job job) { - std::cout << job.id << " waiting for event " << event->name << std::endl; + //std::cout << job.id << " waiting for event " << event.name << std::endl; std::unique_lock lock(waitingLock); - waitingJobs[*event].add(std::move(job)); + waitingJobs[event].add(std::move(job)); } -void ThreadPool::enqueueWaiting(Event* event, MainJob&& job) +void ThreadPool::enqueueWaiting(Event& event, MainJob job) { - std::cout << job.id << " main waiting for event " << event->name << std::endl; + //std::cout << job.id << " main waiting for event " << event.name << std::endl; std::unique_lock lock(waitingMainLock); - waitingMainJobs[*event].add(std::move(job)); + waitingMainJobs[event].add(std::move(job)); } -void ThreadPool::notify(Event* event) +void ThreadPool::notify(Event& event) { { std::unique_lock lock(jobQueueLock); std::unique_lock lock2(waitingLock); - while(!waitingJobs[*event].empty()) + List& jobs = waitingJobs[event]; + for(auto& job : jobs) { - std::cout << "Waking up job " << waitingJobs[*event].front().id << std::endl; - Job job = std::move(waitingJobs[*event].retrieve()); + //assert(job.id != -1ull); + //std::cout << "Waking up job " << job.id << std::endl; jobQueue.add(std::move(job)); jobQueueCV.notify_one(); } + jobs.clear(); } { std::unique_lock lock(mainJobLock); std::unique_lock lock2(waitingMainLock); - while(!waitingMainJobs[*event].empty()) + List& jobs = waitingMainJobs[event]; + for(auto& job : jobs) { - std::cout << "Waking up main job " << waitingMainJobs[*event].front().id << std::endl; - mainJobs.add(std::move(waitingMainJobs[*event].retrieve())); + //assert(job.id != -1ull); + //std::cout << "Waking up main job " << job.id << std::endl; + mainJobs.add(std::move(job)); mainJobCV.notify_one(); } + jobs.clear(); } } void ThreadPool::tryMainJob() @@ -134,8 +139,12 @@ void ThreadPool::threadLoop(const bool mainThread) continue; } } - std::cout << "Starting job " << job.id << std::endl; + //std::cout << "Starting job " << job.id << std::endl; job.resume(); + if(job.done()) + { + job.signal(); + } } } diff --git a/src/Engine/ThreadPool.h b/src/Engine/ThreadPool.h index 2198549..52ced57 100644 --- a/src/Engine/ThreadPool.h +++ b/src/Engine/ThreadPool.h @@ -25,69 +25,6 @@ struct JobPromiseBase exit(1); }; }; -static std::atomic_uint64_t globalCounter; -template -struct JobBase -{ -public: - using promise_type = JobPromiseBase; - - explicit JobBase() - : id(-1) - {} - explicit JobBase(std::coroutine_handle handle) - : handle(handle) - , id(globalCounter++) - { - std::cout << "Creating job " << id << std::endl; - /*if constexpr(MainJob) - { - std::cout << "Creating mainjob " << handle.address() << std::endl; - } - else - { - std::cout << "Creating job " << handle.address() << std::endl; - }*/ - } - JobBase(const JobBase & rhs) = delete; - JobBase(JobBase&& rhs) - : handle(std::move(rhs.handle)) - , id(std::move(rhs.id)) - { - rhs.id = -1; - rhs.handle = nullptr; - } - ~JobBase() - { - if(handle) - { - std::cout << "Destroying job " << id << std::endl; - handle.destroy(); - } - } - JobBase& operator=(const JobBase& rhs) = delete; - JobBase& operator=(JobBase&& rhs) - { - if(this != &rhs) - { - handle = std::move(rhs.handle); - id = std::move(rhs.id); - rhs.id = -1; - rhs.handle = nullptr; - } - return *this; - } - void resume() - { - handle.resume(); - } - std::coroutine_handle handle; - uint64 id; -private: -}; - -using MainJob = JobBase; -using Job = JobBase; struct Event { @@ -119,16 +56,72 @@ private: friend class ThreadPool; }; +static std::atomic_uint64_t globalCounter; +template +struct JobBase +{ +public: + using promise_type = JobPromiseBase; + + explicit JobBase() + : id(-1) + {} + explicit JobBase(std::coroutine_handle handle) + : handle(handle) + , id(globalCounter++) + { + //std::cout << "Creating job " << id << std::endl; + } + JobBase(const JobBase & rhs) = delete; + JobBase(JobBase&& rhs) + : handle(std::move(rhs.handle)) + , id(std::move(rhs.id)) + { + rhs.id = -1; + rhs.handle = nullptr; + } + ~JobBase() + { + if(handle && handle.done()) + { + //std::cout << "Destroying job " << id << std::endl; + handle.destroy(); + } + } + JobBase& operator=(const JobBase& rhs) = delete; + JobBase& operator=(JobBase&& rhs) + { + if(this != &rhs) + { + handle = std::move(rhs.handle); + id = std::move(rhs.id); + rhs.id = -1; + rhs.handle = nullptr; + } + return *this; + } + void resume() + { + handle.resume(); + } +private: + std::coroutine_handle handle; + uint64 id; +}; + +using MainJob = JobBase; +using Job = JobBase; + class ThreadPool { public: - ThreadPool(uint32 threadCount = std::thread::hardware_concurrency()); + ThreadPool(uint32 threadCount = std::thread::hardware_concurrency() + 1); virtual ~ThreadPool(); void addJob(Job&& job); void addJob(MainJob&& job); - void enqueueWaiting(Event* event, Job&& job); - void enqueueWaiting(Event* event, MainJob&& job); - void notify(Event* event); + void enqueueWaiting(Event& event, Job job); + void enqueueWaiting(Event& event, MainJob job); + void notify(Event& event); private: std::atomic_bool running; std::thread* mainThread; @@ -176,7 +169,7 @@ inline auto JobPromiseBase::initial_suspend() const noexcept template inline constexpr void Event::await_suspend(std::coroutine_handle> h) { - getGlobalThreadPool().enqueueWaiting(this, std::move(JobBase(h))); + getGlobalThreadPool().enqueueWaiting(*this, std::move(JobBase(h))); } } // namespace Seele diff --git a/src/Engine/Window/InspectorView.cpp b/src/Engine/Window/InspectorView.cpp index 17581e4..e74cc07 100644 --- a/src/Engine/Window/InspectorView.cpp +++ b/src/Engine/Window/InspectorView.cpp @@ -34,31 +34,36 @@ void InspectorView::prepareRender() } -void InspectorView::render() +Job InspectorView::render() { + co_await uiPass.beginFrame(); + co_await uiPass.render(); + co_await uiPass.endFrame(); + + renderFinishedEvent.raise(); } -void InspectorView::keyCallback(KeyCode code, InputAction action, KeyModifier modifier) +void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) { } -void InspectorView::mouseMoveCallback(double xPos, double yPos) +void InspectorView::mouseMoveCallback(double, double) { } -void InspectorView::mouseButtonCallback(MouseButton button, InputAction action, KeyModifier modifier) +void InspectorView::mouseButtonCallback(MouseButton, InputAction, KeyModifier) { } -void InspectorView::scrollCallback(double xOffset, double yOffset) +void InspectorView::scrollCallback(double, double) { } -void InspectorView::fileCallback(int count, const char** paths) +void InspectorView::fileCallback(int, const char**) { } diff --git a/src/Engine/Window/InspectorView.h b/src/Engine/Window/InspectorView.h index d9fd8b5..bca0bf6 100644 --- a/src/Engine/Window/InspectorView.h +++ b/src/Engine/Window/InspectorView.h @@ -18,7 +18,7 @@ public: virtual void commitUpdate() override; virtual void prepareRender() override; - virtual void render() override; + virtual Job render() override; void selectActor(); protected: UIPass uiPass; diff --git a/src/Engine/Window/SceneView.cpp b/src/Engine/Window/SceneView.cpp index b6ca1a9..1c335d2 100644 --- a/src/Engine/Window/SceneView.cpp +++ b/src/Engine/Window/SceneView.cpp @@ -83,19 +83,21 @@ void SceneView::prepareRender() basePass.updateViewFrame(basePassData); } -void SceneView::render() +Job SceneView::render() { - depthPrepass.beginFrame(); - lightCullingPass.beginFrame(); - basePass.beginFrame(); + co_await depthPrepass.beginFrame(); + co_await lightCullingPass.beginFrame(); + co_await basePass.beginFrame(); - depthPrepass.render(); - lightCullingPass.render(); - basePass.render(); + co_await depthPrepass.render(); + co_await lightCullingPass.render(); + co_await basePass.render(); - depthPrepass.endFrame(); - lightCullingPass.endFrame(); - basePass.endFrame(); + co_await depthPrepass.endFrame(); + co_await lightCullingPass.endFrame(); + co_await basePass.endFrame(); + + renderFinishedEvent.raise(); } void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier) diff --git a/src/Engine/Window/SceneView.h b/src/Engine/Window/SceneView.h index 7e28e59..9fc213a 100644 --- a/src/Engine/Window/SceneView.h +++ b/src/Engine/Window/SceneView.h @@ -18,7 +18,7 @@ public: virtual void commitUpdate() override; virtual void prepareRender() override; - virtual void render() override; + virtual Job render() override; PScene getScene() const { return scene; } private: diff --git a/src/Engine/Window/View.h b/src/Engine/Window/View.h index 8aa805d..75a1a37 100644 --- a/src/Engine/Window/View.h +++ b/src/Engine/Window/View.h @@ -1,5 +1,6 @@ #pragma once #include "Graphics/RenderPass/RenderGraph.h" +#include "ThreadPool.h" namespace Seele { @@ -20,15 +21,17 @@ public: // These are called from the render thread // prepare render is also locked, so reading from shared memory is also safe virtual void prepareRender() {} - virtual void render() {} + virtual Job render() { co_return; } void applyArea(URect area); void setFocused(); + Event renderFinished() { return renderFinishedEvent; } protected: Gfx::PGraphics graphics; Gfx::PViewport viewport; PWindow owner; std::string name; + Event renderFinishedEvent; virtual void keyCallback(KeyCode code, InputAction action, KeyModifier modifier) = 0; virtual void mouseMoveCallback(double xPos, double yPos) = 0; diff --git a/src/Engine/Window/Window.cpp b/src/Engine/Window/Window.cpp index 4917cbb..b9c2217 100644 --- a/src/Engine/Window/Window.cpp +++ b/src/Engine/Window/Window.cpp @@ -37,6 +37,10 @@ MainJob Window::render() } windowView->view->render(); } + for(auto& windowView : views) + { + co_await windowView->view->renderFinished(); + } gfxHandle->endFrame(); //Enqueue a new render main job render();