diff --git a/src/Engine/Asset/AssetRegistry.cpp b/src/Engine/Asset/AssetRegistry.cpp index 5287ce2..f316225 100644 --- a/src/Engine/Asset/AssetRegistry.cpp +++ b/src/Engine/Asset/AssetRegistry.cpp @@ -104,7 +104,7 @@ void AssetRegistry::importTexture(const std::filesystem::path &filePath) void AssetRegistry::importMaterial(const std::filesystem::path &filePath) { - materialLoader->queueAsset(filePath); + materialLoader->importAsset(filePath); } void AssetRegistry::registerMesh(PMeshAsset mesh) diff --git a/src/Engine/Asset/MaterialLoader.cpp b/src/Engine/Asset/MaterialLoader.cpp index 6f629d8..3651146 100644 --- a/src/Engine/Asset/MaterialLoader.cpp +++ b/src/Engine/Asset/MaterialLoader.cpp @@ -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); - result->load(); - graphics->getShaderCompiler()->registerMaterial(result); - AssetRegistry::get().registerMaterial(result); - // TODO: There is actually no real reason to import a standalone material, - // maybe in the future there could be a substance loader or something - return result; + std::filesystem::path assetPath = name.filename(); + assetPath.replace_extension("asset"); + PMaterialAsset asset = new MaterialAsset(assetPath.generic_string()); + asset->setStatus(Asset::Status::Loading); + AssetRegistry::get().registerMaterial(asset); + import(name, asset); +} + +Job MaterialLoader::import(std::filesystem::path, PMaterialAsset asset) +{ + asset->load(); + graphics->getShaderCompiler()->registerMaterial(asset); + AssetRegistry::get().registerMaterial(asset); + co_return; } PMaterialAsset MaterialLoader::getPlaceHolderMaterial() diff --git a/src/Engine/Asset/MaterialLoader.h b/src/Engine/Asset/MaterialLoader.h index 1166145..99cac01 100644 --- a/src/Engine/Asset/MaterialLoader.h +++ b/src/Engine/Asset/MaterialLoader.h @@ -1,6 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "Containers/List.h" +#include "ThreadPool.h" #include #include #include @@ -14,9 +15,10 @@ class MaterialLoader public: MaterialLoader(Gfx::PGraphics graphic); ~MaterialLoader(); - PMaterialAsset queueAsset(const std::filesystem::path& filePath); + void importAsset(const std::filesystem::path& name); PMaterialAsset getPlaceHolderMaterial(); private: + Job import(std::filesystem::path filePath, PMaterialAsset asset); Gfx::PGraphics graphics; List> futures; PMaterialAsset placeholderMaterial; diff --git a/src/Engine/Asset/MeshLoader.cpp b/src/Engine/Asset/MeshLoader.cpp index 8bd70d6..a25ad29 100644 --- a/src/Engine/Asset/MeshLoader.cpp +++ b/src/Engine/Asset/MeshLoader.cpp @@ -30,9 +30,10 @@ void MeshLoader::importAsset(const std::filesystem::path &path) { std::filesystem::path assetPath = path.filename(); assetPath.replace_extension("asset"); - PMeshAsset meshAsset = new MeshAsset(assetPath.generic_string()); - AssetRegistry::get().registerMesh(meshAsset); - futures.add(std::async(std::launch::async, &MeshLoader::import, this, meshAsset, path)); + PMeshAsset asset = new MeshAsset(assetPath.generic_string()); + asset->setStatus(Asset::Status::Loading); + AssetRegistry::get().registerMesh(asset); + import(path, asset); } void MeshLoader::loadMaterials(const aiScene* scene, Array& globalMaterials, Gfx::PGraphics graphics) @@ -228,7 +229,7 @@ void MeshLoader::loadTextures(const aiScene* scene, const std::filesystem::path& 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 "<setStatus(Asset::Status::Loading); @@ -263,4 +264,5 @@ void MeshLoader::import(PMeshAsset meshAsset, const std::filesystem::path &path) meshAsset->setStatus(Asset::Status::Ready); meshAsset->save(); std::cout << "Finished loading " << path << std::endl; + co_return; } diff --git a/src/Engine/Asset/MeshLoader.h b/src/Engine/Asset/MeshLoader.h index 0c4ebc7..edae908 100644 --- a/src/Engine/Asset/MeshLoader.h +++ b/src/Engine/Asset/MeshLoader.h @@ -1,6 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "Containers/List.h" +#include "ThreadPool.h" #include #include #include @@ -25,7 +26,7 @@ private: void loadGlobalMeshes(const aiScene* scene, Array& globalMeshes, const Array& materials, Gfx::PGraphics graphics); 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> futures; Gfx::PGraphics graphics; }; diff --git a/src/Engine/Asset/TextureLoader.cpp b/src/Engine/Asset/TextureLoader.cpp index ac23c07..d030cd6 100644 --- a/src/Engine/Asset/TextureLoader.cpp +++ b/src/Engine/Asset/TextureLoader.cpp @@ -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; - PTextureAsset asset = new TextureAsset(assetFileName.replace_extension("asset").filename().generic_string()); + std::filesystem::path assetPath = path.filename(); + assetPath.replace_extension("asset"); + PTextureAsset asset = new TextureAsset(assetPath.generic_string()); asset->setStatus(Asset::Status::Loading); asset->setTexture(placeholderAsset->getTexture()); AssetRegistry::get().registerTexture(asset); - futures.add(std::async(std::launch::async, [this, filePath, asset] () mutable { - using namespace std::chrono_literals; - //std::this_thread::sleep_for(5s); - import(filePath, asset); - asset->load(); - asset->setStatus(Asset::Status::Ready); - })); + import(path, asset); } PTextureAsset TextureLoader::getPlaceholderTexture() @@ -43,7 +38,7 @@ PTextureAsset TextureLoader::getPlaceholderTexture() 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; 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_Destroy(ktxTexture(kTexture)); + + textureAsset->load(); + textureAsset->setStatus(Asset::Status::Ready); + co_return; } \ No newline at end of file diff --git a/src/Engine/Asset/TextureLoader.h b/src/Engine/Asset/TextureLoader.h index addf294..c268869 100644 --- a/src/Engine/Asset/TextureLoader.h +++ b/src/Engine/Asset/TextureLoader.h @@ -1,6 +1,7 @@ #pragma once #include "MinimalEngine.h" #include "Containers/List.h" +#include "ThreadPool.h" #include #include #include @@ -18,7 +19,7 @@ public: void importAsset(const std::filesystem::path& filePath); PTextureAsset getPlaceholderTexture(); private: - void import(const std::filesystem::path& path, PTextureAsset asset); + Job import(std::filesystem::path path, PTextureAsset asset); Gfx::PGraphics graphics; List> futures; PTextureAsset placeholderAsset; diff --git a/src/Engine/Containers/List.h b/src/Engine/Containers/List.h index 63e96fa..6197ed8 100644 --- a/src/Engine/Containers/List.h +++ b/src/Engine/Containers/List.h @@ -246,6 +246,20 @@ public: _size++; 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 constexpr reference emplace(args... arguments) { diff --git a/src/Engine/Containers/Map.h b/src/Engine/Containers/Map.h index 7a8de4c..1dc7d53 100644 --- a/src/Engine/Containers/Map.h +++ b/src/Engine/Containers/Map.h @@ -1,6 +1,6 @@ #pragma once #include -#include "List.h" +#include "Array.h" namespace Seele { diff --git a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp index f80bf5d..75c05e2 100644 --- a/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp +++ b/src/Engine/Graphics/Vulkan/VulkanBuffer.cpp @@ -51,7 +51,7 @@ ShaderBuffer::ShaderBuffer(PGraphics graphics, uint32 size, VkBufferUsageFlags u memRequirements.pNext = &dedicatedRequirements; 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; 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); diff --git a/src/Engine/MinimalEngine.h b/src/Engine/MinimalEngine.h index e1fd69c..b9bed65 100644 --- a/src/Engine/MinimalEngine.h +++ b/src/Engine/MinimalEngine.h @@ -2,7 +2,6 @@ #include "Containers/Map.h" #include "EngineTypes.h" #include "Math/Math.h" -//#include "ThreadPool.h" #define DEFINE_REF(x) \ typedef RefPtr P##x; \ @@ -80,23 +79,19 @@ public: } 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; - } - inline bool operator<(const RefObject &other) const - { - return handle < other.handle; + return handle <=> rhs.handle; } void addRef() { refCount++; } - inline void removeRef() + void removeRef() { refCount--; if (refCount == 0) @@ -235,17 +230,13 @@ public: 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; - } - bool operator<(const RefPtr &other) const - { - return object < other.object; + return object <=> rhs.object; } inline T *operator->() { diff --git a/src/Engine/Scene/Actor/Actor.cpp b/src/Engine/Scene/Actor/Actor.cpp index ac84b84..35091b9 100644 --- a/src/Engine/Scene/Actor/Actor.cpp +++ b/src/Engine/Scene/Actor/Actor.cpp @@ -14,12 +14,10 @@ Actor::~Actor() } void Actor::tick(float deltaTime) { - addWorldRotation(glm::vec3(0, 1 * deltaTime, 0)); } void Actor::notifySceneAttach(PScene scene) { owningScene = scene; - scene->getSceneUpdater()->registerActorUpdate(this); rootComponent->notifySceneAttach(scene); for(auto child : children) { diff --git a/src/Engine/Scene/CMakeLists.txt b/src/Engine/Scene/CMakeLists.txt index b1774e5..a592c30 100644 --- a/src/Engine/Scene/CMakeLists.txt +++ b/src/Engine/Scene/CMakeLists.txt @@ -1,9 +1,7 @@ target_sources(SeeleEngine PRIVATE Scene.cpp - Scene.h - SceneUpdater.h - SceneUpdater.cpp) + Scene.h) add_subdirectory(Actor/) add_subdirectory(Components/) \ No newline at end of file diff --git a/src/Engine/Scene/Components/Component.cpp b/src/Engine/Scene/Components/Component.cpp index f27bcdd..b0be1b8 100644 --- a/src/Engine/Scene/Components/Component.cpp +++ b/src/Engine/Scene/Components/Component.cpp @@ -36,7 +36,6 @@ PActor Component::getOwner() void Component::notifySceneAttach(PScene scene) { owningScene = scene; - scene->getSceneUpdater()->registerComponentUpdate(this); for (auto child : children) { child->notifySceneAttach(scene); diff --git a/src/Engine/Scene/Scene.cpp b/src/Engine/Scene/Scene.cpp index 07d8d10..96aa4ec 100644 --- a/src/Engine/Scene/Scene.cpp +++ b/src/Engine/Scene/Scene.cpp @@ -13,7 +13,6 @@ inline float frand() Scene::Scene(Gfx::PGraphics graphics) : graphics(graphics) - , updater(new SceneUpdater()) { lightEnv.directionalLights[0].color = Vector4(1, 1, 1, 1); lightEnv.directionalLights[0].direction = Vector4(1, 1, 0, 1); @@ -36,7 +35,6 @@ Scene::~Scene() void Scene::tick(double deltaTime) { - updater->runUpdates(static_cast(deltaTime)); for(auto &&meshBatch : staticMeshes) { meshBatch.material->updateDescriptorData(); diff --git a/src/Engine/Scene/Scene.h b/src/Engine/Scene/Scene.h index 77b3340..d023eca 100644 --- a/src/Engine/Scene/Scene.h +++ b/src/Engine/Scene/Scene.h @@ -4,7 +4,6 @@ #include "Graphics/GraphicsResources.h" #include "Components/PrimitiveComponent.h" #include "Graphics/MeshBatch.h" -#include "SceneUpdater.h" namespace Seele { @@ -46,13 +45,11 @@ public: const Array& getPrimitives() const { return primitives; } const Array& getStaticMeshes() const { return staticMeshes; } const LightEnv& getLightBuffer() const { return lightEnv; } - UPSceneUpdater& getSceneUpdater() { return updater; } private: Array staticMeshes; Array rootActors; Array primitives; LightEnv lightEnv; Gfx::PGraphics graphics; - UPSceneUpdater updater; }; } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Scene/SceneUpdater.h b/src/Engine/Scene/SceneUpdater.h index 948c9e7..cbe0b6a 100644 --- a/src/Engine/Scene/SceneUpdater.h +++ b/src/Engine/Scene/SceneUpdater.h @@ -2,7 +2,7 @@ #include "MinimalEngine.h" #include "Containers/List.h" #include - +//DEPRECATED namespace Seele { DECLARE_REF(Component); diff --git a/src/Engine/ThreadPool.cpp b/src/Engine/ThreadPool.cpp index 9b6f3e5..45a738f 100644 --- a/src/Engine/ThreadPool.cpp +++ b/src/Engine/ThreadPool.cpp @@ -46,42 +46,53 @@ ThreadPool::~ThreadPool() void ThreadPool::addJob(Job&& job) { 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) { 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) { + //std::cout << job << " 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) { + //std::cout << job << " 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) { { std::unique_lock lock(jobQueueLock); 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 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(); } @@ -95,9 +106,22 @@ void ThreadPool::threadLoop(const bool mainThread) if(!mainJobs.empty()) { MainJob&& job = mainJobs.retrieve(); + lock.unlock(); 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(); + } } } diff --git a/src/Engine/ThreadPool.h b/src/Engine/ThreadPool.h index 3f42f9d..0609208 100644 --- a/src/Engine/ThreadPool.h +++ b/src/Engine/ThreadPool.h @@ -30,16 +30,49 @@ struct JobBase public: using promise_type = JobPromiseBase; + explicit JobBase() + {} explicit JobBase(std::coroutine_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() { if(handle) { + std::cout << "Destroying job " << handle.address() << std::endl; 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& operator<<(std::basic_ostream& stream, const JobBase& obj) + { + if (obj.handle == nullptr) + { + stream << nullptr; + } + else + { + stream << obj.handle.address(); + } + return stream; + } void resume() { handle.resume(); @@ -56,6 +89,15 @@ struct Event public: Event(); Event(const std::string& name); + auto operator<=>(const Event& other) const + { + return name <=> other.name; + } + Event operator co_await() + { + return *this; + } + void raise(); void reset(); bool await_ready(); @@ -65,6 +107,7 @@ public: private: std::string name; RefPtr flag; + friend class ThreadPool; }; class ThreadPool @@ -84,14 +127,16 @@ private: List mainJobs; std::mutex mainJobLock; + std::condition_variable mainJobCV; List jobQueue; std::mutex jobQueueLock; + std::condition_variable jobQueueCV; - Map> waitingJobs; + Map> waitingJobs; std::mutex waitingLock; - Map> waitingMainJobs; + Map> waitingMainJobs; std::mutex waitingMainLock; void threadLoop(const bool isMainThread); @@ -100,7 +145,7 @@ private: template inline JobBase JobPromiseBase::get_return_object() noexcept { - return JobBase { std::coroutine_handle>::from_promise(*this) }; + return JobBase(); } template @@ -111,7 +156,7 @@ inline auto JobPromiseBase::initial_suspend() const noexcept constexpr bool await_ready() { return false; } constexpr void await_suspend(std::coroutine_handle> h) { - getGlobalThreadPool().addJob(JobBase(h)); + getGlobalThreadPool().addJob(std::move(JobBase(h))); } constexpr void await_resume() {} }; @@ -121,7 +166,7 @@ inline auto JobPromiseBase::initial_suspend() const noexcept template inline constexpr void Event::await_suspend(std::coroutine_handle> h) { - getGlobalThreadPool().enqueueWaiting(this, JobBase(h)); + getGlobalThreadPool().enqueueWaiting(this, std::move(JobBase(h))); } } // namespace Seele diff --git a/src/Engine/Window/Window.cpp b/src/Engine/Window/Window.cpp index f640c84..e236b3e 100644 --- a/src/Engine/Window/Window.cpp +++ b/src/Engine/Window/Window.cpp @@ -18,8 +18,10 @@ void Window::addView(PView view) { WindowView* windowView = new WindowView(); windowView->view = view; + windowView->updateFinished = Event("test"); //windowView->worker = std::thread(&Window::viewWorker, this, windowView); - views.add(windowView); + views.add(windowView); + viewWorker(views.size() - 1); } MainJob Window::render() @@ -27,8 +29,8 @@ MainJob Window::render() gfxHandle->beginFrame(); for(auto& windowView : views) { - viewWorker(windowView); co_await windowView->updateFinished; + std::cout << "view update finished" << std::endl; { std::unique_lock lock(windowView->workerMutex); windowView->view->prepareRender(); @@ -36,6 +38,8 @@ MainJob Window::render() windowView->view->render(); } gfxHandle->endFrame(); + //Enqueue a new render main job + render(); } Gfx::PWindow Window::getGfxHandle() @@ -60,17 +64,18 @@ void Window::setFocused(PView view) }); } - -Job Window::viewWorker(WindowView* windowView) +Job Window::viewWorker(size_t viewIndex) { - while(true) + WindowView* windowView = views[viewIndex]; + windowView->view->beginUpdate(); + windowView->view->update(); { - windowView->view->beginUpdate(); - windowView->view->update(); - { - std::unique_lock lock(windowView->workerMutex); - windowView->view->commitUpdate(); - } - windowView->updateFinished.raise(); + std::unique_lock lock(windowView->workerMutex); + windowView->view->commitUpdate(); } + std::cout << "Update completed" << std::endl; + windowView->updateFinished.raise(); + // enqueue next frame update + viewWorker(viewIndex); + co_return; } diff --git a/src/Engine/Window/Window.h b/src/Engine/Window/Window.h index ccd658d..d6870ed 100644 --- a/src/Engine/Window/Window.h +++ b/src/Engine/Window/Window.h @@ -29,7 +29,7 @@ protected: Array views; Gfx::PWindow gfxHandle; - Job viewWorker(WindowView* view); + Job viewWorker(size_t viewIndex); }; DEFINE_REF(Window) } // namespace Seele \ No newline at end of file diff --git a/src/Engine/Window/WindowManager.cpp b/src/Engine/Window/WindowManager.cpp index a654c31..283e098 100644 --- a/src/Engine/Window/WindowManager.cpp +++ b/src/Engine/Window/WindowManager.cpp @@ -39,4 +39,9 @@ PWindow WindowManager::addWindow(const WindowCreateInfo &createInfo) void WindowManager::notifyWindowClosed(PWindow window) { windows.remove(windows.find(window)); + if(windows.empty()) + { + std::unique_lock lock(windowsLock); + windowsCV.notify_all(); + } } diff --git a/src/Engine/Window/WindowManager.h b/src/Engine/Window/WindowManager.h index 0ac3171..83014b8 100644 --- a/src/Engine/Window/WindowManager.h +++ b/src/Engine/Window/WindowManager.h @@ -11,6 +11,7 @@ class WindowManager public: WindowManager(); ~WindowManager(); + Job init(); PWindow addWindow(const WindowCreateInfo &createInfo); void notifyWindowClosed(PWindow window); static Gfx::PGraphics getGraphics() @@ -21,9 +22,16 @@ public: { return windows.size(); } + void waitForCompletion() + { + std::unique_lock lock(windowsLock); + windowsCV.wait(lock); + } private: Array windows; + std::mutex windowsLock; + std::condition_variable windowsCV; static Gfx::PGraphics graphics; }; DEFINE_REF(WindowManager) diff --git a/src/Engine/main.cpp b/src/Engine/main.cpp index 3be06e0..ea5cf11 100644 --- a/src/Engine/main.cpp +++ b/src/Engine/main.cpp @@ -34,9 +34,7 @@ int main() PInspectorView inspectorView = new InspectorView(windowManager->getGraphics(), window, inspectorViewInfo); window->addView(inspectorView); sceneView->setFocused(); - while(windowManager->isActive()) - { - window->render(); - } + window->render(); + windowManager->waitForCompletion(); return 0; } \ No newline at end of file diff --git a/test/Engine/Containers/List.cpp b/test/Engine/Containers/List.cpp index 84dab80..0088420 100644 --- a/test/Engine/Containers/List.cpp +++ b/test/Engine/Containers/List.cpp @@ -40,4 +40,22 @@ BOOST_AUTO_TEST_CASE(basic_remove) BOOST_REQUIRE_EQUAL(list.size(), 2); } +BOOST_AUTO_TEST_CASE(list_join) +{ + List list1; + List 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() \ No newline at end of file