coroutines truly are cursed

This commit is contained in:
2021-11-11 20:12:50 +01:00
parent 1848bb5139
commit 01049019fd
25 changed files with 202 additions and 92 deletions
+1 -1
View File
@@ -104,7 +104,7 @@ void AssetRegistry::importTexture(const std::filesystem::path &filePath)
void AssetRegistry::importMaterial(const std::filesystem::path &filePath) void AssetRegistry::importMaterial(const std::filesystem::path &filePath)
{ {
materialLoader->queueAsset(filePath); materialLoader->importAsset(filePath);
} }
void AssetRegistry::registerMesh(PMeshAsset mesh) void AssetRegistry::registerMesh(PMeshAsset mesh)
+15 -8
View File
@@ -17,15 +17,22 @@ MaterialLoader::~MaterialLoader()
{ {
} }
PMaterialAsset MaterialLoader::queueAsset(const std::filesystem::path& filePath) void MaterialLoader::importAsset(const std::filesystem::path& name)
{ {
PMaterialAsset result = new MaterialAsset(filePath); std::filesystem::path assetPath = name.filename();
result->load(); assetPath.replace_extension("asset");
graphics->getShaderCompiler()->registerMaterial(result); PMaterialAsset asset = new MaterialAsset(assetPath.generic_string());
AssetRegistry::get().registerMaterial(result); asset->setStatus(Asset::Status::Loading);
// TODO: There is actually no real reason to import a standalone material, AssetRegistry::get().registerMaterial(asset);
// maybe in the future there could be a substance loader or something import(name, asset);
return result; }
Job MaterialLoader::import(std::filesystem::path, PMaterialAsset asset)
{
asset->load();
graphics->getShaderCompiler()->registerMaterial(asset);
AssetRegistry::get().registerMaterial(asset);
co_return;
} }
PMaterialAsset MaterialLoader::getPlaceHolderMaterial() PMaterialAsset MaterialLoader::getPlaceHolderMaterial()
+3 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Containers/List.h" #include "Containers/List.h"
#include "ThreadPool.h"
#include <thread> #include <thread>
#include <future> #include <future>
#include <filesystem> #include <filesystem>
@@ -14,9 +15,10 @@ class MaterialLoader
public: public:
MaterialLoader(Gfx::PGraphics graphic); MaterialLoader(Gfx::PGraphics graphic);
~MaterialLoader(); ~MaterialLoader();
PMaterialAsset queueAsset(const std::filesystem::path& filePath); void importAsset(const std::filesystem::path& name);
PMaterialAsset getPlaceHolderMaterial(); PMaterialAsset getPlaceHolderMaterial();
private: private:
Job import(std::filesystem::path filePath, PMaterialAsset asset);
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
List<std::future<void>> futures; List<std::future<void>> futures;
PMaterialAsset placeholderMaterial; PMaterialAsset placeholderMaterial;
+6 -4
View File
@@ -30,9 +30,10 @@ void MeshLoader::importAsset(const std::filesystem::path &path)
{ {
std::filesystem::path assetPath = path.filename(); std::filesystem::path assetPath = path.filename();
assetPath.replace_extension("asset"); assetPath.replace_extension("asset");
PMeshAsset meshAsset = new MeshAsset(assetPath.generic_string()); PMeshAsset asset = new MeshAsset(assetPath.generic_string());
AssetRegistry::get().registerMesh(meshAsset); asset->setStatus(Asset::Status::Loading);
futures.add(std::async(std::launch::async, &MeshLoader::import, this, meshAsset, path)); AssetRegistry::get().registerMesh(asset);
import(path, asset);
} }
void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics) void MeshLoader::loadMaterials(const aiScene* scene, Array<PMaterialAsset>& globalMaterials, Gfx::PGraphics graphics)
@@ -228,7 +229,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path&
AssetRegistry::importFile(texPngPath.string()); AssetRegistry::importFile(texPngPath.string());
} }
} }
void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path) Job 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);
@@ -263,4 +264,5 @@ void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path)
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;
} }
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Containers/List.h" #include "Containers/List.h"
#include "ThreadPool.h"
#include <thread> #include <thread>
#include <future> #include <future>
#include <filesystem> #include <filesystem>
@@ -25,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);
void import(PMeshAsset meshAsset, const std::filesystem::path& path); Job import(std::filesystem::path path, PMeshAsset meshAsset);
List<std::future<void>> futures; List<std::future<void>> futures;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
}; };
+10 -11
View File
@@ -22,20 +22,15 @@ TextureLoader::~TextureLoader()
{ {
} }
void TextureLoader::importAsset(const std::filesystem::path& filePath) void TextureLoader::importAsset(const std::filesystem::path& path)
{ {
auto assetFileName = filePath; std::filesystem::path assetPath = path.filename();
PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string()); assetPath.replace_extension("asset");
PTextureAsset asset = new TextureAsset(assetPath.generic_string());
asset->setStatus(Asset::Status::Loading); asset->setStatus(Asset::Status::Loading);
asset->setTexture(placeholderAsset->getTexture()); asset->setTexture(placeholderAsset->getTexture());
AssetRegistry::get().registerTexture(asset); AssetRegistry::get().registerTexture(asset);
futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { import(path, asset);
using namespace std::chrono_literals;
//std::this_thread::sleep_for(5s);
import(filePath, asset);
asset->load();
asset->setStatus(Asset::Status::Ready);
}));
} }
PTextureAsset TextureLoader::getPlaceholderTexture() PTextureAsset TextureLoader::getPlaceholderTexture()
@@ -43,7 +38,7 @@ PTextureAsset TextureLoader::getPlaceholderTexture()
return placeholderAsset; return placeholderAsset;
} }
void TextureLoader::import(const std::filesystem::path& path, PTextureAsset textureAsset) Job TextureLoader::import(std::filesystem::path path, PTextureAsset textureAsset)
{ {
int x, y, n; int x, y, n;
unsigned char* data = stbi_load(path.string().c_str(), &x, &y, &n, 4); unsigned char* data = stbi_load(path.string().c_str(), &x, &y, &n, 4);
@@ -72,4 +67,8 @@ void TextureLoader::import(const std::filesystem::path& path, PTextureAsset text
ktxTexture_WriteToNamedFile(ktxTexture(kTexture), textureAsset->getFullPath().c_str()); ktxTexture_WriteToNamedFile(ktxTexture(kTexture), textureAsset->getFullPath().c_str());
ktxTexture_Destroy(ktxTexture(kTexture)); ktxTexture_Destroy(ktxTexture(kTexture));
textureAsset->load();
textureAsset->setStatus(Asset::Status::Ready);
co_return;
} }
+2 -1
View File
@@ -1,6 +1,7 @@
#pragma once #pragma once
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Containers/List.h" #include "Containers/List.h"
#include "ThreadPool.h"
#include <thread> #include <thread>
#include <future> #include <future>
#include <filesystem> #include <filesystem>
@@ -18,7 +19,7 @@ public:
void importAsset(const std::filesystem::path& filePath); void importAsset(const std::filesystem::path& filePath);
PTextureAsset getPlaceholderTexture(); PTextureAsset getPlaceholderTexture();
private: private:
void import(const std::filesystem::path& path, PTextureAsset asset); Job import(std::filesystem::path path, PTextureAsset asset);
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
List<std::future<void>> futures; List<std::future<void>> futures;
PTextureAsset placeholderAsset; PTextureAsset placeholderAsset;
+14
View File
@@ -246,6 +246,20 @@ public:
_size++; _size++;
return insertedElement; return insertedElement;
} }
// takes all elements from other and move-inserts them into
// this, clearing other in the process
void moveElements(List& other){
tail->prev->next = other.root;
other.root->prev = tail->prev;
_size += other._size;
deallocateNode(tail);
tail = other.tail;
other._size = 0;
other.root = nullptr;
other.tail = nullptr;
markIteratorDirty();
other.markIteratorDirty();
}
template<typename... args> template<typename... args>
constexpr reference emplace(args... arguments) constexpr reference emplace(args... arguments)
{ {
+1 -1
View File
@@ -1,6 +1,6 @@
#pragma once #pragma once
#include <utility> #include <utility>
#include "List.h" #include "Array.h"
namespace Seele namespace Seele
{ {
+1 -1
View File
@@ -51,7 +51,7 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags u
memRequirements.pNext = &dedicatedRequirements; memRequirements.pNext = &dedicatedRequirements;
for (uint32 i = 0; i < numBuffers; ++i) for (uint32 i = 0; i < numBuffers; ++i)
{ {
vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer); VK_CHECK(vkCreateBuffer(graphics->getDevice(), &info, nullptr, &buffers[i].buffer));
bufferReqInfo.buffer = buffers[i].buffer; bufferReqInfo.buffer = buffers[i].buffer;
vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements); vkGetBufferMemoryRequirements2(graphics->getDevice(), &bufferReqInfo, &memRequirements);
auto temp = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer); auto temp = graphics->getAllocator()->allocate(memRequirements, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT, buffers[i].buffer);
+9 -18
View File
@@ -2,7 +2,6 @@
#include "Containers/Map.h" #include "Containers/Map.h"
#include "EngineTypes.h" #include "EngineTypes.h"
#include "Math/Math.h" #include "Math/Math.h"
//#include "ThreadPool.h"
#define DEFINE_REF(x) \ #define DEFINE_REF(x) \
typedef RefPtr<x> P##x; \ typedef RefPtr<x> P##x; \
@@ -80,23 +79,19 @@ public:
} }
return *this; return *this;
} }
inline bool operator==(const RefObject &other) const bool operator==(const RefObject &rhs) const
{ {
return handle == other.handle; return handle == rhs.handle;
} }
inline bool operator!=(const RefObject &other) const auto operator<=>(const RefObject& rhs) const
{ {
return handle != other.handle; return handle <=> rhs.handle;
}
inline bool operator<(const RefObject &other) const
{
return handle < other.handle;
} }
void addRef() void addRef()
{ {
refCount++; refCount++;
} }
inline void removeRef() void removeRef()
{ {
refCount--; refCount--;
if (refCount == 0) if (refCount == 0)
@@ -235,17 +230,13 @@ public:
object->removeRef(); object->removeRef();
} }
} }
inline bool operator==(const RefPtr &other) const bool operator==(const RefPtr& rhs) const
{ {
return object == other.object; return object == rhs.object;
} }
inline bool operator!=(const RefPtr &other) const auto operator<=>(const RefPtr &rhs) const
{ {
return object != other.object; return object <=> rhs.object;
}
bool operator<(const RefPtr &other) const
{
return object < other.object;
} }
inline T *operator->() inline T *operator->()
{ {
-2
View File
@@ -14,12 +14,10 @@ Actor::~Actor()
} }
void Actor::tick(float deltaTime) void Actor::tick(float deltaTime)
{ {
addWorldRotation(glm::vec3(0, 1 * deltaTime, 0));
} }
void Actor::notifySceneAttach(PScene scene) void Actor::notifySceneAttach(PScene scene)
{ {
owningScene = scene; owningScene = scene;
scene->getSceneUpdater()->registerActorUpdate(this);
rootComponent->notifySceneAttach(scene); rootComponent->notifySceneAttach(scene);
for(auto child : children) for(auto child : children)
{ {
+1 -3
View File
@@ -1,9 +1,7 @@
target_sources(SeeleEngine target_sources(SeeleEngine
PRIVATE PRIVATE
Scene.cpp Scene.cpp
Scene.h Scene.h)
SceneUpdater.h
SceneUpdater.cpp)
add_subdirectory(Actor/) add_subdirectory(Actor/)
add_subdirectory(Components/) add_subdirectory(Components/)
@@ -36,7 +36,6 @@ PActor Component::getOwner()
void Component::notifySceneAttach(PScene scene) void Component::notifySceneAttach(PScene scene)
{ {
owningScene = scene; owningScene = scene;
scene->getSceneUpdater()->registerComponentUpdate(this);
for (auto child : children) for (auto child : children)
{ {
child->notifySceneAttach(scene); child->notifySceneAttach(scene);
-2
View File
@@ -13,7 +13,6 @@ inline float frand()
Scene::Scene(Gfx::PGraphics graphics) Scene::Scene(Gfx::PGraphics graphics)
: graphics(graphics) : graphics(graphics)
, updater(new SceneUpdater())
{ {
lightEnv.directionalLights[0].color = Vector4(1, 1, 1, 1); lightEnv.directionalLights[0].color = Vector4(1, 1, 1, 1);
lightEnv.directionalLights[0].direction = Vector4(1, 1, 0, 1); lightEnv.directionalLights[0].direction = Vector4(1, 1, 0, 1);
@@ -36,7 +35,6 @@ Scene::~Scene()
void Scene::tick(double deltaTime) void Scene::tick(double deltaTime)
{ {
updater->runUpdates(static_cast<float>(deltaTime));
for(auto &&meshBatch : staticMeshes) for(auto &&meshBatch : staticMeshes)
{ {
meshBatch.material->updateDescriptorData(); meshBatch.material->updateDescriptorData();
-3
View File
@@ -4,7 +4,6 @@
#include "Graphics/GraphicsResources.h" #include "Graphics/GraphicsResources.h"
#include "Components/PrimitiveComponent.h" #include "Components/PrimitiveComponent.h"
#include "Graphics/MeshBatch.h" #include "Graphics/MeshBatch.h"
#include "SceneUpdater.h"
namespace Seele namespace Seele
{ {
@@ -46,13 +45,11 @@ public:
const Array<PPrimitiveComponent>& getPrimitives() const { return primitives; } const Array<PPrimitiveComponent>& getPrimitives() const { return primitives; }
const Array<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; } const Array<StaticMeshBatch>& getStaticMeshes() const { return staticMeshes; }
const LightEnv& getLightBuffer() const { return lightEnv; } const LightEnv& getLightBuffer() const { return lightEnv; }
UPSceneUpdater& getSceneUpdater() { return updater; }
private: private:
Array<StaticMeshBatch> staticMeshes; Array<StaticMeshBatch> staticMeshes;
Array<PActor> rootActors; Array<PActor> rootActors;
Array<PPrimitiveComponent> primitives; Array<PPrimitiveComponent> primitives;
LightEnv lightEnv; LightEnv lightEnv;
Gfx::PGraphics graphics; Gfx::PGraphics graphics;
UPSceneUpdater updater;
}; };
} // namespace Seele } // namespace Seele
+1 -1
View File
@@ -2,7 +2,7 @@
#include "MinimalEngine.h" #include "MinimalEngine.h"
#include "Containers/List.h" #include "Containers/List.h"
#include <semaphore> #include <semaphore>
//DEPRECATED
namespace Seele namespace Seele
{ {
DECLARE_REF(Component); DECLARE_REF(Component);
+34 -10
View File
@@ -46,42 +46,53 @@ ThreadPool::~ThreadPool()
void ThreadPool::addJob(Job&& job) void ThreadPool::addJob(Job&& job)
{ {
std::unique_lock lock(jobQueueLock); std::unique_lock lock(jobQueueLock);
jobQueue.add(job); //std::cout << "Adding job " << job << std::endl;
jobQueue.add(std::move(job));
jobQueueCV.notify_one();
} }
void ThreadPool::addJob(MainJob&& job) void ThreadPool::addJob(MainJob&& job)
{ {
std::unique_lock lock(mainJobLock); std::unique_lock lock(mainJobLock);
mainJobs.add(job); //std::cout << "Adding main job " << job << 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 << " waiting for event " << event->name << std::endl;
std::unique_lock lock(waitingLock); 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 << " main waiting for event " << event->name << std::endl;
std::unique_lock lock(waitingMainLock); 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 lock(jobQueueLock);
std::unique_lock lock2(waitingLock); std::unique_lock lock2(waitingLock);
for(auto&& job : waitingJobs[event]) for(Job& job : waitingJobs[*event])
{ {
jobQueue.add(job); //std::cout << "Waking up job " << job << std::endl;
jobQueue.add(std::move(job));
jobQueueCV.notify_one();
} }
waitingJobs[event].clear(); waitingJobs[*event].clear();
} }
{ {
std::unique_lock lock(mainJobLock); std::unique_lock lock(mainJobLock);
std::unique_lock lock2(waitingMainLock); std::unique_lock lock2(waitingMainLock);
for(auto&& job : waitingMainJobs[event]) auto&& jobsToQueue = std::move(waitingMainJobs[*event]);
waitingMainJobs.erase(*event);
for(MainJob& job : jobsToQueue)
{ {
mainJobs.add(job); //std::cout << "Waking up main job " << job << std::endl;
mainJobs.add(std::move(job));
mainJobCV.notify_one();
} }
waitingMainJobs[event].clear();
} }
event->reset(); event->reset();
} }
@@ -95,9 +106,22 @@ void ThreadPool::threadLoop(const bool mainThread)
if(!mainJobs.empty()) if(!mainJobs.empty())
{ {
MainJob&& job = mainJobs.retrieve(); MainJob&& job = mainJobs.retrieve();
lock.unlock();
job.resume(); job.resume();
} }
} }
std::unique_lock lock(jobQueueLock);
if(jobQueue.empty())
{
jobQueueCV.wait(lock);
}
if(!jobQueue.empty())
{
Job&& job = jobQueue.retrieve();
lock.unlock();
//std::cout << "Starting job " << job << std::endl;
job.resume();
}
} }
} }
+51 -6
View File
@@ -30,16 +30,49 @@ struct JobBase
public: public:
using promise_type = JobPromiseBase<MainJob>; using promise_type = JobPromiseBase<MainJob>;
explicit JobBase()
{}
explicit JobBase(std::coroutine_handle<promise_type> handle) explicit JobBase(std::coroutine_handle<promise_type> handle)
: handle(handle) : handle(handle)
{} {
std::cout << "Creating job " << handle.address() << std::endl;
}
JobBase(const JobBase & rhs) = delete;
JobBase(JobBase&& rhs)
: handle(std::move(rhs.handle))
{
rhs.handle = nullptr;
}
~JobBase() ~JobBase()
{ {
if(handle) if(handle)
{ {
std::cout << "Destroying job " << handle.address() << std::endl;
handle.destroy(); handle.destroy();
} }
} }
JobBase& operator=(const JobBase& rhs) = delete;
JobBase& operator=(JobBase&& rhs)
{
if(this != &rhs)
{
handle = std::move(rhs.handle);
rhs.handle = nullptr;
}
return *this;
}
friend std::basic_ostream<char>& operator<<(std::basic_ostream<char>& stream, const JobBase& obj)
{
if (obj.handle == nullptr)
{
stream << nullptr;
}
else
{
stream << obj.handle.address();
}
return stream;
}
void resume() void resume()
{ {
handle.resume(); handle.resume();
@@ -56,6 +89,15 @@ struct Event
public: public:
Event(); Event();
Event(const std::string& name); Event(const std::string& name);
auto operator<=>(const Event& other) const
{
return name <=> other.name;
}
Event operator co_await()
{
return *this;
}
void raise(); void raise();
void reset(); void reset();
bool await_ready(); bool await_ready();
@@ -65,6 +107,7 @@ public:
private: private:
std::string name; std::string name;
RefPtr<std::atomic_bool> flag; RefPtr<std::atomic_bool> flag;
friend class ThreadPool;
}; };
class ThreadPool class ThreadPool
@@ -84,14 +127,16 @@ private:
List<MainJob> mainJobs; List<MainJob> mainJobs;
std::mutex mainJobLock; std::mutex mainJobLock;
std::condition_variable mainJobCV;
List<Job> jobQueue; List<Job> jobQueue;
std::mutex jobQueueLock; std::mutex jobQueueLock;
std::condition_variable jobQueueCV;
Map<Event*, List<Job>> waitingJobs; Map<Event, List<Job>> waitingJobs;
std::mutex waitingLock; std::mutex waitingLock;
Map<Event*, List<MainJob>> waitingMainJobs; Map<Event, List<MainJob>> waitingMainJobs;
std::mutex waitingMainLock; std::mutex waitingMainLock;
void threadLoop(const bool isMainThread); void threadLoop(const bool isMainThread);
@@ -100,7 +145,7 @@ private:
template<bool MainJob> template<bool MainJob>
inline JobBase<MainJob> JobPromiseBase<MainJob>::get_return_object() noexcept { inline JobBase<MainJob> JobPromiseBase<MainJob>::get_return_object() noexcept {
return JobBase<MainJob> { std::coroutine_handle<JobPromiseBase<MainJob>>::from_promise(*this) }; return JobBase<MainJob>();
} }
template<bool MainJob> template<bool MainJob>
@@ -111,7 +156,7 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() const noexcept
constexpr bool await_ready() { return false; } constexpr bool await_ready() { return false; }
constexpr void await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h) constexpr void await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h)
{ {
getGlobalThreadPool().addJob(JobBase<MainJob>(h)); getGlobalThreadPool().addJob(std::move(JobBase<MainJob>(h)));
} }
constexpr void await_resume() {} constexpr void await_resume() {}
}; };
@@ -121,7 +166,7 @@ inline auto JobPromiseBase<MainJob>::initial_suspend() const noexcept
template<bool MainJob> template<bool MainJob>
inline constexpr void Event::await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h) inline constexpr void Event::await_suspend(std::coroutine_handle<JobPromiseBase<MainJob>> h)
{ {
getGlobalThreadPool().enqueueWaiting(this, JobBase<MainJob>(h)); getGlobalThreadPool().enqueueWaiting(this, std::move(JobBase<MainJob>(h)));
} }
} // namespace Seele } // namespace Seele
+17 -12
View File
@@ -18,8 +18,10 @@ void Window::addView(PView view)
{ {
WindowView* windowView = new WindowView(); WindowView* windowView = new WindowView();
windowView->view = view; windowView->view = view;
windowView->updateFinished = Event("test");
//windowView->worker = std::thread(&Window::viewWorker, this, windowView); //windowView->worker = std::thread(&Window::viewWorker, this, windowView);
views.add(windowView); views.add(windowView);
viewWorker(views.size() - 1);
} }
MainJob Window::render() MainJob Window::render()
@@ -27,8 +29,8 @@ MainJob Window::render()
gfxHandle->beginFrame(); gfxHandle->beginFrame();
for(auto& windowView : views) for(auto& windowView : views)
{ {
viewWorker(windowView);
co_await windowView->updateFinished; co_await windowView->updateFinished;
std::cout << "view update finished" << std::endl;
{ {
std::unique_lock lock(windowView->workerMutex); std::unique_lock lock(windowView->workerMutex);
windowView->view->prepareRender(); windowView->view->prepareRender();
@@ -36,6 +38,8 @@ MainJob Window::render()
windowView->view->render(); windowView->view->render();
} }
gfxHandle->endFrame(); gfxHandle->endFrame();
//Enqueue a new render main job
render();
} }
Gfx::PWindow Window::getGfxHandle() Gfx::PWindow Window::getGfxHandle()
@@ -60,17 +64,18 @@ void Window::setFocused(PView view)
}); });
} }
Job Window::viewWorker(size_t viewIndex)
Job Window::viewWorker(WindowView* windowView)
{ {
while(true) WindowView* windowView = views[viewIndex];
windowView->view->beginUpdate();
windowView->view->update();
{ {
windowView->view->beginUpdate(); std::unique_lock lock(windowView->workerMutex);
windowView->view->update(); windowView->view->commitUpdate();
{
std::unique_lock lock(windowView->workerMutex);
windowView->view->commitUpdate();
}
windowView->updateFinished.raise();
} }
std::cout << "Update completed" << std::endl;
windowView->updateFinished.raise();
// enqueue next frame update
viewWorker(viewIndex);
co_return;
} }
+1 -1
View File
@@ -29,7 +29,7 @@ protected:
Array<WindowView*> views; Array<WindowView*> views;
Gfx::PWindow gfxHandle; Gfx::PWindow gfxHandle;
Job viewWorker(WindowView* view); Job viewWorker(size_t viewIndex);
}; };
DEFINE_REF(Window) DEFINE_REF(Window)
} // namespace Seele } // namespace Seele
+5
View File
@@ -39,4 +39,9 @@ PWindow WindowManager::addWindow(const WindowCreateInfo &createInfo)
void WindowManager::notifyWindowClosed(PWindow window) void WindowManager::notifyWindowClosed(PWindow window)
{ {
windows.remove(windows.find(window)); windows.remove(windows.find(window));
if(windows.empty())
{
std::unique_lock lock(windowsLock);
windowsCV.notify_all();
}
} }
+8
View File
@@ -11,6 +11,7 @@ class WindowManager
public: public:
WindowManager(); WindowManager();
~WindowManager(); ~WindowManager();
Job init();
PWindow addWindow(const WindowCreateInfo &createInfo); PWindow addWindow(const WindowCreateInfo &createInfo);
void notifyWindowClosed(PWindow window); void notifyWindowClosed(PWindow window);
static Gfx::PGraphics getGraphics() static Gfx::PGraphics getGraphics()
@@ -21,9 +22,16 @@ public:
{ {
return windows.size(); return windows.size();
} }
void waitForCompletion()
{
std::unique_lock lock(windowsLock);
windowsCV.wait(lock);
}
private: private:
Array<PWindow> windows; Array<PWindow> windows;
std::mutex windowsLock;
std::condition_variable windowsCV;
static Gfx::PGraphics graphics; static Gfx::PGraphics graphics;
}; };
DEFINE_REF(WindowManager) DEFINE_REF(WindowManager)
+2 -4
View File
@@ -34,9 +34,7 @@ int main()
PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo); PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo);
window->addView(inspectorView); window->addView(inspectorView);
sceneView->setFocused(); sceneView->setFocused();
while(windowManager->isActive()) window->render();
{ windowManager->waitForCompletion();
window->render();
}
return 0; return 0;
} }
+18
View File
@@ -40,4 +40,22 @@ BOOST_AUTO_TEST_CASE(basic_remove)
BOOST_REQUIRE_EQUAL(list.size(), 2); BOOST_REQUIRE_EQUAL(list.size(), 2);
} }
BOOST_AUTO_TEST_CASE(list_join)
{
List<int> list1;
List<int> list2;
list1.add(2);
list1.add(1);
list1.add(3);
list1.add(4);
list2.add(5);
list2.add(7);
list2.add(8);
list2.add(6);
list2.add(9);
list1.moveElements(list2);
BOOST_REQUIRE_EQUAL(list1.size(), 9);
BOOST_REQUIRE_EQUAL(list2.size(), 0);
}
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()