diff --git a/Content/Scenes/PerfTest.scene b/Content/Scenes/PerfTest.scene new file mode 100644 index 0000000..0ba8252 --- /dev/null +++ b/Content/Scenes/PerfTest.scene @@ -0,0 +1,32 @@ +{ + "ID": "2a86c77242441f5ac25b4a8bbf4029a8", + "TypeName": "FlaxEngine.SceneAsset", + "EngineBuild": 6804, + "Data": [ + { + "ID": "2a86c77242441f5ac25b4a8bbf4029a8", + "TypeName": "FlaxEngine.Scene", + "LightmapSettings": { + "IndirectLightingIntensity": 1.0, + "GlobalObjectsScale": 1.0, + "ChartsPadding": 3, + "AtlasSize": 1024, + "BounceCount": 1, + "CompressLightmaps": true, + "UseGeometryWithNoMaterials": true, + "Quality": 10 + } + }, + { + "ID": "5b51518c45ce815817a6f1978fec4699", + "TypeName": "Game.MyScript", + "ParentID": "2a86c77242441f5ac25b4a8bbf4029a8" + }, + { + "ID": "efa3263d4596af098d5babb8fd6ea6fb", + "TypeName": "Game.MyScriptTwo", + "ParentID": "2a86c77242441f5ac25b4a8bbf4029a8", + "V": {} + } + ] +} \ No newline at end of file diff --git a/Source/Game/Console/ConsolePlugin.cs b/Source/Game/Console/ConsolePlugin.cs index 6f2f841..ad6b7d1 100644 --- a/Source/Game/Console/ConsolePlugin.cs +++ b/Source/Game/Console/ConsolePlugin.cs @@ -3,6 +3,8 @@ using FlaxEngine; using Console = Game.Console; using System.Linq; using System.Threading; +using FlaxEngine.Json; + #if FLAX_EDITOR using FlaxEditor; @@ -137,6 +139,9 @@ public class ConsoleEditorPlugin : EditorPlugin private void OnPlayModeBegin() { + if (!Level.Scenes.Any(x => x.ID == JsonSerializer.ParseID("194e05f445ece24ec5448d886e1334df"))) // MainScene + return; + //FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin; LoadConfig(); //GameMode.Connect(); diff --git a/Source/Game/MyScript.cpp b/Source/Game/MyScript.cpp new file mode 100644 index 0000000..f1556fa --- /dev/null +++ b/Source/Game/MyScript.cpp @@ -0,0 +1,553 @@ +#include "MyScript.h" +#include "Engine/Level/Actor.h" +#include "Engine/Core/Log.h" +#include "Engine/Renderer/RenderList.h" +#include "Engine/Scripting/ManagedCLR/MUtils.h" +#include "Engine/Scripting/ManagedCLR/MCore.h" +#include "Engine/Scripting/ManagedCLR/MClass.h" +#include "Engine/Scripting/ManagedCLR/MEvent.h" +#include "Engine/Scripting/ManagedCLR/MMethod.h" +#include "Engine/Level/Scene/Scene.h" +#include "Engine/Core/Collections/Sorting.h" + +#define NEW_VERSION 1 + +#if BUILD_DEBUG +#define LONGER 1 +#define CHUNK_TIMES 10 +#else +#define LONGER 10 +#define CHUNK_TIMES 1000 +#endif +#define TIMES (10000*LONGER) +#define TIMES2 (1000*LONGER) +#define TIMES3 (100*LONGER) +#define TIMES4 (10*LONGER) +#define TIMES5 (1*LONGER) + +MyScript2::MyScript2(const SpawnParams& params) + : Script(params) +{ + // _tickUpdate = true; + +} + +MyScript::MyScript(const SpawnParams& params) + : Script(params) +{ + // _tickUpdate = true; + +} + +#define BENCHMARK_CALL_ARGS0(REPEAT, FUNC) \ +{ \ + LOG(Info, #FUNC); \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + scriptTwo->FUNC(); \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); \ +} +#define BENCHMARK_CALL_ARGS1(REPEAT, FUNC, PARAM1) \ +{ \ + LOG(Info, #FUNC); \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + scriptTwo->FUNC(PARAM1); \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); \ +} +#define BENCHMARK_CALL_ARGS1_REF(REPEAT, FUNC, PARAM1) \ +{ \ + LOG(Info, #FUNC); \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + { \ + auto _param1_orig_value = PARAM1; \ + scriptTwo->FUNC(_param1_orig_value); \ + } \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); \ +} +#define BENCHMARK_CALL_ARGS5(REPEAT, FUNC, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5) \ +{ \ + LOG(Info, #FUNC); \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + scriptTwo->FUNC(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5); \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - VirtualCall: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); \ +} +#define BENCHMARK_THUNK_BEGIN_ARGS0(REPEAT, FUNC) \ +{ \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + typedef void (*Thunk)(void* instance, MObject** exception); \ + const auto thunk = (Thunk)scriptTwo->GetClass()->GetMethod(#FUNC, 0)->GetThunk(); \ + const auto instance = scriptTwo->GetOrCreateManagedInstance(); \ + MObject* exception = nullptr; +#define BENCHMARK_THUNK_CALL_ARGS0() \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + thunk(instance, &exception); \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); +#define BENCHMARK_THUNK_BEGIN_ARGS1(REPEAT, FUNC) \ +{ \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + typedef void (*Thunk)(void* instance, void*, MObject** exception); \ + const auto thunk = (Thunk)scriptTwo->GetClass()->GetMethod(#FUNC, 1)->GetThunk(); \ + const auto instance = scriptTwo->GetOrCreateManagedInstance(); \ + MObject* exception = nullptr; \ + void* params[1]; +#define BENCHMARK_THUNK_CALL_ARGS1() \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + thunk(instance, params[0], &exception); \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); +#define BENCHMARK_THUNK_CALL_ARGS1_REF(FUN) \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + { \ + thunk(instance, params[0], &exception); \ + FUN \ + } \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); +#define BENCHMARK_THUNK_BEGIN_ARGS5(REPEAT, FUNC) \ +{ \ + const auto times = REPEAT; \ + const auto chunkTimes = CHUNK_TIMES; \ + typedef void (*Thunk)(void* instance, void*, void*, void*, void*, void*, MObject** exception); \ + const auto thunk = (Thunk)scriptTwo->GetClass()->GetMethod(#FUNC, 5)->GetThunk(); \ + const auto instance = scriptTwo->GetOrCreateManagedInstance(); \ + MObject* exception = nullptr; \ + void* params[5]; +#define BENCHMARK_THUNK_CALL_ARGS5() \ + const auto freq = Platform::GetClockFrequency(); \ + results.Clear(); \ + auto start2 = Platform::GetTimeCycles(); \ + for (int i = 0; i < times; ++i) \ + { \ + auto start = Platform::GetTimeCycles(); \ + for (int j = 0; j < chunkTimes; ++j) \ + thunk(instance, params[0], params[1], params[2], params[3], params[4], &exception); \ + auto end = Platform::GetTimeCycles(); \ + auto elapsed = end - start; \ + results.Add(elapsed); \ + } \ + auto end2 = Platform::GetTimeCycles(); \ + auto elapsed2 = end2 - start2; \ + Sorting::MergeSort(results); \ + const auto resultsIndex = 0; \ + LOG(Info, " - InvokeThunkOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast(freq)) * 1000), times*chunkTimes); +#define BENCHMARK_THUNK_END() \ +} + + +void MyScript::OnStart() +{ + LOG(Info, "C++ OnStart"); + MyScript2* scriptTwo = (MyScript2*)GetActor()->GetScript(1); + if (scriptTwo == nullptr) + return; + + bool otherTests = true; + bool arrayTests = true; + bool asRefTests = true; + + Array results(TIMES); + auto CyclesToSeconds = 1.0 / static_cast(Platform::GetClockFrequency()); + LOG(Info, "CyclesToSeconds: {}, freq: {}", CyclesToSeconds, Platform::GetClockFrequency()); + + String shortString = TEXT("Testing string parameter marshalling"); + StringAnsi shortStringAnsi = "Testing string parameter marshalling"; + Actor* actor = GetActor(); + SceneReference sceneRef; sceneRef.ID = actor->GetScene()->GetID(); + BehaviorUpdateContext behaviorUpdateContext = {}; + RenderContext renderContext = MainRenderTask::Instance; + renderContext.List = RenderList::GetFromPool(); + Array simpleArray; for (int i=0; i<10; i++) simpleArray.Add(i); + Array actorArray; for (int i=0; i<10; i++) actorArray.Add(actor); + TestStruct testStruct; testStruct.Object = actor; testStruct.SceneRef = sceneRef; + Array complexArray; for (int i=0; i<10; i++) complexArray.Add(testStruct); + + if (otherTests) + { + BENCHMARK_CALL_ARGS0(TIMES2, SimpleCall); + BENCHMARK_THUNK_BEGIN_ARGS0(TIMES2, SimpleCall); + BENCHMARK_THUNK_CALL_ARGS0(); + BENCHMARK_THUNK_END(); + } + + + if (otherTests) + { + BENCHMARK_CALL_ARGS5(TIMES4, SimpleParams, 1, 2, '3', 4, 5); + BENCHMARK_THUNK_BEGIN_ARGS5(TIMES3, SimpleParams); + params[0] = MUtils::Box(1, MCore::TypeCache::Int32); + params[1] = MUtils::Box(2, MCore::TypeCache::Single); + params[2] = MUtils::Box('3', MCore::TypeCache::SByte); + params[3] = MUtils::Box(4, MCore::TypeCache::Double); + params[4] = MUtils::Box(5, MCore::TypeCache::Int64); + BENCHMARK_THUNK_CALL_ARGS5(); +#if NEW_VERSION + auto __param0_handle = *(MGCHandle*)¶ms[0]; + MCore::GCHandle::Free(__param0_handle); + auto __param1_handle = *(MGCHandle*)¶ms[1]; + MCore::GCHandle::Free(__param1_handle); + auto __param2_handle = *(MGCHandle*)¶ms[2]; + MCore::GCHandle::Free(__param2_handle); + auto __param3_handle = *(MGCHandle*)¶ms[3]; + MCore::GCHandle::Free(__param3_handle); + auto __param4_handle = *(MGCHandle*)¶ms[4]; + MCore::GCHandle::Free(__param4_handle); +#endif + BENCHMARK_THUNK_END(); + } + + + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES3, StringParamAnsi, shortStringAnsi); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamAnsi); + params[0] = MUtils::Box(shortStringAnsi, MCore::TypeCache::String); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + auto __param0_handle = *(MGCHandle*)¶ms[0]; + MCore::GCHandle::Free(__param0_handle); +#endif + BENCHMARK_THUNK_END(); + } + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES3, StringParam, shortString); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParam); + params[0] = MUtils::Box(shortString, MCore::TypeCache::String); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + auto __param0_handle = *(MGCHandle*)¶ms[0]; + MCore::GCHandle::Free(__param0_handle); +#endif + BENCHMARK_THUNK_END(); + } + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES3, StringParamRef, shortString); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamRef); + params[0] = MUtils::Box(shortString, MCore::TypeCache::String); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + auto __param0_handle = *(MGCHandle*)¶ms[0]; + MCore::GCHandle::Free(__param0_handle); +#endif + BENCHMARK_THUNK_END(); + } + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES3, StringParamRefConst, shortString); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamRefConst); + params[0] = MUtils::Box(shortString, MCore::TypeCache::String); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + auto __param0_handle = *(MGCHandle*)¶ms[0]; + MCore::GCHandle::Free(__param0_handle); +#endif + BENCHMARK_THUNK_END(); + } + if (asRefTests) + { + String str = shortString; + BENCHMARK_CALL_ARGS1_REF(TIMES3, StringParamAsRef, str); + LOG(Info, " - InvokeThunkOnly: not valid"); +/* str = shortString; + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, StringParamAsRef); +#if NEW_VERSION + auto __param_orig_str = MUtils::Box(str, MCore::TypeCache::String); + auto __param_str = __param_orig_str; + params[0] = &__param_str; +#else + auto __param_str = MUtils::Box(str, MCore::TypeCache::String); + params[0] = &__param_str; +#endif + BENCHMARK_THUNK_CALL_ARGS1_REF({ params[0] = &__param_str; }); + str = MUtils::Unbox(*(MObject**)params[0]); + ASSERT(str == shortString); +#if NEW_VERSION + MUtils::FreeManaged((MObject*)__param_str); + if (__param_orig_str != __param_str) + MUtils::FreeManaged((MObject*)__param_orig_str); +#endif + BENCHMARK_THUNK_END();*/ + } + + + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES2, ActorParam, actor); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, ActorParam); + params[0] = ScriptingObject::ToManaged((ScriptingObject*)actor); + BENCHMARK_THUNK_CALL_ARGS1(); + BENCHMARK_THUNK_END(); + } + + + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES3, ComplexParam, behaviorUpdateContext); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, ComplexParam); + params[0] = MUtils::Box(behaviorUpdateContext, BehaviorUpdateContext::TypeInitializer.GetClass()); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + MUtils::FreeManaged((MObject*)params[0]); +#endif + BENCHMARK_THUNK_END(); + } + + + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES4, Complex2Param, renderContext); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2Param); + params[0] = MUtils::Box(renderContext, RenderContext::TypeInitializer.GetClass()); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + MUtils::FreeManaged((MObject*)params[0]); +#endif + BENCHMARK_THUNK_END(); + } + if (otherTests) + { + BENCHMARK_CALL_ARGS1(TIMES4, Complex2ParamConst, renderContext); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2ParamConst); + params[0] = MUtils::Box(renderContext, RenderContext::TypeInitializer.GetClass()); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + MUtils::FreeManaged((MObject*)params[0]); +#endif + BENCHMARK_THUNK_END(); + } + if (asRefTests) + { + RenderContext context = renderContext; + BENCHMARK_CALL_ARGS1_REF(TIMES4, Complex2ParamAsRef, context); + LOG(Info, " - InvokeThunkOnly: not valid"); +/* context = renderContext; + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2ParamAsRef); +#if NEW_VERSION + auto __param_orig_context = MUtils::Box(context, RenderContext::TypeInitializer.GetClass()); + auto __param_context = __param_orig_context; + params[0] = &__param_context; +#else + auto __param_context = MUtils::Box(context, RenderContext::TypeInitializer.GetClass()); + params[0] = &__param_context; +#endif + BENCHMARK_THUNK_CALL_ARGS1_REF({ if (__param_orig_context != __param_context) MUtils::FreeManaged((MObject*)__param_orig_context); params[0] = &__param_context; }); + context = MUtils::Unbox(*(MObject**)params[0]); + ASSERT(context.Buffers == renderContext.Buffers); + ASSERT(context.Task == renderContext.Task); +#if NEW_VERSION + MUtils::FreeManaged((MObject*)__param_context); + if (__param_orig_context != __param_context) + MUtils::FreeManaged((MObject*)__param_orig_context); +#endif + BENCHMARK_THUNK_END();*/ + } + + + if (arrayTests) + { + BENCHMARK_CALL_ARGS1(TIMES4, SimpleArrayParam, simpleArray); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, SimpleArrayParam); + params[0] = MUtils::ToArray(simpleArray, MCore::TypeCache::Int32); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + //TODO +#endif + BENCHMARK_THUNK_END(); + } + if (arrayTests && asRefTests) + { + Array arr = simpleArray; + BENCHMARK_CALL_ARGS1_REF(TIMES4, SimpleArrayParamAsRef, simpleArray); + LOG(Info, " - InvokeThunkOnly: not valid"); +/* arr = simpleArray; + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, SimpleArrayParamAsRef); +#if NEW_VERSION + auto __param_orig_arr = MUtils::ToArray(arr, MCore::TypeCache::Int32); + auto __param_arr = __param_orig_arr; + params[0] = &__param_arr; +#else + auto __param_arr = MUtils::ToArray(arr, MCore::TypeCache::Int32); + params[0] = &__param_arr; +#endif + BENCHMARK_THUNK_CALL_ARGS1(); + arr = MUtils::Unbox>(*(MObject**)params[0]); + ASSERT(arr.Count() == simpleArray.Count()); + for (int i=0; i((MObject*)params[0]); +#endif + BENCHMARK_THUNK_END(); + } + + if (arrayTests) + { + BENCHMARK_CALL_ARGS1(TIMES4, ComplexArrayParam, complexArray); + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, ComplexArrayParam); + params[0] = MUtils::ToArray(complexArray, TestStruct::TypeInitializer.GetClass()); + BENCHMARK_THUNK_CALL_ARGS1(); +#if NEW_VERSION + //MUtils::FreeManaged((MObject*)params[0]); +#endif + BENCHMARK_THUNK_END(); + } + if (arrayTests && asRefTests) + { + Array arr = complexArray; + BENCHMARK_CALL_ARGS1_REF(TIMES4, ComplexArrayParamAsRef, arr); + LOG(Info, " - InvokeThunkOnly: not valid"); +/* arr = complexArray; + BENCHMARK_THUNK_BEGIN_ARGS1(TIMES4, ComplexArrayParamAsRef); + +#if NEW_VERSION + auto __param_orig_arr = MUtils::ToArray(arr, TestStruct::TypeInitializer.GetClass()); + auto __param_arr = __param_orig_arr; + params[0] = &__param_arr; +#else + auto __param_arr = MUtils::ToArray(arr, TestStruct::TypeInitializer.GetClass()); + params[0] = &__param_arr; +#endif + BENCHMARK_THUNK_CALL_ARGS1(); + arr = MUtils::Unbox>(*(MObject**)params[0]); + ASSERT(arr.Count() == complexArray.Count()); + for (int i = 0; i < arr.Count(); i++) ASSERT(arr[i] == complexArray[i]); +#if NEW_VERSION + //MUtils::FreeManaged((MObject*)params[0]); +#endif + BENCHMARK_THUNK_END();*/ + } +} + +void MyScript::OnEnable() +{ + //LOG(Info, "C++ OnEnable"); +} + +void MyScript::OnDisable() +{ + LOG(Info, "running garbage collector"); + MCore::GC::Collect(MCore::GC::MaxGeneration(), MGCCollectionMode::Aggressive, true, true); + MCore::GC::WaitForPendingFinalizers(); +} + +void MyScript::OnUpdate() +{ +} diff --git a/Source/Game/MyScript.h b/Source/Game/MyScript.h new file mode 100644 index 0000000..4367332 --- /dev/null +++ b/Source/Game/MyScript.h @@ -0,0 +1,108 @@ +#pragma once + +#include "Engine/Scripting/Script.h" +#include +#include + +#include "Engine/Graphics/PostProcessEffect.h" +#include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/Graphics.h" +#include "Engine/Scripting/SoftTypeReference.h" +#include "Engine/Content/SceneReference.h" + +API_ENUM() enum TestTypeEnum +{ + None, + Value1, + Value22, +}; + +/*template +API_STRUCT() struct GAME_API MyThinger +{ +public: + T fieldo; +};*/ + +API_STRUCT(NoDefault) struct TestStruct : public ISerializable +{ + API_AUTO_SERIALIZATION(); + DECLARE_SCRIPTING_TYPE_MINIMAL(TestStruct); + + // Var + API_FIELD() Float3 Vector = Float3::One; + // Ref + API_FIELD() ScriptingObject* Object = nullptr; + // Soft Type Ref + API_FIELD() SoftTypeReference SoftTypeRef; + // Scene Ref + API_FIELD() SceneReference SceneRef; + + friend bool operator==(const TestStruct& lhs, const TestStruct& rhs) + { + return lhs.Vector == rhs.Vector && + lhs.Object == rhs.Object && + lhs.SoftTypeRef == rhs.SoftTypeRef && + lhs.SceneRef == rhs.SceneRef; + } +}; + +API_CLASS() class GAME_API MyScript2 : public Script +{ + API_AUTO_SERIALIZATION(); + DECLARE_SCRIPTING_TYPE(MyScript2); + + API_FUNCTION() virtual void SimpleCall() {}; + API_FUNCTION() virtual void SimpleParams(int a, float b, char c, double d, long e) {}; + API_FUNCTION() virtual void StringParamAnsi(StringAnsi str) {}; + API_FUNCTION() virtual void StringParam(String str) {}; + API_FUNCTION() virtual void StringParamRef(String& str) {}; + API_FUNCTION() virtual void StringParamRefConst(const String& str) {}; + API_FUNCTION() virtual void StringParamAsRef(API_PARAM(Ref) String& str) {}; + API_FUNCTION() virtual void ActorParam(Actor* actor) {}; + API_FUNCTION() virtual void ComplexParam(BehaviorUpdateContext context) {}; + API_FUNCTION() virtual void Complex2Param(RenderContext& context) {}; + API_FUNCTION() virtual void Complex2ParamConst(const RenderContext& context) {}; + API_FUNCTION() virtual void Complex2ParamAsRef(API_PARAM(Ref) RenderContext& context) {}; + API_FUNCTION() virtual void SimpleArrayParam(Array arr) {}; + API_FUNCTION() virtual void SimpleArrayParamRef(Array& arr) {}; + API_FUNCTION() virtual void SimpleArrayParamRefConst(const Array& arr) {}; + API_FUNCTION() virtual void SimpleArrayParamAsRef(API_PARAM(Ref) Array& arr) {}; + API_FUNCTION() virtual void ActorArrayParam(Array arr) {}; + API_FUNCTION() virtual void ActorArrayParamRef(Array& arr) {}; + API_FUNCTION() virtual void ActorArrayParamRefConst(const Array& arr) {}; + //API_FUNCTION() virtual void ActorArrayParamAsRef(API_PARAM(Ref) Array& arr) {}; + API_FUNCTION() virtual void ComplexArrayParam(Array arr) {}; + API_FUNCTION() virtual void ComplexArrayParamRef(Array& arr) {}; + API_FUNCTION() virtual void ComplexArrayParamRefConst(const Array& arr) {}; + API_FUNCTION() virtual void ComplexArrayParamAsRef(API_PARAM(Ref) Array& arr) {}; + + + //API_EVENT() Delegate&, Array&> TestEvent; + +}; + +API_CLASS() class GAME_API MyScript : public Script +{ +API_AUTO_SERIALIZATION(); +DECLARE_SCRIPTING_TYPE(MyScript); + + /*API_STRUCT() struct GAME_API InnerStructer + { + public: + float floaty; + };*/ + + //API_FIELD() MyThinger thingey; + + // [Script] + void OnStart() override; + void OnEnable() override; + void OnDisable() override; + void OnUpdate() override; + + + + //API_FUNCTION() void Test1(API_PARAM(REF) Array& eenums) {}; + //API_FUNCTION() BezierCurve.Keyframe Test2(BezierCurve kef) {}; +}; diff --git a/Source/Game/MyScriptTwo.cs b/Source/Game/MyScriptTwo.cs new file mode 100644 index 0000000..3c9165b --- /dev/null +++ b/Source/Game/MyScriptTwo.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using FlaxEngine; + +namespace Game; + +/// +/// MyScriptTwo Script. +/// +public class MyScriptTwo : MyScript2 +{ + private int counter = 0; + /// + public override void OnStart() + { + Debug.Log("C# OnStart"); + } + + /// + public override void OnEnable() + { + //counter++; + } + + /// + public override void OnDisable() + { + } + + /// + public override void OnUpdate() + { + } + + public override void SimpleCall() {} + public override void SimpleParams(int a, float b, sbyte c, double d, long e) {} + public override void StringParamAnsi(string str) {} + public override void StringParam(string str) {} + public override void StringParamRef(string str) {} + public override void StringParamRefConst(string str) {} + public override void StringParamAsRef(ref string str) {} + public override void ActorParam(Actor actor) {} + public override void ComplexParam(BehaviorUpdateContext context) {} + public override void Complex2Param(RenderContext context) {} + public override void Complex2ParamConst(RenderContext context) {} + public override void Complex2ParamAsRef(ref RenderContext context) {} + public override void SimpleArrayParam(int[] arr) {} + public override void SimpleArrayParamRef(int[] arr) {} + public override void SimpleArrayParamRefConst(int[] arr) {} + public override void SimpleArrayParamAsRef(ref int[] arr) {} + public override void ActorArrayParam(Actor[] arr) {} + public override void ActorArrayParamRef(Actor[] arr) {} + public override void ActorArrayParamRefConst(Actor[] arr) {} + //public override void ActorArrayParamAsRef(ref Actor[] arr) {} + public override void ComplexArrayParam(TestStruct[] arr) {} + public override void ComplexArrayParamRef(TestStruct[] arr) {} + public override void ComplexArrayParamRefConst(TestStruct[] arr) {} + public override void ComplexArrayParamAsRef(ref TestStruct[] arr) {} +} diff --git a/Source/GameTarget.Build.cs b/Source/GameTarget.Build.cs index 0866fb7..594cb13 100644 --- a/Source/GameTarget.Build.cs +++ b/Source/GameTarget.Build.cs @@ -24,13 +24,16 @@ public class GameTarget : GameProjectTarget OutputType = TargetOutputType.Executable; } Modules.Add("Game"); + Modules.Add("Graphics"); } public override void SetupTargetEnvironment(BuildOptions options) { base.SetupTargetEnvironment(options); +#pragma warning disable CS0618 // X is obsolete options.LinkEnv.UseFastPDBLinking = true; +#pragma warning restore CS0618 // X is obsolete } public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null)