Compare commits
9 Commits
dynamic_li
...
interop_te
| Author | SHA1 | Date | |
|---|---|---|---|
| 856be55132 | |||
| 8561d28642 | |||
| 3cfb7d319b | |||
| d1c73d6c74 | |||
| e4cd76fdaf | |||
| 43e1acacce | |||
| 5af8610c0c | |||
| 95de571eb5 | |||
| 0d324c0ff0 |
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ID": "82e58c9d462fba5a0df1a599417ff684",
|
"ID": "82e58c9d462fba5a0df1a599417ff684",
|
||||||
"TypeName": "FlaxEngine.Prefab",
|
"TypeName": "FlaxEngine.Prefab",
|
||||||
"EngineBuild": 6340,
|
"EngineBuild": 6704,
|
||||||
"Data": [
|
"Data": [
|
||||||
{
|
{
|
||||||
"ID": "a50f3639419a8306036ecfab7115e772",
|
"ID": "a50f3639419a8306036ecfab7115e772",
|
||||||
@@ -17,7 +17,11 @@
|
|||||||
"ID": "bc518e2f40ec06a4523d78b52809c668",
|
"ID": "bc518e2f40ec06a4523d78b52809c668",
|
||||||
"TypeName": "Game.PlayerMovement",
|
"TypeName": "Game.PlayerMovement",
|
||||||
"ParentID": "a50f3639419a8306036ecfab7115e772",
|
"ParentID": "a50f3639419a8306036ecfab7115e772",
|
||||||
"V": {},
|
"V": {
|
||||||
|
"maskTest": {
|
||||||
|
"Mask": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
"Enabled": false
|
"Enabled": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -162,8 +166,8 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"StaticFlags": 0,
|
"StaticFlags": 0,
|
||||||
"ContactOffset": 0.0,
|
|
||||||
"Material": "d99b8b6f40198beea4703dadd642150e",
|
"Material": "d99b8b6f40198beea4703dadd642150e",
|
||||||
|
"ContactOffset": 0.0,
|
||||||
"Radius": 16.0,
|
"Radius": 16.0,
|
||||||
"Height": 52.0
|
"Height": 52.0
|
||||||
},
|
},
|
||||||
@@ -173,8 +177,8 @@
|
|||||||
"ParentID": "a50f3639419a8306036ecfab7115e772",
|
"ParentID": "a50f3639419a8306036ecfab7115e772",
|
||||||
"Name": "BoxCollider",
|
"Name": "BoxCollider",
|
||||||
"StaticFlags": 0,
|
"StaticFlags": 0,
|
||||||
"ContactOffset": 0.0,
|
|
||||||
"Material": "ffe0e84c49607480f67a3994a7fe11a8",
|
"Material": "ffe0e84c49607480f67a3994a7fe11a8",
|
||||||
|
"ContactOffset": 0.0,
|
||||||
"Size": {
|
"Size": {
|
||||||
"X": 30.0,
|
"X": 30.0,
|
||||||
"Y": 56.0,
|
"Y": 56.0,
|
||||||
@@ -211,9 +215,9 @@
|
|||||||
"Name": "PlayerModel",
|
"Name": "PlayerModel",
|
||||||
"Transform": {
|
"Transform": {
|
||||||
"Scale": {
|
"Scale": {
|
||||||
"X": 0.30000001192092898,
|
"X": 0.30000001192092896,
|
||||||
"Y": 0.5600000023841858,
|
"Y": 0.5600000023841858,
|
||||||
"Z": 0.30000001192092898
|
"Z": 0.30000001192092896
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"StaticFlags": 0,
|
"StaticFlags": 0,
|
||||||
|
|||||||
34
Content/Scenes/PerfTest.scene
Normal file
34
Content/Scenes/PerfTest.scene
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"ID": "2a86c77242441f5ac25b4a8bbf4029a8",
|
||||||
|
"TypeName": "FlaxEngine.SceneAsset",
|
||||||
|
"EngineBuild": 6805,
|
||||||
|
"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": {
|
||||||
|
"Model": "50310067422bada39f9553b41c4869a4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ID": "af2e52554f7faed7b4937181dd22d166",
|
"ID": "af2e52554f7faed7b4937181dd22d166",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
|
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
|
||||||
"EngineBuild": 6605,
|
"EngineBuild": 6705,
|
||||||
"Data": {
|
"Data": {
|
||||||
"OutputName": "${PROJECT_NAME}",
|
"OutputName": "${PROJECT_NAME}",
|
||||||
"MaxAssetsPerPackage": 4096,
|
"MaxAssetsPerPackage": 4096,
|
||||||
@@ -27,18 +27,9 @@
|
|||||||
"Name": "Preset 3",
|
"Name": "Preset 3",
|
||||||
"Targets": [
|
"Targets": [
|
||||||
{
|
{
|
||||||
"Name": "Win64 Release",
|
"Name": "Windows 64bit",
|
||||||
"Output": "Output\\WindowsRelease",
|
"Output": "Output\\Win64",
|
||||||
"Platform": 2,
|
"Platform": 13,
|
||||||
"Mode": 2,
|
|
||||||
"CustomDefines": null,
|
|
||||||
"PreBuildAction": null,
|
|
||||||
"PostBuildAction": null
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"Name": "Win64 Development",
|
|
||||||
"Output": "Output\\WindowsDevelopment",
|
|
||||||
"Platform": 2,
|
|
||||||
"Mode": 1,
|
"Mode": 1,
|
||||||
"CustomDefines": null,
|
"CustomDefines": null,
|
||||||
"PreBuildAction": null,
|
"PreBuildAction": null,
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
{
|
{
|
||||||
"ID": "f94d5aae457aeba67033a8a4ca753214",
|
"ID": "f94d5aae457aeba67033a8a4ca753214",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.GraphicsSettings",
|
"TypeName": "FlaxEditor.Content.Settings.GraphicsSettings",
|
||||||
"EngineBuild": 6602,
|
"EngineBuild": 6705,
|
||||||
"Data": {
|
"Data": {
|
||||||
"UseVSync": false,
|
"UseVSync": false,
|
||||||
"AAQuality": 3,
|
"AAQuality": 3,
|
||||||
"SSRQuality": 3,
|
"SSRQuality": 3,
|
||||||
"SSAOQuality": 0,
|
"SSAOQuality": 3,
|
||||||
"VolumetricFogQuality": 3,
|
"VolumetricFogQuality": 0,
|
||||||
"ShadowsQuality": 3,
|
"ShadowsQuality": 3,
|
||||||
"ShadowMapsQuality": 3,
|
"ShadowMapsQuality": 3,
|
||||||
"AllowCSMBlending": true,
|
"AllowCSMBlending": true,
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"GenerateSDFOnModelImport": false,
|
"GenerateSDFOnModelImport": false,
|
||||||
"GIQuality": 3,
|
"GIQuality": 3,
|
||||||
"GIProbesSpacing": 100.0,
|
"GIProbesSpacing": 100.0,
|
||||||
|
"GICascadesBlending": false,
|
||||||
"GlobalSurfaceAtlasResolution": 4096,
|
"GlobalSurfaceAtlasResolution": 4096,
|
||||||
"PostProcessSettings": {
|
"PostProcessSettings": {
|
||||||
"AO": {
|
"AO": {
|
||||||
@@ -49,8 +50,10 @@
|
|||||||
"Enabled": false,
|
"Enabled": false,
|
||||||
"Intensity": 1.0,
|
"Intensity": 1.0,
|
||||||
"Threshold": 3.0,
|
"Threshold": 3.0,
|
||||||
"BlurSigma": 4.0,
|
"ThresholdKnee": 0.5,
|
||||||
"Limit": 10.0
|
"Clamp": 3.0,
|
||||||
|
"BaseMix": 0.6,
|
||||||
|
"HighMix": 1.0
|
||||||
},
|
},
|
||||||
"ToneMapping": {
|
"ToneMapping": {
|
||||||
"OverrideFlags": 4,
|
"OverrideFlags": 4,
|
||||||
@@ -198,7 +201,7 @@
|
|||||||
"HistogramHighPercent": 98.0
|
"HistogramHighPercent": 98.0
|
||||||
},
|
},
|
||||||
"CameraArtifacts": {
|
"CameraArtifacts": {
|
||||||
"OverrideFlags": 9,
|
"OverrideFlags": 1,
|
||||||
"VignetteIntensity": 0.0,
|
"VignetteIntensity": 0.0,
|
||||||
"VignetteColor": {
|
"VignetteColor": {
|
||||||
"X": 0.0,
|
"X": 0.0,
|
||||||
@@ -206,8 +209,8 @@
|
|||||||
"Z": 0.001
|
"Z": 0.001
|
||||||
},
|
},
|
||||||
"VignetteShapeFactor": 0.125,
|
"VignetteShapeFactor": 0.125,
|
||||||
"GrainAmount": 0.0,
|
"GrainAmount": 0.22999999,
|
||||||
"GrainParticleSize": 1.6,
|
"GrainParticleSize": 1.0,
|
||||||
"GrainSpeed": 1.0,
|
"GrainSpeed": 1.0,
|
||||||
"ChromaticDistortion": 0.0,
|
"ChromaticDistortion": 0.0,
|
||||||
"ScreenFadeColor": {
|
"ScreenFadeColor": {
|
||||||
@@ -283,7 +286,11 @@
|
|||||||
"TAA_JitterSpread": 0.75,
|
"TAA_JitterSpread": 0.75,
|
||||||
"TAA_Sharpness": 0.0,
|
"TAA_Sharpness": 0.0,
|
||||||
"TAA_StationaryBlending": 0.95,
|
"TAA_StationaryBlending": 0.95,
|
||||||
"TAA_MotionBlending": 0.4
|
"TAA_MotionBlending": 0.4,
|
||||||
|
"CAS_SharpeningAmount": 0.0,
|
||||||
|
"CAS_EdgeSharpening": 0.5,
|
||||||
|
"CAS_MinEdgeThreshold": 0.03,
|
||||||
|
"CAS_OverBlurLimit": 1.0
|
||||||
},
|
},
|
||||||
"PostFxMaterials": {
|
"PostFxMaterials": {
|
||||||
"Materials": null
|
"Materials": null
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ID": "8ec53dba4c238bfbea1d62922e612a4d",
|
"ID": "8ec53dba4c238bfbea1d62922e612a4d",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.InputSettings",
|
"TypeName": "FlaxEditor.Content.Settings.InputSettings",
|
||||||
"EngineBuild": 6335,
|
"EngineBuild": 6705,
|
||||||
"Data": {
|
"Data": {
|
||||||
"ActionMappings": [
|
"ActionMappings": [
|
||||||
{
|
{
|
||||||
@@ -84,6 +84,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 0,
|
"PositiveButton": 0,
|
||||||
"NegativeButton": 0,
|
"NegativeButton": 0,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.0,
|
"DeadZone": 0.0,
|
||||||
"Sensitivity": 0.11,
|
"Sensitivity": 0.11,
|
||||||
"Gravity": 1.0,
|
"Gravity": 1.0,
|
||||||
@@ -96,6 +98,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 0,
|
"PositiveButton": 0,
|
||||||
"NegativeButton": 0,
|
"NegativeButton": 0,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.0,
|
"DeadZone": 0.0,
|
||||||
"Sensitivity": 0.11,
|
"Sensitivity": 0.11,
|
||||||
"Gravity": 1.0,
|
"Gravity": 1.0,
|
||||||
@@ -108,9 +112,11 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 68,
|
"PositiveButton": 68,
|
||||||
"NegativeButton": 65,
|
"NegativeButton": 65,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.01,
|
"DeadZone": 0.01,
|
||||||
"Sensitivity": 5.0,
|
"Sensitivity": 0.0,
|
||||||
"Gravity": 5.0,
|
"Gravity": 0.0,
|
||||||
"Scale": 1.0,
|
"Scale": 1.0,
|
||||||
"Snap": true
|
"Snap": true
|
||||||
},
|
},
|
||||||
@@ -120,9 +126,11 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 87,
|
"PositiveButton": 87,
|
||||||
"NegativeButton": 83,
|
"NegativeButton": 83,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.01,
|
"DeadZone": 0.01,
|
||||||
"Sensitivity": 5.0,
|
"Sensitivity": 0.0,
|
||||||
"Gravity": 5.0,
|
"Gravity": 0.0,
|
||||||
"Scale": 1.0,
|
"Scale": 1.0,
|
||||||
"Snap": true
|
"Snap": true
|
||||||
},
|
},
|
||||||
@@ -132,6 +140,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 39,
|
"PositiveButton": 39,
|
||||||
"NegativeButton": 37,
|
"NegativeButton": 37,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.0,
|
"DeadZone": 0.0,
|
||||||
"Sensitivity": 1.0,
|
"Sensitivity": 1.0,
|
||||||
"Gravity": 800.0,
|
"Gravity": 800.0,
|
||||||
@@ -144,6 +154,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 38,
|
"PositiveButton": 38,
|
||||||
"NegativeButton": 40,
|
"NegativeButton": 40,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.0,
|
"DeadZone": 0.0,
|
||||||
"Sensitivity": 1.0,
|
"Sensitivity": 1.0,
|
||||||
"Gravity": 800.0,
|
"Gravity": 800.0,
|
||||||
@@ -156,6 +168,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 0,
|
"PositiveButton": 0,
|
||||||
"NegativeButton": 0,
|
"NegativeButton": 0,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.19,
|
"DeadZone": 0.19,
|
||||||
"Sensitivity": 1.0,
|
"Sensitivity": 1.0,
|
||||||
"Gravity": 1.0,
|
"Gravity": 1.0,
|
||||||
@@ -168,6 +182,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 0,
|
"PositiveButton": 0,
|
||||||
"NegativeButton": 0,
|
"NegativeButton": 0,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.19,
|
"DeadZone": 0.19,
|
||||||
"Sensitivity": 1.0,
|
"Sensitivity": 1.0,
|
||||||
"Gravity": 1.0,
|
"Gravity": 1.0,
|
||||||
@@ -180,6 +196,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 0,
|
"PositiveButton": 0,
|
||||||
"NegativeButton": 0,
|
"NegativeButton": 0,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.19,
|
"DeadZone": 0.19,
|
||||||
"Sensitivity": 1.0,
|
"Sensitivity": 1.0,
|
||||||
"Gravity": 1.0,
|
"Gravity": 1.0,
|
||||||
@@ -192,6 +210,8 @@
|
|||||||
"Gamepad": 0,
|
"Gamepad": 0,
|
||||||
"PositiveButton": 0,
|
"PositiveButton": 0,
|
||||||
"NegativeButton": 0,
|
"NegativeButton": 0,
|
||||||
|
"GamepadPositiveButton": 0,
|
||||||
|
"GamepadNegativeButton": 0,
|
||||||
"DeadZone": 0.19,
|
"DeadZone": 0.19,
|
||||||
"Sensitivity": 1.0,
|
"Sensitivity": 1.0,
|
||||||
"Gravity": 1.0,
|
"Gravity": 1.0,
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
{
|
{
|
||||||
"ID": "0c69a0c7471f8d0805965caf343d2f27",
|
"ID": "0c69a0c7471f8d0805965caf343d2f27",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.NetworkSettings",
|
"TypeName": "FlaxEditor.Content.Settings.NetworkSettings",
|
||||||
"EngineBuild": 6340,
|
"EngineBuild": 6705,
|
||||||
"Data": {
|
"Data": {
|
||||||
"MaxClients": 100,
|
"MaxClients": 100,
|
||||||
"ProtocolVersion": 1,
|
"ProtocolVersion": 1,
|
||||||
"NetworkFPS": 60.0,
|
"NetworkFPS": 1.0,
|
||||||
"Address": "127.0.0.1",
|
"Address": "127.0.0.1",
|
||||||
"Port": 59183,
|
"Port": 59183,
|
||||||
"NetworkDriver": "FlaxEngine.Networking.ENetDriver"
|
"NetworkDriver": "FlaxEngine.Networking.ENetDriver"
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"ID": "4bd8a4cc460399b5f1975fbe0a668e3f",
|
"ID": "4bd8a4cc460399b5f1975fbe0a668e3f",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.PhysicsSettings",
|
"TypeName": "FlaxEditor.Content.Settings.PhysicsSettings",
|
||||||
"EngineBuild": 6510,
|
"EngineBuild": 6705,
|
||||||
"Data": {
|
"Data": {
|
||||||
"DefaultGravity": {
|
"DefaultGravity": {
|
||||||
"X": 0.0,
|
"X": 0.0,
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
"RestitutionCombineMode": 0,
|
"RestitutionCombineMode": 0,
|
||||||
"DisableCCD": false,
|
"DisableCCD": false,
|
||||||
"BroadPhaseType": 3,
|
"BroadPhaseType": 3,
|
||||||
|
"EnableEnhancedDeterminism": false,
|
||||||
"SolverType": 0,
|
"SolverType": 0,
|
||||||
"MaxDeltaTime": 0.1,
|
"MaxDeltaTime": 0.1,
|
||||||
"EnableSubstepping": false,
|
"EnableSubstepping": false,
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
{
|
{
|
||||||
"ID": "a55dc3c04da4ea3744b7f1994565beac",
|
"ID": "a55dc3c04da4ea3744b7f1994565beac",
|
||||||
"TypeName": "FlaxEditor.Content.Settings.TimeSettings",
|
"TypeName": "FlaxEditor.Content.Settings.TimeSettings",
|
||||||
"EngineBuild": 6332,
|
"EngineBuild": 6705,
|
||||||
"Data": {
|
"Data": {
|
||||||
"UpdateMode": 1,
|
|
||||||
"UpdateFPS": 120.0,
|
"UpdateFPS": 120.0,
|
||||||
"PhysicsFPS": 120.0,
|
"PhysicsFPS": 120.0,
|
||||||
"DrawFPS": 120.0,
|
"DrawFPS": 120.0,
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
// comment
|
// comment
|
||||||
r_shadows 1
|
r_shadows 1
|
||||||
r_lighting 1
|
r_lighting 1
|
||||||
cl_maxfps 240
|
cl_maxfps 120
|
||||||
r_upscaling 0
|
r_upscaling 0
|
||||||
r_gi 0
|
r_gi 0
|
||||||
r_staticbatch 1
|
r_staticbatch 1
|
||||||
|
sensitivity 0.5
|
||||||
@@ -5,8 +5,8 @@
|
|||||||
"gulp.autoDetect": "off",
|
"gulp.autoDetect": "off",
|
||||||
"jake.autoDetect": "off",
|
"jake.autoDetect": "off",
|
||||||
"grunt.autoDetect": "off",
|
"grunt.autoDetect": "off",
|
||||||
"omnisharp.defaultLaunchSolution": "GoakeFlax.sln",
|
"omnisharp.useModernNet": true,
|
||||||
"omnisharp.useModernNet": true
|
"dotnet.defaultSolution": "GoakeFlax.sln"
|
||||||
},
|
},
|
||||||
"folders": [
|
"folders": [
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -137,7 +137,7 @@ public class CameraRender : PostProcessEffect
|
|||||||
private bool lastRescale = false;
|
private bool lastRescale = false;
|
||||||
public override void OnUpdate()
|
public override void OnUpdate()
|
||||||
{
|
{
|
||||||
#if FLAX_EDITOR
|
/*#if FLAX_EDITOR
|
||||||
if (Input.GetKeyDown(KeyboardKeys.F7))
|
if (Input.GetKeyDown(KeyboardKeys.F7))
|
||||||
{
|
{
|
||||||
PhysicsSettings physicsSettings = GameSettings.Load<PhysicsSettings>();
|
PhysicsSettings physicsSettings = GameSettings.Load<PhysicsSettings>();
|
||||||
@@ -145,7 +145,7 @@ public class CameraRender : PostProcessEffect
|
|||||||
GameSettings.Save(physicsSettings);
|
GameSettings.Save(physicsSettings);
|
||||||
//GameSettings.Apply();
|
//GameSettings.Apply();
|
||||||
}
|
}
|
||||||
#endif
|
#endif*/
|
||||||
|
|
||||||
if (lastEnabled != camera.IsActive)
|
if (lastEnabled != camera.IsActive)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -2,6 +2,10 @@
|
|||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using Console = Game.Console;
|
using Console = Game.Console;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading;
|
||||||
|
using FlaxEngine.Json;
|
||||||
|
|
||||||
|
|
||||||
#if FLAX_EDITOR
|
#if FLAX_EDITOR
|
||||||
using FlaxEditor;
|
using FlaxEditor;
|
||||||
#endif
|
#endif
|
||||||
@@ -135,6 +139,9 @@ public class ConsoleEditorPlugin : EditorPlugin
|
|||||||
|
|
||||||
private void OnPlayModeBegin()
|
private void OnPlayModeBegin()
|
||||||
{
|
{
|
||||||
|
if (!Level.Scenes.Any(x => x.ID == JsonSerializer.ParseID("194e05f445ece24ec5448d886e1334df"))) // MainScene
|
||||||
|
return;
|
||||||
|
|
||||||
//FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin;
|
//FlaxEditor.Editor.Instance.PlayModeBegin -= Instance_PlayModeBegin;
|
||||||
LoadConfig();
|
LoadConfig();
|
||||||
//GameMode.Connect();
|
//GameMode.Connect();
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
using FlaxEngine.Assertions;
|
using FlaxEngine.Assertions;
|
||||||
|
|
||||||
@@ -71,16 +72,16 @@ internal class ConsoleVariable
|
|||||||
if (type == typeof(string))
|
if (type == typeof(string))
|
||||||
{
|
{
|
||||||
if (field != null)
|
if (field != null)
|
||||||
return (string)field.GetValue(null);
|
return Unsafe.As<string>(field.GetValue(null));
|
||||||
if (getter != null)
|
if (getter != null)
|
||||||
return ((float)getter.Invoke(null, null)).ToString();
|
return Unsafe.As<string>(getter.Invoke(null, null));
|
||||||
}
|
}
|
||||||
else if (type == typeof(float))
|
else if (type == typeof(float))
|
||||||
{
|
{
|
||||||
if (field != null)
|
if (field != null)
|
||||||
return field.GetValue(null).ToString();
|
return field.GetValue(null).ToString();
|
||||||
if (getter != null)
|
if (getter != null)
|
||||||
return ((float)getter.Invoke(null, null)).ToString();
|
return getter.Invoke(null, null).ToString();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
throw new Exception($"ConsoleVariable: Unsupported variable type '{type.FullName}'");
|
throw new Exception($"ConsoleVariable: Unsupported variable type '{type.FullName}'");
|
||||||
|
|||||||
@@ -22,4 +22,16 @@ public static class Utilities
|
|||||||
Profiler.EndEvent();
|
Profiler.EndEvent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class VectorExtensions
|
||||||
|
{
|
||||||
|
/*extension(Float3 value)
|
||||||
|
{
|
||||||
|
Float2 XY => new Float2(value.X, value.Y);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public static Float2 XY(this Float3 vec) => new Float2(vec.X, vec.Y);
|
||||||
|
|
||||||
|
public static Vector2 XY(this Vector3 vec) => new Vector2(vec.X, vec.Y);
|
||||||
}
|
}
|
||||||
@@ -27,7 +27,13 @@ public class Game : GameModule
|
|||||||
public override void Setup(BuildOptions options)
|
public override void Setup(BuildOptions options)
|
||||||
{
|
{
|
||||||
options.ScriptingAPI.IgnoreMissingDocumentationWarnings = true;
|
options.ScriptingAPI.IgnoreMissingDocumentationWarnings = true;
|
||||||
//options.CompileEnv.PreprocessorDefinitions.Add("COMPILE_WITH_CSG_BUILDER");
|
options.ScriptingAPI.IgnoreSpecificWarnings.Add("CS9191"); // ref with in parameters
|
||||||
|
options.ScriptingAPI.IgnoreSpecificWarnings.Add("CS1717"); // assignment with itself
|
||||||
|
options.ScriptingAPI.IgnoreSpecificWarnings.Add("CS0219"); // assignment unused
|
||||||
|
options.ScriptingAPI.IgnoreSpecificWarnings.Add("CS0414"); // assignment unused
|
||||||
|
options.ScriptingAPI.IgnoreSpecificWarnings.Add("CS0649"); // default value assignment
|
||||||
|
|
||||||
|
options.CompileEnv.PreprocessorDefinitions.Add("COMPILE_WITH_CSG_BUILDER");
|
||||||
//options.PublicDefinitions.Add("COMPILE_WITH_CSG_BUILDER");
|
//options.PublicDefinitions.Add("COMPILE_WITH_CSG_BUILDER");
|
||||||
|
|
||||||
base.Setup(options);
|
base.Setup(options);
|
||||||
@@ -35,6 +41,8 @@ public class Game : GameModule
|
|||||||
//Tags["Network"] = string.Empty;
|
//Tags["Network"] = string.Empty;
|
||||||
//options.PublicDependencies.Add("Networking");
|
//options.PublicDependencies.Add("Networking");
|
||||||
|
|
||||||
|
//options.PublicDependencies.Add("FidelityFXFSR");
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//options.ScriptingAPI.FileReferences.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "DotNet", "Newtonsoft.Json.dll"));
|
//options.ScriptingAPI.FileReferences.Add(Path.Combine(Globals.EngineRoot, "Source", "Platforms", "DotNet", "Newtonsoft.Json.dll"));
|
||||||
@@ -50,7 +58,7 @@ public class Game : GameModule
|
|||||||
options.ScriptingAPI.Defines.Add("COMPILE_WITH_FSR1");
|
options.ScriptingAPI.Defines.Add("COMPILE_WITH_FSR1");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
options.PublicDependencies.Add("OnlinePlatformSteam");
|
//options.PublicDependencies.Add("OnlinePlatformSteam");
|
||||||
// Here you can modify the build options for your game module
|
// Here you can modify the build options for your game module
|
||||||
// To reference another module use: options.PublicDependencies.Add("Audio");
|
// To reference another module use: options.PublicDependencies.Add("Audio");
|
||||||
// To add C++ define use: options.PublicDefinitions.Add("COMPILE_WITH_FLAX");
|
// To add C++ define use: options.PublicDefinitions.Add("COMPILE_WITH_FLAX");
|
||||||
|
|||||||
@@ -161,10 +161,10 @@ public static partial class NetworkManager
|
|||||||
public static void Cleanup()
|
public static void Cleanup()
|
||||||
{
|
{
|
||||||
Scripting.Exit -= Cleanup;
|
Scripting.Exit -= Cleanup;
|
||||||
Scripting.FixedUpdate -= OnDemoUpdate;
|
Scripting.Update -= OnDemoUpdate;
|
||||||
Scripting.FixedUpdate -= OnServerNetworkUpdate;
|
Scripting.Update -= OnServerNetworkUpdate;
|
||||||
Level.ActorSpawned -= OnServerActorSpawned;
|
Level.ActorSpawned -= OnServerActorSpawned;
|
||||||
Scripting.FixedUpdate -= OnClientNetworkUpdate;
|
Scripting.Update -= OnClientNetworkUpdate;
|
||||||
Level.ActorSpawned -= OnClientActorSpawned;
|
Level.ActorSpawned -= OnClientActorSpawned;
|
||||||
|
|
||||||
if (server != null)
|
if (server != null)
|
||||||
|
|||||||
@@ -24,14 +24,17 @@ public static partial class NetworkManager
|
|||||||
|
|
||||||
//var driver = Object.New(typeof(ENetDriver));
|
//var driver = Object.New(typeof(ENetDriver));
|
||||||
//ClientNetworkDriver = null;
|
//ClientNetworkDriver = null;
|
||||||
NetworkLagDriver driver = Object.New<NetworkLagDriver>();
|
|
||||||
driver.Lag = 0f;
|
//INetworkDriver driver = Object.New<ENetDriver>();
|
||||||
|
INetworkDriver driver = Object.New<NetworkLagDriver>();
|
||||||
|
if (driver is NetworkLagDriver networkLagDriver)
|
||||||
|
networkLagDriver.Lag = 50.0f;
|
||||||
ClientNetworkDriver = driver;
|
ClientNetworkDriver = driver;
|
||||||
|
|
||||||
|
|
||||||
client = NetworkPeer.CreatePeer(new NetworkConfig
|
client = NetworkPeer.CreatePeer(new NetworkConfig
|
||||||
{
|
{
|
||||||
NetworkDriver = driver,
|
NetworkDriver = (Object)driver,
|
||||||
ConnectionsLimit = MaximumClients,
|
ConnectionsLimit = MaximumClients,
|
||||||
MessagePoolSize = 2048,
|
MessagePoolSize = 2048,
|
||||||
MessageSize = MTU,
|
MessageSize = MTU,
|
||||||
@@ -61,7 +64,7 @@ public static partial class NetworkManager
|
|||||||
}*/
|
}*/
|
||||||
World.InitClient();
|
World.InitClient();
|
||||||
|
|
||||||
Scripting.FixedUpdate += OnClientNetworkUpdate;
|
Scripting.Update += OnClientNetworkUpdate;
|
||||||
if (!listenServer)
|
if (!listenServer)
|
||||||
{
|
{
|
||||||
Scripting.Exit += Cleanup;
|
Scripting.Exit += Cleanup;
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ public static unsafe partial class NetworkManager
|
|||||||
return false;
|
return false;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
Scripting.FixedUpdate += OnDemoUpdate;
|
Scripting.Update += OnDemoUpdate;
|
||||||
//if (!listenServer)
|
//if (!listenServer)
|
||||||
{
|
{
|
||||||
Scripting.Exit += Cleanup;
|
Scripting.Exit += Cleanup;
|
||||||
|
|||||||
@@ -22,19 +22,21 @@ public static partial class NetworkManager
|
|||||||
|
|
||||||
public static bool StartServer(bool listenServer = true)
|
public static bool StartServer(bool listenServer = true)
|
||||||
{
|
{
|
||||||
|
Time.Synchronize();
|
||||||
Cleanup();
|
Cleanup();
|
||||||
ConnectedClients = new List<NetworkConnection>(MaximumClients);
|
ConnectedClients = new List<NetworkConnection>(MaximumClients);
|
||||||
|
|
||||||
|
|
||||||
//var driver = Object.New(typeof(ENetDriver));
|
INetworkDriver driver = Object.New<ENetDriver>();
|
||||||
//ServerNetworkDriver = null;
|
//NetworkLagDriver driver = Object.New<NetworkLagDriver>();
|
||||||
NetworkLagDriver driver = Object.New<NetworkLagDriver>();
|
if (driver is NetworkLagDriver networkLagDriver)
|
||||||
driver.Lag = 200f;
|
networkLagDriver.Lag = 50.0f;//200f;
|
||||||
|
|
||||||
ServerNetworkDriver = driver;
|
ServerNetworkDriver = driver;
|
||||||
|
|
||||||
server = NetworkPeer.CreatePeer(new NetworkConfig
|
server = NetworkPeer.CreatePeer(new NetworkConfig
|
||||||
{
|
{
|
||||||
NetworkDriver = driver,
|
NetworkDriver = (Object)driver,
|
||||||
ConnectionsLimit = MaximumClients,
|
ConnectionsLimit = MaximumClients,
|
||||||
MessagePoolSize = 2048,
|
MessagePoolSize = 2048,
|
||||||
MessageSize = MTU,
|
MessageSize = MTU,
|
||||||
@@ -47,7 +49,7 @@ public static partial class NetworkManager
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Scripting.FixedUpdate += OnServerNetworkUpdate;
|
Scripting.Update += OnServerNetworkUpdate;
|
||||||
Scripting.Exit += Cleanup;
|
Scripting.Exit += Cleanup;
|
||||||
Level.ActorSpawned += OnServerActorSpawned;
|
Level.ActorSpawned += OnServerActorSpawned;
|
||||||
|
|
||||||
|
|||||||
@@ -22,31 +22,25 @@ public enum GameModeMessageType2 : byte
|
|||||||
LastMessageType = 128,
|
LastMessageType = 128,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class PlayerFrame
|
||||||
|
{
|
||||||
|
public ulong frame => inputState.Frame;
|
||||||
|
public Float3 position;
|
||||||
|
public PlayerInputState2 inputState;
|
||||||
|
public PlayerMovementState movementState;
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IClientInfo
|
||||||
|
{
|
||||||
|
public NetworkConnection Connection { get; set; }
|
||||||
|
public PlayerActor PlayerActor { get; set; }
|
||||||
|
public PlayerFrame[] FrameHistory { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public class World
|
public class World
|
||||||
{
|
{
|
||||||
protected class ClientInfo
|
|
||||||
{
|
|
||||||
public NetworkConnection Connection;
|
|
||||||
public PlayerActor PlayerActor;
|
|
||||||
public PlayerFrame[] FrameHistory = new PlayerFrame[120];
|
|
||||||
|
|
||||||
public ClientInfo()
|
|
||||||
{
|
|
||||||
for (int i = 0; i < FrameHistory.Length; i++)
|
|
||||||
FrameHistory[i] = new PlayerFrame();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class PlayerFrame
|
|
||||||
{
|
|
||||||
public ulong frame;
|
|
||||||
public Float3 position;
|
|
||||||
public PlayerInputState2 inputState;
|
|
||||||
public PlayerMovementState movementState;
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsServer => this is ServerWorld;
|
public bool IsServer => this is ServerWorld;
|
||||||
public bool IsClient => !IsServer;
|
public bool IsClient => this is ClientWorld;
|
||||||
public ulong Frame { get; protected set; }
|
public ulong Frame { get; protected set; }
|
||||||
public ulong ServerFrame { get; protected set; } // Last received frame from server
|
public ulong ServerFrame { get; protected set; } // Last received frame from server
|
||||||
public float GameTime { get; protected set; } // The join time
|
public float GameTime { get; protected set; } // The join time
|
||||||
@@ -54,7 +48,6 @@ public class World
|
|||||||
|
|
||||||
protected Scene _scene;
|
protected Scene _scene;
|
||||||
protected Actor _worldSpawn;
|
protected Actor _worldSpawn;
|
||||||
protected Dictionary<uint, ClientInfo> _clients = new();
|
|
||||||
|
|
||||||
public static void InitClient()
|
public static void InitClient()
|
||||||
{
|
{
|
||||||
@@ -65,6 +58,9 @@ public class World
|
|||||||
{
|
{
|
||||||
WorldStore.ServerWorld = new ServerWorld();
|
WorldStore.ServerWorld = new ServerWorld();
|
||||||
WorldStore.ServerWorld.Init();
|
WorldStore.ServerWorld.Init();
|
||||||
|
Scripting.Update += WorldStore.ServerWorld.OnUpdate;
|
||||||
|
Scripting.LateUpdate += WorldStore.ServerWorld.OnUpdateLate;
|
||||||
|
Scripting.FixedUpdate += WorldStore.ServerWorld.OnFixedUpdate;
|
||||||
}
|
}
|
||||||
public static void CleanupClient()
|
public static void CleanupClient()
|
||||||
{
|
{
|
||||||
@@ -79,12 +75,17 @@ public class World
|
|||||||
|
|
||||||
virtual protected void Init()
|
virtual protected void Init()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
Scripting.LateFixedUpdate += OnLateUpdate;
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual protected void Cleanup()
|
virtual protected void Cleanup()
|
||||||
{
|
{
|
||||||
//Level.SceneLoaded -= OnLevelLoaded;
|
//Level.SceneLoaded -= OnLevelLoaded;
|
||||||
//Scripting.LateUpdate -= OnLateUpdatePre;
|
//Scripting.LateUpdate -= OnLateUpdatePre;
|
||||||
|
Scripting.Update -= OnUpdate;
|
||||||
|
Scripting.LateUpdate -= OnUpdateLate;
|
||||||
|
Scripting.FixedUpdate -= OnFixedUpdate;
|
||||||
Scripting.LateFixedUpdate -= OnLateUpdate;
|
Scripting.LateFixedUpdate -= OnLateUpdate;
|
||||||
|
|
||||||
if (_scene)
|
if (_scene)
|
||||||
@@ -99,14 +100,35 @@ public class World
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void OnUpdate()
|
||||||
|
{
|
||||||
|
//Console.Print("server Update");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnUpdateLate()
|
||||||
|
{
|
||||||
|
//Console.Print("server LateUpdate");
|
||||||
|
}
|
||||||
|
|
||||||
|
void OnFixedUpdate()
|
||||||
|
{
|
||||||
|
//Console.Print("server FixedUpdate");
|
||||||
|
}
|
||||||
|
|
||||||
protected void CreateScene(string sceneNamePrefix, string sceneGuid)
|
protected void CreateScene(string sceneNamePrefix, string sceneGuid)
|
||||||
{
|
{
|
||||||
string physicsSceneName = $"{sceneNamePrefix}PhysicsScene";
|
if (false && sceneNamePrefix == "Client")
|
||||||
PhysicsScene localPhysicsScene = Physics.FindOrCreateScene(physicsSceneName);
|
{
|
||||||
|
_scene = Level.Scenes.FirstOrDefault(x => !x.Name.StartsWith("Server"));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
string physicsSceneName = $"{sceneNamePrefix}PhysicsScene";
|
||||||
|
PhysicsScene localPhysicsScene = Physics.FindOrCreateScene(physicsSceneName);
|
||||||
|
|
||||||
Guid guid = JsonSerializer.ParseID(sceneGuid);
|
Guid guid = JsonSerializer.ParseID(sceneGuid);
|
||||||
string guidStr = JsonSerializer.GetStringID(guid);
|
string guidStr = JsonSerializer.GetStringID(guid);
|
||||||
string sceneData = $@"
|
string sceneData = $@"
|
||||||
{{
|
{{
|
||||||
""ID"": ""{guidStr}"",
|
""ID"": ""{guidStr}"",
|
||||||
""TypeName"": ""FlaxEngine.SceneAsset"",
|
""TypeName"": ""FlaxEngine.SceneAsset"",
|
||||||
@@ -129,25 +151,26 @@ public class World
|
|||||||
]
|
]
|
||||||
}}";
|
}}";
|
||||||
|
|
||||||
{
|
|
||||||
var onSceneLoaded = (Scene loadedScene, Guid id) =>
|
|
||||||
{
|
{
|
||||||
if (guid == id)
|
var onSceneLoaded = (Scene loadedScene, Guid id) =>
|
||||||
{
|
{
|
||||||
loadedScene.PhysicsScene = localPhysicsScene;
|
if (guid == id)
|
||||||
//scene = loadedScene;
|
{
|
||||||
}
|
loadedScene.PhysicsScene = localPhysicsScene;
|
||||||
};
|
//scene = loadedScene;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Level.SceneLoaded += onSceneLoaded;
|
Level.SceneLoaded += onSceneLoaded;
|
||||||
//Level.LoadScene(new SceneReference(guid));
|
//Level.LoadScene(new SceneReference(guid));
|
||||||
_scene = Level.LoadSceneFromBytes(Encoding.ASCII.GetBytes(sceneData));
|
_scene = Level.LoadSceneFromBytes(Encoding.ASCII.GetBytes(sceneData));
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
Level.SceneLoaded -= onSceneLoaded;
|
Level.SceneLoaded -= onSceneLoaded;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Assert.IsTrue(_scene);
|
Assert.IsTrue(_scene);
|
||||||
@@ -155,7 +178,7 @@ public class World
|
|||||||
_scene.Name = $"{sceneNamePrefix}Scene";
|
_scene.Name = $"{sceneNamePrefix}Scene";
|
||||||
|
|
||||||
//Level.SceneLoaded += OnLevelLoaded;
|
//Level.SceneLoaded += OnLevelLoaded;
|
||||||
Scripting.LateFixedUpdate += OnLateUpdate;
|
|
||||||
|
|
||||||
var importer = FlaxEngine.Object.New<Q3MapImporter>();
|
var importer = FlaxEngine.Object.New<Q3MapImporter>();
|
||||||
importer.mapPath = @"C:\dev\GoakeFlax\Assets\Maps\aerowalk.map";
|
importer.mapPath = @"C:\dev\GoakeFlax\Assets\Maps\aerowalk.map";
|
||||||
@@ -167,16 +190,12 @@ public class World
|
|||||||
Assert.IsTrue(_worldSpawn);
|
Assert.IsTrue(_worldSpawn);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void OnLateUpdate()
|
virtual protected void OnLateUpdate()
|
||||||
{
|
{
|
||||||
Frame++;
|
Frame++;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void OnClientConnected(NetworkConnection connection)
|
virtual protected IClientInfo GetClient(uint playerId) => null;
|
||||||
{
|
|
||||||
uint playerId = connection.ConnectionId;
|
|
||||||
_clients.Add(playerId, new ClientInfo() { Connection = connection });
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual protected PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles)
|
virtual protected PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles)
|
||||||
{
|
{
|
||||||
@@ -189,7 +208,8 @@ public class World
|
|||||||
playerActor.Initialize(playerId, position, eulerAngles);
|
playerActor.Initialize(playerId, position, eulerAngles);
|
||||||
//playerActor.Teleport(position, eulerAngles);
|
//playerActor.Teleport(position, eulerAngles);
|
||||||
|
|
||||||
_clients[playerId].PlayerActor = playerActor;
|
IClientInfo player = GetClient(playerId);
|
||||||
|
player.PlayerActor = playerActor;
|
||||||
IPlayerInput playerInput = playerActor.GetScript<PlayerMovement>().Input;
|
IPlayerInput playerInput = playerActor.GetScript<PlayerMovement>().Input;
|
||||||
playerInput.SetFrame(Frame);
|
playerInput.SetFrame(Frame);
|
||||||
/*if (IsServer)
|
/*if (IsServer)
|
||||||
@@ -211,14 +231,17 @@ public class World
|
|||||||
|
|
||||||
virtual public bool IsLocalPlayer(uint playerId) => false;
|
virtual public bool IsLocalPlayer(uint playerId) => false;
|
||||||
|
|
||||||
|
virtual public ulong GetLastProcessedFrame(uint playerId) => 0;
|
||||||
|
|
||||||
|
virtual public ulong GetLastReceivedFrame(uint playerId) => 0;
|
||||||
|
|
||||||
public PlayerFrame GetPlayerFrame(uint playerId, ulong frame)
|
public PlayerFrame GetPlayerFrame(uint playerId, ulong frame)
|
||||||
{
|
{
|
||||||
ClientInfo player = _clients[playerId];
|
IClientInfo player = GetClient(playerId);
|
||||||
PlayerFrame playerFrame = player.FrameHistory[frame % 120];
|
PlayerFrame playerFrame = player.FrameHistory[frame % 120];
|
||||||
if (playerFrame.frame != frame)
|
if (playerFrame.inputState.Frame == frame || playerFrame.movementState.frame == frame)
|
||||||
return null;
|
return playerFrame;
|
||||||
|
return null;
|
||||||
return playerFrame;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool HasPlayerFrame(uint playerId, ulong frame) => GetPlayerFrame(playerId, frame) != null;
|
public bool HasPlayerFrame(uint playerId, ulong frame) => GetPlayerFrame(playerId, frame) != null;
|
||||||
@@ -229,10 +252,70 @@ public class World
|
|||||||
inputState = playerFrame?.inputState ?? default;
|
inputState = playerFrame?.inputState ?? default;
|
||||||
return playerFrame != null;
|
return playerFrame != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
virtual public void UpdatePlayerInputState(uint playerId, ulong frame, PlayerInputState2 inputState, PlayerMovementState movementState)
|
||||||
|
{
|
||||||
|
IClientInfo player = GetClient(playerId);
|
||||||
|
|
||||||
|
PlayerFrame playerFrame = player.FrameHistory[frame % 120];
|
||||||
|
/*if (playerFrame.frame == frame)
|
||||||
|
{
|
||||||
|
var old = playerFrame.inputState with { Frame = inputState.Frame };
|
||||||
|
playerFrame.inputState = inputState with
|
||||||
|
{
|
||||||
|
ViewDelta = playerFrame.inputState.ViewDelta + inputState.ViewDelta,
|
||||||
|
MoveForward = MathF.MaxMagnitude(playerFrame.inputState.MoveForward, inputState.MoveForward),
|
||||||
|
MoveRight = MathF.MaxMagnitude(playerFrame.inputState.MoveRight, inputState.MoveRight),
|
||||||
|
Attack = playerFrame.inputState.Attack || inputState.Attack,
|
||||||
|
Jump = playerFrame.inputState.Jump || inputState.Jump,
|
||||||
|
};
|
||||||
|
|
||||||
|
if (old != playerFrame.inputState)
|
||||||
|
old = old;
|
||||||
|
}
|
||||||
|
else*/
|
||||||
|
playerFrame.inputState = inputState;
|
||||||
|
playerFrame.inputState.Frame = frame;
|
||||||
|
//playerFrame.movementState = movementState;
|
||||||
|
//playerFrame.frame = frame;
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual public void UpdatePlayerState(uint playerId, ulong frame, PlayerMovementState movementState)
|
||||||
|
{
|
||||||
|
IClientInfo player = GetClient(playerId);
|
||||||
|
PlayerFrame playerFrame = player.FrameHistory[frame % 120];
|
||||||
|
playerFrame.movementState = movementState;
|
||||||
|
playerFrame.movementState.frame = frame;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file class ServerWorld : World
|
file class ServerWorld : World
|
||||||
{
|
{
|
||||||
|
protected class ClientInfo : IClientInfo
|
||||||
|
{
|
||||||
|
public NetworkConnection Connection { get; set; }
|
||||||
|
public PlayerActor PlayerActor { get; set; }
|
||||||
|
public PlayerFrame[] FrameHistory { get; set; } = new PlayerFrame[120];
|
||||||
|
public ulong LastReceivedFrame = 0;
|
||||||
|
public ulong LastSentDeltaFrame = 0; // TODO: Accumulate deltas since this frame
|
||||||
|
public ulong LastProcessedFrame = 0; // In case player is lagged behind, these frames should be caught up during next simulation
|
||||||
|
public int SendRate = 0; // How many updates the client wants to receive per second
|
||||||
|
|
||||||
|
public ClientInfo()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < FrameHistory.Length; i++)
|
||||||
|
{
|
||||||
|
FrameHistory[i] = new PlayerFrame();
|
||||||
|
FrameHistory[i].inputState.Frame = ulong.MaxValue;
|
||||||
|
FrameHistory[i].movementState.frame = ulong.MaxValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected Dictionary<uint, ClientInfo> _clients = new();
|
||||||
|
|
||||||
|
protected override IClientInfo GetClient(uint playerId) => _clients[playerId];
|
||||||
|
|
||||||
protected override void Init()
|
protected override void Init()
|
||||||
{
|
{
|
||||||
NetworkManager.RegisterServerCallbacks(OnMessage, OnClientConnecting, OnClientConnected);
|
NetworkManager.RegisterServerCallbacks(OnMessage, OnClientConnecting, OnClientConnected);
|
||||||
@@ -249,6 +332,18 @@ file class ServerWorld : World
|
|||||||
base.Cleanup();
|
base.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected override void OnLateUpdate()
|
||||||
|
{
|
||||||
|
//Console.Print("server LateFixedUpdate");
|
||||||
|
base.OnLateUpdate();
|
||||||
|
|
||||||
|
foreach (var client in _clients.Values)
|
||||||
|
{
|
||||||
|
// We assume all the scripts have processed the frames during this cycle
|
||||||
|
client.LastProcessedFrame = client.LastReceivedFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public bool OnMessage(ref NetworkEvent networkEvent)
|
public bool OnMessage(ref NetworkEvent networkEvent)
|
||||||
{
|
{
|
||||||
byte messageTypeByte = networkEvent.Message.ReadByte();
|
byte messageTypeByte = networkEvent.Message.ReadByte();
|
||||||
@@ -266,23 +361,9 @@ file class ServerWorld : World
|
|||||||
{
|
{
|
||||||
case GameModeMessageType2.AcceptConnection: // Client
|
case GameModeMessageType2.AcceptConnection: // Client
|
||||||
{
|
{
|
||||||
AcceptConnectionMessage message = AcceptConnectionMessage.Read(ref networkEvent.Message);
|
break;
|
||||||
Frame += message.Frame;
|
|
||||||
GameTime = message.GameTime;
|
|
||||||
ServerFrame = message.Frame;
|
|
||||||
|
|
||||||
/*foreach (var player in message.Players)
|
|
||||||
{
|
|
||||||
SpawnPlayer(player.PlayerId, player.PlayerPosition, new Float3(0));
|
|
||||||
|
|
||||||
var playerFrames = new PlayerFrame[120];
|
|
||||||
for (int j = 0; j < playerFrames.Length; j++)
|
|
||||||
playerFrames[j] = new PlayerFrame();
|
|
||||||
clientWorldState.playerFrameHistory.Add(player.PlayerId, playerFrames);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
break;
|
case GameModeMessageType2.PlayerPosition: // FIXME: Should be the delta frame
|
||||||
case GameModeMessageType2.PlayerPosition:
|
|
||||||
{
|
{
|
||||||
//uint playerId = networkEvent.Sender.ConnectionId;
|
//uint playerId = networkEvent.Sender.ConnectionId;
|
||||||
PlayerInputState2 inputState; //?
|
PlayerInputState2 inputState; //?
|
||||||
@@ -308,16 +389,70 @@ file class ServerWorld : World
|
|||||||
actorState.jumped = networkEvent.Message.ReadBoolean();
|
actorState.jumped = networkEvent.Message.ReadBoolean();
|
||||||
|
|
||||||
//inputState.frame = receivedFrame;
|
//inputState.frame = receivedFrame;
|
||||||
inputState.ViewDelta.X = networkEvent.Message.ReadSingle();
|
//inputState.ViewDelta.X = networkEvent.Message.ReadSingle();
|
||||||
inputState.ViewDelta.Y = networkEvent.Message.ReadSingle();
|
//inputState.ViewDelta.Y = networkEvent.Message.ReadSingle();
|
||||||
inputState.MoveForward = networkEvent.Message.ReadSingle();
|
inputState.MoveForward = networkEvent.Message.ReadSingle();
|
||||||
inputState.MoveRight = networkEvent.Message.ReadSingle();
|
inputState.MoveRight = networkEvent.Message.ReadSingle();
|
||||||
inputState.Attack = networkEvent.Message.ReadBoolean();
|
inputState.Attack = networkEvent.Message.ReadBoolean();
|
||||||
inputState.Jump = networkEvent.Message.ReadBoolean();
|
inputState.Jump = networkEvent.Message.ReadBoolean();
|
||||||
|
|
||||||
ServerFrame = receivedFrame;
|
ServerFrame = receivedFrame;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case GameModeMessageType2.PlayerInput:
|
||||||
|
{
|
||||||
|
PlayerInputState2 inputState; //?
|
||||||
|
|
||||||
|
ulong receivedFrame = inputState.Frame = networkEvent.Message.ReadUInt64();
|
||||||
|
uint playerId = networkEvent.Message.ReadUInt32();
|
||||||
|
float time = networkEvent.Message.ReadSingle();
|
||||||
|
float delay = Time.TimeSinceStartup - time;
|
||||||
|
inputState.ViewDelta = Float2.Zero;
|
||||||
|
inputState.ViewAngles.X = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.ViewAngles.Y = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.MoveForward = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.MoveRight = networkEvent.Message.ReadSingle();
|
||||||
|
inputState.Attack = networkEvent.Message.ReadBoolean();
|
||||||
|
inputState.Jump = networkEvent.Message.ReadBoolean();
|
||||||
|
|
||||||
|
//Console.Print("recv: " + receivedFrame.ToString());
|
||||||
|
|
||||||
|
ClientInfo player = GetClient(playerId) as ClientInfo;
|
||||||
|
if (receivedFrame <= player.LastReceivedFrame)
|
||||||
|
{
|
||||||
|
if (receivedFrame < player.LastProcessedFrame)
|
||||||
|
{
|
||||||
|
Console.PrintWarning($"Dropping late frame from client: {receivedFrame}, last processed: {player.LastProcessedFrame}");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Console.PrintWarning($"Out-of-order frame received from client: {receivedFrame}, latest: {player.LastReceivedFrame}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player.LastReceivedFrame = Math.Max(receivedFrame, player.LastReceivedFrame);
|
||||||
|
//if (player.LastProcessedFrame == 0)
|
||||||
|
// player.LastProcessedFrame = receivedFrame - 1;
|
||||||
|
|
||||||
|
//Console.Print($"server receive client frame {receivedFrame}, current server frame {Frame}");
|
||||||
|
var asdf = receivedFrame;
|
||||||
|
//receivedFrame = Frame; // TODO: receive all frames from players, simulate all unprocessed frames in next simulation cycle?
|
||||||
|
|
||||||
|
if (inputState.MoveForward != 0)
|
||||||
|
receivedFrame = receivedFrame;
|
||||||
|
|
||||||
|
//Console.Print($"delay: {delay * 1000}ms");
|
||||||
|
|
||||||
|
// Sanity check
|
||||||
|
if (GetPlayerInputState(playerId, receivedFrame, out var prevInputState))
|
||||||
|
{
|
||||||
|
Console.PrintWarning($"Duplicate frame received from client: {asdf}, delay: {delay*1000}ms");
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdatePlayerInputState(playerId, receivedFrame, inputState, default);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -346,11 +481,10 @@ file class ServerWorld : World
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public new void OnClientConnected(NetworkConnection connection)
|
public void OnClientConnected(NetworkConnection connection)
|
||||||
{
|
{
|
||||||
base.OnClientConnected(connection);
|
|
||||||
uint playerId = connection.ConnectionId;
|
uint playerId = connection.ConnectionId;
|
||||||
|
_clients.Add(playerId, new ClientInfo() { Connection = connection });
|
||||||
|
|
||||||
var spawns = _worldSpawn.GetChildren<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
|
var spawns = _worldSpawn.GetChildren<Actor>().Where(x => x.Name.StartsWith("PlayerSpawn_")).ToArray();
|
||||||
Console.Print($"found {spawns.Length} spawns");
|
Console.Print($"found {spawns.Length} spawns");
|
||||||
@@ -375,12 +509,56 @@ file class ServerWorld : World
|
|||||||
NetworkManager.ServerEndSendMessage(ref message, connection);
|
NetworkManager.ServerEndSendMessage(ref message, connection);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override ulong GetLastProcessedFrame(uint playerId)
|
||||||
|
{
|
||||||
|
ClientInfo player = GetClient(playerId) as ClientInfo;
|
||||||
|
return player.LastProcessedFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ulong GetLastReceivedFrame(uint playerId)
|
||||||
|
{
|
||||||
|
ClientInfo player = GetClient(playerId) as ClientInfo;
|
||||||
|
return player.LastReceivedFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void UpdatePlayerInputState(uint playerId, ulong frame, PlayerInputState2 inputState, PlayerMovementState movementState)
|
||||||
|
{
|
||||||
|
base.UpdatePlayerInputState(playerId, frame, inputState, movementState);
|
||||||
|
|
||||||
|
//ClientInfo player = GetClient(playerId) as ClientInfo;
|
||||||
|
//player.LastReceivedFrame = frame; // Dropped frames should be ignored?
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override PlayerActor SpawnPlayer(uint playerId, Float3 position, Vector3 eulerAngles)
|
||||||
|
{
|
||||||
|
var playerActor = base.SpawnPlayer(playerId, position, eulerAngles);
|
||||||
|
playerActor.Input = new PlayerInputNetwork2(playerId, this);
|
||||||
|
return playerActor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
file class ClientWorld : World
|
file class ClientWorld : World
|
||||||
{
|
{
|
||||||
|
protected class ClientInfo : IClientInfo
|
||||||
|
{
|
||||||
|
public NetworkConnection Connection { get; set; }
|
||||||
|
public PlayerActor PlayerActor { get; set; }
|
||||||
|
public PlayerFrame[] FrameHistory { get; set; } = new PlayerFrame[120];
|
||||||
|
|
||||||
|
public ClientInfo()
|
||||||
|
{
|
||||||
|
for (int i = 0; i < FrameHistory.Length; i++)
|
||||||
|
FrameHistory[i] = new PlayerFrame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private uint _localPlayerId;
|
private uint _localPlayerId;
|
||||||
|
|
||||||
|
protected Dictionary<uint, ClientInfo> _clients = new();
|
||||||
|
|
||||||
|
protected override IClientInfo GetClient(uint playerId) => _clients[playerId];
|
||||||
|
|
||||||
protected override void Init()
|
protected override void Init()
|
||||||
{
|
{
|
||||||
NetworkManager.RegisterClientCallbacks(OnMessage, null, OnClientConnected);
|
NetworkManager.RegisterClientCallbacks(OnMessage, null, OnClientConnected);
|
||||||
@@ -396,6 +574,49 @@ file class ClientWorld : World
|
|||||||
base.Cleanup();
|
base.Cleanup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override protected void OnLateUpdate()
|
||||||
|
{
|
||||||
|
foreach (var player in _scene.GetChildren<PlayerActor>())
|
||||||
|
{
|
||||||
|
if (player.PlayerId != _localPlayerId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
ClientInfo playerClient = GetClient(player.PlayerId) as ClientInfo;
|
||||||
|
PlayerInputState2 inputState = player.Input.GetState();
|
||||||
|
PlayerMovementState movementState = player.GetScript<PlayerMovement>().movementState;
|
||||||
|
|
||||||
|
if (inputState.Frame == 0)
|
||||||
|
inputState = inputState;
|
||||||
|
/*public Float2 ViewDelta;
|
||||||
|
public float MoveForward;
|
||||||
|
public float MoveRight;
|
||||||
|
public bool Attack;
|
||||||
|
public bool Jump;*/
|
||||||
|
|
||||||
|
|
||||||
|
//Console.Print($"client send {Frame}");
|
||||||
|
UpdatePlayerInputState(player.PlayerId, Frame, inputState, movementState);
|
||||||
|
//Console.Print($"cframe: {Frame}");
|
||||||
|
|
||||||
|
NetworkMessage message = NetworkManager.ClientBeginSendMessage();
|
||||||
|
message.WriteByte((byte)GameModeMessageType2.PlayerInput);
|
||||||
|
message.WriteUInt64(Frame);
|
||||||
|
message.WriteUInt32(player.PlayerId);
|
||||||
|
message.WriteSingle(Time.TimeSinceStartup);
|
||||||
|
message.WriteSingle(movementState.viewAngles.X);
|
||||||
|
message.WriteSingle(movementState.viewAngles.Y);
|
||||||
|
//message.WriteSingle(movementState.viewAngles.Z);
|
||||||
|
message.WriteSingle(inputState.MoveForward);
|
||||||
|
message.WriteSingle(inputState.MoveRight);
|
||||||
|
message.WriteBoolean(inputState.Attack);
|
||||||
|
message.WriteBoolean(inputState.Jump);
|
||||||
|
NetworkManager.ClientEndSendMessage(ref message);
|
||||||
|
|
||||||
|
//Console.Print("send: " + Frame.ToString());
|
||||||
|
}
|
||||||
|
base.OnLateUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
public bool OnMessage(ref NetworkEvent networkEvent)
|
public bool OnMessage(ref NetworkEvent networkEvent)
|
||||||
{
|
{
|
||||||
byte messageTypeByte = networkEvent.Message.ReadByte();
|
byte messageTypeByte = networkEvent.Message.ReadByte();
|
||||||
@@ -426,8 +647,8 @@ file class ClientWorld : World
|
|||||||
}
|
}
|
||||||
|
|
||||||
Console.Print("received welcome: frame " + ServerFrame);
|
Console.Print("received welcome: frame " + ServerFrame);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
case GameModeMessageType2.SpawnPlayer:
|
case GameModeMessageType2.SpawnPlayer:
|
||||||
{
|
{
|
||||||
uint playerId = networkEvent.Message.ReadUInt32();
|
uint playerId = networkEvent.Message.ReadUInt32();
|
||||||
@@ -447,8 +668,8 @@ file class ClientWorld : World
|
|||||||
|
|
||||||
//if (NetworkManager.IsClient)
|
//if (NetworkManager.IsClient)
|
||||||
//players[playerId].GetScript<PlayerMovement>().Input.SetFrame(ClientFrame);
|
//players[playerId].GetScript<PlayerMovement>().Input.SetFrame(ClientFrame);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
#if false
|
#if false
|
||||||
case GameModeMessageType2.PlayerPosition:
|
case GameModeMessageType2.PlayerPosition:
|
||||||
{
|
{
|
||||||
@@ -484,8 +705,8 @@ file class ClientWorld : World
|
|||||||
inputState.Jump = networkEvent.Message.ReadBoolean();
|
inputState.Jump = networkEvent.Message.ReadBoolean();
|
||||||
|
|
||||||
ServerFrame = receivedFrame;
|
ServerFrame = receivedFrame;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
#endif
|
#endif
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@@ -496,10 +717,24 @@ file class ClientWorld : World
|
|||||||
|
|
||||||
public override bool IsLocalPlayer(uint playerId) => playerId == _localPlayerId;
|
public override bool IsLocalPlayer(uint playerId) => playerId == _localPlayerId;
|
||||||
|
|
||||||
public new void OnClientConnected(NetworkConnection connection)
|
public override ulong GetLastProcessedFrame(uint playerId)
|
||||||
{
|
{
|
||||||
base.OnClientConnected(connection);
|
//ClientInfo player = GetClient(playerId) as ClientInfo;
|
||||||
_localPlayerId = connection.ConnectionId;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override ulong GetLastReceivedFrame(uint playerId)
|
||||||
|
{
|
||||||
|
//ClientInfo player = GetClient(playerId) as ClientInfo;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnClientConnected(NetworkConnection connection)
|
||||||
|
{
|
||||||
|
uint playerId = connection.ConnectionId;
|
||||||
|
_clients.Add(playerId, new ClientInfo() { Connection = connection });
|
||||||
|
|
||||||
|
_localPlayerId = playerId;
|
||||||
Console.Print($"ClientWorld: Connected, playerId: {_localPlayerId}");
|
Console.Print($"ClientWorld: Connected, playerId: {_localPlayerId}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
948
Source/Game/MyScript.cpp
Normal file
948
Source/Game/MyScript.cpp
Normal file
@@ -0,0 +1,948 @@
|
|||||||
|
#include "MyScript.h"
|
||||||
|
|
||||||
|
#include "Engine/Content/Content.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"
|
||||||
|
#include "Engine/Render2D/FontAsset.h"
|
||||||
|
|
||||||
|
#define NEW_VERSION 0
|
||||||
|
#define TRACK_GCHANDLE_ALLOCS 1
|
||||||
|
|
||||||
|
#if NEW_VERSION
|
||||||
|
#define TRACK_GCHANDLE_ALLOCS 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if BUILD_DEBUG
|
||||||
|
#define LONGER 3
|
||||||
|
#define CHUNK_TIMES 100
|
||||||
|
#else
|
||||||
|
#define LONGER 10//*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)
|
||||||
|
#define TIMES_ONCE 1
|
||||||
|
|
||||||
|
MyScript2::MyScript2(const SpawnParams& params)
|
||||||
|
: Script(params)
|
||||||
|
{
|
||||||
|
// _tickUpdate = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MyScript::MyScript(const SpawnParams& params)
|
||||||
|
: Script(params)
|
||||||
|
{
|
||||||
|
// _tickUpdate = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double t95(int n) { return 1.96 + 2.4 / (n - 1.0); }
|
||||||
|
|
||||||
|
template<typename... TArgs>
|
||||||
|
void MyScript::BenchmarkCall(BenchmarkContext& context, void(MyScript2::* fun)(TArgs...),
|
||||||
|
TArgs... args)
|
||||||
|
{
|
||||||
|
long totalTimes = 0;
|
||||||
|
auto chunkTimes = CHUNK_TIMES;
|
||||||
|
const auto cycleTimes = 1 * LONGER;
|
||||||
|
const double minTime = 200;
|
||||||
|
const double maxMaxTime = 5000;
|
||||||
|
double maxTime = maxMaxTime;
|
||||||
|
const auto freq = Platform::GetClockFrequency();
|
||||||
|
context.results.Clear();
|
||||||
|
uint64 bestResult = UINT64_MAX;
|
||||||
|
|
||||||
|
{
|
||||||
|
auto start0 = Platform::GetTimeCycles();
|
||||||
|
for (int i = 0; i < 10; ++i)
|
||||||
|
(*context.scriptTwo.*fun)(args...);
|
||||||
|
auto end0 = Platform::GetTimeCycles();
|
||||||
|
auto elapsed0 = end0 - start0;
|
||||||
|
auto elapsed0ns = (elapsed0 * (1.0 / static_cast<double>(freq)) * 1000000000);
|
||||||
|
|
||||||
|
if (elapsed0 > 100000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 50;
|
||||||
|
else if (elapsed0 > 80000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 40;
|
||||||
|
else if (elapsed0 > 60000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 30;
|
||||||
|
else if (elapsed0 > 30000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 20;
|
||||||
|
else if (elapsed0 > 20000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 10;
|
||||||
|
else if (elapsed0 > 10000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 5;
|
||||||
|
else if (elapsed0 > 5000)
|
||||||
|
chunkTimes = CHUNK_TIMES / 2;
|
||||||
|
|
||||||
|
/*if (chunkTimes != CHUNK_TIMES)
|
||||||
|
LOG(Info, " - chunk times adjusted to {} (elapsed {})", chunkTimes, elapsed0);
|
||||||
|
else
|
||||||
|
LOG(Info, " - elapsed {}", elapsed0);*/
|
||||||
|
}
|
||||||
|
|
||||||
|
auto start1 = Platform::GetTimeCycles();
|
||||||
|
uint64 totaccum = 0;
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
uint64 previousBest = bestResult;
|
||||||
|
uint64 currentBest = UINT64_MAX;
|
||||||
|
auto start2 = Platform::GetTimeCycles();
|
||||||
|
for (int i = 0; i < cycleTimes; ++i)
|
||||||
|
{
|
||||||
|
auto start = Platform::GetTimeCycles();
|
||||||
|
for (int j = 0; j < chunkTimes; ++j)
|
||||||
|
(*context.scriptTwo.*fun)(args...);
|
||||||
|
auto end = Platform::GetTimeCycles();
|
||||||
|
auto elapsed = end - start;
|
||||||
|
|
||||||
|
if (elapsed < currentBest)
|
||||||
|
currentBest = elapsed;
|
||||||
|
context.results.Add(elapsed);
|
||||||
|
totaccum += elapsed;
|
||||||
|
}
|
||||||
|
auto end2 = Platform::GetTimeCycles();
|
||||||
|
auto elapsed2 = end2 - start2;
|
||||||
|
auto elapsed2Ms = (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000);
|
||||||
|
|
||||||
|
//Sorting::MergeSort(context.results);
|
||||||
|
totalTimes += cycleTimes * chunkTimes;
|
||||||
|
if (currentBest < bestResult)
|
||||||
|
bestResult = currentBest;
|
||||||
|
|
||||||
|
auto elapsed1 = Platform::GetTimeCycles() - start1;
|
||||||
|
auto elapsedMs = (elapsed1 * (1.0 / static_cast<double>(freq)) * 1000);
|
||||||
|
if (elapsedMs < minTime)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (context.results.Count() > 20)
|
||||||
|
{
|
||||||
|
double avg = (double)totaccum / context.results.Count();
|
||||||
|
//avg = (avg * (1.0 / static_cast<double>(freq)) * 1000000000);
|
||||||
|
|
||||||
|
double stdev = 0;
|
||||||
|
{
|
||||||
|
auto n = context.results.Count();
|
||||||
|
double s = 0.0;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
//double d = (context.results[i] * (1.0 / static_cast<double>(freq)) * 1000000000);
|
||||||
|
double d = (double)context.results[i];
|
||||||
|
d = d - avg;
|
||||||
|
s += d * d;
|
||||||
|
}
|
||||||
|
stdev = sqrt(s / (n - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
double ci = t95(context.results.Count()) * stdev / sqrt((double)context.results.Count());
|
||||||
|
double rel = (ci / avg) * 100;
|
||||||
|
if (rel < 1.0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (elapsedMs >= maxTime)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
double avg = (double)totaccum / context.results.Count();
|
||||||
|
avg = (avg * (1.0 / static_cast<double>(freq)) * 1000000000);
|
||||||
|
|
||||||
|
double stdev = 0;
|
||||||
|
{
|
||||||
|
auto n = context.results.Count();
|
||||||
|
double s = 0.0;
|
||||||
|
for (int i = 0; i < n; ++i) {
|
||||||
|
double d = (context.results[i] * (1.0 / static_cast<double>(freq)) * 1000000000);
|
||||||
|
d = d - avg;
|
||||||
|
s += d * d;
|
||||||
|
}
|
||||||
|
stdev = sqrt(s / (n - 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
double ci = t95(context.results.Count()) * stdev / sqrt((double)context.results.Count());
|
||||||
|
double rel = (ci / avg) * 100;
|
||||||
|
ci /= chunkTimes;
|
||||||
|
stdev /= chunkTimes;
|
||||||
|
avg /= chunkTimes;
|
||||||
|
|
||||||
|
auto elapsed1 = Platform::GetTimeCycles() - start1;
|
||||||
|
const auto bestResultNs = (bestResult * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes);
|
||||||
|
LOG(Info, " - VirtualCall: {:.1f}ns +-{:.1f}ns, std:{:.1f}ns, {:.1f}%, avg:{:.1f} ({:.0f}ms/{})", bestResultNs, ci, stdev, rel, avg, (elapsed1 * (1.0 / static_cast<double>(freq)) * 1000), totalTimes, ci);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MyScript::OnStart()
|
||||||
|
{
|
||||||
|
LOG(Info, "C++ OnStart");
|
||||||
|
MyScript2* scriptTwo = (MyScript2*)GetActor()->GetScript(1);
|
||||||
|
if (scriptTwo == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
bool callTests = true;
|
||||||
|
bool thunkTests = false;
|
||||||
|
bool invokeTests = false; // requires manual type conversion
|
||||||
|
bool coverageTests = false;
|
||||||
|
|
||||||
|
bool otherTests = true;
|
||||||
|
bool arrayTests = true;
|
||||||
|
bool asRefTests = true;
|
||||||
|
|
||||||
|
Array<uint64> results(TIMES);
|
||||||
|
auto CyclesToSeconds = 1.0 / static_cast<double>(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<int> simpleArray; for (int i=0; i<10; i++) simpleArray.Add(i);
|
||||||
|
Array<Actor*> actorArray; for (int i=0; i<10; i++) actorArray.Add(actor);
|
||||||
|
TestStruct testStruct; testStruct.Object = actor; testStruct.SceneRef = sceneRef;
|
||||||
|
Array<TestStruct> complexArray; for (int i=0; i<10; i++) complexArray.Add(testStruct);
|
||||||
|
StringStruct stringStruct;
|
||||||
|
Array<StringStruct> stringStructArray; for (int i = 0; i < 10; i++) stringStructArray.Add(stringStruct);
|
||||||
|
|
||||||
|
BenchmarkContext benchmarkContext;
|
||||||
|
benchmarkContext.scriptTwo = scriptTwo;
|
||||||
|
benchmarkContext.results = results;
|
||||||
|
|
||||||
|
// Coverage
|
||||||
|
if (coverageTests)
|
||||||
|
{
|
||||||
|
int32 integer = 1;
|
||||||
|
bool boolean = true;
|
||||||
|
Float3 f3(1.0f, 2.0f, 3.0f);
|
||||||
|
Guid fontAssetGuid; Guid::Parse("ab96b25a49461d9f4f819484cf5c8213", fontAssetGuid);
|
||||||
|
FontAsset* fontAsset = Content::LoadAsync<FontAsset>(fontAssetGuid);
|
||||||
|
NetworkChannelType networkChannelType = NetworkChannelType::Reliable;
|
||||||
|
OnlineLeaderboardSortModes onlineLeaderboardSortModes = OnlineLeaderboardSortModes::Ascending;
|
||||||
|
OnlineLeaderboardValueFormats onlineLeaderboardValueFormats = OnlineLeaderboardValueFormats::Numeric;
|
||||||
|
AssetReference<FontAsset> fontAssetRef(fontAsset);
|
||||||
|
ModelLOD* lod = nullptr;
|
||||||
|
|
||||||
|
Array<int32> ints(&integer, 1);
|
||||||
|
Array<bool> booleans(&boolean, 1);
|
||||||
|
Array<Actor*> actors(&actor, 1);
|
||||||
|
Array<String> strings(&shortString, 1);
|
||||||
|
Array<StringAnsi> ansiStrings(&shortStringAnsi, 1);
|
||||||
|
Array<Float3> float3s(&f3, 1);
|
||||||
|
Array<ModelLOD*> lods(&lod, 1);
|
||||||
|
BytesContainer bytes;
|
||||||
|
bytes.Append((byte*)&f3, sizeof(Float3));
|
||||||
|
BytesContainer bytesOut;
|
||||||
|
|
||||||
|
COVERAGE_CALL_ARGS6(CoverageTest1, integer, boolean, actor, shortString, shortStringAnsi, f3);
|
||||||
|
COVERAGE_CALL_ARGS6(CoverageTest1Array, ints, booleans, actors, strings, ansiStrings, float3s);
|
||||||
|
|
||||||
|
COVERAGE_CALL_ARGS5(CoverageTest1ByRef, integer, boolean/*, actor*/, shortString, shortStringAnsi, f3);
|
||||||
|
//COVERAGE_CALL_ARGS5(CoverageTest1ArrayByRef, ints, booleans/*, actors*/, strings, ansiStrings, float3s);
|
||||||
|
COVERAGE_CALL_ARGS4(CoverageTest2, fontAssetGuid, fontAssetRef, Array<Guid>(&fontAssetGuid, 1), Array<AssetReference<FontAsset>>(&fontAssetRef, 1));
|
||||||
|
COVERAGE_CALL_ARGS2(CoverageTest3, lod, lods);
|
||||||
|
//COVERAGE_CALL_ARGS2(CoverageTest4, bytes, bytesOut);
|
||||||
|
COVERAGE_CALL_ARGS6(CoverageNamespaces1, networkChannelType, Array<NetworkChannelType>(&networkChannelType, 1), onlineLeaderboardSortModes, Array<OnlineLeaderboardSortModes>(&onlineLeaderboardSortModes, 1), onlineLeaderboardValueFormats, Array<OnlineLeaderboardValueFormats>(&onlineLeaderboardValueFormats, 1));
|
||||||
|
|
||||||
|
scriptTwo->ManagedCoverageTests();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warmup busy-loop
|
||||||
|
{
|
||||||
|
const auto freq = Platform::GetClockFrequency();
|
||||||
|
auto startt = Platform::GetTimeCycles();
|
||||||
|
auto elapsedMs = ((Platform::GetTimeCycles() - startt) * (1.0 / static_cast<double>(freq)) * 1000);
|
||||||
|
while (elapsedMs > 2000)
|
||||||
|
{
|
||||||
|
elapsedMs = ((Platform::GetTimeCycles() - startt) * (1.0 / static_cast<double>(freq)) * 1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TRACK_GCHANDLE_ALLOCS
|
||||||
|
int64 allocationsBefore, deallocationsBefore;
|
||||||
|
scriptTwo->GetStats(allocationsBefore, deallocationsBefore);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(SimpleCall);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::SimpleCall);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS0(TIMES2, SimpleCall);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS0();
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS0(TIMES2, SimpleCall);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(SimpleParams);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::SimpleParams, (int32)1, (float)2, '3', (double)4, (int64)5);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS5(TIMES3, SimpleParams);
|
||||||
|
params[0] = MUtils::Box<int>(1, MCore::TypeCache::Int32);
|
||||||
|
params[1] = MUtils::Box<float>(2, MCore::TypeCache::Single);
|
||||||
|
params[2] = MUtils::Box<char>('3', MCore::TypeCache::SByte);
|
||||||
|
params[3] = MUtils::Box<double>(4, MCore::TypeCache::Double);
|
||||||
|
params[4] = MUtils::Box<long>(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();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
//#if NEW_VERSION
|
||||||
|
/*BENCHMARK_INVOKE_ARGS5(TIMES3, SimpleParams,
|
||||||
|
(int32)1,
|
||||||
|
(float)2,
|
||||||
|
(char)'3',
|
||||||
|
(double)4,
|
||||||
|
(int64)5);*/
|
||||||
|
//#else
|
||||||
|
int32 a = 1;
|
||||||
|
float b = 2;
|
||||||
|
char c = 3;
|
||||||
|
double d = 4;
|
||||||
|
int64 e = 5;
|
||||||
|
BENCHMARK_INVOKE_ARGS5(TIMES3, SimpleParams,
|
||||||
|
(void*)&a,
|
||||||
|
(void*)&b,
|
||||||
|
(void*)&c,
|
||||||
|
(void*)&d,
|
||||||
|
(void*)&e);
|
||||||
|
//#endif
|
||||||
|
/*void* params[5];
|
||||||
|
{
|
||||||
|
auto klass = MyScript2::GetStaticClass();
|
||||||
|
auto method = klass->GetMethod("SimpleParams", 5);
|
||||||
|
auto instance = scriptTwo->GetManagedInstance();
|
||||||
|
MObject* exception = nullptr;
|
||||||
|
const auto times = (100 * 3);
|
||||||
|
const auto chunkTimes = 100;
|
||||||
|
const auto freq = Platform::GetClockFrequency();
|
||||||
|
params[0] = MUtils::Box<int32>(1, MCore::TypeCache::Int32);
|
||||||
|
params[1] = MUtils::Box<float>(2, MCore::TypeCache::Single);
|
||||||
|
params[2] = MUtils::Box<char>('3', MCore::TypeCache::SByte);
|
||||||
|
params[3] = MUtils::Box<double>(4, MCore::TypeCache::Double);
|
||||||
|
params[4] = MUtils::Box<int64>(5, MCore::TypeCache::Int64);
|
||||||
|
results.Clear();
|
||||||
|
auto start2 = Platform::GetTimeCycles();
|
||||||
|
for (int i = 0; i < times; ++i)
|
||||||
|
{
|
||||||
|
auto start = Platform::GetTimeCycles();
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) method->Invoke(instance, params, &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::Logger::Write(LogType::Info, ::String::Format(L" - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times * chunkTimes));
|
||||||
|
};*/
|
||||||
|
#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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringParamAnsi);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::StringParamAnsi, shortStringAnsi);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamAnsi);
|
||||||
|
params[0] = MUtils::Box<StringAnsi>(shortStringAnsi, MCore::TypeCache::String);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<StringAnsi>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES2, StringParamAnsi,
|
||||||
|
MUtils::Box<StringAnsi>(shortStringAnsi, MCore::TypeCache::String));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<StringAnsi>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::StringParam, shortString);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParam);
|
||||||
|
params[0] = MUtils::Box<String>(shortString, MCore::TypeCache::String);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES2, StringParam,
|
||||||
|
MUtils::Box<String>(shortString, MCore::TypeCache::String));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#if false
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringParamRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(&MyScript2::StringParamRef, shortString);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamRef);
|
||||||
|
params[0] = MUtils::Box<String>(shortString, MCore::TypeCache::String);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES2, StringParamRef,
|
||||||
|
MUtils::Box<String>(shortString, MCore::TypeCache::String));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringParamRefConst);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall<const String&>(benchmarkContext, &MyScript2::StringParamRefConst, shortString);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, StringParamRefConst);
|
||||||
|
params[0] = MUtils::Box<String>(shortString, MCore::TypeCache::String);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES2, StringParamRefConst,
|
||||||
|
MUtils::Box<String>(shortString, MCore::TypeCache::String));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (asRefTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringParamAsRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
String str = shortString;
|
||||||
|
BenchmarkCall<String&>(benchmarkContext, &MyScript2::StringParamAsRef, str);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
LOG(Info, " - InvokeThunkOnly: not valid");
|
||||||
|
/* str = shortString;
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, StringParamAsRef);
|
||||||
|
#if NEW_VERSION
|
||||||
|
auto __param_orig_str = MUtils::Box<String>(str, MCore::TypeCache::String);
|
||||||
|
auto __param_str = __param_orig_str;
|
||||||
|
params[0] = &__param_str;
|
||||||
|
#else
|
||||||
|
auto __param_str = MUtils::Box<String>(str, MCore::TypeCache::String);
|
||||||
|
params[0] = &__param_str;
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1_REF({ params[0] = &__param_str; });
|
||||||
|
str = MUtils::Unbox<String>(*(MObject**)params[0]);
|
||||||
|
ASSERT(str == shortString);
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<String>((MObject*)__param_str);
|
||||||
|
if (__param_orig_str != __param_str)
|
||||||
|
MUtils::FreeManaged<String>((MObject*)__param_orig_str);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();*/
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
String str = shortString;
|
||||||
|
#if NEW_VERSION
|
||||||
|
BENCHMARK_INVOKE_ARGS1_REF(TIMES3, StringParamAsRef,
|
||||||
|
MUtils::Box<String>(shortString, MCore::TypeCache::String),
|
||||||
|
MUtils::FreeManaged<String>);
|
||||||
|
#else
|
||||||
|
BENCHMARK_INVOKE_ARGS1_REF(TIMES3, StringParamAsRef,
|
||||||
|
MUtils::Box<String>(shortString, MCore::TypeCache::String),
|
||||||
|
{});
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(ActorParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::ActorParam, actor);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, ActorParam);
|
||||||
|
params[0] = ScriptingObject::ToManaged((ScriptingObject*)actor);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES2, ActorParam,
|
||||||
|
ScriptingObject::ToManaged((ScriptingObject*)actor));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(ComplexParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::ComplexParam, behaviorUpdateContext);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES2, ComplexParam);
|
||||||
|
params[0] = MUtils::Box<BehaviorUpdateContext>(behaviorUpdateContext, BehaviorUpdateContext::TypeInitializer.GetClass());
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<BehaviorUpdateContext>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
//auto param1 = MUtils::Box<BehaviorUpdateContext>(behaviorUpdateContext, BehaviorUpdateContext::TypeInitializer.GetClass());
|
||||||
|
/*void* params[1];
|
||||||
|
{
|
||||||
|
auto klass = MyScript2::GetStaticClass();
|
||||||
|
auto method = klass->GetMethod("ComplexParam", 1);
|
||||||
|
auto instance = scriptTwo->GetManagedInstance();
|
||||||
|
MObject* exception = nullptr;
|
||||||
|
const auto times = (1000 * 3);
|
||||||
|
const auto chunkTimes = 100;
|
||||||
|
const auto freq = Platform::GetClockFrequency();
|
||||||
|
params[0] = &behaviorUpdateContext;
|
||||||
|
results.Clear();
|
||||||
|
auto start2 = Platform::GetTimeCycles();
|
||||||
|
for (int i = 0; i < times; ++i) {
|
||||||
|
auto start = Platform::GetTimeCycles();
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) method->Invoke(instance, params, &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::Logger::Write(LogType::Info, ::String::Format(L" - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times * chunkTimes));
|
||||||
|
};*/
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES2, ComplexParam, &behaviorUpdateContext);
|
||||||
|
#if NEW_VERSION
|
||||||
|
//MUtils::FreeManaged<BehaviorUpdateContext>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(Complex2Param);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall<RenderContext&>(benchmarkContext, &MyScript2::Complex2Param, renderContext);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2Param);
|
||||||
|
params[0] = MUtils::Box<RenderContext>(renderContext, RenderContext::TypeInitializer.GetClass());
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES3, Complex2Param, &renderContext);
|
||||||
|
#if NEW_VERSION
|
||||||
|
//MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(Complex2ParamConst);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall<const RenderContext&>(benchmarkContext, &MyScript2::Complex2ParamConst, renderContext);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2ParamConst);
|
||||||
|
params[0] = MUtils::Box<RenderContext>(renderContext, RenderContext::TypeInitializer.GetClass());
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES3, Complex2ParamConst, &renderContext);
|
||||||
|
#if NEW_VERSION
|
||||||
|
//MUtils::FreeManaged<RenderContext>((MObject*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (asRefTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(Complex2ParamAsRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
RenderContext context = renderContext;
|
||||||
|
BenchmarkCall<RenderContext&>(benchmarkContext, &MyScript2::Complex2ParamAsRef, context);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
LOG(Info, " - InvokeThunkOnly: not valid");
|
||||||
|
/* context = renderContext;
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, Complex2ParamAsRef);
|
||||||
|
#if NEW_VERSION
|
||||||
|
auto __param_orig_context = MUtils::Box<RenderContext>(context, RenderContext::TypeInitializer.GetClass());
|
||||||
|
auto __param_context = __param_orig_context;
|
||||||
|
params[0] = &__param_context;
|
||||||
|
#else
|
||||||
|
auto __param_context = MUtils::Box<RenderContext>(context, RenderContext::TypeInitializer.GetClass());
|
||||||
|
params[0] = &__param_context;
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1_REF({ if (__param_orig_context != __param_context) MUtils::FreeManaged<RenderContext>((MObject*)__param_orig_context); params[0] = &__param_context; });
|
||||||
|
context = MUtils::Unbox<RenderContext>(*(MObject**)params[0]);
|
||||||
|
ASSERT(context.Buffers == renderContext.Buffers);
|
||||||
|
ASSERT(context.Task == renderContext.Task);
|
||||||
|
#if NEW_VERSION
|
||||||
|
context = MUtils::Unbox<RenderContext>(*(MObject**)params[0]);
|
||||||
|
MUtils::FreeManaged<RenderContext>((MObject*)__param_context);
|
||||||
|
if (__param_orig_context != __param_context)
|
||||||
|
MUtils::FreeManaged<RenderContext>((MObject*)__param_orig_context);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();*/
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (arrayTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(SimpleArrayParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::SimpleArrayParam, simpleArray);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, SimpleArrayParam);
|
||||||
|
params[0] = MUtils::ToArray(simpleArray, MCore::TypeCache::Int32);
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<int>((MArray*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES3, SimpleArrayParam,
|
||||||
|
MUtils::ToArray(simpleArray, MCore::TypeCache::Int32));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<int>((MArray*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrayTests && asRefTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(SimpleArrayParamAsRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
Array<int> arr = simpleArray;
|
||||||
|
BenchmarkCall<Array<int32>&>(benchmarkContext, &MyScript2::SimpleArrayParamAsRef, simpleArray);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
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<Array<int>>(*(MObject**)params[0]);
|
||||||
|
ASSERT(arr.Count() == simpleArray.Count());
|
||||||
|
for (int i=0; i<arr.Count(); i++) ASSERT(arr[i] == simpleArray[i]);
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<int>(__param_arr); //fgfgh3
|
||||||
|
if (__param_orig_arr != __param_arr)
|
||||||
|
MUtils::FreeManagedArray<int>(__param_orig_arr); //fgfgh4
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();*/
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (arrayTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(ActorArrayParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::ActorArrayParam, actorArray);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, ActorArrayParam);
|
||||||
|
params[0] = MUtils::ToArray(actorArray, Actor::TypeInitializer.GetClass());
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<Actor*>((MArray*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES3, ActorArrayParam,
|
||||||
|
MUtils::ToArray(actorArray, Actor::TypeInitializer.GetClass()));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<Actor*>((MArray*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (otherTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringFieldStructParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall<StringStruct&>(benchmarkContext, &MyScript2::StringFieldStructParam, stringStruct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (otherTests && asRefTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringFieldStructParamAsRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
StringStruct ss = stringStruct;
|
||||||
|
BenchmarkCall<StringStruct&>(benchmarkContext, &MyScript2::StringFieldStructParamAsRef, ss);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrayTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringFieldStructArrayParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall<Array<StringStruct>&>(benchmarkContext, &MyScript2::StringFieldStructArrayParam, stringStructArray);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrayTests && asRefTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(StringFieldStructArrayParamAsRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
Array<StringStruct> arr = stringStructArray;
|
||||||
|
BenchmarkCall<Array<StringStruct>&>(benchmarkContext, &MyScript2::StringFieldStructArrayParamAsRef, arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrayTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(ComplexArrayParam);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
BenchmarkCall(benchmarkContext, &MyScript2::ComplexArrayParam, complexArray);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_THUNK_BEGIN_ARGS1(TIMES3, ComplexArrayParam);
|
||||||
|
params[0] = MUtils::ToArray(complexArray, TestStruct::TypeInitializer.GetClass());
|
||||||
|
BENCHMARK_THUNK_CALL_ARGS1();
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<TestStruct>((MArray*)params[0]);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
if (invokeTests)
|
||||||
|
{
|
||||||
|
BENCHMARK_INVOKE_ARGS1(TIMES3, ComplexArrayParam,
|
||||||
|
MUtils::ToArray(complexArray, TestStruct::TypeInitializer.GetClass()));
|
||||||
|
#if NEW_VERSION
|
||||||
|
MUtils::FreeManagedArray<TestStruct>((MArray*)params[0]);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (arrayTests && asRefTests)
|
||||||
|
{
|
||||||
|
LOG_TEST(ComplexArrayParamAsRef);
|
||||||
|
if (callTests)
|
||||||
|
{
|
||||||
|
Array<TestStruct> arr = complexArray;
|
||||||
|
BenchmarkCall<Array<TestStruct>&>(benchmarkContext, &MyScript2::ComplexArrayParamAsRef, arr);
|
||||||
|
}
|
||||||
|
if (thunkTests)
|
||||||
|
{
|
||||||
|
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<Array<TestStruct>>(*(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::FreeManagedArray<TestStruct>(__param_arr);
|
||||||
|
if (__param_orig_arr != __param_arr)
|
||||||
|
MUtils::FreeManagedArray<TestStruct>(__param_orig_arr);
|
||||||
|
#endif
|
||||||
|
BENCHMARK_THUNK_END();*/
|
||||||
|
}
|
||||||
|
//else
|
||||||
|
// LOG(Info, " - InvokeThunkOnly: skipped");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TRACK_GCHANDLE_ALLOCS
|
||||||
|
int64 allocationsAfter, deallocationsAfter;
|
||||||
|
scriptTwo->GetStats(allocationsAfter, deallocationsAfter);
|
||||||
|
int64 allocationsDiff = allocationsAfter-allocationsBefore;
|
||||||
|
int64 deallocationsDiff = deallocationsAfter-deallocationsBefore;
|
||||||
|
int64 leftover = allocationsDiff - deallocationsDiff;
|
||||||
|
LOG(Info, "Total ManagedHandle allocations: {}, deallocations: {}, leftover: {}", allocationsDiff, deallocationsDiff, leftover);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
}
|
||||||
522
Source/Game/MyScript.h
Normal file
522
Source/Game/MyScript.h
Normal file
@@ -0,0 +1,522 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Scripting/Script.h"
|
||||||
|
#include <Engine/Animations/Curve.h>
|
||||||
|
#include <Engine/AI/Behavior.h>
|
||||||
|
|
||||||
|
#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"
|
||||||
|
#include "Engine/Content/Assets/Model.h"
|
||||||
|
#include "Engine/Networking/NetworkChannelType.h"
|
||||||
|
#include "Engine/Online/IOnlinePlatform.h"
|
||||||
|
#include "Engine/Render2D/FontAsset.h"
|
||||||
|
|
||||||
|
API_STRUCT(NoDefault) struct StringStruct : public ISerializable
|
||||||
|
{
|
||||||
|
API_AUTO_SERIALIZATION();
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(StringStruct);
|
||||||
|
|
||||||
|
API_FIELD() String StringContent = TEXT("test");
|
||||||
|
API_FIELD() String StringEmpty = TEXT("");
|
||||||
|
API_FIELD() String StringEmpty2 = String::Empty;
|
||||||
|
API_FIELD() String StringNull = nullptr;
|
||||||
|
};
|
||||||
|
|
||||||
|
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<ScriptingObject> 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 GetStats(API_PARAM(Ref) int64& allocations, API_PARAM(Ref) int64& deallocations) {};
|
||||||
|
|
||||||
|
API_FUNCTION() virtual void ManagedCoverageTests() {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest1(int32 intParam, bool boolParam, Actor* actorParam, String& stringRefParam, StringAnsi& stringAnsiRefParam, Float3 float3Param) {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest1Array(Array<int32> intArrayParam, Array<bool> boolArrayParam, Array<Actor*> actorArrayParam, Array<String> stringArrayParam, Array<StringAnsi> stringAnsiArrayParam, Array<Float3> float3ArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest1ByRef(API_PARAM(Ref) int32& intRefParam, API_PARAM(Ref) bool& boolRefParam, API_PARAM(Ref) String& stringRefParam, API_PARAM(Ref) StringAnsi& stringAnsiRefParam, API_PARAM(Ref) Float3& float3RefParam) {};
|
||||||
|
#if false
|
||||||
|
//APIa_FUNCTION() virtual void CoverageTest1ArrayByRef(API_PARAM(Ref) Array<int32>& intArrayRefParam, API_PARAM(Ref) Array<bool>& boolArrayRefParam, API_PARAM(Ref) Array<String>& stringArrayRefParam, API_PARAM(Ref) Array<StringAnsi>& stringAnsiArrayRefParam, API_PARAM(Ref) Array<Float3>& float3ArrayRefParam) {};
|
||||||
|
#endif
|
||||||
|
API_FUNCTION() virtual void CoverageTest2(Guid guidParam, AssetReference<FontAsset> fontAssetReferenceParam, Array<Guid> guidArrayParam, Array<AssetReference<FontAsset>> fontAssetReferenceArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest3(ModelLOD* modelLodParam, API_PARAM(Out) Array<ModelLOD*>& modelLodArrayParam) {};
|
||||||
|
#if false
|
||||||
|
//APIa_FUNCTION() virtual void CoverageTest4(BytesContainer bytesContainerParam, API_PARAM(Out) BytesContainer& bytesContainerOutParam) {};
|
||||||
|
#endif
|
||||||
|
API_FUNCTION() virtual void CoverageNamespaces1(NetworkChannelType a, Array<NetworkChannelType> b, OnlineLeaderboardSortModes c, Array<OnlineLeaderboardSortModes> d, OnlineLeaderboardValueFormats e, Array<OnlineLeaderboardValueFormats> f) {};
|
||||||
|
|
||||||
|
API_FUNCTION() virtual void SimpleCall() { ASSERT(false); };
|
||||||
|
API_FUNCTION() virtual void SimpleParams(int32 intParam, float boolParam, char charParam, double doubleParam, int64 int64Param) {};
|
||||||
|
API_FUNCTION() virtual void StringParamAnsi(StringAnsi str) {};
|
||||||
|
API_FUNCTION() virtual void StringParam(String str) {};
|
||||||
|
#if false
|
||||||
|
//API_FUNCTION() virtual void StringParamRef(String& str) {};
|
||||||
|
#endif
|
||||||
|
API_FUNCTION() virtual void StringParamRefConst(const String& str) {};
|
||||||
|
API_FUNCTION() virtual void StringParamAsRef(API_PARAM(Ref) String& stringRefParam) {};
|
||||||
|
API_FUNCTION() virtual void ActorParam(Actor* actorParam) {};
|
||||||
|
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<int> intArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void SimpleArrayParamRef(Array<int>& intArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void SimpleArrayParamRefConst(const Array<int>& intArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void SimpleArrayParamAsRef(API_PARAM(Ref) Array<int>& intArrayRefParam) {};
|
||||||
|
API_FUNCTION() virtual void ActorArrayParam(Array<Actor*> actorArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void ActorArrayParamRef(Array<Actor*>& actorArrayParam) {};
|
||||||
|
API_FUNCTION() virtual void ActorArrayParamRefConst(const Array<Actor*>& actorArrayParam) {};
|
||||||
|
|
||||||
|
#if false
|
||||||
|
//API_FUN_CTION() virtual void ActorArrayParamAsRef(API_PARAM(Ref) Array<Actor*>& arr) {};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
API_FUNCTION() virtual void StringFieldStructParam(StringStruct& stringStruct) { ASSERT(false); };
|
||||||
|
API_FUNCTION() virtual void StringFieldStructParamAsRef(API_PARAM(Ref) StringStruct& stringStruct) { ASSERT(false); };
|
||||||
|
API_FUNCTION() virtual void StringFieldStructArrayParam(Array<StringStruct>& stringStructArray) { ASSERT(false); };
|
||||||
|
API_FUNCTION() virtual void StringFieldStructArrayParamAsRef(API_PARAM(Ref) Array<StringStruct>& stringStructArray) { ASSERT(false); };
|
||||||
|
|
||||||
|
API_FUNCTION() virtual void ComplexArrayParam(Array<TestStruct> arrayParam) {};
|
||||||
|
API_FUNCTION() virtual void ComplexArrayParamRef(Array<TestStruct>& arrayParam) {};
|
||||||
|
API_FUNCTION() virtual void ComplexArrayParamRefConst(const Array<TestStruct>& arrayParam) {};
|
||||||
|
API_FUNCTION() virtual void ComplexArrayParamAsRef(API_PARAM(Ref) Array<TestStruct>& arrayRefParam) {};
|
||||||
|
|
||||||
|
|
||||||
|
//API_EVENT() Delegate<int32, Float3, const String&, String&, TestStruct&, const Array<TestStruct>&, Array<TestStruct>&> TestEvent;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
struct BenchmarkContext
|
||||||
|
{
|
||||||
|
MyScript2* scriptTwo;
|
||||||
|
Array<uint64> results;
|
||||||
|
};
|
||||||
|
|
||||||
|
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<int> thingey;
|
||||||
|
|
||||||
|
template<typename... TArgs>
|
||||||
|
void BenchmarkCall(BenchmarkContext& context, void(MyScript2::* fun)(TArgs...),
|
||||||
|
TArgs...);
|
||||||
|
|
||||||
|
//void BenchmarkCall(int times, BenchmarkContext& context, void(MyScript2::*fun)());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// [Script]
|
||||||
|
void OnStart() override;
|
||||||
|
void OnEnable() override;
|
||||||
|
void OnDisable() override;
|
||||||
|
void OnUpdate() override;
|
||||||
|
|
||||||
|
API_FUNCTION() virtual void ManagedCoverageTests() {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest1(int32 a, bool b, Actor* c, String& d, StringAnsi& e, Float3 f) {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest1Array(Array<int32> a, Array<bool> b, Array<Actor*> c, Array<String> d, Array<StringAnsi> e, Array<Float3> f) {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest1ByRef(API_PARAM(Ref) int32& a, API_PARAM(Ref) bool& b, API_PARAM(Ref) String& d, API_PARAM(Ref) StringAnsi& e, API_PARAM(Ref) Float3& f) {};
|
||||||
|
#if false
|
||||||
|
//APIa_FUNCTION() virtual void CoverageTest1ArrayByRef(API_PARAM(Ref) Array<int32>& a, API_PARAM(Ref) Array<bool>& b, API_PARAM(Ref) Array<String>& d, API_PARAM(Ref) Array<StringAnsi>& e, API_PARAM(Ref) Array<Float3>& f) {};
|
||||||
|
#endif
|
||||||
|
API_FUNCTION() virtual void CoverageTest2(Guid a, AssetReference<FontAsset> b, Array<Guid> c, Array<AssetReference<FontAsset>> d) {};
|
||||||
|
API_FUNCTION() virtual void CoverageTest3(ModelLOD* a, API_PARAM(Out) Array<ModelLOD*>& c) {};
|
||||||
|
#if false
|
||||||
|
//APIa_FUNCTION() virtual void CoverageTest4(BytesContainer a, API_PARAM(Out) BytesContainer& b) {};
|
||||||
|
#endif
|
||||||
|
API_FUNCTION() virtual void CoverageNamespaces1(NetworkChannelType a, Array<NetworkChannelType> b, OnlineLeaderboardSortModes c, Array<OnlineLeaderboardSortModes> d, OnlineLeaderboardValueFormats e, Array<OnlineLeaderboardValueFormats> f) {};
|
||||||
|
|
||||||
|
|
||||||
|
//API_FUNCTION() void Test1(API_PARAM(REF) Array<TestTypeEnum>& eenums) {};
|
||||||
|
//API_FUNCTION() BezierCurve<Transform>.Keyframe Test2(BezierCurve<Transform> kef) {};
|
||||||
|
};
|
||||||
|
|
||||||
|
#define LOG_TEST(FUNC) \
|
||||||
|
if (thunkTests || invokeTests || callTests) LOG(Info, #FUNC);
|
||||||
|
|
||||||
|
#define BENCHMARK_INVOKE_ARGS0(REPEAT, FUNC) \
|
||||||
|
{ \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, 0); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
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) \
|
||||||
|
method->Invoke(instance, nullptr, &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, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
|
||||||
|
}
|
||||||
|
#define BENCHMARK_INVOKE_ARGS1(REPEAT, FUNC, PARAM1) \
|
||||||
|
void* params[1]; \
|
||||||
|
{ \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, 1); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
const auto times = REPEAT; \
|
||||||
|
const auto chunkTimes = CHUNK_TIMES; \
|
||||||
|
const auto freq = Platform::GetClockFrequency(); \
|
||||||
|
params[0] = PARAM1; \
|
||||||
|
results.Clear(); \
|
||||||
|
auto start2 = Platform::GetTimeCycles(); \
|
||||||
|
for (int i = 0; i < times; ++i) \
|
||||||
|
{ \
|
||||||
|
auto start = Platform::GetTimeCycles(); \
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) \
|
||||||
|
method->Invoke(instance, params, &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, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
|
||||||
|
}
|
||||||
|
#define BENCHMARK_INVOKE_ARGS1_REF(REPEAT, FUNC, PARAM1, PARAM1_CLEAN) \
|
||||||
|
{ \
|
||||||
|
auto const NUM_PARAMS = 1; \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, NUM_PARAMS); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
const auto times = REPEAT; \
|
||||||
|
const auto chunkTimes = CHUNK_TIMES; \
|
||||||
|
const auto freq = Platform::GetClockFrequency(); \
|
||||||
|
void* params[NUM_PARAMS]; \
|
||||||
|
params[0] = PARAM1; \
|
||||||
|
results.Clear(); \
|
||||||
|
auto start2 = Platform::GetTimeCycles(); \
|
||||||
|
for (int i = 0; i < times; ++i) \
|
||||||
|
{ \
|
||||||
|
void* params_call[CHUNK_TIMES * NUM_PARAMS]; \
|
||||||
|
void* params_call_orig[CHUNK_TIMES * NUM_PARAMS]; \
|
||||||
|
for (int j = 0; j < chunkTimes * NUM_PARAMS; j += NUM_PARAMS) \
|
||||||
|
{ \
|
||||||
|
params_call_orig[j+0] = params[0]; \
|
||||||
|
params_call[j+0] = ¶ms_call_orig[j+0]; \
|
||||||
|
} \
|
||||||
|
auto start = Platform::GetTimeCycles(); \
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) \
|
||||||
|
{ \
|
||||||
|
method->Invoke(instance, ¶ms_call[j * NUM_PARAMS], &exception); \
|
||||||
|
} \
|
||||||
|
auto end = Platform::GetTimeCycles(); \
|
||||||
|
auto elapsed = end - start; \
|
||||||
|
results.Add(elapsed); \
|
||||||
|
for (int j = 0; j < chunkTimes * NUM_PARAMS; j += NUM_PARAMS) \
|
||||||
|
{ \
|
||||||
|
if (params_call_orig[j+0] != params[0]) \
|
||||||
|
{ \
|
||||||
|
void* param = params_call_orig[j+0]; \
|
||||||
|
PARAM1_CLEAN((MObject*)param); \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
auto end2 = Platform::GetTimeCycles(); \
|
||||||
|
auto elapsed2 = end2 - start2; \
|
||||||
|
Sorting::MergeSort(results); \
|
||||||
|
{ \
|
||||||
|
void* param = params[0]; \
|
||||||
|
PARAM1_CLEAN((MObject*)param); \
|
||||||
|
} \
|
||||||
|
const auto resultsIndex = 0; \
|
||||||
|
LOG(Info, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
|
||||||
|
}
|
||||||
|
#define BENCHMARK_INVOKE_ARGS2(REPEAT, FUNC, PARAM1, PARAM2) \
|
||||||
|
void* params[2]; \
|
||||||
|
{ \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, 2); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
const auto times = REPEAT; \
|
||||||
|
const auto chunkTimes = CHUNK_TIMES; \
|
||||||
|
const auto freq = Platform::GetClockFrequency(); \
|
||||||
|
params[0] = PARAM1; \
|
||||||
|
params[1] = PARAM2; \
|
||||||
|
results.Clear(); \
|
||||||
|
auto start2 = Platform::GetTimeCycles(); \
|
||||||
|
for (int i = 0; i < times; ++i) \
|
||||||
|
{ \
|
||||||
|
auto start = Platform::GetTimeCycles(); \
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) \
|
||||||
|
method->Invoke(instance, params, &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, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
|
||||||
|
}
|
||||||
|
#define BENCHMARK_INVOKE_ARGS3(REPEAT, FUNC, PARAM1, PARAM2, PARAM3) \
|
||||||
|
void* params[3]; \
|
||||||
|
{ \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, 3); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
const auto times = REPEAT; \
|
||||||
|
const auto chunkTimes = CHUNK_TIMES; \
|
||||||
|
const auto freq = Platform::GetClockFrequency(); \
|
||||||
|
params[0] = PARAM1; \
|
||||||
|
params[1] = PARAM2; \
|
||||||
|
params[2] = PARAM3; \
|
||||||
|
results.Clear(); \
|
||||||
|
auto start2 = Platform::GetTimeCycles(); \
|
||||||
|
for (int i = 0; i < times; ++i) \
|
||||||
|
{ \
|
||||||
|
auto start = Platform::GetTimeCycles(); \
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) \
|
||||||
|
method->Invoke(instance, params, &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, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
|
||||||
|
}
|
||||||
|
#define BENCHMARK_INVOKE_ARGS4(REPEAT, FUNC, PARAM1, PARAM2, PARAM3, PARAM4) \
|
||||||
|
void* params[4]; \
|
||||||
|
{ \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, 4); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
const auto times = REPEAT; \
|
||||||
|
const auto chunkTimes = CHUNK_TIMES; \
|
||||||
|
const auto freq = Platform::GetClockFrequency(); \
|
||||||
|
params[0] = PARAM1; \
|
||||||
|
params[1] = PARAM2; \
|
||||||
|
params[2] = PARAM3; \
|
||||||
|
params[3] = PARAM4; \
|
||||||
|
results.Clear(); \
|
||||||
|
auto start2 = Platform::GetTimeCycles(); \
|
||||||
|
for (int i = 0; i < times; ++i) \
|
||||||
|
{ \
|
||||||
|
auto start = Platform::GetTimeCycles(); \
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) \
|
||||||
|
method->Invoke(instance, params, &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, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes); \
|
||||||
|
}
|
||||||
|
#define BENCHMARK_INVOKE_ARGS5(REPEAT, FUNC, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5) \
|
||||||
|
void* params[5]; \
|
||||||
|
{ \
|
||||||
|
auto klass = MyScript2::GetStaticClass(); \
|
||||||
|
auto method = klass->GetMethod(#FUNC, 5); \
|
||||||
|
auto instance = scriptTwo->GetManagedInstance(); \
|
||||||
|
MObject* exception = nullptr; \
|
||||||
|
const auto times = REPEAT; \
|
||||||
|
const auto chunkTimes = CHUNK_TIMES; \
|
||||||
|
const auto freq = Platform::GetClockFrequency(); \
|
||||||
|
params[0] = PARAM1; \
|
||||||
|
params[1] = PARAM2; \
|
||||||
|
params[2] = PARAM3; \
|
||||||
|
params[3] = PARAM4; \
|
||||||
|
params[4] = PARAM5; \
|
||||||
|
results.Clear(); \
|
||||||
|
auto start2 = Platform::GetTimeCycles(); \
|
||||||
|
for (int i = 0; i < times; ++i) \
|
||||||
|
{ \
|
||||||
|
auto start = Platform::GetTimeCycles(); \
|
||||||
|
for (int j = 0; j < chunkTimes; ++j) \
|
||||||
|
method->Invoke(instance, params, &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, " - InvokeOnly: {:.1f}ns ({:.0f}ms total {} times)", (results[resultsIndex] * (1.0 / static_cast<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(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<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(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<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(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<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(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<double>(freq)) * 1000000000 / chunkTimes), (elapsed2 * (1.0 / static_cast<double>(freq)) * 1000), times*chunkTimes);
|
||||||
|
#define BENCHMARK_THUNK_END() \
|
||||||
|
}
|
||||||
|
#define COVERAGE_CALL_ARGS2(FUNC, PARAM1, PARAM2) \
|
||||||
|
{ \
|
||||||
|
LOG(Info, #FUNC); \
|
||||||
|
scriptTwo->FUNC(PARAM1, PARAM2); \
|
||||||
|
}
|
||||||
|
#define COVERAGE_CALL_ARGS3(FUNC, PARAM1, PARAM2, PARAM3) \
|
||||||
|
{ \
|
||||||
|
LOG(Info, #FUNC); \
|
||||||
|
scriptTwo->FUNC(PARAM1, PARAM2, PARAM3); \
|
||||||
|
}
|
||||||
|
#define COVERAGE_CALL_ARGS4(FUNC, PARAM1, PARAM2, PARAM3, PARAM4) \
|
||||||
|
{ \
|
||||||
|
LOG(Info, #FUNC); \
|
||||||
|
scriptTwo->FUNC(PARAM1, PARAM2, PARAM3, PARAM4); \
|
||||||
|
}
|
||||||
|
#define COVERAGE_CALL_ARGS5(FUNC, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5) \
|
||||||
|
{ \
|
||||||
|
LOG(Info, #FUNC); \
|
||||||
|
scriptTwo->FUNC(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5); \
|
||||||
|
}
|
||||||
|
#define COVERAGE_CALL_ARGS6(FUNC, PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6) \
|
||||||
|
{ \
|
||||||
|
LOG(Info, #FUNC); \
|
||||||
|
scriptTwo->FUNC(PARAM1, PARAM2, PARAM3, PARAM4, PARAM5, PARAM6); \
|
||||||
|
}
|
||||||
128
Source/Game/MyScriptTwo.cs
Normal file
128
Source/Game/MyScriptTwo.cs
Normal file
@@ -0,0 +1,128 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using FlaxEngine;
|
||||||
|
using FlaxEngine.Interop;
|
||||||
|
using FlaxEngine.Networking;
|
||||||
|
using FlaxEngine.Online;
|
||||||
|
|
||||||
|
namespace Game;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MyScriptTwo Script.
|
||||||
|
/// </summary>
|
||||||
|
public class MyScriptTwo : MyScript2
|
||||||
|
{
|
||||||
|
public Model Model;
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void OnStart()
|
||||||
|
{
|
||||||
|
Debug.Log("C# OnStart");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void OnEnable()
|
||||||
|
{
|
||||||
|
//counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void OnDisable()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc/>
|
||||||
|
public override void OnUpdate()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void GetStats(ref long allocations, ref long deallocations)
|
||||||
|
{
|
||||||
|
allocations = ManagedHandle.Allocations;
|
||||||
|
deallocations = ManagedHandle.Deallocations;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void ManagedCoverageTests()
|
||||||
|
{
|
||||||
|
Actor actor = this.Actor;
|
||||||
|
MyScript script = actor.GetScript<MyScript>();
|
||||||
|
|
||||||
|
string shortString = "Testing string parameter marshalling";
|
||||||
|
Float3 f3 = new Float3(1, 2, 3);
|
||||||
|
|
||||||
|
|
||||||
|
if (true)
|
||||||
|
{
|
||||||
|
int[] ints = { 1 };
|
||||||
|
bool[] booleans = { true };
|
||||||
|
Actor[] actors = { actor };
|
||||||
|
string[] strings = { shortString };
|
||||||
|
Float3[] float3s = { f3 };
|
||||||
|
Guid fontAssetGuid = new Guid("ab96b25a49461d9f4f819484cf5c8213");
|
||||||
|
FontAsset fontAsset = Content.LoadAsync<FontAsset>(fontAssetGuid);
|
||||||
|
ModelLOD[] modelLods = Model.LODs;
|
||||||
|
|
||||||
|
Debug.Log($"{nameof(CoverageTest1)} (Managed)");
|
||||||
|
script.CoverageTest1(1, true, actor, shortString, shortString, f3);
|
||||||
|
|
||||||
|
Debug.Log($"{nameof(CoverageTest1Array)} (Managed)");
|
||||||
|
script.CoverageTest1Array(ints, booleans, actors, strings, strings, float3s);
|
||||||
|
|
||||||
|
Debug.Log($"{nameof(CoverageTest1ByRef)} (Managed)");
|
||||||
|
script.CoverageTest1ByRef(ref ints[0], ref booleans[0]/*, ref actors[0]*/, ref strings[0], ref strings[0], ref float3s[0]);
|
||||||
|
|
||||||
|
//Debug.Log($"{nameof(CoverageTest1ArrayByRef)} (Managed)");
|
||||||
|
//script.CoverageTest1ArrayByRef(ref ints, ref booleans/*, ref actors*/, ref strings, ref strings, ref float3s);
|
||||||
|
|
||||||
|
Debug.Log($"{nameof(CoverageTest2)} (Managed)");
|
||||||
|
script.CoverageTest2(fontAssetGuid, fontAsset, [fontAssetGuid], [fontAsset]);
|
||||||
|
|
||||||
|
Debug.Log($"{nameof(CoverageTest3)} (Managed)");
|
||||||
|
script.CoverageTest3(modelLods[0]/*, out var modelLod*/, out var modelLodsOut);
|
||||||
|
|
||||||
|
//Debug.Log($"{nameof(CoverageTest4)} (Managed)");
|
||||||
|
//script.CoverageTest4([1], out var bytesOut);
|
||||||
|
//script.CoverageTest2(fontAssetGuid, fontAssetRef, Array<Guid>(&fontAssetGuid, 1), Array<AssetReference<FontAsset>>(&fontAssetRef, 1));
|
||||||
|
//script.CoverageNamespaces1(networkChannelType, Array<NetworkChannelType>(&networkChannelType, 1), onlineLeaderboardSortModes, Array<OnlineLeaderboardSortModes>(&onlineLeaderboardSortModes, 1), onlineLeaderboardValueFormats, Array<OnlineLeaderboardValueFormats>(&onlineLeaderboardValueFormats, 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public override void CoverageTest1(int a, bool b, Actor c, String d, String e, Float3 f) {}
|
||||||
|
public override void CoverageTest1Array(int[] a, bool[] b, Actor[] c, String[] d, String[] e, Float3[] f) {}
|
||||||
|
public override void CoverageTest1ByRef(ref int a, ref bool b/*, ref Actor c*/, ref String d, ref String e, ref Float3 f) {}
|
||||||
|
//public override void CoverageTest1ArrayByRef(ref int[] a, ref bool[] b/*, ref Actor[] c*/, ref String[] d, ref String[] e, ref Float3[] f) {}
|
||||||
|
public override void CoverageTest2(Guid a, FontAsset b, Guid[] c, FontAsset[] d) {}
|
||||||
|
public override void CoverageTest3(ModelLOD a, out ModelLOD[] b) { b = null; }
|
||||||
|
//public override void CoverageTest4(byte[] a, out byte[] b) { b = null; }
|
||||||
|
|
||||||
|
public override void CoverageNamespaces1(NetworkChannelType a, NetworkChannelType[] b, OnlineLeaderboardSortModes c, OnlineLeaderboardSortModes[] d, OnlineLeaderboardValueFormats e, OnlineLeaderboardValueFormats[] f) {}
|
||||||
|
|
||||||
|
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 StringFieldStructParam(StringStruct stringStruct) {}
|
||||||
|
public override void StringFieldStructParamAsRef(ref StringStruct stringStruct) {}
|
||||||
|
public override void StringFieldStructArrayParam(StringStruct[] stringStructArray) {}
|
||||||
|
public override void StringFieldStructArrayParamAsRef(ref StringStruct[] stringStructArray) { }
|
||||||
|
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) {}
|
||||||
|
}
|
||||||
@@ -1,22 +1,59 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FlaxEngine;
|
using FlaxEngine;
|
||||||
|
|
||||||
namespace Game;
|
namespace Game;
|
||||||
|
|
||||||
[StructLayout(LayoutKind.Sequential)]
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
public struct PlayerInputState2
|
public struct PlayerInputState2 : IEquatable<PlayerInputState2>
|
||||||
{
|
{
|
||||||
//public ulong frame;
|
public ulong Frame;
|
||||||
public Float2 ViewDelta;
|
public Float2 ViewAngles;
|
||||||
public float MoveForward;
|
public float MoveForward;
|
||||||
public float MoveRight;
|
public float MoveRight;
|
||||||
public bool Attack;
|
public bool Attack;
|
||||||
public bool Jump;
|
public bool Jump;
|
||||||
|
|
||||||
|
public Float2 ViewDelta; // Only used when gathering input for local player
|
||||||
|
|
||||||
|
/*public override bool Equals([NotNullWhen(true)] object obj)
|
||||||
|
{
|
||||||
|
if (obj is not PlayerInputState2 other)
|
||||||
|
return false;
|
||||||
|
return Frame == other.Frame && ViewDelta == other.ViewDelta && MoveForward == other.MoveForward && MoveRight == other.MoveRight && Attack == other.Attack && Jump == other.Jump;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
public bool Equals(PlayerInputState2 other)
|
||||||
|
{
|
||||||
|
return Frame == other.Frame && ViewAngles == other.ViewAngles && MoveForward == other.MoveForward && MoveRight == other.MoveRight && Attack == other.Attack && Jump == other.Jump && ViewDelta == other.ViewDelta;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool operator ==(PlayerInputState2 left, PlayerInputState2 right) => left.Equals(right);
|
||||||
|
|
||||||
|
public static bool operator !=(PlayerInputState2 left, PlayerInputState2 right) => !left.Equals(right);
|
||||||
|
|
||||||
|
// Apply delta to calculate the final view angles for this state
|
||||||
|
public void UpdateViewAngles(Float2 lastInputViewAngles)
|
||||||
|
{
|
||||||
|
ViewAngles = lastInputViewAngles + ViewDelta;
|
||||||
|
ViewDelta = Float2.Zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override bool Equals(object obj)
|
||||||
|
{
|
||||||
|
return obj is PlayerInputState2 && Equals((PlayerInputState2)obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
public override int GetHashCode()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface IPlayerInput
|
public interface IPlayerInput
|
||||||
@@ -53,8 +90,13 @@ public class PlayerInput2 : IPlayerInput
|
|||||||
[ConsoleVariable("sensitivity")]
|
[ConsoleVariable("sensitivity")]
|
||||||
private static float _sensitivity { get; set; } = 1.0f;
|
private static float _sensitivity { get; set; } = 1.0f;
|
||||||
|
|
||||||
|
private ulong _frame;
|
||||||
|
|
||||||
public void SetFrame(ulong frame)
|
public void SetFrame(ulong frame)
|
||||||
{
|
{
|
||||||
|
if (_frame != frame)
|
||||||
|
ResetState();
|
||||||
|
_frame = frame;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void UpdateState()
|
public void UpdateState()
|
||||||
@@ -68,12 +110,20 @@ public class PlayerInput2 : IPlayerInput
|
|||||||
float turnSpeed = 100.0f;
|
float turnSpeed = 100.0f;
|
||||||
|
|
||||||
_recordState.ViewDelta += new Float2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")) * _sensitivity;
|
_recordState.ViewDelta += new Float2(Input.GetAxisRaw("Mouse X"), Input.GetAxisRaw("Mouse Y")) * _sensitivity;
|
||||||
_recordState.ViewDelta += new Float2(Input.GetAxisRaw("LookRight"), Input.GetAxisRaw("LookUp")) * Time.DeltaTime * turnSpeed;
|
_recordState.ViewDelta += new Float2(Input.GetAxisRaw("LookRight"), Input.GetAxisRaw("LookUp")) * Time.DeltaTime * turnSpeed;
|
||||||
|
|
||||||
_recordState.MoveForward = MathF.MaxMagnitude(_recordState.MoveForward, Input.GetAxis("Vertical"));
|
_recordState.MoveForward = MathF.MaxMagnitude(_recordState.MoveForward, Input.GetAxis("Vertical"));
|
||||||
_recordState.MoveRight = MathF.MaxMagnitude(_recordState.MoveRight, Input.GetAxis("Horizontal"));
|
_recordState.MoveRight = MathF.MaxMagnitude(_recordState.MoveRight, Input.GetAxis("Horizontal"));
|
||||||
_recordState.Attack |= Input.GetAction("Attack");
|
_recordState.Attack |= Input.GetAction("Attack");
|
||||||
_recordState.Jump |= Input.GetAction("Jump");
|
_recordState.Jump |= Input.GetAction("Jump");
|
||||||
|
_recordState.Frame = _frame;
|
||||||
|
|
||||||
|
if (Input.GetKeyDown(KeyboardKeys.F))
|
||||||
|
Thread.Sleep(20);
|
||||||
|
|
||||||
|
var asdf = Input.GetAxis("Vertical");
|
||||||
|
if (asdf != 0.0f)
|
||||||
|
asdf = asdf;
|
||||||
}
|
}
|
||||||
|
|
||||||
public PlayerInputState2 GetState() => _recordState;
|
public PlayerInputState2 GetState() => _recordState;
|
||||||
|
|||||||
@@ -74,6 +74,7 @@ public struct PlayerMovementState
|
|||||||
public int numJumps;
|
public int numJumps;
|
||||||
public bool jumped;
|
public bool jumped;
|
||||||
public bool onGround;
|
public bool onGround;
|
||||||
|
public ulong frame;
|
||||||
|
|
||||||
|
|
||||||
public PlayerMovementState()
|
public PlayerMovementState()
|
||||||
@@ -136,7 +137,11 @@ public class PlayerMovement : Script
|
|||||||
private PlayerActor playerActor;
|
private PlayerActor playerActor;
|
||||||
public Actor rootActor;
|
public Actor rootActor;
|
||||||
|
|
||||||
public Float3 viewAngles;
|
public Float3 viewAngles
|
||||||
|
{
|
||||||
|
get => movementState.viewAngles;
|
||||||
|
set => movementState.viewAngles = value;
|
||||||
|
}
|
||||||
private Float3 viewAnglesLastFrame;
|
private Float3 viewAnglesLastFrame;
|
||||||
|
|
||||||
public uint PlayerId => playerActor ? playerActor.PlayerId : 0;
|
public uint PlayerId => playerActor ? playerActor.PlayerId : 0;
|
||||||
@@ -250,14 +255,27 @@ public class PlayerMovement : Script
|
|||||||
viewAnglesLastFrame = viewAngles;
|
viewAnglesLastFrame = viewAngles;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static int framedropped = 0;
|
||||||
public override void OnUpdate()
|
public override void OnUpdate()
|
||||||
{
|
{
|
||||||
|
if (World.IsServer && Mathf.Abs(Time.DeltaTime - (1.0f / Time.UpdateFPS)) > (1.0f / Time.UpdateFPS) * 0.999f)
|
||||||
|
{
|
||||||
|
Console.Print($"drop: {Time.DeltaTime*1000.0f}ms");
|
||||||
|
framedropped = 3;
|
||||||
|
}
|
||||||
|
else if (World.IsServer && framedropped > 0)
|
||||||
|
{
|
||||||
|
Console.Print("dropping...");
|
||||||
|
framedropped--;
|
||||||
|
}
|
||||||
|
//Console.Print($"{(World.IsClient ? "[cl] " : "[sv] ") + World.Frame.ToString()} playerMovement OnUpdate");
|
||||||
//input.OnUpdate();
|
//input.OnUpdate();
|
||||||
|
|
||||||
|
|
||||||
//if (Input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/)
|
//if (Input is PlayerInputDemo /*&& currentInputFrame2 >= currentInputFrame*/)
|
||||||
// return;
|
// return;
|
||||||
|
|
||||||
|
|
||||||
Input.SetFrame(World.Frame);
|
Input.SetFrame(World.Frame);
|
||||||
Input.UpdateState();
|
Input.UpdateState();
|
||||||
|
|
||||||
@@ -311,13 +329,14 @@ public class PlayerMovement : Script
|
|||||||
|
|
||||||
public override void OnFixedUpdate()
|
public override void OnFixedUpdate()
|
||||||
{
|
{
|
||||||
|
//Console.Print($"{(World.IsClient ? "[cl] " : "[sv] ") + World.Frame.ToString()} playerMovement OnFixedUpdate");
|
||||||
float timeDeltaDiff = Time.DeltaTime - 1.0f / Time.PhysicsFPS;
|
float timeDeltaDiff = Time.DeltaTime - 1.0f / Time.PhysicsFPS;
|
||||||
if (Time.PhysicsFPS > 0 && Math.Abs(timeDeltaDiff) > 0.0001f)
|
if (Time.PhysicsFPS > 0 && Math.Abs(timeDeltaDiff) > 0.0001f)
|
||||||
Console.Print("Time.DeltaTime is not stable: " + timeDeltaDiff);
|
Console.Print("Time.DeltaTime is not stable: " + timeDeltaDiff);
|
||||||
|
|
||||||
//Input.OnFixedUpdate();
|
//Input.OnFixedUpdate();
|
||||||
PlayerInputState2 inputState = Input.GetState();
|
PlayerInputState2 inputState = Input.GetState();
|
||||||
bool predict = World.IsClient;
|
bool predict = World.IsClient && false;
|
||||||
if (predict)
|
if (predict)
|
||||||
{
|
{
|
||||||
// Get the latest frame we have predicted
|
// Get the latest frame we have predicted
|
||||||
@@ -408,13 +427,95 @@ public class PlayerMovement : Script
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!predict)
|
if (World.IsServer)
|
||||||
|
{
|
||||||
|
ulong currentFrame = World.GetLastProcessedFrame(PlayerId);
|
||||||
|
{
|
||||||
|
// Rewind to last confirmed state
|
||||||
|
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
|
||||||
|
if (frameInfo != null && frameInfo.movementState.frame == currentFrame)
|
||||||
|
{
|
||||||
|
// Reset all state to latest confirmed state from server
|
||||||
|
movementState.position = frameInfo.movementState.position;
|
||||||
|
movementState.currentVelocity = frameInfo.movementState.currentVelocity;
|
||||||
|
movementState.lastJumped = frameInfo.movementState.lastJumped;
|
||||||
|
movementState.numJumps = frameInfo.movementState.numJumps;
|
||||||
|
movementState.jumped = frameInfo.movementState.jumped;
|
||||||
|
Actor.Position = movementState.position;
|
||||||
|
SetCameraEulerAngles(frameInfo.movementState.viewAngles, true);
|
||||||
|
//ApplyInputToCamera(frameInfo.inputState, true);
|
||||||
|
}
|
||||||
|
else if (frameInfo == null)
|
||||||
|
{
|
||||||
|
// First frame, update the known state
|
||||||
|
movementState.viewAngles = viewAngles;
|
||||||
|
World.UpdatePlayerState(PlayerId, currentFrame, movementState);
|
||||||
|
}
|
||||||
|
currentFrame++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Console.Print("before:" + viewAngles.ToString());
|
||||||
|
|
||||||
|
ulong lastFrame = World.GetLastReceivedFrame(PlayerId);
|
||||||
|
PlayerFrame lastFrameInfo = null;
|
||||||
|
for (; currentFrame < lastFrame+1; currentFrame++)
|
||||||
|
{
|
||||||
|
var frameInfo = World.GetPlayerFrame(PlayerId, currentFrame);
|
||||||
|
if (frameInfo == null || frameInfo.inputState.Frame != currentFrame)
|
||||||
|
//if (!Input.GetState(currentFrame, out var pastInputState, out var pastActorState))
|
||||||
|
{
|
||||||
|
Console.Print($"frame {currentFrame} missing");
|
||||||
|
frameInfo = lastFrameInfo; // Use last known input
|
||||||
|
|
||||||
|
if (frameInfo == null)
|
||||||
|
{
|
||||||
|
// FIXME
|
||||||
|
frameInfo = new PlayerFrame()
|
||||||
|
{
|
||||||
|
inputState =
|
||||||
|
{
|
||||||
|
Frame = currentFrame,
|
||||||
|
ViewAngles = movementState.viewAngles.XY(),
|
||||||
|
},
|
||||||
|
movementState = movementState,
|
||||||
|
};
|
||||||
|
frameInfo.movementState.frame = currentFrame;
|
||||||
|
}
|
||||||
|
//continue;
|
||||||
|
//Console.Print($"not predicting");
|
||||||
|
//predict = false;
|
||||||
|
//break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Input.SetFrame(currentFrame);
|
||||||
|
Input.UpdateState();
|
||||||
|
|
||||||
|
SetCameraEulerAngles(new Float3(frameInfo.inputState.ViewAngles.X, frameInfo.inputState.ViewAngles.Y, viewAngles.Z), true);
|
||||||
|
//ApplyInputToCamera(frameInfo.inputState, true);
|
||||||
|
lastFrameInfo = frameInfo;
|
||||||
|
}
|
||||||
|
SimulatePlayerMovement(frameInfo.inputState, currentFrame);
|
||||||
|
movementState.viewAngles = viewAngles;
|
||||||
|
|
||||||
|
//Console.Print("tick: " + viewAngles.ToString());
|
||||||
|
|
||||||
|
//if (frameInfo.movementState.frame != currentFrame)
|
||||||
|
World.UpdatePlayerState(PlayerId, currentFrame, movementState);
|
||||||
|
//else
|
||||||
|
// currentFrame = currentFrame;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (!predict)
|
||||||
{
|
{
|
||||||
SetCameraEulerAngles(viewAnglesLastFrame, true);
|
SetCameraEulerAngles(viewAnglesLastFrame, true);
|
||||||
ApplyInputToCamera(inputState, true);
|
ApplyInputToCamera(inputState, true);
|
||||||
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
|
SimulatePlayerMovement(inputState, World.Frame); // MAYBE?
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//if (!movementState.currentVelocity.IsZero)
|
||||||
|
// Console.Print($"{(World.IsClient ? "client" : "server")} {World.Frame} vel: {movementState.currentVelocity}, pos: {movementState.position}");
|
||||||
|
|
||||||
viewAnglesLastFrame = viewAngles;
|
viewAnglesLastFrame = viewAngles;
|
||||||
|
|
||||||
#if false
|
#if false
|
||||||
@@ -962,7 +1063,7 @@ public class PlayerMovement : Script
|
|||||||
if (capsuleCollider && capsuleCollider.IsActive)
|
if (capsuleCollider && capsuleCollider.IsActive)
|
||||||
{
|
{
|
||||||
Quaternion rotation = capsuleCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f);
|
Quaternion rotation = capsuleCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f);
|
||||||
DebugDraw.DrawWireTube(capsuleCollider.Position, rotation, capsuleCollider.Radius,
|
DebugDraw.DrawWireCapsule(capsuleCollider.Position, rotation, capsuleCollider.Radius,
|
||||||
capsuleCollider.Height, Color.GreenYellow * 0.8f);
|
capsuleCollider.Height, Color.GreenYellow * 0.8f);
|
||||||
}
|
}
|
||||||
else if (meshCollider && meshCollider.IsActive)
|
else if (meshCollider && meshCollider.IsActive)
|
||||||
@@ -970,7 +1071,7 @@ public class PlayerMovement : Script
|
|||||||
//Quaternion rotation = meshCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f);
|
//Quaternion rotation = meshCollider.LocalOrientation * Quaternion.Euler(0f, 90f, 0f);
|
||||||
DebugDraw.DrawWireCylinder(meshCollider.Position, meshCollider.Orientation, capsuleCollider.Radius,
|
DebugDraw.DrawWireCylinder(meshCollider.Position, meshCollider.Orientation, capsuleCollider.Radius,
|
||||||
capsuleCollider.Height + capsuleCollider.Radius * 2, Color.GreenYellow * 0.8f);
|
capsuleCollider.Height + capsuleCollider.Radius * 2, Color.GreenYellow * 0.8f);
|
||||||
//DebugDraw.DrawWireTube(meshCollider.Position, rotation, meshCollider.Radius, meshCollider.Height, Color.GreenYellow * 0.8f);
|
//DebugDraw.DrawWireCapsule(meshCollider.Position, rotation, meshCollider.Radius, meshCollider.Height, Color.GreenYellow * 0.8f);
|
||||||
}
|
}
|
||||||
else if (boxCollider && boxCollider.IsActive)
|
else if (boxCollider && boxCollider.IsActive)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -24,13 +24,16 @@ public class GameTarget : GameProjectTarget
|
|||||||
OutputType = TargetOutputType.Executable;
|
OutputType = TargetOutputType.Executable;
|
||||||
}
|
}
|
||||||
Modules.Add("Game");
|
Modules.Add("Game");
|
||||||
|
Modules.Add("Graphics");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void SetupTargetEnvironment(BuildOptions options)
|
public override void SetupTargetEnvironment(BuildOptions options)
|
||||||
{
|
{
|
||||||
base.SetupTargetEnvironment(options);
|
base.SetupTargetEnvironment(options);
|
||||||
|
|
||||||
|
#pragma warning disable CS0618 // X is obsolete
|
||||||
options.LinkEnv.UseFastPDBLinking = true;
|
options.LinkEnv.UseFastPDBLinking = true;
|
||||||
|
#pragma warning restore CS0618 // X is obsolete
|
||||||
}
|
}
|
||||||
|
|
||||||
public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null)
|
public override string GetOutputFilePath(BuildOptions options, TargetOutputType? outputType = null)
|
||||||
|
|||||||
Reference in New Issue
Block a user