diff --git a/src/Engine/Concepts.h b/src/Engine/Concepts.h new file mode 100644 index 0000000..33dcd4d --- /dev/null +++ b/src/Engine/Concepts.h @@ -0,0 +1,13 @@ +#pragma once +#include + +namespace Seele +{ +template +concept iterable = requires(A&& a) +{ + a.begin(); a.end(); +}; +template +concept invocable = std::invocable; +} \ No newline at end of file diff --git a/src/Engine/Graphics/RenderPass/BasePass.cpp b/src/Engine/Graphics/RenderPass/BasePass.cpp index 1e6ce6e..7637cae 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.cpp +++ b/src/Engine/Graphics/RenderPass/BasePass.cpp @@ -112,7 +112,7 @@ BasePass::~BasePass() { } -void BasePass::beginFrame() +MainJob BasePass::beginFrame() { processor->clearCommands(); primitiveLayout->reset(); @@ -132,6 +132,7 @@ void BasePass::beginFrame() descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); + co_return; } MainJob BasePass::render() @@ -161,8 +162,9 @@ MainJob BasePass::render() graphics->endRenderPass(); } -void BasePass::endFrame() +MainJob BasePass::endFrame() { + co_return; } void BasePass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/BasePass.h b/src/Engine/Graphics/RenderPass/BasePass.h index f2234f3..b1ac803 100644 --- a/src/Engine/Graphics/RenderPass/BasePass.h +++ b/src/Engine/Graphics/RenderPass/BasePass.h @@ -37,9 +37,9 @@ class BasePass : public RenderPass public: BasePass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source); virtual ~BasePass(); - virtual void beginFrame() override; + virtual MainJob beginFrame() override; virtual MainJob render() override; - virtual void endFrame() override; + virtual MainJob 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 53dd6f5..8a76ff7 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.cpp +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.cpp @@ -93,7 +93,7 @@ DepthPrepass::~DepthPrepass() { } -void DepthPrepass::beginFrame() +MainJob DepthPrepass::beginFrame() { processor->clearCommands(); primitiveLayout->reset(); @@ -111,6 +111,7 @@ void DepthPrepass::beginFrame() descriptorSets[INDEX_VIEW_PARAMS] = viewLayout->allocateDescriptorSet(); descriptorSets[INDEX_VIEW_PARAMS]->updateBuffer(0, viewParamBuffer); descriptorSets[INDEX_VIEW_PARAMS]->writeChanges(); + co_return; } MainJob DepthPrepass::render() @@ -130,8 +131,9 @@ MainJob DepthPrepass::render() graphics->endRenderPass(); } -void DepthPrepass::endFrame() +MainJob DepthPrepass::endFrame() { + co_return; } void DepthPrepass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/DepthPrepass.h b/src/Engine/Graphics/RenderPass/DepthPrepass.h index bb53568..f6c386f 100644 --- a/src/Engine/Graphics/RenderPass/DepthPrepass.h +++ b/src/Engine/Graphics/RenderPass/DepthPrepass.h @@ -36,9 +36,9 @@ class DepthPrepass : public RenderPass public: DepthPrepass(Gfx::PGraphics graphics, Gfx::PViewport viewport, PCameraActor source); ~DepthPrepass(); - virtual void beginFrame() override; + virtual MainJob beginFrame() override; virtual MainJob render() override; - virtual void endFrame() override; + virtual MainJob 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 7bd2b10..3df6084 100644 --- a/src/Engine/Graphics/RenderPass/LightCullingPass.cpp +++ b/src/Engine/Graphics/RenderPass/LightCullingPass.cpp @@ -18,7 +18,7 @@ LightCullingPass::~LightCullingPass() } -void LightCullingPass::beginFrame() +MainJob LightCullingPass::beginFrame() { uint32_t viewportWidth = viewport->getSizeX(); uint32_t viewportHeight = viewport->getSizeY(); @@ -75,6 +75,7 @@ void LightCullingPass::beginFrame() lightEnvDescriptorSet->updateBuffer(2, pointLightBuffer); lightEnvDescriptorSet->updateBuffer(3, numPointLightBuffer); lightEnvDescriptorSet->writeChanges(); + co_return; } MainJob LightCullingPass::render() @@ -104,8 +105,9 @@ MainJob LightCullingPass::render() co_return; } -void LightCullingPass::endFrame() +MainJob LightCullingPass::endFrame() { + co_return; } void LightCullingPass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/LightCullingPass.h b/src/Engine/Graphics/RenderPass/LightCullingPass.h index 8a3baa6..1d8ea7f 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 MainJob beginFrame() override; virtual MainJob render() override; - virtual void endFrame() override; + virtual MainJob endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; static void modifyRenderPassMacros(Map& defines); diff --git a/src/Engine/Graphics/RenderPass/RenderPass.h b/src/Engine/Graphics/RenderPass/RenderPass.h index 83e4663..d87a31a 100644 --- a/src/Engine/Graphics/RenderPass/RenderPass.h +++ b/src/Engine/Graphics/RenderPass/RenderPass.h @@ -22,9 +22,9 @@ public: void updateViewFrame(RenderPassDataType viewFrame) { passData = std::move(viewFrame); } - virtual void beginFrame() = 0; + virtual MainJob beginFrame() = 0; virtual MainJob render() = 0; - virtual void endFrame() = 0; + virtual MainJob 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 f6376e3..0c59947 100644 --- a/src/Engine/Graphics/RenderPass/UIPass.cpp +++ b/src/Engine/Graphics/RenderPass/UIPass.cpp @@ -15,8 +15,9 @@ UIPass::~UIPass() } -void UIPass::beginFrame() +MainJob UIPass::beginFrame() { + co_return; } MainJob UIPass::render() @@ -31,8 +32,9 @@ MainJob UIPass::render() co_return; } -void UIPass::endFrame() +MainJob UIPass::endFrame() { + co_return; } void UIPass::publishOutputs() diff --git a/src/Engine/Graphics/RenderPass/UIPass.h b/src/Engine/Graphics/RenderPass/UIPass.h index 877e9c1..f2b5248 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 MainJob beginFrame() override; virtual MainJob render() override; - virtual void endFrame() override; + virtual MainJob endFrame() override; virtual void publishOutputs() override; virtual void createRenderPass() override; private: diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp index bc1ef85..c54466e 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.cpp @@ -236,7 +236,7 @@ DescriptorAllocator::DescriptorAllocator(PGraphics graphics, DescriptorLayout &l { for(uint32 i = 0; i < cachedHandles.size(); ++i) { - cachedHandles[i] = new DescriptorSet(graphics, this); + cachedHandles[i] = nullptr; } uint32 perTypeSizes[VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT]; // TODO: FIX ENUM @@ -280,6 +280,10 @@ void DescriptorAllocator::allocateDescriptorSet(Gfx::PDescriptorSet &descriptorS for(uint32 setIndex = 0; setIndex < cachedHandles.size(); ++setIndex) { + if(cachedHandles[setIndex] == nullptr) + { + cachedHandles[setIndex] = new DescriptorSet(graphics, this); + } if(cachedHandles[setIndex]->isCurrentlyBound() || cachedHandles[setIndex]->isCurrentlyInUse()) { // Currently in use, skip @@ -308,6 +312,10 @@ void DescriptorAllocator::reset() { for(uint32 i = 0; i < cachedHandles.size(); ++i) { + if(cachedHandles[i] == nullptr) + { + return; + } cachedHandles[i]->free(); } } \ No newline at end of file diff --git a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h index 382ba44..0272f82 100644 --- a/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h +++ b/src/Engine/Graphics/Vulkan/VulkanDescriptorSets.h @@ -142,7 +142,7 @@ public: private: PGraphics graphics; DescriptorLayout &layout; - const static int maxSets = 512; + const static int maxSets = 64; StaticArray cachedHandles; VkDescriptorPool poolHandle; }; diff --git a/src/Engine/ThreadPool.cpp b/src/Engine/ThreadPool.cpp index 57d14b3..05ceb98 100644 --- a/src/Engine/ThreadPool.cpp +++ b/src/Engine/ThreadPool.cpp @@ -3,6 +3,7 @@ using namespace Seele; + Event::Event() : flag(new std::atomic_bool()) {} diff --git a/src/Engine/ThreadPool.h b/src/Engine/ThreadPool.h index a756f09..1fcaaaa 100644 --- a/src/Engine/ThreadPool.h +++ b/src/Engine/ThreadPool.h @@ -3,6 +3,7 @@ #include #include "MinimalEngine.h" #include "Containers/List.h" +#include "Concepts.h" namespace Seele { @@ -10,12 +11,14 @@ extern class ThreadPool& getGlobalThreadPool(); template struct JobBase; +struct Event; +static std::atomic_uint64_t globalCounter; template struct JobPromiseBase { JobBase get_return_object() noexcept; - inline auto initial_suspend() const noexcept; + inline auto initial_suspend() noexcept; inline auto final_suspend() const noexcept; void return_void() noexcept {} @@ -23,7 +26,9 @@ struct JobPromiseBase std::cerr << "Unhandled exception" << std::endl; exit(1); }; - std::coroutine_handle<> continuation; + std::coroutine_handle<> continuation = std::noop_coroutine(); + uint64 id; + Event finishedEvent; }; struct Event @@ -57,9 +62,7 @@ private: friend class ThreadPool; }; - -static std::atomic_uint64_t globalCounter; -template +template struct JobBase { public: @@ -67,16 +70,18 @@ public: explicit JobBase() : id(-1) - {} - explicit JobBase(std::coroutine_handle handle) + { + } + explicit JobBase(std::coroutine_handle handle, uint64 id, Event finishedEvent) : handle(handle) - , id(globalCounter++) - , event(std::format("Job {}", id)) + , event(std::move(finishedEvent)) + , id(id) { } JobBase(const JobBase & rhs) = delete; JobBase(JobBase&& rhs) : handle(std::move(rhs.handle)) + , event(rhs.event) , id(std::move(rhs.id)) { rhs.id = -1; @@ -86,6 +91,7 @@ public: { if(handle && handle.done()) { + std::cout << "Destroy job " << handle.address() << std::endl; handle.destroy(); } } @@ -95,6 +101,7 @@ public: if(this != &rhs) { handle = std::move(rhs.handle); + event = std::move(rhs.event); id = std::move(rhs.id); rhs.id = -1; rhs.handle = nullptr; @@ -105,9 +112,15 @@ public: { handle.resume(); } - void then(JobBase continuation) + template + inline JobBase then(Callable callable) + { + return then(callable()); + } + JobBase then(JobBase continuation) { handle.promise().continuation = continuation.handle; + return continuation; } bool done() { @@ -125,12 +138,13 @@ public: { return event; } + static JobBase all() = delete; template static JobBase all(Awaitable... jobs) { - co_await jobs; + (co_await jobs, ...); } - template + template static JobBase all(Iterable&& collection) { for(auto&& it : collection) @@ -138,7 +152,7 @@ public: co_await it; } } - template + template static JobBase launchJobs(JobFunc&& func, IterableParams params) { List jobs; @@ -194,23 +208,27 @@ private: template -inline JobBase JobPromiseBase::get_return_object() noexcept { - return JobBase(); +inline JobBase JobPromiseBase::get_return_object() noexcept +{ + id = globalCounter++; + return JobBase(std::coroutine_handle>::from_promise(*this), id, finishedEvent); } template -inline auto JobPromiseBase::initial_suspend() const noexcept +inline auto JobPromiseBase::initial_suspend() noexcept { struct JobAwaitable { constexpr bool await_ready() { return false; } constexpr void await_suspend(std::coroutine_handle> h) { - getGlobalThreadPool().addJob(std::move(JobBase(h))); + getGlobalThreadPool().addJob(std::move(JobBase(h, id, event))); } constexpr void await_resume() {} + uint64 id; + Event& event; }; - return JobAwaitable{}; + return JobAwaitable{id, finishedEvent}; } template inline auto JobPromiseBase::final_suspend() const noexcept @@ -230,7 +248,7 @@ inline auto JobPromiseBase::final_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, h.promise().id, *this))); } } // namespace Seele diff --git a/src/Engine/Window/InspectorView.cpp b/src/Engine/Window/InspectorView.cpp index 047c08f..d9fb946 100644 --- a/src/Engine/Window/InspectorView.cpp +++ b/src/Engine/Window/InspectorView.cpp @@ -40,12 +40,14 @@ void InspectorView::prepareRender() MainJob InspectorView::render() { - uiPass.beginFrame(); - uiPass.render(); - uiPass.endFrame(); - - renderFinishedEvent.raise(); - co_return; + return uiPass.beginFrame() + .then(uiPass.render()) + .then(uiPass.endFrame()) + .then([=]() -> MainJob + { + renderFinishedEvent.raise(); + co_return; + }); } void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) diff --git a/src/Engine/Window/SceneView.cpp b/src/Engine/Window/SceneView.cpp index c7e1e3d..145547f 100644 --- a/src/Engine/Window/SceneView.cpp +++ b/src/Engine/Window/SceneView.cpp @@ -84,20 +84,20 @@ void SceneView::prepareRender() MainJob SceneView::render() { - depthPrepass.beginFrame(); - lightCullingPass.beginFrame(); - basePass.beginFrame(); - - depthPrepass.render(); - lightCullingPass.render(); - basePass.render(); - - depthPrepass.endFrame(); - lightCullingPass.endFrame(); - basePass.endFrame(); - - renderFinishedEvent.raise(); - co_return; + return depthPrepass.beginFrame() + .then(lightCullingPass.beginFrame()) + .then(basePass.beginFrame()) + .then(depthPrepass.render()) + .then(lightCullingPass.render()) + .then(basePass.render()) + .then(depthPrepass.endFrame()) + .then(lightCullingPass.endFrame()) + .then(basePass.endFrame()) + .then([=]() -> MainJob + { + renderFinishedEvent.raise(); + co_return; + }); } void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier) diff --git a/src/Engine/Window/View.cpp b/src/Engine/Window/View.cpp index 6c8b339..12a0945 100644 --- a/src/Engine/Window/View.cpp +++ b/src/Engine/Window/View.cpp @@ -5,7 +5,10 @@ using namespace Seele; View::View(Gfx::PGraphics graphics, PWindow window, const ViewportCreateInfo &viewportInfo, std::string name) - : graphics(graphics), owner(window), name(name) + : graphics(graphics) + , owner(window) + , name(name) + , renderFinishedEvent(name + "RenderFinished") { viewport = graphics->createViewport(owner->getGfxHandle(), viewportInfo); }