From 862d13aec80944af8428dcc6732497fe0d097af4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tur=C3=A1nszki=20J=C3=A1nos?= Date: Fri, 10 May 2024 07:55:27 +0200 Subject: [PATCH] Lua Async task tracking (#842) --- .../ScriptingAPI-Documentation.md | 10 ++++++ WickedEngine/CMakeLists.txt | 2 ++ WickedEngine/WickedEngine_SOURCE.vcxitems | 2 ++ .../WickedEngine_SOURCE.vcxitems.filters | 6 ++++ WickedEngine/wiAsync_BindLua.cpp | 34 ++++++++++++++++++ WickedEngine/wiAsync_BindLua.h | 24 +++++++++++++ WickedEngine/wiLua.cpp | 2 ++ WickedEngine/wiLuna.h | 3 +- WickedEngine/wiScene_BindLua.cpp | 36 +++++++++++++++++++ WickedEngine/wiScene_BindLua.h | 1 + WickedEngine/wiVersion.cpp | 2 +- 11 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 WickedEngine/wiAsync_BindLua.cpp create mode 100644 WickedEngine/wiAsync_BindLua.h diff --git a/Content/Documentation/ScriptingAPI-Documentation.md b/Content/Documentation/ScriptingAPI-Documentation.md index b49d26eb8..adce9bd6d 100644 --- a/Content/Documentation/ScriptingAPI-Documentation.md +++ b/Content/Documentation/ScriptingAPI-Documentation.md @@ -22,6 +22,7 @@ This is a reference and explanation of Lua scripting features in Wicked Engine. 3. [SoundInstance3D](#soundinstance3d) 7. [Vector](#vector) 8. [Matrix](#matrix) + 8. [Async](#async) 9. [Scene](#scene) 1. [Entity](#entity) 2. [Scene](#scene) @@ -641,6 +642,13 @@ A four by four matrix, efficient calculations with SIMD support. - GetRight(Matrix mat) : Vector -- returns right direction of parameter matrix +### Async +The Async object can be used for tracking or Wait for completion of functions that are running on background threads. + +- [constructor]Async() -- constructs a new Async tracker object +- Wait() -- wait for completion of async tasks on this tracker +- IsCompleted() : bool -- checks if all async tasks on this tracker have been completed + ### Scene System (using entity-component system) Manipulate the 3D scene with these components. @@ -676,11 +684,13 @@ The scene holds components. Entity handles can be used to retrieve associated co - Clear() -- deletes every entity and component inside the scene - Merge(Scene other) -- moves contents from an other scene into this one. The other scene will be empty after this operation (contents are moved, not copied) - UpdateHierarchy() -- updates the full scene hierarchy system. Useful if you modified for example a parent transform and children immediately need up to date result in the script +- Instantiate(Scene prefab, opt bool attached = false) : Entity -- Duplicates everything in the prefab scene into the current scene. If attached parameter is st to `true` then everything in prefab scene will be attached to a common root entity (with TransformComponent and LayerComponent) and the function will return that root entity. - CreateEntity() : int entity -- creates an empty entity and returns it - FindAllEntities() : table[entities] -- returns a table with all the entities present in the given scene - Entity_FindByName(string value, opt Entity ancestor = INVALID_ENTITY) : int entity -- returns an entity ID if it exists, and INVALID_ENTITY otherwise. You can specify an ancestor entity if you only want to find entities that are descendants of ancestor entity - Entity_Remove(Entity entity, bool recursive = true, bool keep_sorted = false) -- removes an entity and deletes all its components if it exists. If recursive is specified, then all children will be removed as well (enabled by default). If keep_sorted is specified, then component order will be kept (disabled by default, slower) +- Entity_Remove_Async(Async async, Entity entity, bool recursive = true, bool keep_sorted = false) -- Same as Entity_Remove, but it runs on a background thread, status can be tracked by the [Async](#async) object that you provide - Entity_Duplicate(Entity entity) : int entity -- duplicates all of an entity's components and creates a new entity with them. Returns the clone entity handle - Entity_IsDescendant(Entity entity, Entity ancestor) : bool result -- Check whether entity is a descendant of ancestor. Returns `true` if entity is in the hierarchy tree of ancestor, `false` otherwise diff --git a/WickedEngine/CMakeLists.txt b/WickedEngine/CMakeLists.txt index 2970fd580..918811ba0 100644 --- a/WickedEngine/CMakeLists.txt +++ b/WickedEngine/CMakeLists.txt @@ -152,6 +152,7 @@ set(HEADER_FILES wiPathQuery_BindLua.h wiTrailRenderer.h wiTrailRenderer_BindLua.h + wiAsync_BindLua.h ) add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} @@ -232,6 +233,7 @@ add_library(${TARGET_NAME} ${WICKED_LIBRARY_TYPE} wiPathQuery_BindLua.cpp wiTrailRenderer.cpp wiTrailRenderer_BindLua.cpp + wiAsync_BindLua.cpp ${HEADER_FILES} ) add_library(WickedEngine ALIAS ${TARGET_NAME}) diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems b/WickedEngine/WickedEngine_SOURCE.vcxitems index 05ddddd6f..a277cd091 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems @@ -236,6 +236,7 @@ + @@ -521,6 +522,7 @@ + diff --git a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters index af629b040..c5e58a0af 100644 --- a/WickedEngine/WickedEngine_SOURCE.vcxitems.filters +++ b/WickedEngine/WickedEngine_SOURCE.vcxitems.filters @@ -1143,6 +1143,9 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Scripting\LuaBindings + @@ -1916,6 +1919,9 @@ ENGINE\Scripting\LuaBindings + + ENGINE\Scripting\LuaBindings + diff --git a/WickedEngine/wiAsync_BindLua.cpp b/WickedEngine/wiAsync_BindLua.cpp new file mode 100644 index 000000000..34074e71b --- /dev/null +++ b/WickedEngine/wiAsync_BindLua.cpp @@ -0,0 +1,34 @@ +#include "wiAsync_BindLua.h" + +namespace wi::lua +{ + Luna::FunctionType Async_BindLua::methods[] = { + lunamethod(Async_BindLua, Wait), + lunamethod(Async_BindLua, IsCompleted), + { NULL, NULL } + }; + Luna::PropertyType Async_BindLua::properties[] = { + { NULL, NULL } + }; + + int Async_BindLua::Wait(lua_State* L) + { + wi::jobsystem::Wait(ctx); + return 0; + } + int Async_BindLua::IsCompleted(lua_State* L) + { + wi::lua::SSetBool(L, wi::jobsystem::IsBusy(ctx) == false); + return 1; + } + + void Async_BindLua::Bind() + { + static bool initialized = false; + if (!initialized) + { + initialized = true; + Luna::Register(wi::lua::GetLuaState()); + } + } +} diff --git a/WickedEngine/wiAsync_BindLua.h b/WickedEngine/wiAsync_BindLua.h new file mode 100644 index 000000000..21ce927c1 --- /dev/null +++ b/WickedEngine/wiAsync_BindLua.h @@ -0,0 +1,24 @@ +#pragma once +#include "wiLua.h" +#include "wiLuna.h" +#include "wiJobSystem.h" + +namespace wi::lua +{ + class Async_BindLua + { + public: + wi::jobsystem::context ctx; + inline static constexpr char className[] = "Async"; + static Luna::FunctionType methods[]; + static Luna::PropertyType properties[]; + + Async_BindLua() = default; + Async_BindLua(lua_State* L) {} + + int Wait(lua_State* L); + int IsCompleted(lua_State* L); + + static void Bind(); + }; +} diff --git a/WickedEngine/wiLua.cpp b/WickedEngine/wiLua.cpp index 7ee7634e6..638147021 100644 --- a/WickedEngine/wiLua.cpp +++ b/WickedEngine/wiLua.cpp @@ -24,6 +24,7 @@ #include "wiVoxelGrid_BindLua.h" #include "wiPathQuery_BindLua.h" #include "wiTrailRenderer_BindLua.h" +#include "wiAsync_BindLua.h" #include "wiTimer.h" #include "wiVector.h" @@ -234,6 +235,7 @@ namespace wi::lua VoxelGrid_BindLua::Bind(); PathQuery_BindLua::Bind(); TrailRenderer_BindLua::Bind(); + Async_BindLua::Bind(); wi::backlog::post("wi::lua Initialized (" + std::to_string((int)std::round(timer.elapsed())) + " ms)"); } diff --git a/WickedEngine/wiLuna.h b/WickedEngine/wiLuna.h index 9117caf65..75d3bbd8c 100644 --- a/WickedEngine/wiLuna.h +++ b/WickedEngine/wiLuna.h @@ -160,7 +160,7 @@ public: Loads an instance of the class into the Lua stack, and provides you a pointer so you can modify it. */ template - static void push(lua_State * L, ARG&&... args) + static T* push(lua_State * L, ARG&&... args) { T **a = (T **)lua_newuserdata(L, sizeof(T *)); // Create userdata *a = allocator.allocate(std::forward(args)...); @@ -168,6 +168,7 @@ public: luaL_getmetatable(L, T::className); lua_setmetatable(L, -2); + return *a; } // Pushes an instance and registers it into a global object diff --git a/WickedEngine/wiScene_BindLua.cpp b/WickedEngine/wiScene_BindLua.cpp index 47a8f7eb2..94a6d260b 100644 --- a/WickedEngine/wiScene_BindLua.cpp +++ b/WickedEngine/wiScene_BindLua.cpp @@ -12,6 +12,7 @@ #include "wiUnorderedMap.h" #include "wiVoxelGrid_BindLua.h" #include "wiAudio_BindLua.h" +#include "wiAsync_BindLua.h" #include @@ -521,6 +522,7 @@ Luna::FunctionType Scene_BindLua::methods[] = { lunamethod(Scene_BindLua, FindAllEntities), lunamethod(Scene_BindLua, Entity_FindByName), lunamethod(Scene_BindLua, Entity_Remove), + lunamethod(Scene_BindLua, Entity_Remove_Async), lunamethod(Scene_BindLua, Entity_Duplicate), lunamethod(Scene_BindLua, Entity_IsDescendant), lunamethod(Scene_BindLua, Component_CreateName), @@ -812,6 +814,40 @@ int Scene_BindLua::Entity_Remove(lua_State* L) } return 0; } +int Scene_BindLua::Entity_Remove_Async(lua_State* L) +{ + int argc = wi::lua::SGetArgCount(L); + if (argc > 1) + { + Async_BindLua* async = Luna::lightcheck(L, 1); + if (async == nullptr) + { + wi::lua::SError(L, "Scene::Entity_Remove_Async(Async async, Entity entity) first argument is not an Async!"); + return 0; + } + Entity entity = (Entity)wi::lua::SGetLongLong(L, 2); + bool recursive = true; + bool keep_sorted = false; + + if (argc > 2) + { + recursive = wi::lua::SGetBool(L, 3); + if (argc > 3) + { + keep_sorted = wi::lua::SGetBool(L, 4); + } + } + + wi::jobsystem::Execute(async->ctx, [=](wi::jobsystem::JobArgs args) { + scene->Entity_Remove(entity, recursive, keep_sorted); + }); + } + else + { + wi::lua::SError(L, "Scene::Entity_Remove_Async(Async async, Entity entity) not enough arguments!"); + } + return 0; +} int Scene_BindLua::Entity_Duplicate(lua_State* L) { int argc = wi::lua::SGetArgCount(L); diff --git a/WickedEngine/wiScene_BindLua.h b/WickedEngine/wiScene_BindLua.h index c1c4fceb7..0577d99e7 100644 --- a/WickedEngine/wiScene_BindLua.h +++ b/WickedEngine/wiScene_BindLua.h @@ -44,6 +44,7 @@ namespace wi::lua::scene int FindAllEntities(lua_State* L); int Entity_FindByName(lua_State* L); int Entity_Remove(lua_State* L); + int Entity_Remove_Async(lua_State* L); int Entity_Duplicate(lua_State* L); int Entity_IsDescendant(lua_State* L); diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index f5d00b82a..b290c2ab2 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -9,7 +9,7 @@ namespace wi::version // minor features, major updates, breaking compatibility changes const int minor = 71; // minor bug fixes, alterations, refactors, updates - const int revision = 454; + const int revision = 455; const std::string version_string = std::to_string(major) + "." + std::to_string(minor) + "." + std::to_string(revision);