UnrealCLR icon indicating copy to clipboard operation
UnrealCLR copied to clipboard

Blueprint nodes generation at runtime

Open nxrighthere opened this issue 3 years ago • 16 comments

A robust and flexible system should be implemented to generate blueprint nodes and data types weaved with managed code that exposes functionality to the engine.

nxrighthere avatar Sep 06 '20 00:09 nxrighthere

The first prototype implemented. Current challenges:

  • Auto-generated C++ plugin with blueprint functions cannot be hot reloaded with headers that generated by the Unreal's header tool for a blueprint function library
  • Unhandled exceptions cannot be transparently handled and redirected in functions that implemented by a user to prevent termination of the process by .NET runtime (see dotnet/runtime#39587)

nxrighthere avatar Sep 15 '20 19:09 nxrighthere

Seems like it's possible to generate blueprint nodes dynamically at runtime. The current challenge at this point is the invocation of user functions with variable-length parameters. In terms of performance, the invocation of functions with predefined fixed-length parameters are 195% faster than the closest equivalent for variable-length parameters:

BenchmarkDotNet=v0.12.1, OS=Windows 10.0.19041.508
AMD Ryzen 5 1400, 1 CPU, 8 logical and 4 physical cores
.NET Core SDK=5.0.100-rc.1.20452.10
  [Host] : .NET Core 5.0.0 (CoreCLR 5.0.20.45114, CoreFX 5.0.20.45114), X64 RyuJIT
Method Mean Error StdDev
'Fixed-length parameters, Function()' 2.878 ns 0.0149 ns 0.0140 ns
'Fixed-length parameters, Delegate.Invoke()' 3.850 ns 0.0264 ns 0.0234 ns
'Fixed-length parameters, Dynamic->Delegate.Invoke()' 18.292 ns 0.3381 ns 0.2997 ns
'Variable-length parameters, Dynamic->Method.Invoke()' 224.541 ns 1.3883 ns 1.2986 ns
'Variable-length parameters, Dynamic->Delegate.DynamicInvoke()' 372.478 ns 1.4545 ns 1.3605 ns

All delegates for user functions should be stored as dynamic types in a single cached collection for fast access from native code once all entry points are cached at startup.

This approach has a significant impact on performance, unlike the code generation where all functions with parameters can be predefined at compilation time.

A performant solution might be a custom blittable representation of function parameters using a single predefined function for the invocation from blueprints, but that means intermediate conversion to appropriate data types in the user function itself. This approach is counterproductive.

nxrighthere avatar Sep 25 '20 06:09 nxrighthere

Related to https://github.com/dotnet/csharplang/issues/3718

nxrighthere avatar Sep 25 '20 10:09 nxrighthere

Blocked by https://github.com/dotnet/runtime/issues/42275

nxrighthere avatar Oct 04 '20 20:10 nxrighthere

Looking forward to this feature. Is it in the main branch or is it pending the initial stable release?

dagillespie avatar Feb 16 '21 10:02 dagillespie

This feature is on hold at the moment, but I think I can ship it partially in the following weeks with certain limitations. The main problem is that .NET 5 lacks functionality to implement this feature the right way.

nxrighthere avatar Feb 18 '21 07:02 nxrighthere

Happy to wait if .NET 5 is the blocker here (does 6 help?) but equally very happy to kick the tyres of your implementation.

dagillespie avatar Feb 19 '21 09:02 dagillespie

Happy to wait if .NET 5 is the blocker here (does 6 help?)

Unfortunately, as long as this issue remains unresolved, it wouldn't help.

nxrighthere avatar Feb 23 '21 15:02 nxrighthere

Happy to wait if .NET 5 is the blocker here (does 6 help?)

Unfortunately, as long as this issue remains unresolved, it wouldn't help.

As of July 12, 2021, it seems they moved the feature to the Future roadmap, which basically means "anytime between tomorrow and the next big bang, if we're still alive" although I agree with the feature, MS is MS... I think it would be a good time to think on alternatives. I'll check what I can come up with.

darkguy2008 avatar Sep 27 '21 03:09 darkguy2008

Since the API has been approved, I think a PR from community will definitely push the process of implementing https://github.com/dotnet/runtime/issues/42275

hez2010 avatar Oct 05 '21 12:10 hez2010

What about use Source Generator instead runtime to improve performance?

danielmeza avatar Dec 28 '21 16:12 danielmeza

@danielmeza Blueprint function libraries compiled from C++ can't be hot reloaded. You have to restart the editor to reflect changes of nodes.

nxrighthere avatar Dec 29 '21 21:12 nxrighthere

@nxrighthere so, every code made with a Source Generator, will need an editor restart to see it on the editor?

I´m talking about this Seems like it's possible to generate blueprint nodes dynamically at runtime. we can use Source Generators to generate those nodes not at runtime but on precompile time so the performance can be improved there.

danielmeza avatar Jan 04 '22 23:01 danielmeza

@danielmeza Blueprint function libraries compiled from C++ can't be hot reloaded. You have to restart the editor to reflect changes of nodes.

C++ can be hot reloaded into UE4 without an editor restart however it does a temporary patch of the DLLs meaning at times an editor restart is needed. Saying that USharp was able to implement hot reloading of blueprint nodes from C#.

dagillespie avatar Jan 05 '22 09:01 dagillespie

C++ can be hot reloaded into UE4 without an editor restart however it does a temporary patch of the DLLs meaning at times an editor restart is needed.

I'm talking about the cases where static blueprint callable functions are used. Once they are loaded into memory, the engine locks the entire module from hot reloading.

Saying that USharp was able to implement hot reloading of blueprint nodes from C#.

It's based on a very different approach, such as a mix of runtime pointer manipulations and code generation.

nxrighthere avatar Jan 05 '22 11:01 nxrighthere

Happy to wait if .NET 5 is the blocker here (does 6 help?)

Unfortunately, as long as this issue remains unresolved, it wouldn't help.

It seems that issue is gaining some traction now (yay!) so hopefully once it's done it will help to fix this important one. They're having an ongoing discussion now and are asking for feedback. The more we can help, the better! :)

darkguy2008 avatar Mar 08 '22 22:03 darkguy2008