Then chaining still kinda broken

This commit is contained in:
Dynamitos
2021-12-22 14:32:40 +01:00
parent 8ccaa26223
commit 79ced0a30f
14 changed files with 131 additions and 53 deletions
+1 -2
View File
@@ -229,7 +229,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path&
AssetRegistry::importFile(texPngPath.string()); AssetRegistry::importFile(texPngPath.string());
} }
} }
Job MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset) void MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset)
{ {
std::cout << "Starting to import "<<path << std::endl; std::cout << "Starting to import "<<path << std::endl;
meshAsset->setStatus(Asset::Status::Loading); meshAsset->setStatus(Asset::Status::Loading);
@@ -264,5 +264,4 @@ Job MeshLoader::import(std::filesystem::path path, PMeshAsset meshAsset)
meshAsset->setStatus(Asset::Status::Ready); meshAsset->setStatus(Asset::Status::Ready);
meshAsset->save(); meshAsset->save();
std::cout << "Finished loading " << path << std::endl; std::cout << "Finished loading " << path << std::endl;
co_return;
} }
+1 -1
View File
@@ -26,7 +26,7 @@ private:
void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics); void loadGlobalMeshes(const aiScene* scene, Array<PMesh>& globalMeshes, const Array<PMaterialAsset>& materials, Gfx::PGraphics graphics);
void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels); void convertAssimpARGB(unsigned char* dst, aiTexel* src, uint32 numPixels);
Job import(std::filesystem::path path, PMeshAsset meshAsset); void import(std::filesystem::path path, PMeshAsset meshAsset);
List<std::future<void>> futures; List<std::future<void>> futures;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
}; };
@@ -63,6 +63,7 @@ Job BasePassMeshProcessor::processMeshBatch(
collection->fragmentShader, collection->fragmentShader,
false); false);
} }
std::unique_lock lock(commandLock);
renderCommands.add(renderCommand); renderCommands.add(renderCommand);
co_return; co_return;
} }
@@ -160,6 +161,7 @@ MainJob BasePass::render()
co_await Job::all(jobs); co_await Job::all(jobs);
graphics->executeCommands(processor->getRenderCommands()); graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass(); graphics->endRenderPass();
co_return;
} }
MainJob BasePass::endFrame() MainJob BasePass::endFrame()
@@ -27,6 +27,7 @@ Job DepthPrepassMeshProcessor::processMeshBatch(
Array<Gfx::PDescriptorSet> descriptorSets, Array<Gfx::PDescriptorSet> descriptorSets,
int32 /*staticMeshId*/) int32 /*staticMeshId*/)
{ {
std::cout << "Depth job started" << std::endl;
PMaterialAsset material = batch.material; PMaterialAsset material = batch.material;
//const Gfx::MaterialShadingModel shadingModel = material->getShadingModel(); //const Gfx::MaterialShadingModel shadingModel = material->getShadingModel();
@@ -60,7 +61,9 @@ Job DepthPrepassMeshProcessor::processMeshBatch(
collection->fragmentShader, collection->fragmentShader,
true); true);
} }
std::unique_lock lock(commandLock);
renderCommands.add(renderCommand); renderCommands.add(renderCommand);
std::cout << "Finished depth job" << std::endl;
co_return; co_return;
} }
@@ -127,8 +130,10 @@ MainJob DepthPrepass::render()
jobs.add(processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets)); jobs.add(processor->processMeshBatch(meshBatch, renderPass, depthPrepassLayout, primitiveLayout, descriptorSets));
} }
co_await Job::all(jobs); co_await Job::all(jobs);
std::cout << "Finished waiting depth jobs " << std::endl;
graphics->executeCommands(processor->getRenderCommands()); graphics->executeCommands(processor->getRenderCommands());
graphics->endRenderPass(); graphics->endRenderPass();
co_return;
} }
MainJob DepthPrepass::endFrame() MainJob DepthPrepass::endFrame()
@@ -20,9 +20,7 @@ public:
int32 staticMeshId = -1) override; int32 staticMeshId = -1) override;
private: private:
//Array<Gfx::PDescriptorSet> cachedPrimitiveSets;
Gfx::PViewport target; Gfx::PViewport target;
//uint32 cachedPrimitiveIndex;
}; };
DEFINE_REF(DepthPrepassMeshProcessor) DEFINE_REF(DepthPrepassMeshProcessor)
DECLARE_REF(CameraActor) DECLARE_REF(CameraActor)
@@ -38,6 +38,7 @@ protected:
Gfx::PGeometryShader geometryShader, Gfx::PGeometryShader geometryShader,
Gfx::PFragmentShader fragmentShader, Gfx::PFragmentShader fragmentShader,
bool positionOnly); bool positionOnly);
std::mutex commandLock;
Array<Gfx::PRenderCommand> renderCommands; Array<Gfx::PRenderCommand> renderCommands;
}; };
} // namespace Seele } // namespace Seele
@@ -74,6 +74,7 @@ void CmdBuffer::beginRenderPass(PRenderPass newRenderPass, PFramebuffer newFrame
beginInfo.framebuffer = framebuffer->getHandle(); beginInfo.framebuffer = framebuffer->getHandle();
vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents()); vkCmdBeginRenderPass(handle, &beginInfo, renderPass->getSubpassContents());
state = State::RenderPassActive; state = State::RenderPassActive;
std::cout << "Beginning renderPass" << std::endl;
} }
void CmdBuffer::endRenderPass() void CmdBuffer::endRenderPass()
@@ -81,6 +82,7 @@ void CmdBuffer::endRenderPass()
std::unique_lock lock(handleLock); std::unique_lock lock(handleLock);
vkCmdEndRenderPass(handle); vkCmdEndRenderPass(handle);
state = State::InsideBegin; state = State::InsideBegin;
std::cout << "Ending renderPass" << std::endl;
} }
void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands) void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
@@ -88,7 +90,6 @@ void CmdBuffer::executeCommands(const Array<Gfx::PRenderCommand>& commands)
assert(state == State::RenderPassActive); assert(state == State::RenderPassActive);
if(commands.size() == 0) if(commands.size() == 0)
{ {
std::cout << "No commands!" << std::endl;
return; return;
} }
std::unique_lock lock(handleLock); std::unique_lock lock(handleLock);
+11 -4
View File
@@ -54,35 +54,42 @@ ThreadPool::~ThreadPool()
void ThreadPool::enqueueWaiting(Event &event, Promise* job) void ThreadPool::enqueueWaiting(Event &event, Promise* job)
{ {
assert(!job->done()); assert(!job->done());
assert(job->schedulable);
if(event == nullptr) if(event == nullptr)
{ {
std::unique_lock lock(jobQueueLock); std::unique_lock lock(jobQueueLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
jobQueue.add(job); jobQueue.add(job);
jobQueueCV.notify_one(); jobQueueCV.notify_one();
} }
else else
{ {
std::unique_lock lock(waitingLock); std::unique_lock lock(waitingLock);
//std::cout << "Job " << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingJobs[event].add(job); waitingJobs[event].add(job);
} }
} }
void ThreadPool::enqueueWaiting(Event &event, MainPromise* job) void ThreadPool::enqueueWaiting(Event &event, MainPromise* job)
{ {
assert(!job->done()); assert(!job->done());
assert(job->schedulable);
if(event == nullptr) if(event == nullptr)
{ {
std::unique_lock lock(mainJobLock); std::unique_lock lock(mainJobLock);
//std::cout << "Queueing job " << job->finishedEvent.name << std::endl;
mainJobs.add(job); mainJobs.add(job);
mainJobCV.notify_one(); mainJobCV.notify_one();
} }
else else
{ {
std::unique_lock lock(waitingMainLock); std::unique_lock lock(waitingMainLock);
//std::cout << job->finishedEvent.name << " waiting on event " << event.name << std::endl;
waitingMainJobs[event].add(job); waitingMainJobs[event].add(job);
} }
} }
void ThreadPool::notify(Event &event) void ThreadPool::notify(Event &event)
{ {
//std::cout << "Event " << event.name << " raised" << std::endl;
{ {
std::unique_lock lock(jobQueueLock); std::unique_lock lock(jobQueueLock);
std::unique_lock lock2(waitingLock); std::unique_lock lock2(waitingLock);
@@ -90,11 +97,11 @@ void ThreadPool::notify(Event &event)
for (auto &job : jobs) for (auto &job : jobs)
{ {
//assert(job.id != -1ull); //assert(job.id != -1ull);
//std::cout << "Waking up job " << job.id << std::endl; //std::cout << "Waking up " << job->finishedEvent.name << std::endl;
jobQueue.add(job); jobQueue.add(job);
jobQueueCV.notify_one(); jobQueueCV.notify_one();
} }
jobs.clear(); waitingJobs.erase(event);
} }
{ {
std::unique_lock lock(mainJobLock); std::unique_lock lock(mainJobLock);
@@ -103,11 +110,11 @@ void ThreadPool::notify(Event &event)
for (auto &job : jobs) for (auto &job : jobs)
{ {
//assert(job.id != -1ull); //assert(job.id != -1ull);
//std::cout << "Waking up main job " << job.id << std::endl; //std::cout << "Waking up main " << job->finishedEvent.name << std::endl;
mainJobs.add(job); mainJobs.add(job);
mainJobCV.notify_one(); mainJobCV.notify_one();
} }
jobs.clear(); waitingMainJobs.erase(event);
} }
} }
void ThreadPool::threadLoop(const bool mainThread) void ThreadPool::threadLoop(const bool mainThread)
+14 -19
View File
@@ -74,6 +74,7 @@ struct JobPromiseBase
if(handle && !handle.done()) if(handle && !handle.done())
{ {
handle.resume(); handle.resume();
schedulable = true;
} }
} }
void setContinuation(JobPromiseBase* cont) void setContinuation(JobPromiseBase* cont)
@@ -99,16 +100,22 @@ struct JobPromiseBase
} }
void enqueue(Event& event) void enqueue(Event& event)
{ {
if(!handle || handle.done() || !schedulable)
{
return;
}
getGlobalThreadPool().enqueueWaiting(event, this); getGlobalThreadPool().enqueueWaiting(event, this);
schedulable = false;
} }
void schedule() void schedule()
{ {
std::unique_lock lock(promiseLock); std::unique_lock lock(promiseLock);
if(!handle || handle.done()) if(!handle || handle.done() || !schedulable)
{ {
return; return;
} }
getGlobalThreadPool().enqueueWaiting(precondition, this); getGlobalThreadPool().enqueueWaiting(precondition, this);
schedulable = false;
} }
std::mutex promiseLock; std::mutex promiseLock;
@@ -117,6 +124,7 @@ struct JobPromiseBase
uint64 id; uint64 id;
Event finishedEvent; Event finishedEvent;
Event precondition = nullptr; Event precondition = nullptr;
bool schedulable = true;
}; };
template<bool MainJob = false> template<bool MainJob = false>
@@ -145,14 +153,14 @@ public:
promise->resume(); promise->resume();
} }
template<std::invocable Callable> template<std::invocable Callable>
inline JobBase then(Callable callable) inline JobBase&& then(Callable callable)
{ {
return then(callable()); return then(callable());
} }
JobBase then(JobBase&& continuation) JobBase&& then(JobBase&& continuation)
{ {
promise->setContinuation(continuation.promise); promise->setContinuation(continuation.promise);
return continuation; return std::move(continuation);
} }
bool done() bool done()
{ {
@@ -168,7 +176,6 @@ public:
} }
Event operator co_await() Event operator co_await()
{ {
promise->resume();
return promise->finishedEvent; return promise->finishedEvent;
} }
static JobBase all() = delete; static JobBase all() = delete;
@@ -230,10 +237,10 @@ private:
std::mutex jobQueueLock; std::mutex jobQueueLock;
std::condition_variable jobQueueCV; std::condition_variable jobQueueCV;
Map<Event, List<MainPromise*>> waitingMainJobs; std::map<Event, List<MainPromise*>> waitingMainJobs;
std::mutex waitingMainLock; std::mutex waitingMainLock;
Map<Event, List<Promise*>> waitingJobs; std::map<Event, List<Promise*>> waitingJobs;
std::mutex waitingLock; std::mutex waitingLock;
}; };
@@ -246,18 +253,6 @@ inline JobBase<MainJob> JobPromiseBase<MainJob>::get_return_object() noexcept
template<bool MainJob> template<bool MainJob>
inline auto JobPromiseBase<MainJob>::initial_suspend() noexcept inline auto JobPromiseBase<MainJob>::initial_suspend() noexcept
{ {
/*struct JobAwaitable
{
constexpr bool await_ready() { return false; }
constexpr void await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h)
{
getGlobalThreadPool().addJob(std::move(JobBase<MainJob>(h, id, event)));
}
constexpr void await_resume() {}
uint64 id;
Event& event;
};
return JobAwaitable{id, finishedEvent};*/
return std::suspend_always{}; return std::suspend_always{};
} }
template<bool MainJob> template<bool MainJob>
+5 -8
View File
@@ -40,14 +40,11 @@ void InspectorView::prepareRender()
MainJob InspectorView::render() MainJob InspectorView::render()
{ {
return uiPass.beginFrame() co_await uiPass.beginFrame();
.then(uiPass.render()) co_await uiPass.render();
.then(uiPass.endFrame()) co_await uiPass.endFrame();
.then([=]() -> MainJob renderFinishedEvent.raise();
{ co_return;
renderFinishedEvent.raise();
co_return;
});
} }
void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier) void InspectorView::keyCallback(KeyCode, InputAction, KeyModifier)
+11 -14
View File
@@ -84,20 +84,17 @@ void SceneView::prepareRender()
MainJob SceneView::render() MainJob SceneView::render()
{ {
return depthPrepass.beginFrame() co_await depthPrepass.beginFrame();
.then(lightCullingPass.beginFrame()) co_await lightCullingPass.beginFrame();
.then(basePass.beginFrame()) co_await basePass.beginFrame();
.then(depthPrepass.render()) co_await depthPrepass.render();
.then(lightCullingPass.render()) co_await lightCullingPass.render();
.then(basePass.render()) co_await basePass.render();
.then(depthPrepass.endFrame()) co_await depthPrepass.endFrame();
.then(lightCullingPass.endFrame()) co_await lightCullingPass.endFrame();
.then(basePass.endFrame()) co_await basePass.endFrame();
.then([&](Event& event) -> MainJob renderFinishedEvent.raise();
{ co_return;
event.raise();
co_return;
}(renderFinishedEvent));
} }
void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier) void SceneView::keyCallback(KeyCode code, InputAction action, KeyModifier)
+3 -1
View File
@@ -1,8 +1,10 @@
target_sources(Seele_unit_tests target_sources(Seele_unit_tests
PRIVATE PRIVATE
../../src/Engine/MinimalEngine.cpp ../../src/Engine/MinimalEngine.cpp
../../src/Engine/ThreadPool.cpp
EngineTest.h EngineTest.h
EngineTest.cpp) EngineTest.cpp
ThreadPool.cpp)
target_include_directories(Seele_unit_tests PUBLIC ./) target_include_directories(Seele_unit_tests PUBLIC ./)
add_subdirectory(Containers/) add_subdirectory(Containers/)
add_subdirectory(Graphics/) add_subdirectory(Graphics/)
+74
View File
@@ -0,0 +1,74 @@
#include "EngineTest.h"
#include "ThreadPool.h"
#include <boost/test/unit_test.hpp>
BOOST_AUTO_TEST_SUITE(ThreadPool)
uint64 basicJobState = 0;
Job basicThenFirst()
{
basicJobState = 10;
co_return;
}
Job basicThenSecond()
{
BOOST_REQUIRE_EQUAL(basicJobState, 10);
basicJobState = 20;
co_return;
}
Job basicThenThird()
{
BOOST_REQUIRE_EQUAL(basicJobState, 20);
co_return;
}
BOOST_AUTO_TEST_CASE(basic_then)
{
basicThenFirst()
.then(basicThenSecond())
.then(basicThenThird());
}
uint64 basicAllState1 = 0;
uint64 basicAllState2 = 0;
Job basicAllFirst()
{
basicAllState1 = 10;
co_return;
}
Job basicAllSecond()
{
basicAllState2 = 10;
co_return;
}
Job basicAllThen()
{
BOOST_REQUIRE_EQUAL(basicAllState1, 10);
BOOST_REQUIRE_EQUAL(basicAllState2, 10);
co_return;
}
BOOST_AUTO_TEST_CASE(basic_all)
{
Job::all(basicAllFirst(), basicAllSecond()).then(basicAllThen());
}
uint64 basicCallable = 0;
Job basicCallableFunc()
{
basicCallable = 10;
co_return;
}
BOOST_AUTO_TEST_CASE(basic_callable)
{
basicCallableFunc()
.then([=]() -> Job{
BOOST_REQUIRE_EQUAL(basicCallable, 10);
co_return;
});
}
BOOST_AUTO_TEST_SUITE_END()