Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use Huge Typed Array? #61

Closed
mflux opened this issue Apr 13, 2016 · 12 comments
Closed

How to use Huge Typed Array? #61

mflux opened this issue Apr 13, 2016 · 12 comments

Comments

@mflux
Copy link

mflux commented Apr 13, 2016

Hi Nako, I seem to be running into speed issues passing large arrays from JS into Unreal. The size range is between 3000 to 16000 floats, for passing geometry data from JS to Unreal.

I'm 99% sure the speed loss is due to JS transfering data and needs to use: https://github.com/ncsoft/Unreal.js/wiki/Huge-typed-array

However, I'm uncertain how to actually pass to for example, ProceduralMesh component's UpdateMeshSection function.

I'm comfortable enough with C++ do dive in however this is still confusing to me:

let ab = new ArrayBuffer(32*1024); // 32K bytes buffer
let u8 = new Uint8Array(ab); // typed array
memory.bind(ab);
GWorld.MySuperMemoryFunction();
memory.unbind(ab);

What is MySuperMemoryFunction()? Is this compiled from somewhere? How do you go about creating that function? Is 'ab' variable supposed to be passed in?

void UMyBlueprintFunctionLibrary::MySuperMemoryFunction(UWorld* World)
{
    auto size = FArrayBufferAccessor::GetSize();
    auto buffer = FArrayBufferAccessor::GetData();
}

Is there just a single FArrayBufferAccessor that's bound as a global variable? What's the best way to go from here to ProceduralMesh's UpdateMeshSection?

@mflux
Copy link
Author

mflux commented Apr 13, 2016

Continuing from the above... I was able to get a BlueprintFunctionLibrary compiled, however FArrayBufferAccessor is not found.

According to some examples found in the Unreal.js plugin, it comes from one of these:

#include "JavascriptEditor.h"
#include "JavascriptEditorLibrary.h"

However the source for that is not accessible. Am I going about this the right way? Am I supposed to include the plugin source to have access to these functions?

@nakosung
Copy link
Collaborator

Array buffer accessor is located at 'JavascriptContext.h`. (https://github.com/ncsoft/Unreal.js-core/blob/master/Source/V8/Public/JavascriptContext.h)

If you want to read back from huge typed array (which is passed from C++), there is a working example. (https://github.com/nakosung/UnrealDarknet/blob/master/Content/Scripts/yolo.js)

@mflux
Copy link
Author

mflux commented Apr 13, 2016

Thanks Nako

What's the proper way to include JavascriptContext.h? Should I include all the project files for the plugin into my game project/folder?

@nakosung
Copy link
Collaborator

No. Add project dependency in your game.Build.cs. And add #include "JavascriptContext.h" in your cpp. :)

@nakosung
Copy link
Collaborator

@mflux
Copy link
Author

mflux commented Apr 13, 2016

Ah thanks! Add V8 instead of Unreal.js? How does Unreal's build system know where to look for this dependency? I currently have the V8 source in my Program Files/Epic/UE/4.1/plugin/UnrealJS/etc... folder. Does the path matter? Should it be inside my project folder instead?

@nakosung
Copy link
Collaborator

If you build engine from source, plugin can be installed as an engine plugin. I'm not sure with packaged build from epic.

@mflux
Copy link
Author

mflux commented Apr 13, 2016

Alright, will look into it, thanks!

@mflux mflux closed this as completed Apr 13, 2016
@mflux
Copy link
Author

mflux commented Apr 14, 2016

I got it mostly working. It looks like memory.bind is deprecated?

Warning: memory.bind is deprecated. use memory.exec(ab,fn) instead.

Should it be like this?

let ab = new ArrayBuffer(32*1024); // 32K bytes buffer
let u8 = new Uint8Array(ab); // typed array
memory.exec(ab, function(){      
  return [someArrayofData];
});

//  BP-Library Function that uses memory
GWorld.FastArrayCopy();

I couldn't find any documentation of memory.exec.

The yolo.js example you linked https://github.com/nakosung/UnrealDarknet/blob/master/Content/Scripts/yolo.js made no use of memory.bind either.

Furthermore, the Hello.js example has this but it isn't clear to me how the memory value is being used afterwards:

memory.exec(ab,_ => {

@mflux mflux reopened this Apr 14, 2016
@nakosung
Copy link
Collaborator

Yes, unguarded operations are deprecated. :)

memory.exec(ab, function() {
  // all operations which accesses array buffer should be guarded within this function.
  GWorld.FastArrayCopy();
})

@mflux
Copy link
Author

mflux commented Apr 14, 2016

Haha. Yes, that seems much safer.

Are there examples of accessing the data inside a FArrayBufferAccessor? For example looping over it?

@mflux mflux closed this as completed Apr 14, 2016
@mflux
Copy link
Author

mflux commented Apr 14, 2016

I figured it out 👍

In Javascript

let fa = Float32Array.from( [ 10000, 99999, 123456, 30.2000, 3.1419 ]); // typed array

memory.exec(fa.buffer, function(){
  GWorld.FastArrayCopy();
});

In C++

auto size = FArrayBufferAccessor::GetSize();
auto buffer = FArrayBufferAccessor::GetData();

float* conv = static_cast<float*>(buffer);
int length = size / 4;

UE_LOG(LogTemp, Log, TEXT("length of array %d"), length);
for (int i = 0; i < length; i++) {
    float f = float( conv[i]);
    UE_LOG(LogTemp, Log, TEXT("%f"), f);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants